diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2a020a6080..ba526085e4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -24,7 +24,7 @@ #/avm/res/compute/availability-set/ @Azure/avm-res-compute-availabilityset-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/compute/disk/ @Azure/avm-res-compute-disk-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/compute/disk-encryption-set/ @Azure/avm-res-compute-diskencryptionset-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/compute/gallery/ @Azure/avm-res-compute-gallery-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/compute/gallery/ @Azure/avm-res-compute-gallery-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/compute/image/ @Azure/avm-res-compute-image-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/compute/proximity-placement-group/ @Azure/avm-res-compute-proximityplacementgroup-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/compute/ssh-public-key/ @Azure/avm-res-compute-sshpublickey-module-owners-bicep @Azure/avm-core-team-technical-bicep diff --git a/.github/workflows/avm.res.compute.gallery.yml b/.github/workflows/avm.res.compute.gallery.yml new file mode 100644 index 0000000000..ef880b882f --- /dev/null +++ b/.github/workflows/avm.res.compute.gallery.yml @@ -0,0 +1,83 @@ +name: "avm.res.compute.gallery" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + workflow_dispatch: + inputs: + staticValidation: + type: boolean + description: "Execute static validation" + required: false + default: true + deploymentValidation: + type: boolean + description: "Execute deployment validation" + required: false + default: true + removeDeployment: + type: boolean + description: "Remove deployed module" + required: false + default: true + + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.compute.gallery.yml" + - "avm/res/compute/gallery/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/compute/gallery" + workflowPath: ".github/workflows/avm.res.compute.gallery.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/compute/gallery/ORPHANED.md b/avm/res/compute/gallery/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/compute/gallery/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/compute/gallery/README.md b/avm/res/compute/gallery/README.md new file mode 100644 index 0000000000..76d2b2178c --- /dev/null +++ b/avm/res/compute/gallery/README.md @@ -0,0 +1,880 @@ +# Azure Compute Galleries `[Microsoft.Compute/galleries]` + +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + +This module deploys an Azure Compute Gallery (formerly known as Shared Image Gallery). + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.Compute/galleries` | [2022-03-03](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-03-03/galleries) | +| `Microsoft.Compute/galleries/applications` | [2022-03-03](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-03-03/galleries/applications) | +| `Microsoft.Compute/galleries/images` | [2022-03-03](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-03-03/galleries/images) | + +## Usage examples + +The following section provides usage examples for the module, which were used to validate and deploy the module successfully. For a full reference, please review the module's test folder in its repository. + +>**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/compute/gallery:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [WAF-aligned](#example-3-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep +module gallery 'br/public:avm/res/compute/gallery:' = { + name: '${uniqueString(deployment().name, location)}-test-cgmin' + params: { + // Required parameters + name: 'cgmin001' + // Non-required parameters + location: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "cgmin001" + }, + // Non-required parameters + "location": { + "value": "" + } + } +} +``` + +
+

+ +### Example 2: _Using large parameter set_ + +This instance deploys the module with most of its features enabled. + + +

