Skip to content
Open
Show file tree
Hide file tree
Changes from 15 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
8 changes: 7 additions & 1 deletion .github/workflows/powershell-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
branches: [ main ]
paths:
- 'helpers/software-report-base/**'
- 'images.CI/linux-and-win/**'

jobs:
powershell-tests:
Expand All @@ -22,4 +23,9 @@ jobs:
run: |
$ErrorActionPreference = "Stop"
Invoke-Pester -Output Detailed "helpers/software-report-base/tests"


- name: Run linux-and-win scripts tests
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
Invoke-Pester -Output Detailed "images.CI/linux-and-win/tests"
6 changes: 3 additions & 3 deletions docs/create-image-and-azure-resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,18 +235,18 @@ The following variables are required to be passed to the Packer process:
| `client_id` | `ARM_CLIENT_ID` | The Active Directory service principal associated with your builder.
| `client_secret` | `ARM_CLIENT_SECRET` | The password or secret for your service principal; may be omitted if `client_cert_path` is set.
| `client_cert_path` | `ARM_CLIENT_CERT_PATH` | The location of a PEM file containing a certificate and private key for the service principal; may be omitted if `client_secret` is set.
| `location` | `ARM_RESOURCE_LOCATION` | The Azure datacenter in which your VM will be built.
| `managed_image_resource_group_name` | `ARM_RESOURCE_GROUP` | The resource group under which the final artifact will be stored.

### Optional variables

The following variables are optional:

