Skip to content

Commit f4d8d72

Browse files
authored
fix: test and fix windows VHD release process (#8605)
1 parent 90baef2 commit f4d8d72

9 files changed

Lines changed: 151 additions & 37 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ e2e/scenario-logs
1616
**/vhd-publishing-info.json
1717
out/
1818
build/
19+
coverage/
20+
test-results/
21+
.devcontainer/devcontainer-lock.json
1922

2023
test/junit/
2124
test/e2e/kubernetes/junit.xml

.pipelines/templates/.build-and-test-windows-vhd-template.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ stages:
101101
- stage: e2e_${{ parameters.stageName }}
102102
displayName: E2E (${{ parameters.artifactName }})
103103
dependsOn: build_${{ parameters.stageName }}
104-
condition: and(succeeded(), eq('${{ parameters.build }}', True), ne(variables.SKIP_E2E_TESTS, 'true'))
104+
condition: and(succeeded(), eq('${{ parameters.build }}', True), ne(variables.SKIP_E2E_TESTS, 'true'), ne(dependencies.build_${{ parameters.stageName }}.outputs['build_${{ parameters.stageName }}.skipVhd.skipping_vhd_build'], 'true'))
105105
variables:
106106
VHD_BUILD_ID: $(Build.BuildId)
107107
TAGS_TO_RUN: imageName=${{ parameters.imageName }}

.pipelines/templates/.builder-release-template-windows.yaml

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,24 @@ steps:
7070
overrideBranch: ${{ parameters.overrideBranch }}
7171
useOverrides: ${{ parameters.useOverrides }}
7272

73+
- bash: |
74+
skip_vhd=$(jq -r ".WindowsBaseVersions.\"${WINDOWS_SKU}\".skip_vhd // false" <vhdbuilder/packer/windows/windows_settings.json)
75+
if [ "${skip_vhd}" = "true" ]; then
76+
echo "skip_vhd is set to true for ${WINDOWS_SKU}, skipping VHD build."
77+
echo "##vso[task.logissue type=error]Not building VHD for ${WINDOWS_SKU} because skip_vhd is set to true in windows_settings.json"
78+
echo "##vso[task.setvariable variable=skipping_vhd_build;isOutput=true]true"
79+
echo "##vso[task.setvariable variable=skipping_vhd_build]true"
80+
exit 0
81+
fi
82+
echo "##vso[task.setvariable variable=skipping_vhd_build;isOutput=true]false"
83+
echo "##vso[task.setvariable variable=skipping_vhd_build]false"
84+
name: skipVhd
85+
displayName: Determine VHD Skip
86+
env:
87+
WINDOWS_SKU: ${{ parameters.windowsSku }}
88+
7389
- task: DownloadPipelineArtifact@2
90+
condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'))
7491
displayName: Download CSE package
7592
inputs:
7693
source: current
@@ -79,6 +96,8 @@ steps:
7996
targetPath: ${{ parameters.csePackageDir }}
8097

8198
- task: AzureCLI@2
99+
condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'))
100+
name: buildVhd
82101
inputs:
83102
azureSubscription: $(VHD_ARM_SERVICE_CONNECTION)
84103
scriptType: bash
@@ -122,6 +141,7 @@ steps:
122141

123142
# Note: use -a to grep MANAGED_SIG_ID (packer-output should be read as a binary file in Linux)
124143
- task: AzureCLI@2
144+
condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'))
125145
inputs:
126146
azureSubscription: $(VHD_ARM_SERVICE_CONNECTION)
127147
scriptType: bash
@@ -179,14 +199,17 @@ steps:
179199
mv tmp.json ${AKS_WINDOWS_IMAGE_VERSION}-image-list.json
180200
cp release-notes.txt ${AKS_WINDOWS_IMAGE_VERSION}.txt
181201
displayName: Reformat image-bom.json and rename release-notes.txt
202+
condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'))
182203
183204
- task: PublishPipelineArtifact@0
205+
condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'))
184206
inputs:
185207
artifactName: 'vhd-release-notes-${{ parameters.artifactName }}'
186208
targetPath: '$(AKS_WINDOWS_IMAGE_VERSION).txt'
187209

188210
# We can upload image bom json for check-in pr and sig mode to validate whether it is expected.
189211
- task: PublishPipelineArtifact@0
212+
condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'))
190213
inputs:
191214
artifactName: 'vhd-image-list-${{ parameters.artifactName }}'
192215
targetPath: '$(AKS_WINDOWS_IMAGE_VERSION)-image-list.json'
@@ -209,7 +232,7 @@ steps:
209232
210233
make -f packer.mk convert-sig-to-classic-storage-account-blob
211234
displayName: Convert Shared Image Gallery To VHD Blob In Classic Storage Account
212-
condition: and(succeeded(), eq(variables.DRY_RUN, 'False'), eq(variables.SIG_FOR_PRODUCTION, 'True'))
235+
condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'), eq(variables.DRY_RUN, 'False'), eq(variables.SIG_FOR_PRODUCTION, 'True'))
213236
env:
214237
LOCATION: $(AZURE_BUILD_LOCATION)
215238
RESOURCE_GROUP_NAME: $(AZURE_RESOURCE_GROUP_NAME)
@@ -245,7 +268,7 @@ steps:
245268
246269
./vhdbuilder/packer/cleanup.sh
247270
displayName: Clean Up Packer Generated Resources
248-
condition: always()
271+
condition: and(always(), ne(variables.skipping_vhd_build, 'true'))
249272
env:
250273
MODE: $(MODE)
251274
DRY_RUN: $( DRY_RUN )
@@ -280,7 +303,7 @@ steps:
280303
281304
make -f packer.mk generate-publishing-info
282305
displayName: Getting Shared Access Signature URI
283-
condition: and(succeeded(), eq(variables.DRY_RUN, 'False'), eq(variables.SIG_FOR_PRODUCTION, 'True'))
306+
condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'), eq(variables.DRY_RUN, 'False'), eq(variables.SIG_FOR_PRODUCTION, 'True'))
284307
env:
285308
SUBSCRIPTION_ID: $(AZURE_PROD_SUBSCRIPTION_ID)
286309
STORAGE_ACCT_BLOB_URL: $(STORAGE_ACCT_BLOB_URL)
@@ -300,4 +323,4 @@ steps:
300323
inputs:
301324
artifactName: 'publishing-info-${{ parameters.artifactName }}'
302325
targetPath: 'vhd-publishing-info.json'
303-
condition: and(succeeded(), eq(variables.DRY_RUN, 'False'), eq(variables.SIG_FOR_PRODUCTION, 'True'))
326+
condition: and(succeeded(), ne(variables.skipping_vhd_build, 'true'), eq(variables.DRY_RUN, 'False'), eq(variables.SIG_FOR_PRODUCTION, 'True'))

.pipelines/templates/.template-copy-file.yaml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,28 @@ steps:
1212
- bash: |
1313
set -euo pipefail
1414
# we check for existence of both src and destination file because if neither of those exist then the override will fail.
15-
15+
1616
if [ ! -f "${destinationFile}" ]; then
17+
echo "##vso[task.logissue type=error]Destination file does not exist, could not copy: ${destinationFile}"
1718
echo "destination file file does not exist, not copying as it must have been moved in a refactor: ${destinationFile}"
1819
exit 1
1920
fi
2021
2122
if [ ! -f "${sourceFile}" ]; then
22-
echo "src ${sourceFile} file does not exist, aborting: ${sourceFile}"
23-
exit 1
23+
echo "##vso[task.logissue type=error]Source file does not exist, could not copy: ${sourceFile}"
24+
exit 0
2425
fi
25-
26+
2627
echo "Found source to use for overrides: ${sourceFile}"
2728
echo "Found file to overwrite: ${destinationFile}"
2829
30+
echo "##vso[task.logissue type=warning]Overwriting file ${destinationFile} from ${sourceFile}"
31+
2932
echo "Overwriting ${sourceFile} -> ${destinationFile}"
3033
cp -af "${sourceFile}" "${destinationFile}"
3134
3235
condition: and(succeeded(), eq('${{ parameters.enabled }}', true))
3336
displayName: Overwrite file ${{ parameters.destinationFile }}
37+
env:
38+
destinationFile: ${{ parameters.destinationFile }}
39+
sourceFile: ${{ parameters.sourceFile }}

schemas/windows_settings.cue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
base_image_version: string
2828
windows_image_name: string
2929
patches_to_apply: #WindowsPatches
30+
sig_source_gallery_name?: string
31+
skip_vhd?: bool
3032
}
3133