+ +via Bicep module + +```bicep +module gallery 'br/public:avm/res/compute/gallery:' = { + name: '${uniqueString(deployment().name, location)}-test-cgmax' + params: { + // Required parameters + name: 'cgmax001' + // Non-required parameters + applications: [ + { + name: 'cgmax-appd-001' + } + { + name: 'cgmax-appd-002' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + supportedOSType: 'Windows' + } + ] + images: [ + { + name: 'az-imgd-ws-001' + } + { + hyperVGeneration: 'V1' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: 'az-imgd-ws-002' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + sku: '2022-datacenter-azure-edition' + } + { + hyperVGeneration: 'V2' + isHibernateSupported: 'true' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: 'az-imgd-ws-003' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + sku: '2022-datacenter-azure-edition-hibernate' + } + { + hyperVGeneration: 'V2' + isAcceleratedNetworkSupported: 'true' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: 'az-imgd-ws-004' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + sku: '2022-datacenter-azure-edition-accnet' + } + { + hyperVGeneration: 'V2' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 4 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: 'az-imgd-wdtl-002' + offer: 'WindowsDesktop' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsDesktop' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + securityType: 'TrustedLaunch' + sku: 'Win11-21H2' + } + { + hyperVGeneration: 'V2' + maxRecommendedMemory: 32 + maxRecommendedvCPUs: 4 + minRecommendedMemory: 4 + minRecommendedvCPUs: 1 + name: 'az-imgd-us-001' + offer: '0001-com-ubuntu-server-focal' + osState: 'Generalized' + osType: 'Linux' + publisher: 'canonical' + sku: '20_04-lts-gen2' + } + ] + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "cgmax001" + }, + // Non-required parameters + "applications": { + "value": [ + { + "name": "cgmax-appd-001" + }, + { + "name": "cgmax-appd-002", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "supportedOSType": "Windows" + } + ] + }, + "images": { + "value": [ + { + "name": "az-imgd-ws-001" + }, + { + "hyperVGeneration": "V1", + "maxRecommendedMemory": 16, + "maxRecommendedvCPUs": 8, + "minRecommendedMemory": 4, + "minRecommendedvCPUs": 2, + "name": "az-imgd-ws-002", + "offer": "WindowsServer", + "osState": "Generalized", + "osType": "Windows", + "publisher": "MicrosoftWindowsServer", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "sku": "2022-datacenter-azure-edition" + }, + { + "hyperVGeneration": "V2", + "isHibernateSupported": "true", + "maxRecommendedMemory": 16, + "maxRecommendedvCPUs": 8, + "minRecommendedMemory": 4, + "minRecommendedvCPUs": 2, + "name": "az-imgd-ws-003", + "offer": "WindowsServer", + "osState": "Generalized", + "osType": "Windows", + "publisher": "MicrosoftWindowsServer", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "sku": "2022-datacenter-azure-edition-hibernate" + }, + { + "hyperVGeneration": "V2", + "isAcceleratedNetworkSupported": "true", + "maxRecommendedMemory": 16, + "maxRecommendedvCPUs": 8, + "minRecommendedMemory": 4, + "minRecommendedvCPUs": 2, + "name": "az-imgd-ws-004", + "offer": "WindowsServer", + "osState": "Generalized", + "osType": "Windows", + "publisher": "MicrosoftWindowsServer", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "sku": "2022-datacenter-azure-edition-accnet" + }, + { + "hyperVGeneration": "V2", + "maxRecommendedMemory": 16, + "maxRecommendedvCPUs": 4, + "minRecommendedMemory": 4, + "minRecommendedvCPUs": 2, + "name": "az-imgd-wdtl-002", + "offer": "WindowsDesktop", + "osState": "Generalized", + "osType": "Windows", + "publisher": "MicrosoftWindowsDesktop", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "securityType": "TrustedLaunch", + "sku": "Win11-21H2" + }, + { + "hyperVGeneration": "V2", + "maxRecommendedMemory": 32, + "maxRecommendedvCPUs": 4, + "minRecommendedMemory": 4, + "minRecommendedvCPUs": 1, + "name": "az-imgd-us-001", + "offer": "0001-com-ubuntu-server-focal", + "osState": "Generalized", + "osType": "Linux", + "publisher": "canonical", + "sku": "20_04-lts-gen2" + } + ] + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ +### Example 3: _WAF-aligned_ + +This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. + + +

+ +via Bicep module + +```bicep +module gallery 'br/public:avm/res/compute/gallery:' = { + name: '${uniqueString(deployment().name, location)}-test-cgwaf' + params: { + // Required parameters + name: 'cgwaf001' + // Non-required parameters + applications: [ + { + name: 'cgwaf-appd-001' + } + { + name: 'cgwaf-appd-002' + supportedOSType: 'Windows' + } + ] + images: [ + { + name: 'az-imgd-ws-001' + } + { + hyperVGeneration: 'V1' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: 'az-imgd-ws-002' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition' + } + { + hyperVGeneration: 'V2' + isHibernateSupported: 'true' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: 'az-imgd-ws-003' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition-hibernate' + } + { + hyperVGeneration: 'V2' + isAcceleratedNetworkSupported: 'true' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: 'az-imgd-ws-004' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition-accnet' + } + { + hyperVGeneration: 'V2' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 4 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: 'az-imgd-wdtl-002' + offer: 'WindowsDesktop' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsDesktop' + securityType: 'TrustedLaunch' + sku: 'Win11-21H2' + } + { + hyperVGeneration: 'V2' + maxRecommendedMemory: 32 + maxRecommendedvCPUs: 4 + minRecommendedMemory: 4 + minRecommendedvCPUs: 1 + name: 'az-imgd-us-001' + offer: '0001-com-ubuntu-server-focal' + osState: 'Generalized' + osType: 'Linux' + publisher: 'canonical' + sku: '20_04-lts-gen2' + } + ] + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "cgwaf001" + }, + // Non-required parameters + "applications": { + "value": [ + { + "name": "cgwaf-appd-001" + }, + { + "name": "cgwaf-appd-002", + "supportedOSType": "Windows" + } + ] + }, + "images": { + "value": [ + { + "name": "az-imgd-ws-001" + }, + { + "hyperVGeneration": "V1", + "maxRecommendedMemory": 16, + "maxRecommendedvCPUs": 8, + "minRecommendedMemory": 4, + "minRecommendedvCPUs": 2, + "name": "az-imgd-ws-002", + "offer": "WindowsServer", + "osState": "Generalized", + "osType": "Windows", + "publisher": "MicrosoftWindowsServer", + "sku": "2022-datacenter-azure-edition" + }, + { + "hyperVGeneration": "V2", + "isHibernateSupported": "true", + "maxRecommendedMemory": 16, + "maxRecommendedvCPUs": 8, + "minRecommendedMemory": 4, + "minRecommendedvCPUs": 2, + "name": "az-imgd-ws-003", + "offer": "WindowsServer", + "osState": "Generalized", + "osType": "Windows", + "publisher": "MicrosoftWindowsServer", + "sku": "2022-datacenter-azure-edition-hibernate" + }, + { + "hyperVGeneration": "V2", + "isAcceleratedNetworkSupported": "true", + "maxRecommendedMemory": 16, + "maxRecommendedvCPUs": 8, + "minRecommendedMemory": 4, + "minRecommendedvCPUs": 2, + "name": "az-imgd-ws-004", + "offer": "WindowsServer", + "osState": "Generalized", + "osType": "Windows", + "publisher": "MicrosoftWindowsServer", + "sku": "2022-datacenter-azure-edition-accnet" + }, + { + "hyperVGeneration": "V2", + "maxRecommendedMemory": 16, + "maxRecommendedvCPUs": 4, + "minRecommendedMemory": 4, + "minRecommendedvCPUs": 2, + "name": "az-imgd-wdtl-002", + "offer": "WindowsDesktop", + "osState": "Generalized", + "osType": "Windows", + "publisher": "MicrosoftWindowsDesktop", + "securityType": "TrustedLaunch", + "sku": "Win11-21H2" + }, + { + "hyperVGeneration": "V2", + "maxRecommendedMemory": 32, + "maxRecommendedvCPUs": 4, + "minRecommendedMemory": 4, + "minRecommendedvCPUs": 1, + "name": "az-imgd-us-001", + "offer": "0001-com-ubuntu-server-focal", + "osState": "Generalized", + "osType": "Linux", + "publisher": "canonical", + "sku": "20_04-lts-gen2" + } + ] + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Azure Compute Gallery. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`applications`](#parameter-applications) | array | Applications to create. | +| [`description`](#parameter-description) | string | Description of the Azure Shared Image Gallery. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`images`](#parameter-images) | array | Images to create. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | +| [`tags`](#parameter-tags) | object | Tags for all resources. | + +### Parameter: `name` + +Name of the Azure Compute Gallery. + +- Required: Yes +- Type: string + +### Parameter: `applications` + +Applications to create. + +- Required: No +- Type: array + +### Parameter: `description` + +Description of the Azure Shared Image Gallery. + +- Required: No +- Type: string + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `images` + +Images to create. + +- Required: No +- Type: array + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `lock` + +The lock settings of the service. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | +| [`name`](#parameter-lockname) | string | Specify the name of lock. | + +### Parameter: `lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `roleAssignments` + +Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The name of the role to assign. If it cannot be found you can specify the role definition ID instead. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container" | +| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +The name of the role to assign. If it cannot be found you can specify the role definition ID instead. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container" + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `tags` + +Tags for all resources. + +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the deployed image gallery. | +| `resourceGroupName` | string | The resource group of the deployed image gallery. | +| `resourceId` | string | The resource ID of the deployed image gallery. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/compute/gallery/application/README.md b/avm/res/compute/gallery/application/README.md new file mode 100644 index 0000000000..44732656d1 --- /dev/null +++ b/avm/res/compute/gallery/application/README.md @@ -0,0 +1,337 @@ +# Compute Galleries Applications `[Microsoft.Compute/galleries/applications]` + +This module deploys an Azure Compute Gallery Application. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Notes](#Notes) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.Compute/galleries/applications` | [2022-03-03](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-03-03/galleries/applications) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the application definition. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`galleryName`](#parameter-galleryname) | string | The name of the parent Azure Compute Gallery. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`customActions`](#parameter-customactions) | array | A list of custom actions that can be performed with all of the Gallery Application Versions within this Gallery Application. | +| [`description`](#parameter-description) | string | The description of this gallery Application Definition resource. This property is updatable. | +| [`endOfLifeDate`](#parameter-endoflifedate) | string | The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z. | +| [`eula`](#parameter-eula) | string | The Eula agreement for the gallery Application Definition. Has to be a valid URL. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`privacyStatementUri`](#parameter-privacystatementuri) | string | The privacy statement uri. Has to be a valid URL. | +| [`releaseNoteUri`](#parameter-releasenoteuri) | string | The release note uri. Has to be a valid URL. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | +| [`supportedOSType`](#parameter-supportedostype) | string | This property allows you to specify the supported type of the OS that application is built for. | +| [`tags`](#parameter-tags) | object | Tags for all resources. | + +### Parameter: `name` + +Name of the application definition. + +- Required: Yes +- Type: string + +### Parameter: `galleryName` + +The name of the parent Azure Compute Gallery. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `customActions` + +A list of custom actions that can be performed with all of the Gallery Application Versions within this Gallery Application. + +- Required: No +- Type: array + +### Parameter: `description` + +The description of this gallery Application Definition resource. This property is updatable. + +- Required: No +- Type: string + +### Parameter: `endOfLifeDate` + +The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z. + +- Required: No +- Type: string + +### Parameter: `eula` + +The Eula agreement for the gallery Application Definition. Has to be a valid URL. + +- Required: No +- Type: string + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `privacyStatementUri` + +The privacy statement uri. Has to be a valid URL. + +- Required: No +- Type: string + +### Parameter: `releaseNoteUri` + +The release note uri. Has to be a valid URL. + +- Required: No +- Type: string + +### Parameter: `roleAssignments` + +Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The name of the role to assign. If it cannot be found you can specify the role definition ID instead. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container" | +| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +The name of the role to assign. If it cannot be found you can specify the role definition ID instead. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container" + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `supportedOSType` + +This property allows you to specify the supported type of the OS that application is built for. + +- Required: No +- Type: string +- Default: `'Windows'` +- Allowed: + ```Bicep + [ + 'Linux' + 'Windows' + ] + ``` + +### Parameter: `tags` + +Tags for all resources. + +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the image. | +| `resourceGroupName` | string | The resource group the image was deployed into. | +| `resourceId` | string | The resource ID of the image. | + +## Cross-referenced modules + +_None_ + +## Notes + +### Parameter Usage: `customActions` + +Create a list of custom actions that can be performed with all of the Gallery Application Versions within this Gallery Application. + +

+ +Parameter JSON format + +```json +"customActions": { + "value": [ + { + "description": "This is a sample custom action", + "name": "Name of the custom action 1 (Required). Must be unique within the Compute Gallery", + "parameters": [ + { + "defaultValue": "Default Value of Parameter1. Only applies to string types.", + "description": "a description value to help others understands what it means.", + "name": "The parameter name. (Required)", + "required": True, + "type": "ConfigurationDataBlob, LogOutputBlob, or String" + }, + { + "defaultValue": "Default Value of Parameter2. Only applies to string types.", + "description": "a description value to help others understands what it means.", + "name": "The parameter name. (Required)", + "required": False, + "type": "ConfigurationDataBlob, LogOutputBlob, or String" + } + ], + "script": "The script to run when executing this custom action. (Required)" + }, + { + "description": "This is another sample custom action", + "name": "Name of the custom action 2 (Required). Must be unique within the Compute Gallery", + "parameters": [ + { + "defaultValue": "Default Value of Parameter1. Only applies to string types.", + "description": "a description value to help others understands what it means.", + "name": "The parameter name. (Required)", + "required": True, + "type": "ConfigurationDataBlob, LogOutputBlob, or String" + } + ], + "script": "The script to run when executing this custom action. (Required)" + } + ] +} +``` + +
+ +
+ +Bicep format + +```bicep +customActions: [ + { + description: "This is a sample custom action" + name: "Name of the custom action 1 (Required). Must be unique within the Compute Gallery" + parameters: [ + { + defaultValue: "Default Value of Parameter 1. Only applies to string types." + description: "a description value to help others understands what it means." + name: "The parameter name. (Required)" + required: True, + type: "ConfigurationDataBlob, LogOutputBlob, or String" + } + { + defaultValue: "Default Value of Parameter 2. Only applies to string types." + description: "a description value to help others understands what it means." + name: "The parameter name. (Required)" + required: True, + type: "ConfigurationDataBlob, LogOutputBlob, or String" + } + ] + script: "The script to run when executing this custom action. (Required)" + } + { + description: "This is another sample custom action" + name: "Name of the custom action 2 (Required). Must be unique within the Compute Gallery" + parameters: [ + { + defaultValue: "Default Value of Parameter. Only applies to string types." + description: "a description value to help others understands what it means." + name: "The paramter name. (Required)" + required: True, + type: "ConfigurationDataBlob, LogOutputBlob, or String" + } + ] + script: "The script to run when executing this custom action. (Required)" + } +] +``` + +
+

diff --git a/avm/res/compute/gallery/application/main.bicep b/avm/res/compute/gallery/application/main.bicep new file mode 100644 index 0000000000..26cd930c44 --- /dev/null +++ b/avm/res/compute/gallery/application/main.bicep @@ -0,0 +1,125 @@ +metadata name = 'Compute Galleries Applications' +metadata description = 'This module deploys an Azure Compute Gallery Application.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Required. Name of the application definition.') +param name string + +@sys.description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@sys.description('Conditional. The name of the parent Azure Compute Gallery. Required if the template is used in a standalone deployment.') +@minLength(1) +param galleryName string + +@sys.description('Optional. The description of this gallery Application Definition resource. This property is updatable.') +param description string? + +@sys.description('Optional. The Eula agreement for the gallery Application Definition. Has to be a valid URL.') +param eula string? + +@sys.description('Optional. The privacy statement uri. Has to be a valid URL.') +param privacyStatementUri string? + +@sys.description('Optional. The release note uri. Has to be a valid URL.') +param releaseNoteUri string? + +@sys.description('Optional. This property allows you to specify the supported type of the OS that application is built for.') +@allowed([ + 'Windows' + 'Linux' +]) +param supportedOSType string = 'Windows' + +@sys.description('Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z.') +param endOfLifeDate string? + +@sys.description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') +param roleAssignments roleAssignmentType + +@sys.description('Optional. Tags for all resources.') +param tags object? + +@sys.description('Optional. A list of custom actions that can be performed with all of the Gallery Application Versions within this Gallery Application.') +param customActions array? + +var builtInRoleNames = { + 'Compute Gallery Sharing Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b') + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource gallery 'Microsoft.Compute/galleries@2022-03-03' existing = { + name: galleryName +} + +resource application 'Microsoft.Compute/galleries/applications@2022-03-03' = { + name: name + parent: gallery + location: location + tags: tags + properties: { + customActions: customActions + description: description ?? '' + endOfLifeDate: endOfLifeDate ?? '' + eula: eula ?? '' + privacyStatementUri: privacyStatementUri ?? '' + releaseNoteUri: releaseNoteUri ?? '' + supportedOSType: supportedOSType + } +} + +resource application_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(application.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: application +}] + +@sys.description('The resource group the image was deployed into.') +output resourceGroupName string = resourceGroup().name + +@sys.description('The resource ID of the image.') +output resourceId string = application.id + +@sys.description('The name of the image.') +output name string = application.name + +@sys.description('The location the resource was deployed into.') +output location string = application.location +// =============== // +// Definitions // +// =============== // + +type roleAssignmentType = { + @sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead.') + roleDefinitionIdOrName: string + + @sys.description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @sys.description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @sys.description('Optional. The description of the role assignment.') + description: string? + + @sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"') + condition: string? + + @sys.description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @sys.description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? diff --git a/avm/res/compute/gallery/application/main.json b/avm/res/compute/gallery/application/main.json new file mode 100644 index 0000000000..e4227db2f0 --- /dev/null +++ b/avm/res/compute/gallery/application/main.json @@ -0,0 +1,260 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "9406373999607697824" + }, + "name": "Compute Galleries Applications", + "description": "This module deploys an Azure Compute Gallery Application.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the application definition." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Conditional. The name of the parent Azure Compute Gallery. Required if the template is used in a standalone deployment." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of this gallery Application Definition resource. This property is updatable." + } + }, + "eula": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Eula agreement for the gallery Application Definition. Has to be a valid URL." + } + }, + "privacyStatementUri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The privacy statement uri. Has to be a valid URL." + } + }, + "releaseNoteUri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The release note uri. Has to be a valid URL." + } + }, + "supportedOSType": { + "type": "string", + "defaultValue": "Windows", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Optional. This property allows you to specify the supported type of the OS that application is built for." + } + }, + "endOfLifeDate": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all resources." + } + }, + "customActions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of custom actions that can be performed with all of the Gallery Application Versions within this Gallery Application." + } + } + }, + "variables": { + "builtInRoleNames": { + "Compute Gallery Sharing Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "gallery": { + "existing": true, + "type": "Microsoft.Compute/galleries", + "apiVersion": "2022-03-03", + "name": "[parameters('galleryName')]" + }, + "application": { + "type": "Microsoft.Compute/galleries/applications", + "apiVersion": "2022-03-03", + "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "customActions": "[parameters('customActions')]", + "description": "[coalesce(parameters('description'), '')]", + "endOfLifeDate": "[coalesce(parameters('endOfLifeDate'), '')]", + "eula": "[coalesce(parameters('eula'), '')]", + "privacyStatementUri": "[coalesce(parameters('privacyStatementUri'), '')]", + "releaseNoteUri": "[coalesce(parameters('releaseNoteUri'), '')]", + "supportedOSType": "[parameters('supportedOSType')]" + }, + "dependsOn": [ + "gallery" + ] + }, + "application_roleAssignments": { + "copy": { + "name": "application_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Compute/galleries/{0}/applications/{1}', parameters('galleryName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Compute/galleries/applications', parameters('galleryName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "application" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the image was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the image." + }, + "value": "[resourceId('Microsoft.Compute/galleries/applications', parameters('galleryName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the image." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('application', '2022-03-03', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/compute/gallery/image/README.md b/avm/res/compute/gallery/image/README.md new file mode 100644 index 0000000000..334842274a --- /dev/null +++ b/avm/res/compute/gallery/image/README.md @@ -0,0 +1,405 @@ +# Compute Galleries Image Definitions `[Microsoft.Compute/galleries/images]` + +This module deploys an Azure Compute Gallery Image Definition. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.Compute/galleries/images` | [2022-03-03](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-03-03/galleries/images) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the image definition. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`galleryName`](#parameter-galleryname) | string | The name of the parent Azure Shared Image Gallery. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`description`](#parameter-description) | string | The description of this gallery Image Definition resource. This property is updatable. | +| [`endOfLife`](#parameter-endoflife) | string | The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z. | +| [`eula`](#parameter-eula) | string | The Eula agreement for the gallery Image Definition. Has to be a valid URL. | +| [`excludedDiskTypes`](#parameter-excludeddisktypes) | array | List of the excluded disk types. E.g. Standard_LRS. | +| [`hyperVGeneration`](#parameter-hypervgeneration) | string | The hypervisor generation of the Virtual Machine.

- If this value is not specified, then it is determined by the securityType parameter.

- If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1. | +| [`isAcceleratedNetworkSupported`](#parameter-isacceleratednetworksupported) | string | The image supports accelerated networking.

Accelerated networking enables single root I/O virtualization (SR-IOV) to a VM, greatly improving its networking performance.

This high-performance path bypasses the host from the data path, which reduces latency, jitter, and CPU utilization for the most demanding network workloads on supported VM types. | +| [`isHibernateSupported`](#parameter-ishibernatesupported) | string | The image will support hibernation. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`maxRecommendedMemory`](#parameter-maxrecommendedmemory) | int | The maximum amount of RAM in GB recommended for this image. | +| [`maxRecommendedvCPUs`](#parameter-maxrecommendedvcpus) | int | The maximum number of the CPU cores recommended for this image. | +| [`minRecommendedMemory`](#parameter-minrecommendedmemory) | int | The minimum amount of RAM in GB recommended for this image. | +| [`minRecommendedvCPUs`](#parameter-minrecommendedvcpus) | int | The minimum number of the CPU cores recommended for this image. | +| [`offer`](#parameter-offer) | string | The name of the gallery Image Definition offer. | +| [`osState`](#parameter-osstate) | string | This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'. | +| [`osType`](#parameter-ostype) | string | OS type of the image to be created. | +| [`planName`](#parameter-planname) | string | The plan ID. | +| [`planPublisherName`](#parameter-planpublishername) | string | The publisher ID. | +| [`privacyStatementUri`](#parameter-privacystatementuri) | string | The privacy statement uri. Has to be a valid URL. | +| [`productName`](#parameter-productname) | string | The product ID. | +| [`publisher`](#parameter-publisher) | string | The name of the gallery Image Definition publisher. | +| [`releaseNoteUri`](#parameter-releasenoteuri) | string | The release note uri. Has to be a valid URL. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | +| [`securityType`](#parameter-securitytype) | string | The security type of the image. Requires a hyperVGeneration V2. | +| [`sku`](#parameter-sku) | string | The name of the gallery Image Definition SKU. | +| [`tags`](#parameter-tags) | object | Tags for all resources. | + +### Parameter: `name` + +Name of the image definition. + +- Required: Yes +- Type: string + +### Parameter: `galleryName` + +The name of the parent Azure Shared Image Gallery. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `description` + +The description of this gallery Image Definition resource. This property is updatable. + +- Required: No +- Type: string + +### Parameter: `endOfLife` + +The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z. + +- Required: No +- Type: string + +### Parameter: `eula` + +The Eula agreement for the gallery Image Definition. Has to be a valid URL. + +- Required: No +- Type: string + +### Parameter: `excludedDiskTypes` + +List of the excluded disk types. E.g. Standard_LRS. + +- Required: No +- Type: array + +### Parameter: `hyperVGeneration` + +The hypervisor generation of the Virtual Machine.

- If this value is not specified, then it is determined by the securityType parameter.

- If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + 'V1' + 'V2' + ] + ``` + +### Parameter: `isAcceleratedNetworkSupported` + +The image supports accelerated networking.

Accelerated networking enables single root I/O virtualization (SR-IOV) to a VM, greatly improving its networking performance.

This high-performance path bypasses the host from the data path, which reduces latency, jitter, and CPU utilization for the most demanding network workloads on supported VM types. + +- Required: No +- Type: string +- Default: `'false'` +- Allowed: + ```Bicep + [ + 'false' + 'true' + ] + ``` + +### Parameter: `isHibernateSupported` + +The image will support hibernation. + +- Required: No +- Type: string +- Default: `'false'` +- Allowed: + ```Bicep + [ + 'false' + 'true' + ] + ``` + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `maxRecommendedMemory` + +The maximum amount of RAM in GB recommended for this image. + +- Required: No +- Type: int +- Default: `16` + +### Parameter: `maxRecommendedvCPUs` + +The maximum number of the CPU cores recommended for this image. + +- Required: No +- Type: int +- Default: `4` + +### Parameter: `minRecommendedMemory` + +The minimum amount of RAM in GB recommended for this image. + +- Required: No +- Type: int +- Default: `4` + +### Parameter: `minRecommendedvCPUs` + +The minimum number of the CPU cores recommended for this image. + +- Required: No +- Type: int +- Default: `1` + +### Parameter: `offer` + +The name of the gallery Image Definition offer. + +- Required: No +- Type: string +- Default: `'0001-com-ubuntu-server-jammy'` + +### Parameter: `osState` + +This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'. + +- Required: No +- Type: string +- Default: `'Generalized'` +- Allowed: + ```Bicep + [ + 'Generalized' + 'Specialized' + ] + ``` + +### Parameter: `osType` + +OS type of the image to be created. + +- Required: No +- Type: string +- Default: `'Linux'` +- Allowed: + ```Bicep + [ + 'Linux' + 'Windows' + ] + ``` + +### Parameter: `planName` + +The plan ID. + +- Required: No +- Type: string + +### Parameter: `planPublisherName` + +The publisher ID. + +- Required: No +- Type: string + +### Parameter: `privacyStatementUri` + +The privacy statement uri. Has to be a valid URL. + +- Required: No +- Type: string + +### Parameter: `productName` + +The product ID. + +- Required: No +- Type: string + +### Parameter: `publisher` + +The name of the gallery Image Definition publisher. + +- Required: No +- Type: string +- Default: `'canonical'` + +### Parameter: `releaseNoteUri` + +The release note uri. Has to be a valid URL. + +- Required: No +- Type: string + +### Parameter: `roleAssignments` + +Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The name of the role to assign. If it cannot be found you can specify the role definition ID instead. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container" | +| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +The name of the role to assign. If it cannot be found you can specify the role definition ID instead. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container" + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `securityType` + +The security type of the image. Requires a hyperVGeneration V2. + +- Required: No +- Type: string +- Default: `'Standard'` +- Allowed: + ```Bicep + [ + 'ConfidentialVM' + 'ConfidentialVMSupported' + 'Standard' + 'TrustedLaunch' + ] + ``` + +### Parameter: `sku` + +The name of the gallery Image Definition SKU. + +- Required: No +- Type: string +- Default: `'22_04-lts-gen2'` + +### Parameter: `tags` + +Tags for all resources. + +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the image. | +| `resourceGroupName` | string | The resource group the image was deployed into. | +| `resourceId` | string | The resource ID of the image. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/compute/gallery/image/main.bicep b/avm/res/compute/gallery/image/main.bicep new file mode 100644 index 0000000000..7c00a76deb --- /dev/null +++ b/avm/res/compute/gallery/image/main.bicep @@ -0,0 +1,248 @@ +metadata name = 'Compute Galleries Image Definitions' +metadata description = 'This module deploys an Azure Compute Gallery Image Definition.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Required. Name of the image definition.') +param name string + +@sys.description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@sys.description('Conditional. The name of the parent Azure Shared Image Gallery. Required if the template is used in a standalone deployment.') +@minLength(1) +param galleryName string + +@sys.description('Optional. OS type of the image to be created.') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string = 'Linux' + +@sys.description('Optional. This property allows the user to specify whether the virtual machines created under this image are \'Generalized\' or \'Specialized\'.') +@allowed([ + 'Generalized' + 'Specialized' +]) +param osState string = 'Generalized' + +@sys.description('Optional. The name of the gallery Image Definition publisher.') +param publisher string = 'canonical' + +@sys.description('Optional. The name of the gallery Image Definition offer.') +param offer string = '0001-com-ubuntu-server-jammy' + +@sys.description('Optional. The name of the gallery Image Definition SKU.') +param sku string = '22_04-lts-gen2' + +@sys.description('Optional. The minimum number of the CPU cores recommended for this image.') +@minValue(1) +@maxValue(128) +param minRecommendedvCPUs int = 1 + +@sys.description('Optional. The maximum number of the CPU cores recommended for this image.') +@minValue(1) +@maxValue(128) +param maxRecommendedvCPUs int = 4 + +@sys.description('Optional. The minimum amount of RAM in GB recommended for this image.') +@minValue(1) +@maxValue(4000) +param minRecommendedMemory int = 4 + +@sys.description('Optional. The maximum amount of RAM in GB recommended for this image.') +@minValue(1) +@maxValue(4000) +param maxRecommendedMemory int = 16 + +@sys.description('Optional. The hypervisor generation of the Virtual Machine.

- If this value is not specified, then it is determined by the securityType parameter.

- If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1.') +@allowed([ + '' + 'V1' + 'V2' +]) +param hyperVGeneration string = '' + +@sys.description('Optional. The security type of the image. Requires a hyperVGeneration V2.') +@allowed([ + 'Standard' + 'TrustedLaunch' + 'ConfidentialVM' + 'ConfidentialVMSupported' +]) +param securityType string = 'Standard' + +@sys.description('Optional. The image will support hibernation.') +@allowed([ + 'true' + 'false' +]) +param isHibernateSupported string = 'false' + +@sys.description('Optional. The image supports accelerated networking.

Accelerated networking enables single root I/O virtualization (SR-IOV) to a VM, greatly improving its networking performance.

This high-performance path bypasses the host from the data path, which reduces latency, jitter, and CPU utilization for the most demanding network workloads on supported VM types.') +@allowed([ + 'true' + 'false' +]) +param isAcceleratedNetworkSupported string = 'false' + +@sys.description('Optional. The description of this gallery Image Definition resource. This property is updatable.') +param description string? + +@sys.description('Optional. The Eula agreement for the gallery Image Definition. Has to be a valid URL.') +param eula string? + +@sys.description('Optional. The privacy statement uri. Has to be a valid URL.') +param privacyStatementUri string? + +@sys.description('Optional. The release note uri. Has to be a valid URL.') +param releaseNoteUri string? + +@sys.description('Optional. The product ID.') +param productName string? + +@sys.description('Optional. The plan ID.') +param planName string? + +@sys.description('Optional. The publisher ID.') +param planPublisherName string? + +@sys.description('Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z.') +param endOfLife string? + +@sys.description('Optional. List of the excluded disk types. E.g. Standard_LRS.') +param excludedDiskTypes array? + +@sys.description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') +param roleAssignments roleAssignmentType + +@sys.description('Optional. Tags for all resources.') +param tags object? + +var builtInRoleNames = { + 'Compute Gallery Sharing Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b') + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource gallery 'Microsoft.Compute/galleries@2022-03-03' existing = { + name: galleryName +} + +resource image 'Microsoft.Compute/galleries/images@2022-03-03' = { + name: name + parent: gallery + location: location + tags: tags + properties: { + osType: osType + osState: osState + identifier: { + publisher: publisher + offer: offer + sku: sku + } + recommended: { + vCPUs: { + min: minRecommendedvCPUs + max: maxRecommendedvCPUs + } + memory: { + min: minRecommendedMemory + max: maxRecommendedMemory + } + } + hyperVGeneration: !empty(hyperVGeneration) ? hyperVGeneration : (!empty(securityType) ? 'V2' : 'V1') + features: !empty(securityType) && securityType != 'Standard' ? [ + { + name: 'SecurityType' + value: securityType + } + { + name: 'IsAcceleratedNetworkSupported' + value: isAcceleratedNetworkSupported + } + { + name: 'IsHibernateSupported' + value: isHibernateSupported + } + ] : [ + { + name: 'IsAcceleratedNetworkSupported' + value: isAcceleratedNetworkSupported + } + { + name: 'IsHibernateSupported' + value: isHibernateSupported + } + ] + description: description ?? '' + eula: eula ?? '' + privacyStatementUri: privacyStatementUri ?? '' + releaseNoteUri: releaseNoteUri ?? '' + purchasePlan: { + product: productName + name: planName + publisher: planPublisherName + } + endOfLifeDate: endOfLife ?? '' + disallowed: { + diskTypes: excludedDiskTypes ?? [] + } + } +} + +resource image_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(image.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: image +}] + +@sys.description('The resource group the image was deployed into.') +output resourceGroupName string = resourceGroup().name + +@sys.description('The resource ID of the image.') +output resourceId string = image.id + +@sys.description('The name of the image.') +output name string = image.name + +@sys.description('The location the resource was deployed into.') +output location string = image.location +// =============== // +// Definitions // +// =============== // + +type roleAssignmentType = { + @sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead.') + roleDefinitionIdOrName: string + + @sys.description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @sys.description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @sys.description('Optional. The description of the role assignment.') + description: string? + + @sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"') + condition: string? + + @sys.description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @sys.description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? diff --git a/avm/res/compute/gallery/image/main.json b/avm/res/compute/gallery/image/main.json new file mode 100644 index 0000000000..6f6dbb1c3d --- /dev/null +++ b/avm/res/compute/gallery/image/main.json @@ -0,0 +1,421 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "14441578962181885339" + }, + "name": "Compute Galleries Image Definitions", + "description": "This module deploys an Azure Compute Gallery Image Definition.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the image definition." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Conditional. The name of the parent Azure Shared Image Gallery. Required if the template is used in a standalone deployment." + } + }, + "osType": { + "type": "string", + "defaultValue": "Linux", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Optional. OS type of the image to be created." + } + }, + "osState": { + "type": "string", + "defaultValue": "Generalized", + "allowedValues": [ + "Generalized", + "Specialized" + ], + "metadata": { + "description": "Optional. This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'." + } + }, + "publisher": { + "type": "string", + "defaultValue": "canonical", + "metadata": { + "description": "Optional. The name of the gallery Image Definition publisher." + } + }, + "offer": { + "type": "string", + "defaultValue": "0001-com-ubuntu-server-jammy", + "metadata": { + "description": "Optional. The name of the gallery Image Definition offer." + } + }, + "sku": { + "type": "string", + "defaultValue": "22_04-lts-gen2", + "metadata": { + "description": "Optional. The name of the gallery Image Definition SKU." + } + }, + "minRecommendedvCPUs": { + "type": "int", + "defaultValue": 1, + "minValue": 1, + "maxValue": 128, + "metadata": { + "description": "Optional. The minimum number of the CPU cores recommended for this image." + } + }, + "maxRecommendedvCPUs": { + "type": "int", + "defaultValue": 4, + "minValue": 1, + "maxValue": 128, + "metadata": { + "description": "Optional. The maximum number of the CPU cores recommended for this image." + } + }, + "minRecommendedMemory": { + "type": "int", + "defaultValue": 4, + "minValue": 1, + "maxValue": 4000, + "metadata": { + "description": "Optional. The minimum amount of RAM in GB recommended for this image." + } + }, + "maxRecommendedMemory": { + "type": "int", + "defaultValue": 16, + "minValue": 1, + "maxValue": 4000, + "metadata": { + "description": "Optional. The maximum amount of RAM in GB recommended for this image." + } + }, + "hyperVGeneration": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "V1", + "V2" + ], + "metadata": { + "description": "Optional. The hypervisor generation of the Virtual Machine.

- If this value is not specified, then it is determined by the securityType parameter.

- If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1." + } + }, + "securityType": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Standard", + "TrustedLaunch", + "ConfidentialVM", + "ConfidentialVMSupported" + ], + "metadata": { + "description": "Optional. The security type of the image. Requires a hyperVGeneration V2." + } + }, + "isHibernateSupported": { + "type": "string", + "defaultValue": "false", + "allowedValues": [ + "true", + "false" + ], + "metadata": { + "description": "Optional. The image will support hibernation." + } + }, + "isAcceleratedNetworkSupported": { + "type": "string", + "defaultValue": "false", + "allowedValues": [ + "true", + "false" + ], + "metadata": { + "description": "Optional. The image supports accelerated networking.

Accelerated networking enables single root I/O virtualization (SR-IOV) to a VM, greatly improving its networking performance.

This high-performance path bypasses the host from the data path, which reduces latency, jitter, and CPU utilization for the most demanding network workloads on supported VM types." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of this gallery Image Definition resource. This property is updatable." + } + }, + "eula": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Eula agreement for the gallery Image Definition. Has to be a valid URL." + } + }, + "privacyStatementUri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The privacy statement uri. Has to be a valid URL." + } + }, + "releaseNoteUri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The release note uri. Has to be a valid URL." + } + }, + "productName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The product ID." + } + }, + "planName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The plan ID." + } + }, + "planPublisherName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The publisher ID." + } + }, + "endOfLife": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z." + } + }, + "excludedDiskTypes": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. List of the excluded disk types. E.g. Standard_LRS." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all resources." + } + } + }, + "variables": { + "builtInRoleNames": { + "Compute Gallery Sharing Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "gallery": { + "existing": true, + "type": "Microsoft.Compute/galleries", + "apiVersion": "2022-03-03", + "name": "[parameters('galleryName')]" + }, + "image": { + "type": "Microsoft.Compute/galleries/images", + "apiVersion": "2022-03-03", + "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "osType": "[parameters('osType')]", + "osState": "[parameters('osState')]", + "identifier": { + "publisher": "[parameters('publisher')]", + "offer": "[parameters('offer')]", + "sku": "[parameters('sku')]" + }, + "recommended": { + "vCPUs": { + "min": "[parameters('minRecommendedvCPUs')]", + "max": "[parameters('maxRecommendedvCPUs')]" + }, + "memory": { + "min": "[parameters('minRecommendedMemory')]", + "max": "[parameters('maxRecommendedMemory')]" + } + }, + "hyperVGeneration": "[if(not(empty(parameters('hyperVGeneration'))), parameters('hyperVGeneration'), if(not(empty(parameters('securityType'))), 'V2', 'V1'))]", + "features": "[if(and(not(empty(parameters('securityType'))), not(equals(parameters('securityType'), 'Standard'))), createArray(createObject('name', 'SecurityType', 'value', parameters('securityType')), createObject('name', 'IsAcceleratedNetworkSupported', 'value', parameters('isAcceleratedNetworkSupported')), createObject('name', 'IsHibernateSupported', 'value', parameters('isHibernateSupported'))), createArray(createObject('name', 'IsAcceleratedNetworkSupported', 'value', parameters('isAcceleratedNetworkSupported')), createObject('name', 'IsHibernateSupported', 'value', parameters('isHibernateSupported'))))]", + "description": "[coalesce(parameters('description'), '')]", + "eula": "[coalesce(parameters('eula'), '')]", + "privacyStatementUri": "[coalesce(parameters('privacyStatementUri'), '')]", + "releaseNoteUri": "[coalesce(parameters('releaseNoteUri'), '')]", + "purchasePlan": { + "product": "[parameters('productName')]", + "name": "[parameters('planName')]", + "publisher": "[parameters('planPublisherName')]" + }, + "endOfLifeDate": "[coalesce(parameters('endOfLife'), '')]", + "disallowed": { + "diskTypes": "[coalesce(parameters('excludedDiskTypes'), createArray())]" + } + }, + "dependsOn": [ + "gallery" + ] + }, + "image_roleAssignments": { + "copy": { + "name": "image_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Compute/galleries/{0}/images/{1}', parameters('galleryName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "image" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the image was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the image." + }, + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the image." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('image', '2022-03-03', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/compute/gallery/main.bicep b/avm/res/compute/gallery/main.bicep new file mode 100644 index 0000000000..859c74be5a --- /dev/null +++ b/avm/res/compute/gallery/main.bicep @@ -0,0 +1,191 @@ +metadata name = 'Azure Compute Galleries' +metadata description = 'This module deploys an Azure Compute Gallery (formerly known as Shared Image Gallery).' +metadata owner = 'Azure/module-maintainers' + +@minLength(1) +@sys.description('Required. Name of the Azure Compute Gallery.') +param name string + +@sys.description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@sys.description('Optional. Description of the Azure Shared Image Gallery.') +param description string? + +@sys.description('Optional. Applications to create.') +param applications array? + +@sys.description('Optional. Images to create.') +param images array? + +@sys.description('Optional. The lock settings of the service.') +param lock lockType + +@sys.description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') +param roleAssignments roleAssignmentType + +@sys.description('Optional. Tags for all resources.') +param tags object? + +@sys.description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +var builtInRoleNames = { + 'Compute Gallery Sharing Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b') + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.compute-gallery.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +resource gallery 'Microsoft.Compute/galleries@2022-03-03' = { + name: name + location: location + tags: tags + properties: { + description: description ?? '' + identifier: {} + } +} + +resource gallery_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { + name: lock.?name ?? 'lock-${name}' + properties: { + level: lock.?kind ?? '' + notes: lock.?kind == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot delete or modify the resource or child resources.' + } + scope: gallery +} + +resource gallery_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(gallery.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: gallery +}] + +// Applications +module galleries_applications 'application/main.bicep' = [for (application, index) in (applications ?? []): { + name: '${uniqueString(deployment().name, location)}-Gallery-Application-${index}' + params: { + name: application.name + location: location + galleryName: gallery.name + supportedOSType: application.?supportedOSType + description: application.?description + eula: application.?eula + privacyStatementUri: application.?privacyStatementUri + releaseNoteUri: application.?releaseNoteUri + endOfLifeDate: application.?endOfLifeDate + roleAssignments: application.?roleAssignments + customActions: application.?customActions + tags: application.?tags ?? tags + } +}] + +// Images +module galleries_images 'image/main.bicep' = [for (image, index) in (images ?? []): { + name: '${uniqueString(deployment().name, location)}-Gallery-Image-${index}' + params: { + name: image.name + location: location + galleryName: gallery.name + osType: image.?osType + osState: image.?osState + publisher: image.?publisher + offer: image.?offer + sku: image.?sku + minRecommendedvCPUs: image.?minRecommendedvCPUs + maxRecommendedvCPUs: image.?maxRecommendedvCPUs + minRecommendedMemory: image.?minRecommendedMemory + maxRecommendedMemory: image.?maxRecommendedMemory + hyperVGeneration: image.?hyperVGeneration ?? 'V1' + securityType: image.?securityType + isAcceleratedNetworkSupported: image.?isAcceleratedNetworkSupported + isHibernateSupported: image.?isHibernateSupported + description: image.?description + eula: image.?eula + privacyStatementUri: image.?privacyStatementUri + releaseNoteUri: image.?releaseNoteUri + productName: image.?productName + planName: image.?planName + planPublisherName: image.?planPublisherName + endOfLife: image.?endOfLife + excludedDiskTypes: image.?excludedDiskTypes + roleAssignments: image.?roleAssignments + tags: image.?tags ?? tags + } +}] + +@sys.description('The resource ID of the deployed image gallery.') +output resourceId string = gallery.id + +@sys.description('The resource group of the deployed image gallery.') +output resourceGroupName string = resourceGroup().name + +@sys.description('The name of the deployed image gallery.') +output name string = gallery.name + +@sys.description('The location the resource was deployed into.') +output location string = gallery.location + +// =============== // +// Definitions // +// =============== // + +type lockType = { + @sys.description('Optional. Specify the name of lock.') + name: string? + + @sys.description('Optional. Specify the type of lock.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None')? +}? + +type roleAssignmentType = { + @sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead.') + roleDefinitionIdOrName: string + + @sys.description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @sys.description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @sys.description('Optional. The description of the role assignment.') + description: string? + + @sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"') + condition: string? + + @sys.description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @sys.description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? diff --git a/avm/res/compute/gallery/main.json b/avm/res/compute/gallery/main.json new file mode 100644 index 0000000000..cf2d300f21 --- /dev/null +++ b/avm/res/compute/gallery/main.json @@ -0,0 +1,1118 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "1407952023924481969" + }, + "name": "Azure Compute Galleries", + "description": "This module deploys an Azure Compute Gallery (formerly known as Shared Image Gallery).", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Azure Compute Gallery." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description of the Azure Shared Image Gallery." + } + }, + "applications": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Applications to create." + } + }, + "images": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Images to create." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all resources." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "builtInRoleNames": { + "Compute Gallery Sharing Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.compute-gallery.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "gallery": { + "type": "Microsoft.Compute/galleries", + "apiVersion": "2022-03-03", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "description": "[coalesce(parameters('description'), '')]", + "identifier": {} + } + }, + "gallery_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Compute/galleries/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "gallery" + ] + }, + "gallery_roleAssignments": { + "copy": { + "name": "gallery_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Compute/galleries/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Compute/galleries', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "gallery" + ] + }, + "galleries_applications": { + "copy": { + "name": "galleries_applications", + "count": "[length(coalesce(parameters('applications'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Gallery-Application-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('applications'), createArray())[copyIndex()].name]" + }, + "location": { + "value": "[parameters('location')]" + }, + "galleryName": { + "value": "[parameters('name')]" + }, + "supportedOSType": { + "value": "[tryGet(coalesce(parameters('applications'), createArray())[copyIndex()], 'supportedOSType')]" + }, + "description": { + "value": "[tryGet(coalesce(parameters('applications'), createArray())[copyIndex()], 'description')]" + }, + "eula": { + "value": "[tryGet(coalesce(parameters('applications'), createArray())[copyIndex()], 'eula')]" + }, + "privacyStatementUri": { + "value": "[tryGet(coalesce(parameters('applications'), createArray())[copyIndex()], 'privacyStatementUri')]" + }, + "releaseNoteUri": { + "value": "[tryGet(coalesce(parameters('applications'), createArray())[copyIndex()], 'releaseNoteUri')]" + }, + "endOfLifeDate": { + "value": "[tryGet(coalesce(parameters('applications'), createArray())[copyIndex()], 'endOfLifeDate')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('applications'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "customActions": { + "value": "[tryGet(coalesce(parameters('applications'), createArray())[copyIndex()], 'customActions')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('applications'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "9406373999607697824" + }, + "name": "Compute Galleries Applications", + "description": "This module deploys an Azure Compute Gallery Application.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the application definition." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Conditional. The name of the parent Azure Compute Gallery. Required if the template is used in a standalone deployment." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of this gallery Application Definition resource. This property is updatable." + } + }, + "eula": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Eula agreement for the gallery Application Definition. Has to be a valid URL." + } + }, + "privacyStatementUri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The privacy statement uri. Has to be a valid URL." + } + }, + "releaseNoteUri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The release note uri. Has to be a valid URL." + } + }, + "supportedOSType": { + "type": "string", + "defaultValue": "Windows", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Optional. This property allows you to specify the supported type of the OS that application is built for." + } + }, + "endOfLifeDate": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all resources." + } + }, + "customActions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of custom actions that can be performed with all of the Gallery Application Versions within this Gallery Application." + } + } + }, + "variables": { + "builtInRoleNames": { + "Compute Gallery Sharing Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "gallery": { + "existing": true, + "type": "Microsoft.Compute/galleries", + "apiVersion": "2022-03-03", + "name": "[parameters('galleryName')]" + }, + "application": { + "type": "Microsoft.Compute/galleries/applications", + "apiVersion": "2022-03-03", + "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "customActions": "[parameters('customActions')]", + "description": "[coalesce(parameters('description'), '')]", + "endOfLifeDate": "[coalesce(parameters('endOfLifeDate'), '')]", + "eula": "[coalesce(parameters('eula'), '')]", + "privacyStatementUri": "[coalesce(parameters('privacyStatementUri'), '')]", + "releaseNoteUri": "[coalesce(parameters('releaseNoteUri'), '')]", + "supportedOSType": "[parameters('supportedOSType')]" + }, + "dependsOn": [ + "gallery" + ] + }, + "application_roleAssignments": { + "copy": { + "name": "application_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Compute/galleries/{0}/applications/{1}', parameters('galleryName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Compute/galleries/applications', parameters('galleryName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "application" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the image was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the image." + }, + "value": "[resourceId('Microsoft.Compute/galleries/applications', parameters('galleryName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the image." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('application', '2022-03-03', 'full').location]" + } + } + } + }, + "dependsOn": [ + "gallery" + ] + }, + "galleries_images": { + "copy": { + "name": "galleries_images", + "count": "[length(coalesce(parameters('images'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Gallery-Image-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('images'), createArray())[copyIndex()].name]" + }, + "location": { + "value": "[parameters('location')]" + }, + "galleryName": { + "value": "[parameters('name')]" + }, + "osType": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'osType')]" + }, + "osState": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'osState')]" + }, + "publisher": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'publisher')]" + }, + "offer": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'offer')]" + }, + "sku": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'sku')]" + }, + "minRecommendedvCPUs": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'minRecommendedvCPUs')]" + }, + "maxRecommendedvCPUs": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'maxRecommendedvCPUs')]" + }, + "minRecommendedMemory": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'minRecommendedMemory')]" + }, + "maxRecommendedMemory": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'maxRecommendedMemory')]" + }, + "hyperVGeneration": { + "value": "[coalesce(tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'hyperVGeneration'), 'V1')]" + }, + "securityType": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'securityType')]" + }, + "isAcceleratedNetworkSupported": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'isAcceleratedNetworkSupported')]" + }, + "isHibernateSupported": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'isHibernateSupported')]" + }, + "description": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'description')]" + }, + "eula": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'eula')]" + }, + "privacyStatementUri": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'privacyStatementUri')]" + }, + "releaseNoteUri": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'releaseNoteUri')]" + }, + "productName": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'productName')]" + }, + "planName": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'planName')]" + }, + "planPublisherName": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'planPublisherName')]" + }, + "endOfLife": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'endOfLife')]" + }, + "excludedDiskTypes": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'excludedDiskTypes')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "14441578962181885339" + }, + "name": "Compute Galleries Image Definitions", + "description": "This module deploys an Azure Compute Gallery Image Definition.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the image definition." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "galleryName": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Conditional. The name of the parent Azure Shared Image Gallery. Required if the template is used in a standalone deployment." + } + }, + "osType": { + "type": "string", + "defaultValue": "Linux", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Optional. OS type of the image to be created." + } + }, + "osState": { + "type": "string", + "defaultValue": "Generalized", + "allowedValues": [ + "Generalized", + "Specialized" + ], + "metadata": { + "description": "Optional. This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'." + } + }, + "publisher": { + "type": "string", + "defaultValue": "canonical", + "metadata": { + "description": "Optional. The name of the gallery Image Definition publisher." + } + }, + "offer": { + "type": "string", + "defaultValue": "0001-com-ubuntu-server-jammy", + "metadata": { + "description": "Optional. The name of the gallery Image Definition offer." + } + }, + "sku": { + "type": "string", + "defaultValue": "22_04-lts-gen2", + "metadata": { + "description": "Optional. The name of the gallery Image Definition SKU." + } + }, + "minRecommendedvCPUs": { + "type": "int", + "defaultValue": 1, + "minValue": 1, + "maxValue": 128, + "metadata": { + "description": "Optional. The minimum number of the CPU cores recommended for this image." + } + }, + "maxRecommendedvCPUs": { + "type": "int", + "defaultValue": 4, + "minValue": 1, + "maxValue": 128, + "metadata": { + "description": "Optional. The maximum number of the CPU cores recommended for this image." + } + }, + "minRecommendedMemory": { + "type": "int", + "defaultValue": 4, + "minValue": 1, + "maxValue": 4000, + "metadata": { + "description": "Optional. The minimum amount of RAM in GB recommended for this image." + } + }, + "maxRecommendedMemory": { + "type": "int", + "defaultValue": 16, + "minValue": 1, + "maxValue": 4000, + "metadata": { + "description": "Optional. The maximum amount of RAM in GB recommended for this image." + } + }, + "hyperVGeneration": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "V1", + "V2" + ], + "metadata": { + "description": "Optional. The hypervisor generation of the Virtual Machine.

- If this value is not specified, then it is determined by the securityType parameter.

- If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1." + } + }, + "securityType": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Standard", + "TrustedLaunch", + "ConfidentialVM", + "ConfidentialVMSupported" + ], + "metadata": { + "description": "Optional. The security type of the image. Requires a hyperVGeneration V2." + } + }, + "isHibernateSupported": { + "type": "string", + "defaultValue": "false", + "allowedValues": [ + "true", + "false" + ], + "metadata": { + "description": "Optional. The image will support hibernation." + } + }, + "isAcceleratedNetworkSupported": { + "type": "string", + "defaultValue": "false", + "allowedValues": [ + "true", + "false" + ], + "metadata": { + "description": "Optional. The image supports accelerated networking.

Accelerated networking enables single root I/O virtualization (SR-IOV) to a VM, greatly improving its networking performance.

This high-performance path bypasses the host from the data path, which reduces latency, jitter, and CPU utilization for the most demanding network workloads on supported VM types." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of this gallery Image Definition resource. This property is updatable." + } + }, + "eula": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Eula agreement for the gallery Image Definition. Has to be a valid URL." + } + }, + "privacyStatementUri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The privacy statement uri. Has to be a valid URL." + } + }, + "releaseNoteUri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The release note uri. Has to be a valid URL." + } + }, + "productName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The product ID." + } + }, + "planName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The plan ID." + } + }, + "planPublisherName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The publisher ID." + } + }, + "endOfLife": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z." + } + }, + "excludedDiskTypes": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. List of the excluded disk types. E.g. Standard_LRS." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all resources." + } + } + }, + "variables": { + "builtInRoleNames": { + "Compute Gallery Sharing Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "gallery": { + "existing": true, + "type": "Microsoft.Compute/galleries", + "apiVersion": "2022-03-03", + "name": "[parameters('galleryName')]" + }, + "image": { + "type": "Microsoft.Compute/galleries/images", + "apiVersion": "2022-03-03", + "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "osType": "[parameters('osType')]", + "osState": "[parameters('osState')]", + "identifier": { + "publisher": "[parameters('publisher')]", + "offer": "[parameters('offer')]", + "sku": "[parameters('sku')]" + }, + "recommended": { + "vCPUs": { + "min": "[parameters('minRecommendedvCPUs')]", + "max": "[parameters('maxRecommendedvCPUs')]" + }, + "memory": { + "min": "[parameters('minRecommendedMemory')]", + "max": "[parameters('maxRecommendedMemory')]" + } + }, + "hyperVGeneration": "[if(not(empty(parameters('hyperVGeneration'))), parameters('hyperVGeneration'), if(not(empty(parameters('securityType'))), 'V2', 'V1'))]", + "features": "[if(and(not(empty(parameters('securityType'))), not(equals(parameters('securityType'), 'Standard'))), createArray(createObject('name', 'SecurityType', 'value', parameters('securityType')), createObject('name', 'IsAcceleratedNetworkSupported', 'value', parameters('isAcceleratedNetworkSupported')), createObject('name', 'IsHibernateSupported', 'value', parameters('isHibernateSupported'))), createArray(createObject('name', 'IsAcceleratedNetworkSupported', 'value', parameters('isAcceleratedNetworkSupported')), createObject('name', 'IsHibernateSupported', 'value', parameters('isHibernateSupported'))))]", + "description": "[coalesce(parameters('description'), '')]", + "eula": "[coalesce(parameters('eula'), '')]", + "privacyStatementUri": "[coalesce(parameters('privacyStatementUri'), '')]", + "releaseNoteUri": "[coalesce(parameters('releaseNoteUri'), '')]", + "purchasePlan": { + "product": "[parameters('productName')]", + "name": "[parameters('planName')]", + "publisher": "[parameters('planPublisherName')]" + }, + "endOfLifeDate": "[coalesce(parameters('endOfLife'), '')]", + "disallowed": { + "diskTypes": "[coalesce(parameters('excludedDiskTypes'), createArray())]" + } + }, + "dependsOn": [ + "gallery" + ] + }, + "image_roleAssignments": { + "copy": { + "name": "image_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Compute/galleries/{0}/images/{1}', parameters('galleryName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "image" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the image was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the image." + }, + "value": "[resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the image." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('image', '2022-03-03', 'full').location]" + } + } + } + }, + "dependsOn": [ + "gallery" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed image gallery." + }, + "value": "[resourceId('Microsoft.Compute/galleries', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed image gallery." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed image gallery." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('gallery', '2022-03-03', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/compute/gallery/tests/e2e/defaults/main.test.bicep b/avm/res/compute/gallery/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..756e5b1b97 --- /dev/null +++ b/avm/res/compute/gallery/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,46 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.galleries-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'cgmin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: location + } +}] diff --git a/avm/res/compute/gallery/tests/e2e/max/dependencies.bicep b/avm/res/compute/gallery/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..a7f42aee7b --- /dev/null +++ b/avm/res/compute/gallery/tests/e2e/max/dependencies.bicep @@ -0,0 +1,13 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/compute/gallery/tests/e2e/max/main.test.bicep b/avm/res/compute/gallery/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..89d7c2931a --- /dev/null +++ b/avm/res/compute/gallery/tests/e2e/max/main.test.bicep @@ -0,0 +1,198 @@ +targetScope = 'subscription' + +metadata name = 'Using large parameter set' +metadata description = 'This instance deploys the module with most of its features enabled.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.galleries-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'cgmax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: location + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + applications: [ + { + name: '${namePrefix}-${serviceShort}-appd-001' + } + { + name: '${namePrefix}-${serviceShort}-appd-002' + supportedOSType: 'Windows' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + } + ] + images: [ + { + name: '${namePrefix}-az-imgd-ws-001' + } + { + hyperVGeneration: 'V1' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: '${namePrefix}-az-imgd-ws-002' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + sku: '2022-datacenter-azure-edition' + } + { + hyperVGeneration: 'V2' + isHibernateSupported: 'true' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: '${namePrefix}-az-imgd-ws-003' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + sku: '2022-datacenter-azure-edition-hibernate' + } + { + hyperVGeneration: 'V2' + isAcceleratedNetworkSupported: 'true' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: '${namePrefix}-az-imgd-ws-004' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + sku: '2022-datacenter-azure-edition-accnet' + } + { + hyperVGeneration: 'V2' + securityType: 'TrustedLaunch' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 4 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: '${namePrefix}-az-imgd-wdtl-002' + offer: 'WindowsDesktop' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsDesktop' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + sku: 'Win11-21H2' + } + { + hyperVGeneration: 'V2' + maxRecommendedMemory: 32 + maxRecommendedvCPUs: 4 + minRecommendedMemory: 4 + minRecommendedvCPUs: 1 + name: '${namePrefix}-az-imgd-us-001' + offer: '0001-com-ubuntu-server-focal' + osState: 'Generalized' + osType: 'Linux' + publisher: 'canonical' + sku: '20_04-lts-gen2' + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/compute/gallery/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/gallery/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..32cd165e60 --- /dev/null +++ b/avm/res/compute/gallery/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,137 @@ +targetScope = 'subscription' + +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.galleries-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'cgwaf' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: location + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + applications: [ + { + name: '${namePrefix}-${serviceShort}-appd-001' + } + { + name: '${namePrefix}-${serviceShort}-appd-002' + supportedOSType: 'Windows' + } + ] + images: [ + { + name: '${namePrefix}-az-imgd-ws-001' + } + { + hyperVGeneration: 'V1' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: '${namePrefix}-az-imgd-ws-002' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition' + } + { + hyperVGeneration: 'V2' + isHibernateSupported: 'true' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: '${namePrefix}-az-imgd-ws-003' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition-hibernate' + } + { + hyperVGeneration: 'V2' + isAcceleratedNetworkSupported: 'true' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 8 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: '${namePrefix}-az-imgd-ws-004' + offer: 'WindowsServer' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition-accnet' + } + { + hyperVGeneration: 'V2' + securityType: 'TrustedLaunch' + maxRecommendedMemory: 16 + maxRecommendedvCPUs: 4 + minRecommendedMemory: 4 + minRecommendedvCPUs: 2 + name: '${namePrefix}-az-imgd-wdtl-002' + offer: 'WindowsDesktop' + osState: 'Generalized' + osType: 'Windows' + publisher: 'MicrosoftWindowsDesktop' + sku: 'Win11-21H2' + } + { + hyperVGeneration: 'V2' + maxRecommendedMemory: 32 + maxRecommendedvCPUs: 4 + minRecommendedMemory: 4 + minRecommendedvCPUs: 1 + name: '${namePrefix}-az-imgd-us-001' + offer: '0001-com-ubuntu-server-focal' + osState: 'Generalized' + osType: 'Linux' + publisher: 'canonical' + sku: '20_04-lts-gen2' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/compute/gallery/version.json b/avm/res/compute/gallery/version.json new file mode 100644 index 0000000000..83083db694 --- /dev/null +++ b/avm/res/compute/gallery/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} \ No newline at end of file