- `managed_image_name` - the name of the managed image to create. If not specified, "Runner-Image-{{ImageType}}" will be used;
- `build_resource_group_name` - specify an existing resource group to run the build in; by default, a temporary resource group will be created and destroyed as part of the build; if you do not have permission to do so, use `build_resource_group_name` to specify an existing resource group to run the build in;
- `build_resource_group_name` - specify an existing resource group to run the build in; by default, a temporary resource group will be created and destroyed as part of the build; if you do not have permission to do so, use `build_resource_group_name` to specify an existing resource group to run the build in; not allowed to be used in combination with `location` or `temp_resource_group_name`;
- `object_id` - the object ID for the AAD SP; will be derived from the oAuth token if empty;
- `tenant_id` - the Active Directory tenant identifier with which your `client_id` and `subscription_id` are associated; if not specified, `tenant_id` will be looked up using `subscription_id`;
- `temp_resource_group_name` - the 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;
- `location` | `ARM_RESOURCE_LOCATION` | The Azure datacenter in which your VM will be built; required if the build is in a temporary resource group; not allowed to be used in combination with `build_resource_group_name`;
Comment thread
eduardkuijpers86 marked this conversation as resolved.
Outdated
- `temp_resource_group_name` - the 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; not allowed to be used in combination with `build_resource_group_name`;
- `private_virtual_network_with_public_ip` - this value allows you to set a `virtual_network_name` and obtain a public IP; if this value is not set and `virtual_network_name` is defined, Packer is only allowed to be executed from a host on the same subnet / virtual network;
- `virtual_network_name` - use a pre-existing virtual network for the VM; this option enables private communication with the VM, no public IP address is used or provisioned (unless you set `private_virtual_network_with_public_ip`);
- `virtual_network_resource_group_name` - if `virtual_network_name` is set, this value may also be set; if `virtual_network_name` is set, and this value is not set, the builder attempts to determine the resource group containing the virtual network; if the resource group cannot be found, or it cannot be disambiguated, this value should be set;
Expand Down
74 changes: 56 additions & 18 deletions images.CI/linux-and-win/build-image.ps1
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
[CmdletBinding(DefaultParameterSetName = 'TempResourceGroup')]
param(
[String] [Parameter (Mandatory=$true)] $TemplatePath,
[String] [Parameter (Mandatory=$true)] $BuildTemplateName,
[String] [Parameter (Mandatory=$true)] $ClientId,
[String] [Parameter (Mandatory=$false)] $ClientSecret,
[String] [Parameter (Mandatory=$true)] $Location,
[String] [Parameter (Mandatory=$true, ParameterSetName = 'TempResourceGroup')] $Location,
[String] [Parameter (Mandatory=$true)] $ImageName,
[String] [Parameter (Mandatory=$true)] $ImageResourceGroupName,
[String] [Parameter (Mandatory=$true)] $TempResourceGroupName,
[String] [Parameter (Mandatory=$true, ParameterSetName = 'TempResourceGroup')] $TempResourceGroupName,
[String] [Parameter (Mandatory=$true, ParameterSetName = 'ExistingResourceGroup')] $ExistingResourceGroupName,
[String] [Parameter (Mandatory=$true)] $SubscriptionId,
[String] [Parameter (Mandatory=$true)] $TenantId,
[String] [Parameter (Mandatory=$true)] $ImageOS, # e.g. "ubuntu22", "ubuntu24" or "win22", "win25"
Expand Down Expand Up @@ -40,6 +42,20 @@ $SensitiveData = @(

$azure_tags = $Tags | ConvertTo-Json -Compress

function Add-PackerVariableFlag {
param(
[String[]]$packerVariables
)

$result = @()

foreach ($packerVariable in $packerVariables) {
$result += "-var", $packerVariable
}

return $result
}

Write-Host "Show Packer Version"
packer --version

Expand All @@ -49,24 +65,46 @@ packer plugins install github.com/hashicorp/azure $pluginVersion
Write-Host "Validate packer template"
packer validate -syntax-only -only "$buildName*" $TemplatePath

$packerVariablesList = Add-PackerVariableFlag -packerVariables @(
"client_id=$ClientId",
"client_secret=$ClientSecret",
"install_password=$InstallPassword",
"image_os=$ImageOS",
"managed_image_name=$ImageName",
"managed_image_resource_group_name=$ImageResourceGroupName",
"subscription_id=$SubscriptionId",
"tenant_id=$TenantId",
"virtual_network_name=$VirtualNetworkName",
"virtual_network_resource_group_name=$VirtualNetworkRG",
"virtual_network_subnet_name=$VirtualNetworkSubnet",
"allowed_inbound_ip_addresses=$($AllowedInboundIpAddresses)",
"use_azure_cli_auth=$UseAzureCliAuth",
"azure_tags=$azure_tags"
)

switch ($PSCmdlet.ParameterSetName) {
'TempResourceGroup' {
Write-Host "Use temporary resource group $TempResourceGroupName"
$packerVariablesList += Add-PackerVariableFlag -packerVariables @(
"temp_resource_group_name=$TempResourceGroupName",
"location=$Location"
)

break
}
'ExistingResourceGroup' {
Write-Host "Use existing resource group $ExistingResourceGroupName"
$packerVariablesList += Add-PackerVariableFlag -packerVariables @(
"build_resource_group_name=$ExistingResourceGroupName"
)

break
}
}

Write-Host "Build $buildName VM"
packer build -only "$buildName*" `
-var "client_id=$ClientId" `
-var "client_secret=$ClientSecret" `
-var "install_password=$InstallPassword" `
-var "location=$Location" `
-var "image_os=$ImageOS" `
-var "managed_image_name=$ImageName" `
-var "managed_image_resource_group_name=$ImageResourceGroupName" `
-var "subscription_id=$SubscriptionId" `
-var "temp_resource_group_name=$TempResourceGroupName" `
-var "tenant_id=$TenantId" `
-var "virtual_network_name=$VirtualNetworkName" `
-var "virtual_network_resource_group_name=$VirtualNetworkRG" `
-var "virtual_network_subnet_name=$VirtualNetworkSubnet" `
-var "allowed_inbound_ip_addresses=$($AllowedInboundIpAddresses)" `
-var "use_azure_cli_auth=$UseAzureCliAuth" `
-var "azure_tags=$azure_tags" `
@packerVariablesList `
-color=false `
$TemplatePath `
| Where-Object {
Expand Down
103 changes: 103 additions & 0 deletions images.CI/linux-and-win/tests/build-image.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
Describe "build-image.ps1 parameter sets" {
BeforeAll {
$scriptPath = (Resolve-Path (Join-Path $PSScriptRoot "..\build-image.ps1")).Path
$command = Get-Command -Name $scriptPath
}

It "defines exactly two parameter sets" {
$command.ParameterSets | Should -HaveCount 2
}

It "requires temp resource group parameters in TempResourceGroup set" {
$tempSet = $command.ParameterSets | Where-Object Name -eq "TempResourceGroup"
$tempSet | Should -Not -BeNullOrEmpty

($tempSet.Parameters | Where-Object Name -eq "Location") | Should -Not -BeNullOrEmpty
($tempSet.Parameters | Where-Object Name -eq "Location").IsMandatory | Should -BeTrue

($tempSet.Parameters | Where-Object Name -eq "TempResourceGroupName") | Should -Not -BeNullOrEmpty
($tempSet.Parameters | Where-Object Name -eq "TempResourceGroupName").IsMandatory | Should -BeTrue

$tempSet.Parameters.Name | Should -Not -Contain "ExistingResourceGroupName"
}

It "requires existing resource group parameter in ExistingResourceGroup set" {
$existingSet = $command.ParameterSets | Where-Object Name -eq "ExistingResourceGroup"
$existingSet | Should -Not -BeNullOrEmpty

($existingSet.Parameters | Where-Object Name -eq "ExistingResourceGroupName") | Should -Not -BeNullOrEmpty
($existingSet.Parameters | Where-Object Name -eq "ExistingResourceGroupName").IsMandatory | Should -BeTrue

$existingSet.Parameters.Name | Should -Not -Contain "Location"
$existingSet.Parameters.Name | Should -Not -Contain "TempResourceGroupName"
}
}

Describe "build-image.ps1 switch" {
BeforeAll {
$scriptPath = (Resolve-Path (Join-Path $PSScriptRoot "..\build-image.ps1")).Path

Mock -CommandName Write-Host

$global:packerInvocations = @()
Mock -CommandName packer -MockWith {
param(
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $arguments
)

$global:packerInvocations += ,$arguments
"mocked packer output"
}
}

Context "TempResourceGroup" {
It "calls packer build with temp resource group parameters" {

& $scriptPath -TemplatePath ".\" `
-BuildTemplateName "template.TestBuild" `
-TempResourceGroupName "TestTempRG" `
-ClientId "TestClientId" `
-Location "TestLocation" `
-ImageName "TestImage" `
-ImageResourceGroupName "TestImageRG" `
-SubscriptionId "TestSubId" `
-TenantId "TestTenantId" `
-ImageOS "TestOS" | Out-Null

Should -Invoke -CommandName Write-Host -Times 1 -Exactly -ParameterFilter {
$Object -eq "Use temporary resource group TestTempRG"
}

Should -Invoke -CommandName packer -Times 1 -Exactly -ParameterFilter {
$arguments -contains "temp_resource_group_name=TestTempRG" -and
$arguments -contains "location=TestLocation" -and
$arguments -contains "-var"
}
}
}

Context "ExistingResourceGroup" {
It "calls packer build with existing resource group parameters" {

& $scriptPath -TemplatePath ".\" `
-BuildTemplateName "template.TestBuild" `
-ExistingResourceGroupName "TestExistingRG" `
-ClientId "TestClientId" `
-ImageName "TestImage" `
-ImageResourceGroupName "TestImageRG" `
-SubscriptionId "TestSubId" `
-TenantId "TestTenantId" `
-ImageOS "TestOS" | Out-Null

Should -Invoke -CommandName Write-Host -Times 1 -Exactly -ParameterFilter {
$Object -eq "Use existing resource group TestExistingRG"
}

Should -Invoke -CommandName packer -Times 1 -Exactly -ParameterFilter {
$arguments -contains "build_resource_group_name=TestExistingRG" -and
$arguments -contains "-var"
}
}
}
}
Loading