Skip to content
Open
Changes from 1 commit
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
60 changes: 56 additions & 4 deletions helpers/GenerateResourcesAndImage.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ Function GenerateResourcesAndImage {
The type of image to generate. Valid values are: Windows2022, Windows2025, Windows2025_vs2026, Ubuntu2204, Ubuntu2404.
.PARAMETER ManagedImageName
The name of the managed image to create. The default is "Runner-Image-{{ImageType}}".
.PARAMETER ComputeGalleryName
The name of the compute gallery to create. If specified will override the default behavior of creating a managed image.
Will use the ResourceGroupName parameter as the resource group for the compute gallery.
.PARAMETER ComputeGalleryImageName
The name of the compute gallery image to create. This is required if ComputeGalleryName is specified.
.PARAMETER ComputeGalleryImageVersion
The name of the compute gallery image version to create. This is required if ComputeGalleryName is specified.
.PARAMETER AzureLocation
The Azure location where the Azure resources will be created. For example: "East US"
.PARAMETER ImageGenerationRepositoryRoot
Expand Down Expand Up @@ -130,6 +137,12 @@ Function GenerateResourcesAndImage {
[ImageType] $ImageType,
[Parameter(Mandatory = $False)]
[string] $ManagedImageName = "Runner-Image-$($ImageType)",
[Parameter(Mandatory = $False)]
[string] $ComputeGalleryName,
[Parameter(Mandatory = $False)]
[string] $ComputeGalleryImageName,
[Parameter(Mandatory = $False)]
[string] $ComputeGalleryImageVersion,
[Parameter(Mandatory = $True)]
[string] $AzureLocation,
[Parameter(Mandatory = $False)]
Expand Down Expand Up @@ -161,6 +174,17 @@ Function GenerateResourcesAndImage {
throw "'packer' binary is not found on PATH."
}

# Validate Compute Gallery parameters
if ($ComputeGalleryName -and -not $ComputeGalleryImageName) {
throw "ComputeGalleryImageName parameter is required when ComputeGalleryName is specified."
}
if ($ComputeGalleryName -and -not $ComputeGalleryImageVersion) {
throw "ComputeGalleryImageVersion parameter is required when ComputeGalleryName is specified."
}
if ($ComputeGalleryImageVersion -and -not ($ComputeGalleryImageVersion -match '^\d+\.\d+\.\d+$')) {
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If ComputeGalleryImageName/ComputeGalleryImageVersion are provided without ComputeGalleryName, they are silently ignored and a managed image is produced. Add validation to reject "partial" compute gallery inputs (e.g., if either of the image name/version params are set, require ComputeGalleryName too) to prevent unexpected output artifacts.

Suggested change
if ($ComputeGalleryImageVersion -and -not ($ComputeGalleryImageVersion -match '^\d+\.\d+\.\d+$')) {
if ($ComputeGalleryImageName -and -not $ComputeGalleryName) {
throw "ComputeGalleryName parameter is required when ComputeGalleryImageName is specified."
}
if ($ComputeGalleryImageVersion -and -not $ComputeGalleryName) {
throw "ComputeGalleryName parameter is required when ComputeGalleryImageVersion is specified."
}
if ($ComputeGalleryName -and $ComputeGalleryImageVersion -and -not ($ComputeGalleryImageVersion -match '^\d+\.\d+\.\d+$')) {

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If wanting to do complete validation rather than silently ignore, we could do a more comprehensive check of all scenarios using an array of the 3 inputs, select non-empty and then length -eq 0 or length -eq 3.

Not sure if this is worthwhile as it looks pretty messy, but may give extra validation for people mis-inputting the parameters.

throw "ComputeGalleryImageVersion parameter must be in the format Major.Minor.Patch, for example: 1.0.0."
}

# Get template path
$PackerTemplate = Get-PackerTemplate -RepositoryRoot $ImageGenerationRepositoryRoot -ImageType $ImageType
Write-Debug "Template path: $($PackerTemplate.Path)."
Expand Down Expand Up @@ -204,6 +228,25 @@ Function GenerateResourcesAndImage {
}
Write-Debug "Tags JSON: $TagsJson."

# Prepare artifact arguments
if ($ComputeGalleryName) {
Write-Host "Compute gallery '$ComputeGalleryName' will be used to store the resulting image."
$artifactArgs = @(
"-var=gallery_name=$($ComputeGalleryName)",
"-var=gallery_image_name=$($ComputeGalleryImageName)",
"-var=gallery_image_version=$($ComputeGalleryImageVersion)",
"-var=gallery_resource_group_name=$($ResourceGroupName)"
)
}
else {
Write-Host "A managed image with name '$ManagedImageName' will be created to store the resulting image."
$artifactArgs = @(
"-var=managed_image_name=$($ManagedImageName)",
"-var=managed_image_resource_group_name=$($ResourceGroupName)"
)
}


$InstallPassword = $env:UserName + [System.GUID]::NewGuid().ToString().ToUpper()

Write-Host "Downloading packer plugins..."
Expand All @@ -222,8 +265,7 @@ Function GenerateResourcesAndImage {
"-var=tenant_id=fake" `
"-var=location=$($AzureLocation)" `
"-var=image_os=$($PackerTemplate.ImageOS)" `
"-var=managed_image_name=$($ManagedImageName)" `
"-var=managed_image_resource_group_name=$($ResourceGroupName)" `
@artifactArgs `
"-var=install_password=$($InstallPassword)" `
"-var=allowed_inbound_ip_addresses=$($AllowedInboundIpAddresses)" `
"-var=azure_tags=$($TagsJson)" `
Expand Down Expand Up @@ -257,6 +299,17 @@ Function GenerateResourcesAndImage {
throw "Resource group '$ResourceGroupName' does not exist."
}

# Check compute gallery existence
if ($ComputeGalleryName) {
$ComputeGalleryExists = [System.Convert]::ToBoolean((az sig show --resource-group $ResourceGroupName --gallery-name $ComputeGalleryName --name $ComputeGalleryImageName --query "id" --output tsv 2>$null));
if ($ComputeGalleryExists) {
Write-Verbose "Compute gallery '$ComputeGalleryName' already exists in resource group '$ResourceGroupName'."
}
else {
throw "Compute gallery '$ComputeGalleryName' does not exist in resource group '$ResourceGroupName'."
}
}

# Create service principal
if ([string]::IsNullOrEmpty($AzureClientId)) {
Write-Host "Creating service principal for packer..."
Expand Down Expand Up @@ -292,8 +345,7 @@ Function GenerateResourcesAndImage {
-var "tenant_id=$($TenantId)" `
-var "location=$($AzureLocation)" `
-var "image_os=$($PackerTemplate.ImageOS)" `
-var "managed_image_name=$($ManagedImageName)" `
-var "managed_image_resource_group_name=$($ResourceGroupName)" `
@artifactArgs `
-var "install_password=$($InstallPassword)" `
-var "allowed_inbound_ip_addresses=$($AllowedInboundIpAddresses)" `
-var "azure_tags=$($TagsJson)" `
Expand Down
Loading