From a3cadca9fe625f1cb2085cfae9f4ecdb53fb7d40 Mon Sep 17 00:00:00 2001
From: Alexander Sehr
Date: Sat, 7 Sep 2024 18:13:26 +0200
Subject: [PATCH] fix: Image Template Make `customizations` optional -
`avm/res/virtual-machine-images/image-template` (#2992)
## Description
- The `customizations` property is optional in the API and should also
be in the module in case somebody just wants to backup a marketplace
image
- Fix for script upload (prep for #3005)
## Pipeline Reference
| Pipeline |
| -------- |
|
[![avm.res.virtual-machine-images.image-template](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.virtual-machine-images.image-template.yml/badge.svg?branch=users%2Falsehr%2FoptionalCustomization&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.virtual-machine-images.image-template.yml)
|
## Type of Change
- [ ] Update to CI Environment or utilities (Non-module affecting
changes)
- [ ] Azure Verified Module updates:
- [x] Bugfix containing backwards-compatible bug fixes, and I have NOT
bumped the MAJOR or MINOR version in `version.json`:
- [ ] Someone has opened a bug report issue, and I have included "Closes
#{bug_report_issue_number}" in the PR description.
- [ ] The bug was found by the module author, and no one has opened an
issue to report it yet.
- [ ] Feature update backwards compatible feature updates, and I have
bumped the MINOR version in `version.json`.
- [ ] Breaking changes and I have bumped the MAJOR version in
`version.json`.
- [ ] Update to documentation
---
.../image-template/README.md | 152 ++++++++----------
.../image-template/main.bicep | 8 +-
.../image-template/main.json | 9 +-
.../tests/e2e/defaults/main.test.bicep | 6 -
.../tests/e2e/max/dependencies.bicep | 4 +-
.../tests/e2e/max/main.test.bicep | 2 +-
.../Set-StorageContainerContentByEnvVar.ps1 | 6 +-
7 files changed, 84 insertions(+), 103 deletions(-)
diff --git a/avm/res/virtual-machine-images/image-template/README.md b/avm/res/virtual-machine-images/image-template/README.md
index d8e9e5313d..022c56722c 100644
--- a/avm/res/virtual-machine-images/image-template/README.md
+++ b/avm/res/virtual-machine-images/image-template/README.md
@@ -45,12 +45,6 @@ module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:'
- type: 'Shell'
- }
- {
- destination: 'Initialize-LinuxSoftware.ps1'
- name: 'Initialize-LinuxSoftware'
- sourceUri: ''
- type: 'File'
- }
- {
- inline: [
- 'pwsh \'Initialize-LinuxSoftware.ps1\''
- ]
- name: 'Software installation'
- type: 'Shell'
- }
- ]
distributions: [
{
imageName: 'mi-vmiitmax-001'
@@ -202,6 +168,26 @@ module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:'
+ type: 'Shell'
+ }
+ {
+ destination: 'Initialize-LinuxSoftware.ps1'
+ name: 'Initialize-LinuxSoftware'
+ sourceUri: ''
+ type: 'File'
+ }
+ {
+ inline: [
+ 'pwsh \'Initialize-LinuxSoftware.ps1\''
+ ]
+ name: 'Software installation'
+ type: 'Shell'
+ }
+ ]
location: ''
lock: {
kind: 'CanNotDelete'
@@ -228,7 +214,7 @@ module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:'
}
]
- stagingResourceGroup: ''
+ stagingResourceGroupResourceId: ''
subnetResourceId: ''
tags: {
Environment: 'Non-Prod'
@@ -269,28 +255,6 @@ module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:",
- "type": "Shell"
- },
- {
- "destination": "Initialize-LinuxSoftware.ps1",
- "name": "Initialize-LinuxSoftware",
- "sourceUri": "",
- "type": "File"
- },
- {
- "inline": [
- "pwsh \"Initialize-LinuxSoftware.ps1\""
- ],
- "name": "Software installation",
- "type": "Shell"
- }
- ]
- },
"distributions": {
"value": [
{
@@ -334,6 +298,28 @@ module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:",
+ "type": "Shell"
+ },
+ {
+ "destination": "Initialize-LinuxSoftware.ps1",
+ "name": "Initialize-LinuxSoftware",
+ "sourceUri": "",
+ "type": "File"
+ },
+ {
+ "inline": [
+ "pwsh \"Initialize-LinuxSoftware.ps1\""
+ ],
+ "name": "Software installation",
+ "type": "Shell"
+ }
+ ]
+ },
"location": {
"value": ""
},
@@ -370,8 +356,8 @@ module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:"
+ "stagingResourceGroupResourceId": {
+ "value": ""
},
"subnetResourceId": {
"value": ""
@@ -427,12 +413,6 @@ module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:'
@@ -453,6 +433,12 @@ module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:'
subnetResourceId: ''
tags: {
@@ -477,14 +463,6 @@ module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:"
},
@@ -539,7 +525,6 @@ module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:If this field is empty, a resource group with a random name will be created.
If the resource group specified in this field doesn't exist, it will be created with the same name.If the resource group specified exists, it must be empty and in the same region as the image template.The resource group created will be deleted during template deletion if this field is empty or the resource group specified doesn't exist,but if the resource group specified exists the resources created in the resource group will be deleted during template deletion and the resource group itself will remain. |
+| [`stagingResourceGroupResourceId`](#parameter-stagingresourcegroupresourceid) | string | Resource ID of the staging resource group in the same subscription and location as the image template that will be used to build the image.If this field is empty, a resource group with a random name will be created.If the resource group specified in this field doesn't exist, it will be created with the same name.If the resource group specified exists, it must be empty and in the same region as the image template.The resource group created will be deleted during template deletion if this field is empty or the resource group specified doesn't exist,but if the resource group specified exists the resources created in the resource group will be deleted during template deletion and the resource group itself will remain. |
| [`subnetResourceId`](#parameter-subnetresourceid) | string | Resource ID of an already existing subnet, e.g.: /subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/.If no value is provided, a new temporary VNET and subnet will be created in the staging resource group and will be deleted along with the remaining temporary resources. |
| [`tags`](#parameter-tags) | object | Tags of the resource. |
| [`validationProcess`](#parameter-validationprocess) | object | Configuration options and list of validations to be performed on the resulting image. |
@@ -569,13 +555,6 @@ module imageTemplate 'br/public:avm/res/virtual-machine-images/image-template:If this field is empty, a resource group with a random name will be created.If the resource group specified in this field doesn't exist, it will be created with the same name.If the resource group specified exists, it must be empty and in the same region as the image template.The resource group created will be deleted during template deletion if this field is empty or the resource group specified doesn't exist,but if the resource group specified exists the resources created in the resource group will be deleted during template deletion and the resource group itself will remain.
diff --git a/avm/res/virtual-machine-images/image-template/main.bicep b/avm/res/virtual-machine-images/image-template/main.bicep
index 9aefe03417..c32e5e36f0 100644
--- a/avm/res/virtual-machine-images/image-template/main.bicep
+++ b/avm/res/virtual-machine-images/image-template/main.bicep
@@ -25,11 +25,11 @@ param subnetResourceId string?
@description('Required. Image source definition in object format.')
param imageSource object
-@description('Required. Customization steps to be run when building the VM image.')
-param customizationSteps array
+@description('Optional. Customization steps to be run when building the VM image.')
+param customizationSteps array?
@description('Optional. Resource ID of the staging resource group in the same subscription and location as the image template that will be used to build the image.If this field is empty, a resource group with a random name will be created.If the resource group specified in this field doesn\'t exist, it will be created with the same name.If the resource group specified exists, it must be empty and in the same region as the image template.The resource group created will be deleted during template deletion if this field is empty or the resource group specified doesn\'t exist,but if the resource group specified exists the resources created in the resource group will be deleted during template deletion and the resource group itself will remain.')
-param stagingResourceGroup string?
+param stagingResourceGroupResourceId string?
@description('Optional. The lock settings of the service.')
param lock lockType
@@ -138,7 +138,7 @@ resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2023-07-01
}
source: imageSource
customize: customizationSteps
- stagingResourceGroup: stagingResourceGroup
+ stagingResourceGroup: stagingResourceGroupResourceId
distribute: [
for distribution in distributions: union(
{
diff --git a/avm/res/virtual-machine-images/image-template/main.json b/avm/res/virtual-machine-images/image-template/main.json
index 8af2add54f..df6d5ed0ea 100644
--- a/avm/res/virtual-machine-images/image-template/main.json
+++ b/avm/res/virtual-machine-images/image-template/main.json
@@ -6,7 +6,7 @@
"_generator": {
"name": "bicep",
"version": "0.29.47.4906",
- "templateHash": "12715542154180929791"
+ "templateHash": "495678619291242908"
},
"name": "Virtual Machine Image Templates",
"description": "This module deploys a Virtual Machine Image Template that can be consumed by Azure Image Builder (AIB).",
@@ -458,11 +458,12 @@
},
"customizationSteps": {
"type": "array",
+ "nullable": true,
"metadata": {
- "description": "Required. Customization steps to be run when building the VM image."
+ "description": "Optional. Customization steps to be run when building the VM image."
}
},
- "stagingResourceGroup": {
+ "stagingResourceGroupResourceId": {
"type": "string",
"nullable": true,
"metadata": {
@@ -607,7 +608,7 @@
},
"source": "[parameters('imageSource')]",
"customize": "[parameters('customizationSteps')]",
- "stagingResourceGroup": "[parameters('stagingResourceGroup')]",
+ "stagingResourceGroup": "[parameters('stagingResourceGroupResourceId')]",
"validate": "[parameters('validationProcess')]",
"optimize": "[if(not(equals(parameters('optimizeVmBoot'), null())), createObject('vmBoot', createObject('state', parameters('optimizeVmBoot'))), null())]"
}
diff --git a/avm/res/virtual-machine-images/image-template/tests/e2e/defaults/main.test.bicep b/avm/res/virtual-machine-images/image-template/tests/e2e/defaults/main.test.bicep
index bb557a787c..246c9d8a1f 100644
--- a/avm/res/virtual-machine-images/image-template/tests/e2e/defaults/main.test.bicep
+++ b/avm/res/virtual-machine-images/image-template/tests/e2e/defaults/main.test.bicep
@@ -50,12 +50,6 @@ module testDeployment '../../../main.bicep' = {
params: {
name: '${namePrefix}${serviceShort}001'
location: resourceLocation
- customizationSteps: [
- {
- restartTimeout: '30m'
- type: 'WindowsRestart'
- }
- ]
imageSource: {
offer: 'Windows-11'
publisher: 'MicrosoftWindowsDesktop'
diff --git a/avm/res/virtual-machine-images/image-template/tests/e2e/max/dependencies.bicep b/avm/res/virtual-machine-images/image-template/tests/e2e/max/dependencies.bicep
index 036e72fb96..0581a62957 100644
--- a/avm/res/virtual-machine-images/image-template/tests/e2e/max/dependencies.bicep
+++ b/avm/res/virtual-machine-images/image-template/tests/e2e/max/dependencies.bicep
@@ -271,11 +271,11 @@ resource assetsStorageAccount_upload 'Microsoft.Resources/deploymentScripts@2023
scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Set-StorageContainerContentByEnvVar.ps1')
environmentVariables: [
{
- name: 'script_Install__LinuxPowerShell_sh' // May only be alphanumeric characters & underscores. The upload will replace '_' with '.' and '__' with '-'.
+ name: '__SCRIPT__Install__LinuxPowerShell_sh' // May only be alphanumeric characters & underscores. The upload will replace '_' with '.' and '__' with '-'.
value: loadTextContent('src/Install-LinuxPowerShell.sh')
}
{
- name: 'script_Initialize__LinuxSoftware_ps1' // May only be alphanumeric characters & underscores. The upload will replace '_' with '.' and '__' with '-'.
+ name: '__SCRIPT__Initialize__LinuxSoftware_ps1' // May only be alphanumeric characters & underscores. The upload will replace '_' with '.' and '__' with '-'.
value: loadTextContent('src/Initialize-LinuxSoftware.ps1')
}
]
diff --git a/avm/res/virtual-machine-images/image-template/tests/e2e/max/main.test.bicep b/avm/res/virtual-machine-images/image-template/tests/e2e/max/main.test.bicep
index ff20a8a137..f997482ca2 100644
--- a/avm/res/virtual-machine-images/image-template/tests/e2e/max/main.test.bicep
+++ b/avm/res/virtual-machine-images/image-template/tests/e2e/max/main.test.bicep
@@ -60,7 +60,7 @@ module testDeployment '../../../main.bicep' = {
params: {
name: '${namePrefix}${serviceShort}001'
location: resourceLocation
- stagingResourceGroup: '${subscription().id}/resourcegroups/${resourceGroupName}-staging'
+ stagingResourceGroupResourceId: '${subscription().id}/resourcegroups/${resourceGroupName}-staging'
customizationSteps: [
{
type: 'Shell'
diff --git a/avm/utilities/e2e-template-assets/scripts/Set-StorageContainerContentByEnvVar.ps1 b/avm/utilities/e2e-template-assets/scripts/Set-StorageContainerContentByEnvVar.ps1
index d0af03f8c2..3d06cd5ab1 100644
--- a/avm/utilities/e2e-template-assets/scripts/Set-StorageContainerContentByEnvVar.ps1
+++ b/avm/utilities/e2e-template-assets/scripts/Set-StorageContainerContentByEnvVar.ps1
@@ -15,7 +15,7 @@ Required. The name of the Storage Account to upload to
Required. The container to upload the files to
.EXAMPLE
-Set-StorageContainerContentByEnvVar -StorageAccountName 'mystorage' -TargetContainer 'myContainer'
+. 'Set-StorageContainerContentByEnvVar.ps1' -StorageAccountName 'mystorage' -TargetContainer 'myContainer'
Upload any required data to the storage account 'mystorage' and container 'myContainer'.
#>
@@ -33,9 +33,9 @@ Write-Verbose 'Fetching & storing scripts' -Verbose
$contentDirectoryName = 'scripts'
$contentDirectory = (New-Item $contentDirectoryName -ItemType 'Directory' -Force).FullName
$scriptPaths = @()
-foreach ($scriptEnvVar in (Get-ChildItem 'env:*').Name | Where-Object { $_ -like 'script_*' }) {
+foreach ($scriptEnvVar in (Get-ChildItem 'env:*').Name | Where-Object { $_ -like '__SCRIPT__*' }) {
# Handle value like 'script_Initialize__LinuxSoftware_ps1'
- $scriptName = $scriptEnvVar -replace 'script_', '' -replace '__', '-' -replace '_', '.'
+ $scriptName = $scriptEnvVar -replace '__SCRIPT__', '' -replace '__', '-' -replace '_', '.'
$scriptContent = (Get-Item env:$scriptEnvVar).Value
Write-Verbose ('Storing file [{0}] with length [{1}]' -f $scriptName, $scriptContent.Length) -Verbose