3234
#WindowsComments: [...string]

vhdbuilder/packer/produce-packer-settings-functions.sh

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -258,14 +258,21 @@ function create_new_base_image() {
258258

259259
# Use imported sig image to create the build VM
260260
WINDOWS_IMAGE_URL=""
261-
windows_sigmode_source_subscription_id=$SUBSCRIPTION_ID
262-
windows_sigmode_source_resource_group_name=$AZURE_RESOURCE_GROUP_NAME
263-
windows_sigmode_source_gallery_name=$SIG_GALLERY_NAME
264-
windows_sigmode_source_image_name=$IMPORTED_IMAGE_NAME
265-
windows_sigmode_source_image_version="1.0.0"
261+
windows_sigmode_source_id="/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${AZURE_RESOURCE_GROUP_NAME}/providers/Microsoft.Compute/galleries/${SIG_GALLERY_NAME}/images/${IMPORTED_IMAGE_NAME}/versions/1.0.0"
266262
}
267263

268264
function prepare_windows_vhd() {
265+
local skip_vhd
266+
skip_vhd=$(jq -r ".WindowsBaseVersions.\"${WINDOWS_SKU}\".skip_vhd // false" <$CDIR/windows/windows_settings.json)
267+
if [ "${skip_vhd}" = "true" ]; then
268+
echo "skip_vhd is set to true for ${WINDOWS_SKU}, skipping VHD build."
269+
echo "##vso[task.setvariable variable=skipping_vhd_build;isOutput=true]true"
270+
echo "##vso[task.setvariable variable=skipping_vhd_build]true"
271+
exit 0
272+
fi
273+
echo "##vso[task.setvariable variable=skipping_vhd_build;isOutput=true]false"
274+
echo "##vso[task.setvariable variable=skipping_vhd_build]false"
275+
269276
echo "Set the base image sku and version from windows_settings.json"
270277

271278
WINDOWS_IMAGE_SKU=$(jq -r ".WindowsBaseVersions.\"${WINDOWS_SKU}\".base_image_sku" <$CDIR/windows/windows_settings.json)
@@ -309,12 +316,59 @@ function prepare_windows_vhd() {
309316
exit 1
310317
fi
311318

312-
# Create the sig image from the official images defined in windows-settings.json by default
313-
windows_sigmode_source_subscription_id=""
314-
windows_sigmode_source_resource_group_name=""
315-
windows_sigmode_source_gallery_name=""
316-
windows_sigmode_source_image_name=""
317-
windows_sigmode_source_image_version=""
319+
# By default, packer uses marketplace source (image_publisher/offer/sku/version).
320+
# For VHD imports, we use shared_image_gallery.id (full ARM resource ID).
321+
# For embargo builds, we use direct_shared_gallery_image_id to source from a 1P shared gallery.
322+
windows_sigmode_source_id=""
323+
windows_sigmode_direct_shared_gallery_image_id=""
324+
325+
local sig_source_gallery_name
326+
if sig_source_gallery_name=$(jq -re ".WindowsBaseVersions.\"${WINDOWS_SKU}\".sig_source_gallery_name" <$CDIR/windows/windows_settings.json); then
327+
if [ -n "${sig_source_gallery_name}" ] && [ "${sig_source_gallery_name}" != "null" ]; then
328+
local sig_image_name="${WINDOWS_IMAGE_SKU}"
329+
# Use AZURE_LOCATION for gallery queries — PACKER_BUILD_LOCATION may not be normalized yet for Windows
330+
local gallery_location="${AZURE_LOCATION:-${PACKER_BUILD_LOCATION}}"
331+
332+
# List latest 3 available versions for this image in the shared gallery
333+
echo " Latest 3 available versions in gallery:"
334+
az sig image-version list-shared \
335+
--gallery-unique-name "${sig_source_gallery_name}" \
336+
--gallery-image-definition "${sig_image_name}" \
337+
--location "${gallery_location}" \
338+
--shared-to tenant \
339+
--query "[-3:].name" -o tsv | while read -r ver; do
340+
echo " - ${ver}"
341+
done
342+
343+
# Resolve version dynamically if base_image_version is empty
344+
if [ -z "${WINDOWS_IMAGE_VERSION}" ] || [ "${WINDOWS_IMAGE_VERSION}" = "null" ]; then
345+
echo "base_image_version is empty, resolving latest from shared gallery ${sig_source_gallery_name}/${sig_image_name}..."
346+
WINDOWS_IMAGE_VERSION=$(az sig image-version list-shared \
347+
--gallery-unique-name "${sig_source_gallery_name}" \
348+
--gallery-image-definition "${sig_image_name}" \
349+
--location "${gallery_location}" \
350+
--shared-to tenant \
351+
--query "sort_by(@, &name)[-1].name" -o tsv)
352+
if [ -z "${WINDOWS_IMAGE_VERSION}" ]; then
353+
echo "ERROR: Failed to resolve latest image version from gallery ${sig_source_gallery_name}/${sig_image_name}"
354+
exit 1
355+
fi
356+
echo "Resolved base_image_version: ${WINDOWS_IMAGE_VERSION}"
357+
fi
358+
359+
windows_sigmode_direct_shared_gallery_image_id="/SharedGalleries/${sig_source_gallery_name}/Images/${sig_image_name}/Versions/${WINDOWS_IMAGE_VERSION}"
360+
# Clear marketplace and raw VHD source fields — packer requires exactly one source type
361+
WINDOWS_IMAGE_URL=""
362+
WINDOWS_BASE_IMAGE_URL=""
363+
WINDOWS_IMAGE_PUBLISHER=""
364+
WINDOWS_IMAGE_OFFER=""
365+
WINDOWS_IMAGE_SKU=""
366+
WINDOWS_IMAGE_VERSION=""
367+
echo "Using direct shared gallery source:"
368+
echo " ID: ${windows_sigmode_direct_shared_gallery_image_id}"
369+
370+
fi
371+
fi
318372

319373
# default: build VHD images from a marketplace base image
320374
export AZCOPY_AUTO_LOGIN_TYPE="AZCLI" # use AZCLI for AzCopy authentication
@@ -323,8 +377,8 @@ function prepare_windows_vhd() {
323377
mkdir -p "${AZCOPY_LOG_LOCATION}"
324378
mkdir -p "${AZCOPY_JOB_PLAN_LOCATION}"
325379

326-
echo "VALID IMAGE URL: ${WINDOWS_CONTAINERIMAGE_JSON_URL}"
327380
if [ -n "${WINDOWS_CONTAINERIMAGE_JSON_URL}" ]; then
381+
echo "VALID IMAGE URL: ${WINDOWS_CONTAINERIMAGE_JSON_URL}"
328382
download_windows_json_artifact
329383
extract_windows_image_urls
330384
else
@@ -333,14 +387,14 @@ function prepare_windows_vhd() {
333387
fi
334388

335389
# Check if base, nano, and servercore urls are set
336-
if [ -z "${windows_nanoserver_image_url}" ] || [ -z "${windows_servercore_image_url}" ] || [ -z "${WINDOWS_BASE_IMAGE_URL}" ]; then
337-
echo "Error: One of the Windows image URLs are not set."
390+
if [ -n "${windows_nanoserver_image_url}" ] && [ -n "${windows_servercore_image_url}" ] && [ -n "${WINDOWS_BASE_IMAGE_URL}" ]; then
391+
echo "All Windows image URLs are set."
338392
else
339-
# If all URLs are set, print them
340-
echo "Using Windows base image URL: ${WINDOWS_BASE_IMAGE_URL}"
341-
echo "Using Windows Nano Server image URL: ${windows_nanoserver_image_url}"
342-
echo "Using Windows Server Core image URL: ${windows_servercore_image_url}"
393+
echo "At least one of the Windows image URLs are not set:"
343394
fi
395+
echo " Windows base image URL: ${WINDOWS_BASE_IMAGE_URL}"
396+
echo " Windows Nano Server image URL: ${windows_nanoserver_image_url}"
397+
echo " Windows Server Core image URL: ${windows_servercore_image_url}"
344398

345399
# build from a pre-supplied VHD blob a.k.a. external raw VHD
346400
if [ -n "${WINDOWS_BASE_IMAGE_URL}" ]; then

vhdbuilder/packer/produce-packer-settings.sh

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,8 @@ cat <<EOF > vhdbuilder/packer/settings.json
243243
"nano_image_url": "${windows_nanoserver_image_url}",
244244
"core_image_url": "${windows_servercore_image_url}",
245245
"windows_private_packages_url": "${windows_private_packages_url}",
246-
"windows_sigmode_source_subscription_id": "${windows_sigmode_source_subscription_id}",
247-
"windows_sigmode_source_resource_group_name": "${windows_sigmode_source_resource_group_name}",
248-
"windows_sigmode_source_gallery_name": "${windows_sigmode_source_gallery_name}",
249-
"windows_sigmode_source_image_name": "${windows_sigmode_source_image_name}",
250-
"windows_sigmode_source_image_version": "${windows_sigmode_source_image_version}",
246+
"windows_sigmode_source_id": "${windows_sigmode_source_id}",
247+
"windows_sigmode_direct_shared_gallery_image_id": "${windows_sigmode_direct_shared_gallery_image_id}",
251248
"vnet_name": "${VNET_NAME}",
252249
"subnet_name": "${SUBNET_NAME}",
253250
"vnet_resource_group_name": "${VNET_RG_NAME}",

vhdbuilder/packer/windows/configure-windows-vhd.ps1

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,13 +1012,27 @@ function Test-AzureExtensions
10121012
Write-Log "Azure extensions are not found"
10131013
}
10141014

1015+
function Run-BcdEdit
1016+
{
1017+
Write-Host "Running bcdedit /set hypervisorlaunchtype auto"
1018+
bcdedit /set hypervisorlaunchtype auto
1019+
if ($LASTEXITCODE)
1020+
{
1021+
throw "bcdedit /set hypervisorlaunchtype auto failed with exit code $LASTEXITCODE"
1022+
}
1023+
}
1024+
10151025
# Disable progress writers for this session to greatly speed up operations such as Invoke-WebRequest
10161026
$ProgressPreference = 'SilentlyContinue'
10171027

10181028
try
10191029
{
10201030
switch ($env:ProvisioningPhase)
10211031
{
1032+
"0" {
1033+
Write-Log "Performing actions for provisioning phase 0"
1034+
Run-BcdEdit
1035+
}
10221036
"1" {
10231037
Write-Log "Performing actions for provisioning phase 1"
10241038
Expand-OS-Partition

vhdbuilder/packer/windows/windows-vhd-builder-sig.json

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,8 @@
3838
"image_version": "{{user `windows_image_version`}}",
3939
"image_url": "{{user `windows_image_url`}}",
4040
"shared_image_gallery": {
41-
"subscription": "{{user `windows_sigmode_source_subscription_id`}}",
42-
"resource_group": "{{user `windows_sigmode_source_resource_group_name`}}",
43-
"gallery_name": "{{user `windows_sigmode_source_gallery_name`}}",
44-
"image_name": "{{user `windows_sigmode_source_image_name`}}",
45-
"image_version": "{{user `windows_sigmode_source_image_version`}}"
41+
"id": "{{user `windows_sigmode_source_id`}}",
42+
"direct_shared_gallery_image_id": "{{user `windows_sigmode_direct_shared_gallery_image_id`}}"
4643
},
4744
"shared_image_gallery_destination": {
4845
"resource_group": "{{user `resource_group_name`}}",
@@ -100,6 +97,24 @@
10097
],
10198
"destination": "c:/akse-cache/"
10299
},
100+
{
101+
"elevated_user": "packer",
102+
"elevated_password": "{{.WinRMPassword}}",
103+
"environment_vars": [
104+
"ProvisioningPhase=0",
105+
"WindowsSKU={{user `windows_sku`}}",
106+
"CustomizedDiskSize={{user `os_disk_size_gb`}}",
107+
"INSTALL_OPEN_SSH_SERVER={{ user `INSTALL_OPEN_SSH_SERVER` }}"
108+
],
109+
"type": "powershell",
110+
"scripts": [
111+
"vhdbuilder/packer/windows/configure-windows-vhd.ps1"
112+
]
113+
},
114+
{
115+
"restart_timeout": "10m",
116+
"type": "windows-restart"
117+
},
103118
{
104119
"elevated_user": "packer",
105120
"elevated_password": "{{.WinRMPassword}}",

0 commit comments

Comments
 (0)