Skip to content

Commit c5a1a6f

Browse files
authored
Merge pull request #63 from YannickRe/2.0.0
2.0.0
2 parents de326a5 + 25f6c91 commit c5a1a6f

12 files changed

+75
-162
lines changed

README.md

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ Currently supports Windows Server 2019, Windows Server 2022, Ubuntu 2004 and Ubu
88
- Checkout the latest `main` branch from [actions/runner-images](https://github.com/actions/runner-images)
99
- Build the VM with Packer
1010
- Clean up remaining temporary Azure resources
11-
- Turn VM disk into Azure Managed Image
1211
- Add Azure Managed Image to Azure Compute Gallery or Update Virtual Machine Scale Set with the new image
13-
- Remove Azure Managed Image
12+
- Remove Azure Managed Image when using Azure Compute Gallery
1413
- __[managedimage-cleanup.yml](./managedimage-cleanup.yml)__
1514
- Remove unused Azure Managed Images or old Gallery image versions, depending on selection
1615

@@ -37,26 +36,18 @@ Connect-AzAccount -UseDeviceAuthentication
3736
```
3837
New-AzResourceGroup -Name "DevOps-PackerResources" -Location "West Europe"
3938
```
40-
3. Create an Azure Storage Account to store the generated VHD
41-
```
42-
New-AzStorageAccount -ResourceGroupName "DevOps-PackerResources" -AccountName "devopspacker" -Location "West Europe" -SkuName "Standard_LRS"
43-
```
44-
4. Create Azure AD Service Principal, output client secret and client id
39+
3. Create Azure AD Service Principal, output client secret and client id
4540
```
4641
$sp = New-AzADServicePrincipal -DisplayName "DevOps-Packer"
4742
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($sp.Secret)
4843
$plainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
4944
$plainPassword
5045
$sp.ApplicationId
5146
```
52-
5. Make the Service Principal a Contributor on the subscription
47+
4. Make the Service Principal a Contributor on the subscription
5348
```
5449
New-AzRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $sp.ApplicationId
5550
```
56-
6. Make the Service Principal a Storage Blob Data Contributor on the subscription
57-
```
58-
New-AzRoleAssignment -RoleDefinitionName "Storage Blob Data Contributor" -ServicePrincipalName $sp.ApplicationId
59-
```
6051

6152
### Azure Virtual Machine Scale Set
6253
To use an Azure Virtual Machine Scale Set as an Azure DevOps Scale Set Agent it has to adhere to a certain set of requirements. [The documentation](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/scale-set-agents?view=azure-devops&WT.mc_id=M365-MVP-5003400#create-the-scale-set) contains all the required information, but at the time of writing the following things were important:
@@ -77,8 +68,7 @@ Create a Variable Group in the Azure DevOps project running the pipeline, and gi
7768
|---|---|
7869
| AZURE_AGENTS_RESOURCE_GROUP | Resource Group that contains the Virtual Machine Scale Sets to be used as Scale Set Agents in Azure DevOps |
7970
| AZURE_LOCATION | Azure location where Packer will create the temporary resources |
80-
| AZURE_RESOURCE_GROUP | Resource group containing the Azure Storage Account that will be used by Packer. The resulting Azure Managed Image will also be put in this Resource Group |
81-
| AZURE_STORAGE_ACCOUNT | Storage Account that Packer will use to store the temporary OSDisk and the resulting sysprepped .vhd |
71+
| AZURE_RESOURCE_GROUP | Resource group that will be used by Packer to put the resulting Azure Managed Image. |
8272
| AZURE_SUBSCRIPTION | Subscription ID of the Azure Subscription that is used to host the temporary resources. |
8373
| BUILD_AGENT_VNET_NAME | Name of the existing VNet to use for the VM created by Packer, put $null if you want packer to create a new one |
8474
| BUILD_AGENT_VNET_RESOURCE_GROUP | Name of the resource group containing the existing VNet to use for the VM created by Packer, put $null if you don't have this |
@@ -158,7 +148,7 @@ When calling a template, you must provide certain parameters. For reference, ple
158148
There is one important element you must be aware of:
159149

160150
- repository_base_path
161-
- This variable dictactes how the agent should resolve the assets within this repository. When used, two things will happen:
151+
- This variable dictates how the agent should resolve the assets within this repository. When used, two things will happen:
162152
- First, it will clone the repository resource specified within your YML file, which represents _this_ repository
163153
- It will also use it to properly resolve the path where this repository resides on your pipeline agent
164154
- When a remote template is referenced within an Azure Pipeline YML file, it doesn't clone the repository. Providing this parameter will make sure these templates understands they need to clone it before being able to run any of the scripts.

buildagent-generation-galleryvm.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ jobs:
1919
cancelTimeoutInMinutes: 90
2020
pool:
2121
name: ${{ parameters.agent_pool }}
22+
2223
variables:
23-
- name: ManagedImageId
24-
value: $[stageDependencies.convert_template_to_managedvm.managedimagegeneration.outputs['createmanagedimage.ManagedImageId'] ]
2524
- name: ImageType
2625
value: $[stageDependencies.buildagent_template_vm.imagegeneration.outputs['setVars.ImageType'] ]
2726
- name: ResourcesNamePrefix
@@ -41,11 +40,10 @@ jobs:
4140
arguments: -ResourcesNamePrefix $(ResourcesNamePrefix) `
4241
-ClientId $(CLIENT_ID) `
4342
-ClientSecret $(CLIENT_SECRET) `
44-
-ResourceGroup $(AZURE_AGENTS_RESOURCE_GROUP) `
43+
-ResourceGroup $(AZURE_RESOURCE_GROUP) `
4544
-SubscriptionId $(AZURE_SUBSCRIPTION) `
4645
-TenantId $(AZURE_TENANT) `
4746
-Location $(AZURE_LOCATION) `
4847
-GalleryName $(GALLERY_NAME) `
4948
-GalleryResourceGroup $(GALLERY_RESOURCE_GROUP) `
50-
-ImageType $(ImageType) `
51-
-ManagedImageId $(ManagedImageId)
49+
-ImageType $(ImageType)

buildagent-generation-managedvm.yml

Lines changed: 0 additions & 53 deletions
This file was deleted.

buildagent-generation-template.yml

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,16 @@ stages:
138138
-ClientSecret $(CLIENT_SECRET) `
139139
-TemplatePath $(TemplatePath) `
140140
-ResourceGroup $(AZURE_RESOURCE_GROUP) `
141-
-StorageAccount $(AZURE_STORAGE_ACCOUNT) `
142141
-SubscriptionId $(AZURE_SUBSCRIPTION) `
143142
-TenantId $(AZURE_TENANT) `
144143
-VirtualNetworkName $(BUILD_AGENT_VNET_NAME) `
145144
-VirtualNetworkRG $(BUILD_AGENT_VNET_RESOURCE_GROUP) `
146-
-VirtualNetworkSubnet $(BUILD_AGENT_SUBNET_NAME)
147-
-Location $(AZURE_LOCATION)
145+
-VirtualNetworkSubnet $(BUILD_AGENT_SUBNET_NAME) `
146+
-Location $(AZURE_LOCATION) `
147+
-GalleryResourceGroup $(GALLERY_RESOURCE_GROUP) `
148+
-GalleryName $(GALLERY_NAME) `
149+
-CaptureNamePrefix $(setVars.ResourcesNamePrefix) `
150+
-ImageType ${{ parameters.image_type }}
148151
env:
149152
PACKER_LOG: 1
150153
PACKER_LOG_PATH: $(Build.ArtifactStagingDirectory)/packer-log.txt
@@ -176,25 +179,13 @@ stages:
176179
-ClientSecret $(CLIENT_SECRET) `
177180
-Image $(setVars.ImageType) `
178181
-SubscriptionId $(AZURE_SUBSCRIPTION) `
179-
-TenantId $(AZURE_TENANT) `
180-
-StorageAccount $(AZURE_STORAGE_ACCOUNT)
181-
182-
- stage: convert_template_to_managedvm
183-
displayName: 'Convert Template to Managed VM'
184-
dependsOn: buildagent_template_vm
185-
jobs:
186-
- template: buildagent-generation-managedvm.yml
187-
parameters:
188-
variable_group: ${{ parameters.variable_group }}
189-
agent_pool: ${{ parameters.agent_pool }}
190-
repository_base_path: ${{ parameters.repository_base_path }}
182+
-TenantId $(AZURE_TENANT)
191183

192184
- stage: create_gallery_imagevm
193185
displayName: 'Create Gallery Image Version VM'
194186
condition: and(succeeded(), eq('${{ parameters.update_type }}', 'galleryvm'))
195187
dependsOn:
196188
- buildagent_template_vm
197-
- convert_template_to_managedvm
198189
jobs:
199190
- template: buildagent-generation-galleryvm.yml
200191
parameters:
@@ -206,7 +197,7 @@ stages:
206197
displayName: 'Update VM Scale Set to new Image'
207198
dependsOn:
208199
- buildagent_template_vm
209-
- convert_template_to_managedvm
200+
# - convert_template_to_managedvm
210201
condition: and(succeeded(), eq('${{ parameters.update_type }}', 'vmss'))
211202
variables:
212203
- ${{ if eq(parameters.image_type, 'windows2019') }}:
@@ -227,4 +218,4 @@ stages:
227218
variable_group: ${{ parameters.variable_group }}
228219
agent_pool: ${{ parameters.agent_pool }}
229220
repository_base_path: ${{ parameters.repository_base_path }}
230-
vmss_names: $(VmssNames)
221+
vmss_names: $(VmssNames)

buildagent-generation-update-vmss.yml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,21 @@ parameters:
1414
- name: vmss_names
1515
displayName: VmssNames
1616
type: string
17-
17+
1818
jobs:
1919
- job: updatevmss
2020
displayName: Update Virtual Machine Scale Set
2121
timeoutInMinutes: 600
2222
cancelTimeoutInMinutes: 30
2323
pool:
2424
name: ${{ parameters.agent_pool }}
25+
2526
variables:
26-
- name: ManagedImageId
27-
value: $[stageDependencies.convert_template_to_managedvm.managedimagegeneration.outputs['createmanagedimage.ManagedImageId'] ]
27+
- name: ImageType
28+
value: $[stageDependencies.buildagent_template_vm.imagegeneration.outputs['setVars.ImageType'] ]
29+
- name: ResourcesNamePrefix
30+
value: $[stageDependencies.buildagent_template_vm.imagegeneration.outputs['setVars.ResourcesNamePrefix'] ]
31+
- group: ${{ parameters.variable_group }}
2832
- name: VmssNames
2933
value: ${{ parameters.vmss_names }}
3034
- group: ${{ parameters.variable_group }}
@@ -40,8 +44,10 @@ jobs:
4044
filePath: ${{ parameters.repository_base_path }}/scripts/update-vmss.ps1
4145
arguments: -ClientId $(CLIENT_ID) `
4246
-ClientSecret $(CLIENT_SECRET) `
43-
-ResourceGroup $(AZURE_AGENTS_RESOURCE_GROUP) `
47+
-ResourceGroup $(AZURE_RESOURCE_GROUP) `
48+
-AgentsResourceGroup $(AZURE_AGENTS_RESOURCE_GROUP) `
4449
-SubscriptionId $(AZURE_SUBSCRIPTION) `
4550
-TenantId $(AZURE_TENANT) `
51+
-ResourceNamePrefix $(ResourcesNamePrefix)
52+
-ImageType $(ImageType)
4653
-VmssNames $(VmssNames) `
47-
-ManagedImageId $(ManagedImageId)

managedimage-cleanup-galleryvm.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1+
trigger: none
2+
13
parameters:
24
- name: variable_group
35
displayName: Variable Group
46
type: string
57
default: BuildAgents
6-
- name: gallery_threshold
8+
- name: gallery_images_to_keep
79
displayName: Number of image versions to keep in gallery
810
type: number
9-
default: 3
11+
default: 2
1012
- name: agent_pool
1113
displayName: Agent Pool
12-
type: string
1314
default: 'Host Pool - Image'
15+
type: string
1416
- name: repository_base_path
1517
displayName: Scripts Path
1618
type: string
@@ -24,6 +26,7 @@ jobs:
2426
variables:
2527
- group: ${{ parameters.variable_group }}
2628

29+
2730
steps:
2831
- checkout: self
2932
- ${{ if ne(parameters.repository_base_path, '.') }}:
@@ -40,4 +43,5 @@ jobs:
4043
-ResourceGroup $(AZURE_AGENTS_RESOURCE_GROUP) `
4144
-GalleryName $(GALLERY_NAME) `
4245
-GalleryResourceGroup $(GALLERY_RESOURCE_GROUP) `
43-
-ImageCountThreshold ${{ parameters.gallery_threshold }}
46+
-GalleryImagesToKeep ${{ parameters.gallery_images_to_keep }}
47+

scripts/build-image.ps1

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ param(
55
[String] [Parameter (Mandatory=$true)] $ResourcesNamePrefix,
66
[String] [Parameter (Mandatory=$true)] $Location,
77
[String] [Parameter (Mandatory=$true)] $ResourceGroup,
8-
[String] [Parameter (Mandatory=$true)] $StorageAccount,
98
[String] [Parameter (Mandatory=$true)] $SubscriptionId,
109
[String] [Parameter (Mandatory=$true)] $TenantId,
10+
[String] [Parameter (Mandatory=$true)] $CaptureNamePrefix,
11+
[String] [Parameter (Mandatory=$true)] $GalleryResourceGroup,
12+
[String] [Parameter (Mandatory=$true)] $GalleryName,
13+
[String] [Parameter (Mandatory=$true)] $ImageType,
1114
[String] [Parameter (Mandatory=$false)] $VirtualNetworkName,
1215
[String] [Parameter (Mandatory=$false)] $VirtualNetworkRG,
1316
[String] [Parameter (Mandatory=$false)] $VirtualNetworkSubnet
14-
)
17+
18+
)
1519

1620
if (-not (Test-Path $TemplatePath))
1721
{
@@ -39,20 +43,19 @@ Write-Host "Show Packer Version"
3943
packer --version
4044

4145
Write-Host "Build $Image VM"
42-
packer build -var "capture_name_prefix=$ResourcesNamePrefix" `
43-
-var "client_id=$ClientId" `
46+
packer build -var "client_id=$ClientId" `
4447
-var "client_secret=$ClientSecret" `
4548
-var "install_password=$InstallPassword" `
4649
-var "location=$Location" `
47-
-var "resource_group=$ResourceGroup" `
48-
-var "storage_account=$StorageAccount" `
4950
-var "subscription_id=$SubscriptionId" `
5051
-var "temp_resource_group_name=$TempResourceGroupName" `
5152
-var "tenant_id=$TenantId" `
5253
-var "virtual_network_name=$VirtualNetworkName" `
5354
-var "virtual_network_resource_group_name=$VirtualNetworkRG" `
5455
-var "virtual_network_subnet_name=$VirtualNetworkSubnet" `
5556
-var "run_validation_diskspace=$env:RUN_VALIDATION_FLAG" `
57+
-var "managed_image_name=$ImageType-$ResourcesNamePrefix" `
58+
-var "managed_image_resource_group_name=$ResourceGroup" `
5659
-color=false `
5760
$TemplatePath `
5861
| Foreach-Object {
@@ -69,4 +72,4 @@ packer build -var "capture_name_prefix=$ResourcesNamePrefix" `
6972

7073
$sensitiveString = $SensitiveData | Where-Object { $currentString -match $_ }
7174
$sensitiveString -eq $null
72-
}
75+
}

scripts/cleanup-gallery-vmimageversion.ps1

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
param(
32
[String] [Parameter (Mandatory=$true)] $ClientId,
43
[String] [Parameter (Mandatory=$true)] $ClientSecret,
@@ -7,7 +6,7 @@ param(
76
[String] [Parameter (Mandatory=$true)] $ResourceGroup,
87
[String] [Parameter (Mandatory=$true)] $GalleryName,
98
[String] [Parameter (Mandatory=$true)] $GalleryResourceGroup,
10-
[int] [Parameter (Mandatory=$true)] $ImageCountThreshold
9+
[int] [Parameter (Mandatory=$true)] $GalleryImagesToKeep
1110
)
1211

1312
# Variables
@@ -17,6 +16,7 @@ $imageDefinitions = @(
1716
"windows2019-agentpool-full",
1817
"windows2022-agentpool-full"
1918
)
19+
$ImageCountThreshold = $GalleryImagesToKeep + 1
2020

2121
# install required modules
2222
install-module Az.Compute -Scope CurrentUser -AllowClobber -Force
@@ -58,15 +58,17 @@ if ($gallery) {
5858

5959
if ($images.Count -ge $ImageCountThreshold) {
6060
# Sort the images by creation timestamp in ascending order
61-
$sortedImages = $images | Sort-Object -Property CreatedTime
62-
63-
# Remove the oldest image
64-
$imageToRemove = $sortedImages[0]
61+
#$sortedImages = $images | Sort-Object -Property { [DateTime]::ParseExact($_.PublishingProfile.PublishedDate, 'dd/MM/yyyy HH:mm:ss', $null) }
62+
$sortedImages = $images | Sort-Object -Property $_.PublishingProfile.PublishedDate
6563

66-
Write-Host "##[section]Removing the oldest image version for image definition '$imageDefinition': $($imageToRemove.Name)"
67-
Remove-AzGalleryImageVersion -ResourceGroupName $GalleryResourceGroup -GalleryName $gallery.Name -GalleryImageDefinitionName $imageDefinition -Name $imageToRemove.Name -Force -AsJob
68-
} else {
69-
Write-Host "##[section]The number of images for image definition '$imageDefinition' is less than $ImageCountThreshold"
64+
# Remove all images except the most recent ones
65+
$imagesToRemove = $sortedImages[0..($sortedImages.Count - $GalleryImagesToKeep - 1 )]
66+
foreach ($imageToRemove in $imagesToRemove) {
67+
Write-Host "##[section]Removing image version for image definition '$imageDefinition': $($imageToRemove.Name) with $($imageToRemove.PublishingProfile.PublishedDate)"
68+
Remove-AzGalleryImageVersion -ResourceGroupName $GalleryResourceGroup -GalleryName $gallery.Name -GalleryImageDefinitionName $imageDefinition -Name $imageToRemove.Name -Force -AsJob
69+
}
70+
} else {
71+
Write-Host "##[section]The number of images for image definition '$imageDefinition' has no more than $GalleryImagesToKeep images. No images will be removed."
7072
}
7173
}
7274
}

0 commit comments

Comments
 (0)