Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add quick guide #3

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions doc/how-to-build-customized-image.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Quick guide for the customized image

This is the quick guide about how to geneate the customized image for Dev Box.
The main steps are as below:
- Create a Gallery
- Configure for Gallery
- Create Service Principal
- Generate the image

## Create a Gallery
1. Search "Azure Compute Galleries" in the Azure Portal, click the service "Azure compute galleries"
![Search Gallery](/doc/media/search-azure-compute-gallery.png)

2. Click the "Create" button
![Create Gallery](/doc/media/create-azure-compute-gallery.png)

3. Give the gallery name and select the resource group, then click "Review + Create"
![Create Gallery Detail](/doc/media/create-azure-compute-gallery-detail.png)

## Configure for Gallery
1. Fork the base repository [Azure/dev-box-images](https://github.com/Azure/dev-box-images)
![Fork Base repo](/doc/media/fork-base-repo.png)

2. In your forked repository, change the value in gallery.yml:

name: "the gallery name that we just created in the above step"
resourceGroup: "the resource group that the gallery is located"

Please check the mapping as below:
![Update Gallery Yml](/doc/media/update-gallery-yml.png)

## Create Service Principal

1. Create a Service Principal with the Azure CLI command as below:

az ad sp create-for-rbac --sdk-auth --role contributor --scopes /subscriptions/<subscription id> -n <your service principal name>

You will get the output as below:
{
"clientId": "<GUID>",
"clientSecret": "<STRING>",
"subscriptionId": "<GUID>",
"tenantId": "<GUID>"
(...)
}

Remove all the line breaks and keep a single link as below:
{ "clientId": "<GUID>", "clientSecret": "<GUID>", "subscriptionId": "<GUID>", "tenantId": "<GUID>", (...) }

2. Go to the settings of your forked GitHub project
![GitHub Repo Setting](/doc/media/github-repo-settings.png)

3. Click "Secrets" -> "Actions" -> "New Repository Secret"
![New Repository Secret](/doc/media/new-repo-secret.png)

Secret name is "AZURE_CREDENTIALS". Value is the single line that we prepared before as below:
{ "clientId": "<GUID>", "clientSecret": "<GUID>", "subscriptionId": "<GUID>", "tenantId": "<GUID>", (...) }

## Generate the image
1. Go to the forked GitHub project’s "Actions" page
![GitHub Actions](/doc/media/github-actions.png)

Enable it if there is an option asking to click.

2. Define the software to install
Go to images/VSCodeBox/build.pkr.hcl
If the software can be installed by choco, just execute the command "choco install" to install.
Note: --confirm is required otherwise, it will be installed by confirm yes or no.
If the software cannot be installed by choco, please write up the related PowerShell script to install the specific software.

![Customize Software](/doc/media/cutomize-software.png)

Once you commit the change under the folder images or scripts, the GitHub action pipeline will be triggered.

3. Go to the GitHub Actions, you will see the status of the pipeline
![GitHub Actions Workflow](/doc/media/github-actions-workflow.png)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/media/create-azure-compute-gallery.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/media/cutomize-software.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/media/fork-base-repo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/media/github-actions-workflow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/media/github-actions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/media/github-repo-settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/media/new-repo-secret.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/media/search-azure-compute-gallery.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/media/update-gallery-yml.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
122 changes: 122 additions & 0 deletions images/JavaEclipseBox/build.pkr.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
packer {
required_plugins {
# https://github.com/rgl/packer-plugin-windows-update
windows-update = {
version = "0.14.1"
source = "github.com/rgl/windows-update"
}
}
}

# https://www.packer.io/plugins/builders/azure/arm
source "azure-arm" "vm" {
azure_tags = {
branch = var.branch
build = timestamp()
commit = var.commit
}
communicator = "winrm"
winrm_username = "packer"
winrm_insecure = true
winrm_use_ssl = true
image_publisher = "microsoftwindowsdesktop"
image_offer = "windows-ent-cpc"
image_sku = "win11-21h2-ent-cpc-m365"
image_version = "latest"
use_azure_cli_auth = true
managed_image_name = var.name
managed_image_resource_group_name = var.galleryResourceGroup
location = var.location
temp_resource_group_name = var.tempResourceGroup
build_resource_group_name = var.buildResourceGroup
user_assigned_managed_identities = var.identities
async_resourcegroup_delete = true
os_type = "Windows"
vm_size = "Standard_D8s_v3"
shared_image_gallery_destination {
subscription = var.subscription
resource_group = var.galleryResourceGroup
gallery_name = var.galleryName
image_name = var.name
image_version = var.version
replication_regions = var.replicaLocations
storage_account_type = "Standard_LRS"
}
}

build {
sources = ["source.azure-arm.vm"]

provisioner "powershell" {
environment_vars = [
"ADMIN_USERNAME=${build.User}",
"ADMIN_PASSWORD=${build.Password}"
]
script = "../../scripts/Enable-AutoLogon.ps1"
}

provisioner "windows-restart" {
# needed to get elevated script execution working
restart_timeout = "30m"
pause_before = "2m"
}

# https://github.com/rgl/packer-plugin-windows-update
provisioner "windows-update" {
}

provisioner "powershell" {
elevated_user = build.User
elevated_password = build.Password
scripts = [
"../../scripts/Install-PsModules.ps1",
"../../scripts/Install-AzPsModule.ps1",
"../../scripts/Install-Chocolatey.ps1"
]
}

provisioner "powershell" {
elevated_user = build.User
elevated_password = build.Password
inline = [
"choco install git --yes --no-progres",
"choco install openjdk11 --yes --no-progres",
"choco install maven --version=3.8.4 --yes --no-progres",
"choco install postman --yes --no-progres",
"choco install googlechrome --yes --no-progres"
]
}

provisioner "powershell" {
elevated_user = build.User
elevated_password = build.Password
scripts = [
"../../scripts/Install-HyperV.ps1",
"../../scripts/Install-Python3.8.ps1",
"../../scripts/Install-AzureCLI.ps1",
"../../scripts/Install-VSCode.ps1",
"../../scripts/Install-Eclipse.ps1",
"../../scripts/Install-GCloudCLI.ps1" # depends on python
]
}

# HyperV needs restart, otherise, generalizing will fail
provisioner "windows-restart" {
restart_timeout = "30m"
pause_before = "2m"
}

// this doesn't work yet
// provisioner "powershell" {
// elevated_user = build.User
// elevated_password = build.Password
// scripts = [for r in var.repos : "../../scripts/Clone-Repo.ps1 -Url '${r.url}' -Secret '${r.secret}'"]
// }

provisioner "powershell" {
scripts = [
"../../scripts/Disable-AutoLogon.ps1",
"../../scripts/Generalize-VM.ps1"
]
}
}
9 changes: 9 additions & 0 deletions images/JavaEclipseBox/image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
description: Windows 11 Enterprise + M365 Apps + Eclipse
publisher: Contoso
offer: DevBox
sku: win11-eclipse
version: 1.0.0
os: Windows
replicaLocations:
- eastus
- westeurope
86 changes: 86 additions & 0 deletions images/JavaEclipseBox/variable.pkr.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
variable "branch" {
type = string
default = ""
description = "The branch to use for the build"
}

variable "commit" {
type = string
default = ""
description = "The commit to use for the build"
}

variable "galleryName" {
type = string
default = ""
description = "The name of the gallery to use for the build"
}

variable "galleryResourceGroup" {
type = string
default = ""
description = "The resource group to use for the managed image"
}

variable "name" {
type = string
default = ""
description = "The name of the image to use for the build"
}

variable "replicaLocations" {
type = list(string)
default = []
description = "The locations to replicate the image to"
}

variable "resolvedResourceGroup" {
type = string
default = ""
description = ""
}

variable "location" {
type = string
default = ""
description = "Azure datacenter in which your VM will build, if this is provided buildResourceGroup should be left blank"
}

variable "tempResourceGroup" {
type = string
default = ""
description = "Name assigned to the temporary resource group created during the build. If this value is not set, a random value will be assigned. This resource group is deleted at the end of the build. If this is provided buildResourceGroup should be left blank"
}

variable "buildResourceGroup" {
type = string
default = ""
description = "Specify an existing resource group to run the build in. If this is provided tempResourceGroup and location should not be provided"
}

variable "subscription" {
type = string
default = ""
description = "The subscription to use for the build"
}

variable "version" {
type = string
default = ""
description = "The version to use for the build"
}

variable "identities" {
type = list(string)
default = []
description = "One or more fully-qualified resource IDs of user assigned managed identities to be configured on the VM"
}

variable "repos" {
type = list(object({
url = string
secret = string
}))
default = []
description = "The repositories to clone on the image"
}
26 changes: 26 additions & 0 deletions scripts/Install-Eclipse.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

$ProgressPreference = 'SilentlyContinue' # hide any progress output

$eclipseVersion = "2022-06"
$eclipseDownloadName = "eclipse-jee-${eclipseVersion}.exe"
$eclipseDownloadPath = Join-Path -Path $env:TEMP -ChildPath $eclipseDownloadName
$eclipseInstallPath = "C:\Program Files"

Write-Host "[${env:username}] Downloading Eclipse ..."
$sourceUrl = "https://ftp.osuosl.org/pub/eclipse/technology/epp/downloads/release/${eclipseVersion}/R/eclipse-jee-${eclipseVersion}-R-win32-x86_64.zip"
#echo $sourceUrl
(new-object net.webclient).DownloadFile($sourceUrl, $eclipseDownloadPath)

Write-Host "[${env:username}] Unzip Eclipse ..."

Add-Type -AssemblyName System.IO.Compression.FileSystem
function Unzip
{
param([string]$zipfile, [string]$outpath)

[System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
}

Unzip $eclipseDownloadPath $eclipseInstallPath
20 changes: 20 additions & 0 deletions scripts/Install-GCloudCLI.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Reference: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows?tabs=azure-powershell

$ProgressPreference = 'SilentlyContinue' # hide any progress output

$installerName = 'GoogleCloudSDKInstaller..exe'
$installerPath = Join-Path -Path $env:TEMP -ChildPath $installerName

Write-Host "[${env:username}] Downloading GCloud CLI ..."
(new-object net.webclient).DownloadFile('https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe', $installerPath)

Write-Host "[${env:username}] Installing GCloud CLI ..."
$process = Start-Process -FilePath $installerPath -ArgumentList `
"/S" `
-NoNewWindow -Wait -PassThru

exit $process.ExitCode

19 changes: 19 additions & 0 deletions scripts/Install-Python3.8.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

$ProgressPreference = 'SilentlyContinue' # hide any progress output

$pythonVersion = "3.8.10"

$installerName = "python-${pythonVersion}-amd64.exe"
$InstallerPath = Join-Path -Path $env:TEMP -ChildPath $installerName

Write-Host "[${env:username}] Downloading Python ${pythonVersion} ..."
(new-object net.webclient).DownloadFile("https://www.python.org/ftp/python/${pythonVersion}/python-${pythonVersion}-amd64.exe", $InstallerPath)

Write-Host "[${env:username}] Installing Python ${pythonVersion} ..."
$process = Start-Process -FilePath $installerPath -ArgumentList `
"/quiet" `
-NoNewWindow -Wait -PassThru

exit $process.ExitCode