From 3f333323a5802722337c2efc09cbdfa583c3eff3 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 12 Jan 2024 15:43:23 +1000 Subject: [PATCH 01/13] feat: `avm/res/compute/disk` --- .github/workflows/avm.res.compute.disk.yml | 83 ++ avm/res/compute/disk/README.md | 998 ++++++++++++++++++ avm/res/compute/disk/main.bicep | 270 +++++ avm/res/compute/disk/main.json | 482 +++++++++ .../disk/tests/e2e/defaults/main.test.bicep | 47 + .../disk/tests/e2e/image/dependencies.bicep | 13 + .../disk/tests/e2e/image/main.test.bicep | 79 ++ .../disk/tests/e2e/import/dependencies.bicep | 152 +++ .../tests/e2e/import/dependencies_rbac.bicep | 16 + .../disk/tests/e2e/import/main.test.bicep | 84 ++ .../disk/tests/e2e/max/dependencies.bicep | 13 + .../disk/tests/e2e/max/main.test.bicep | 87 ++ .../tests/e2e/waf-aligned/main.test.bicep | 61 ++ avm/res/compute/disk/version.json | 7 + 14 files changed, 2392 insertions(+) create mode 100644 .github/workflows/avm.res.compute.disk.yml create mode 100644 avm/res/compute/disk/README.md create mode 100644 avm/res/compute/disk/main.bicep create mode 100644 avm/res/compute/disk/main.json create mode 100644 avm/res/compute/disk/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/compute/disk/tests/e2e/image/dependencies.bicep create mode 100644 avm/res/compute/disk/tests/e2e/image/main.test.bicep create mode 100644 avm/res/compute/disk/tests/e2e/import/dependencies.bicep create mode 100644 avm/res/compute/disk/tests/e2e/import/dependencies_rbac.bicep create mode 100644 avm/res/compute/disk/tests/e2e/import/main.test.bicep create mode 100644 avm/res/compute/disk/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/compute/disk/tests/e2e/max/main.test.bicep create mode 100644 avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/compute/disk/version.json diff --git a/.github/workflows/avm.res.compute.disk.yml b/.github/workflows/avm.res.compute.disk.yml new file mode 100644 index 0000000000..719f7dbbb8 --- /dev/null +++ b/.github/workflows/avm.res.compute.disk.yml @@ -0,0 +1,83 @@ +name: "avm.res.compute.disk" + +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.disk.yml" + - "avm/res/compute/disk/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/network/network-security-group" + workflowPath: ".github/workflows/avm.res.compute.disk.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/disk/README.md b/avm/res/compute/disk/README.md new file mode 100644 index 0000000000..c8c16ea0f6 --- /dev/null +++ b/avm/res/compute/disk/README.md @@ -0,0 +1,998 @@ +# Compute Disks `[Microsoft.Compute/disks]` + +This module deploys a Compute Disk + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## 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/disks` | [2022-07-02](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-07-02/disks) | + +## 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/disk:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using an image](#example-2-using-an-image) +- [Import](#example-3-import) +- [Using large parameter set](#example-4-using-large-parameter-set) +- [WAF-aligned](#example-5-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep +module disk 'br/public:avm/res/compute/disk:' = { + name: '${uniqueString(deployment().name, location)}-test-cdmin' + params: { + // Required parameters + name: 'cdmin001' + sku: 'Standard_LRS' + // Non-required parameters + diskSizeGB: 1 + 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": "cdmin001" + }, + "sku": { + "value": "Standard_LRS" + }, + // Non-required parameters + "diskSizeGB": { + "value": 1 + }, + "location": { + "value": "" + } + } +} +``` + +
+

+ +### Example 2: _Using an image_ + +This instance deploys the module with an image reference. + + +

+ +via Bicep module + +```bicep +module disk 'br/public:avm/res/compute/disk:' = { + name: '${uniqueString(deployment().name, location)}-test-cdimg' + params: { + // Required parameters + name: 'cdimg001' + sku: 'Standard_LRS' + // Non-required parameters + createOption: 'FromImage' + imageReferenceId: '' + location: '' + 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": "cdimg001" + }, + "sku": { + "value": "Standard_LRS" + }, + // Non-required parameters + "createOption": { + "value": "FromImage" + }, + "imageReferenceId": { + "value": "" + }, + "location": { + "value": "" + }, + "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: _Import_ + +

+ +via Bicep module + +```bicep +module disk 'br/public:avm/res/compute/disk:' = { + name: '${uniqueString(deployment().name, location)}-test-cdimp' + params: { + // Required parameters + name: 'cdimp001' + sku: 'Standard_LRS' + // Non-required parameters + createOption: 'Import' + location: '' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + sourceUri: '' + storageAccountId: '' + 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": "cdimp001" + }, + "sku": { + "value": "Standard_LRS" + }, + // Non-required parameters + "createOption": { + "value": "Import" + }, + "location": { + "value": "" + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "sourceUri": { + "value": "" + }, + "storageAccountId": { + "value": "" + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module disk 'br/public:avm/res/compute/disk:' = { + name: '${uniqueString(deployment().name, location)}-test-cdmax' + params: { + // Required parameters + name: 'cdmax001' + sku: 'UltraSSD_LRS' + // Non-required parameters + diskIOPSReadWrite: 500 + diskMBpsReadWrite: 60 + diskSizeGB: 128 + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + logicalSectorSize: 512 + osType: 'Windows' + publicNetworkAccess: 'Enabled' + 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": "cdmax001" + }, + "sku": { + "value": "UltraSSD_LRS" + }, + // Non-required parameters + "diskIOPSReadWrite": { + "value": 500 + }, + "diskMBpsReadWrite": { + "value": 60 + }, + "diskSizeGB": { + "value": 128 + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "logicalSectorSize": { + "value": 512 + }, + "osType": { + "value": "Windows" + }, + "publicNetworkAccess": { + "value": "Enabled" + }, + "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 5: _WAF-aligned_ + +This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. + + +

+ +via Bicep module + +```bicep +module disk 'br/public:avm/res/compute/disk:' = { + name: '${uniqueString(deployment().name, location)}-test-cdwaf' + params: { + // Required parameters + name: 'cdwaf001' + sku: 'UltraSSD_LRS' + // Non-required parameters + diskIOPSReadWrite: 500 + diskMBpsReadWrite: 60 + diskSizeGB: 128 + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + logicalSectorSize: 512 + osType: 'Windows' + publicNetworkAccess: 'Enabled' + 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": "cdwaf001" + }, + "sku": { + "value": "UltraSSD_LRS" + }, + // Non-required parameters + "diskIOPSReadWrite": { + "value": 500 + }, + "diskMBpsReadWrite": { + "value": 60 + }, + "diskSizeGB": { + "value": 128 + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "logicalSectorSize": { + "value": 512 + }, + "osType": { + "value": "Windows" + }, + "publicNetworkAccess": { + "value": "Enabled" + }, + "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 | The name of the disk that is being created. | +| [`sku`](#parameter-sku) | string | The disks sku name. Can be . | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`diskSizeGB`](#parameter-disksizegb) | int | The size of the disk to create. Required if create option is Empty. | +| [`storageAccountId`](#parameter-storageaccountid) | string | The resource ID of the storage account containing the blob to import as a disk. Required if create option is Import. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`acceleratedNetwork`](#parameter-acceleratednetwork) | bool | True if the image from which the OS disk is created supports accelerated networking. | +| [`architecture`](#parameter-architecture) | string | CPU architecture supported by an OS disk. | +| [`burstingEnabled`](#parameter-burstingenabled) | bool | Set to true to enable bursting beyond the provisioned performance target of the disk. | +| [`completionPercent`](#parameter-completionpercent) | int | Percentage complete for the background copy when a resource is created via the CopyStart operation. | +| [`createOption`](#parameter-createoption) | string | Sources of a disk creation. | +| [`diskIOPSReadWrite`](#parameter-diskiopsreadwrite) | int | The number of IOPS allowed for this disk; only settable for UltraSSD disks. | +| [`diskMBpsReadWrite`](#parameter-diskmbpsreadwrite) | int | The bandwidth allowed for this disk; only settable for UltraSSD disks. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`hyperVGeneration`](#parameter-hypervgeneration) | string | The hypervisor generation of the Virtual Machine. Applicable to OS disks only. | +| [`imageReferenceId`](#parameter-imagereferenceid) | string | A relative uri containing either a Platform Image Repository or user image reference. | +| [`location`](#parameter-location) | string | Resource location. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`logicalSectorSize`](#parameter-logicalsectorsize) | int | Logical sector size in bytes for Ultra disks. Supported values are 512 ad 4096. | +| [`maxShares`](#parameter-maxshares) | int | The maximum number of VMs that can attach to the disk at the same time. Default value is 0. | +| [`networkAccessPolicy`](#parameter-networkaccesspolicy) | string | Policy for accessing the disk via network. | +| [`optimizedForFrequentAttach`](#parameter-optimizedforfrequentattach) | bool | Setting this property to true improves reliability and performance of data disks that are frequently (more than 5 times a day) by detached from one virtual machine and attached to another. This property should not be set for disks that are not detached and attached frequently as it causes the disks to not align with the fault domain of the virtual machine. | +| [`osType`](#parameter-ostype) | string | Sources of a disk creation. | +| [`publicNetworkAccess`](#parameter-publicnetworkaccess) | string | Policy for controlling export on the disk. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`securityDataUri`](#parameter-securitydatauri) | string | If create option is ImportSecure, this is the URI of a blob to be imported into VM guest state. | +| [`sourceResourceId`](#parameter-sourceresourceid) | string | If create option is Copy, this is the ARM ID of the source snapshot or disk. | +| [`sourceUri`](#parameter-sourceuri) | string | If create option is Import, this is the URI of a blob to be imported into a managed disk. | +| [`tags`](#parameter-tags) | object | Tags of the availability set resource. | +| [`uploadSizeBytes`](#parameter-uploadsizebytes) | int | If create option is Upload, this is the size of the contents of the upload including the VHD footer. | + +### Parameter: `name` + +The name of the disk that is being created. + +- Required: Yes +- Type: string + +### Parameter: `sku` + +The disks sku name. Can be . + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Premium_LRS' + 'Premium_ZRS' + 'Premium_ZRS' + 'PremiumV2_LRS' + 'Standard_LRS' + 'StandardSSD_LRS' + 'UltraSSD_LRS' + ] + ``` + +### Parameter: `diskSizeGB` + +The size of the disk to create. Required if create option is Empty. + +- Required: No +- Type: int +- Default: `0` + +### Parameter: `storageAccountId` + +The resource ID of the storage account containing the blob to import as a disk. Required if create option is Import. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `acceleratedNetwork` + +True if the image from which the OS disk is created supports accelerated networking. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `architecture` + +CPU architecture supported by an OS disk. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + 'Arm64' + 'x64' + ] + ``` + +### Parameter: `burstingEnabled` + +Set to true to enable bursting beyond the provisioned performance target of the disk. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `completionPercent` + +Percentage complete for the background copy when a resource is created via the CopyStart operation. + +- Required: No +- Type: int +- Default: `100` + +### Parameter: `createOption` + +Sources of a disk creation. + +- Required: No +- Type: string +- Default: `'Empty'` +- Allowed: + ```Bicep + [ + 'Attach' + 'Copy' + 'CopyStart' + 'Empty' + 'FromImage' + 'Import' + 'ImportSecure' + 'Restore' + 'Upload' + 'UploadPreparedSecure' + ] + ``` + +### Parameter: `diskIOPSReadWrite` + +The number of IOPS allowed for this disk; only settable for UltraSSD disks. + +- Required: No +- Type: int +- Default: `0` + +### Parameter: `diskMBpsReadWrite` + +The bandwidth allowed for this disk; only settable for UltraSSD disks. + +- Required: No +- Type: int +- Default: `0` + +### Parameter: `enableTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `hyperVGeneration` + +The hypervisor generation of the Virtual Machine. Applicable to OS disks only. + +- Required: No +- Type: string +- Default: `'V2'` +- Allowed: + ```Bicep + [ + 'V1' + 'V2' + ] + ``` + +### Parameter: `imageReferenceId` + +A relative uri containing either a Platform Image Repository or user image reference. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `location` + +Resource location. + +- 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: `logicalSectorSize` + +Logical sector size in bytes for Ultra disks. Supported values are 512 ad 4096. + +- Required: No +- Type: int +- Default: `4096` + +### Parameter: `maxShares` + +The maximum number of VMs that can attach to the disk at the same time. Default value is 0. + +- Required: No +- Type: int +- Default: `1` + +### Parameter: `networkAccessPolicy` + +Policy for accessing the disk via network. + +- Required: No +- Type: string +- Default: `'DenyAll'` +- Allowed: + ```Bicep + [ + 'AllowAll' + 'AllowPrivate' + 'DenyAll' + ] + ``` + +### Parameter: `optimizedForFrequentAttach` + +Setting this property to true improves reliability and performance of data disks that are frequently (more than 5 times a day) by detached from one virtual machine and attached to another. This property should not be set for disks that are not detached and attached frequently as it causes the disks to not align with the fault domain of the virtual machine. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `osType` + +Sources of a disk creation. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + 'Linux' + 'Windows' + ] + ``` + +### Parameter: `publicNetworkAccess` + +Policy for controlling export on the disk. + +- Required: No +- Type: string +- Default: `'Disabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- 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 role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | + +**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 role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- 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: `securityDataUri` + +If create option is ImportSecure, this is the URI of a blob to be imported into VM guest state. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `sourceResourceId` + +If create option is Copy, this is the ARM ID of the source snapshot or disk. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `sourceUri` + +If create option is Import, this is the URI of a blob to be imported into a managed disk. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `tags` + +Tags of the availability set resource. + +- Required: No +- Type: object + +### Parameter: `uploadSizeBytes` + +If create option is Upload, this is the size of the contents of the upload including the VHD footer. + +- Required: No +- Type: int +- Default: `20972032` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the disk. | +| `resourceGroupName` | string | The resource group the disk was deployed into. | +| `resourceId` | string | The resource ID of the disk. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/compute/disk/main.bicep b/avm/res/compute/disk/main.bicep new file mode 100644 index 0000000000..16630825ae --- /dev/null +++ b/avm/res/compute/disk/main.bicep @@ -0,0 +1,270 @@ +metadata name = 'Compute Disks' +metadata description = 'This module deploys a Compute Disk' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the disk that is being created.') +param name string + +@description('Optional. Resource location.') +param location string = resourceGroup().location + +@allowed([ + 'Standard_LRS' + 'Premium_LRS' + 'StandardSSD_LRS' + 'UltraSSD_LRS' + 'Premium_ZRS' + 'Premium_ZRS' + 'PremiumV2_LRS' +]) +@description('Required. The disks sku name. Can be .') +param sku string + +@allowed([ + 'x64' + 'Arm64' + '' +]) +@description('Optional. CPU architecture supported by an OS disk.') +param architecture string = '' + +@description('Optional. Set to true to enable bursting beyond the provisioned performance target of the disk.') +param burstingEnabled bool = false + +@description('Optional. Percentage complete for the background copy when a resource is created via the CopyStart operation.') +param completionPercent int = 100 + +@allowed([ + 'Attach' + 'Copy' + 'CopyStart' + 'Empty' + 'FromImage' + 'Import' + 'ImportSecure' + 'Restore' + 'Upload' + 'UploadPreparedSecure' +]) +@description('Optional. Sources of a disk creation.') +param createOption string = 'Empty' + +@description('Optional. A relative uri containing either a Platform Image Repository or user image reference.') +param imageReferenceId string = '' + +@description('Optional. Logical sector size in bytes for Ultra disks. Supported values are 512 ad 4096.') +param logicalSectorSize int = 4096 + +@description('Optional. If create option is ImportSecure, this is the URI of a blob to be imported into VM guest state.') +param securityDataUri string = '' + +@description('Optional. If create option is Copy, this is the ARM ID of the source snapshot or disk.') +param sourceResourceId string = '' + +@description('Optional. If create option is Import, this is the URI of a blob to be imported into a managed disk.') +param sourceUri string = '' + +@description('Conditional. The resource ID of the storage account containing the blob to import as a disk. Required if create option is Import.') +param storageAccountId string = '' + +@description('Optional. If create option is Upload, this is the size of the contents of the upload including the VHD footer.') +param uploadSizeBytes int = 20972032 + +@description('Conditional. The size of the disk to create. Required if create option is Empty.') +param diskSizeGB int = 0 + +@description('Optional. The number of IOPS allowed for this disk; only settable for UltraSSD disks.') +param diskIOPSReadWrite int = 0 + +@description('Optional. The bandwidth allowed for this disk; only settable for UltraSSD disks.') +param diskMBpsReadWrite int = 0 + +@allowed([ + 'V1' + 'V2' +]) +@description('Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only.') +param hyperVGeneration string = 'V2' + +@description('Optional. The maximum number of VMs that can attach to the disk at the same time. Default value is 0.') +param maxShares int = 1 + +@allowed([ + 'AllowAll' + 'AllowPrivate' + 'DenyAll' +]) +@description('Optional. Policy for accessing the disk via network.') +param networkAccessPolicy string = 'DenyAll' + +@description('Optional. Setting this property to true improves reliability and performance of data disks that are frequently (more than 5 times a day) by detached from one virtual machine and attached to another. This property should not be set for disks that are not detached and attached frequently as it causes the disks to not align with the fault domain of the virtual machine.') +param optimizedForFrequentAttach bool = false + +@allowed([ + 'Windows' + 'Linux' + '' +]) +@description('Optional. Sources of a disk creation.') +param osType string = '' + +@allowed([ + 'Disabled' + 'Enabled' +]) +@description('Optional. Policy for controlling export on the disk.') +param publicNetworkAccess string = 'Disabled' + +@description('Optional. True if the image from which the OS disk is created supports accelerated networking.') +param acceleratedNetwork bool = false + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Tags of the availability set resource.') +param tags object? + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableTelemetry bool = true + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Data Operator for Managed Disks': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '959f8984-c045-4866-89c7-12bf9737be2e') + 'Disk Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24') + 'Disk Pool Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840') + 'Disk Restore Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + 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-disk.${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 disk 'Microsoft.Compute/disks@2022-07-02' = { + name: name + location: location + tags: tags + sku: { + name: sku + } + properties: { + burstingEnabled: burstingEnabled + completionPercent: completionPercent + creationData: { + createOption: createOption + imageReference: createOption != 'FromImage' ? null : { + id: imageReferenceId + } + logicalSectorSize: contains(sku, 'Ultra') ? logicalSectorSize : null + securityDataUri: createOption == 'ImportSecure' ? securityDataUri : null + sourceResourceId: createOption == 'Copy' ? sourceResourceId : null + sourceUri: createOption == 'Import' ? sourceUri : null + storageAccountId: createOption == 'Import' ? storageAccountId : null + uploadSizeBytes: createOption == 'Upload' ? uploadSizeBytes : null + } + diskIOPSReadWrite: contains(sku, 'Ultra') ? diskIOPSReadWrite : null + diskMBpsReadWrite: contains(sku, 'Ultra') ? diskMBpsReadWrite : null + diskSizeGB: createOption == 'Empty' ? diskSizeGB : null + hyperVGeneration: empty(osType) ? null : hyperVGeneration + maxShares: maxShares + networkAccessPolicy: networkAccessPolicy + optimizedForFrequentAttach: optimizedForFrequentAttach + osType: empty(osType) ? any(null) : osType + publicNetworkAccess: publicNetworkAccess + supportedCapabilities: empty(osType) ? {} : { + acceleratedNetwork: acceleratedNetwork + architecture: empty(architecture) ? null : architecture + } + } +} + +resource disk_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: disk +} + +resource disk_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(disk.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: disk +}] + +@description('The resource group the disk was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the disk.') +output resourceId string = disk.id + +@description('The name of the disk.') +output name string = disk.name + +@description('The location the resource was deployed into.') +output location string = disk.location + +// =============== // +// Definitions // +// =============== // + +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. Specify the type of lock.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None')? +}? + +type roleAssignmentType = { + @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') + roleDefinitionIdOrName: string + + @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @description('Optional. The description of the role assignment.') + description: string? + + @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? + + @description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? diff --git a/avm/res/compute/disk/main.json b/avm/res/compute/disk/main.json new file mode 100644 index 0000000000..00f6a47fb8 --- /dev/null +++ b/avm/res/compute/disk/main.json @@ -0,0 +1,482 @@ +{ + "$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.24.24.22086", + "templateHash": "11182999004742950700" + }, + "name": "Compute Disks", + "description": "This module deploys a Compute Disk", + "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 role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "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. The name of the disk that is being created." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Resource location." + } + }, + "sku": { + "type": "string", + "allowedValues": [ + "Standard_LRS", + "Premium_LRS", + "StandardSSD_LRS", + "UltraSSD_LRS", + "Premium_ZRS", + "Premium_ZRS", + "PremiumV2_LRS" + ], + "metadata": { + "description": "Required. The disks sku name. Can be ." + } + }, + "architecture": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "x64", + "Arm64", + "" + ], + "metadata": { + "description": "Optional. CPU architecture supported by an OS disk." + } + }, + "burstingEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Set to true to enable bursting beyond the provisioned performance target of the disk." + } + }, + "completionPercent": { + "type": "int", + "defaultValue": 100, + "metadata": { + "description": "Optional. Percentage complete for the background copy when a resource is created via the CopyStart operation." + } + }, + "createOption": { + "type": "string", + "defaultValue": "Empty", + "allowedValues": [ + "Attach", + "Copy", + "CopyStart", + "Empty", + "FromImage", + "Import", + "ImportSecure", + "Restore", + "Upload", + "UploadPreparedSecure" + ], + "metadata": { + "description": "Optional. Sources of a disk creation." + } + }, + "imageReferenceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. A relative uri containing either a Platform Image Repository or user image reference." + } + }, + "logicalSectorSize": { + "type": "int", + "defaultValue": 4096, + "metadata": { + "description": "Optional. Logical sector size in bytes for Ultra disks. Supported values are 512 ad 4096." + } + }, + "securityDataUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. If create option is ImportSecure, this is the URI of a blob to be imported into VM guest state." + } + }, + "sourceResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. If create option is Copy, this is the ARM ID of the source snapshot or disk." + } + }, + "sourceUri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. If create option is Import, this is the URI of a blob to be imported into a managed disk." + } + }, + "storageAccountId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Conditional. The resource ID of the storage account containing the blob to import as a disk. Required if create option is Import." + } + }, + "uploadSizeBytes": { + "type": "int", + "defaultValue": 20972032, + "metadata": { + "description": "Optional. If create option is Upload, this is the size of the contents of the upload including the VHD footer." + } + }, + "diskSizeGB": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Conditional. The size of the disk to create. Required if create option is Empty." + } + }, + "diskIOPSReadWrite": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. The number of IOPS allowed for this disk; only settable for UltraSSD disks." + } + }, + "diskMBpsReadWrite": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. The bandwidth allowed for this disk; only settable for UltraSSD disks." + } + }, + "hyperVGeneration": { + "type": "string", + "defaultValue": "V2", + "allowedValues": [ + "V1", + "V2" + ], + "metadata": { + "description": "Optional. The hypervisor generation of the Virtual Machine. Applicable to OS disks only." + } + }, + "maxShares": { + "type": "int", + "defaultValue": 1, + "metadata": { + "description": "Optional. The maximum number of VMs that can attach to the disk at the same time. Default value is 0." + } + }, + "networkAccessPolicy": { + "type": "string", + "defaultValue": "DenyAll", + "allowedValues": [ + "AllowAll", + "AllowPrivate", + "DenyAll" + ], + "metadata": { + "description": "Optional. Policy for accessing the disk via network." + } + }, + "optimizedForFrequentAttach": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Setting this property to true improves reliability and performance of data disks that are frequently (more than 5 times a day) by detached from one virtual machine and attached to another. This property should not be set for disks that are not detached and attached frequently as it causes the disks to not align with the fault domain of the virtual machine." + } + }, + "osType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Windows", + "Linux", + "" + ], + "metadata": { + "description": "Optional. Sources of a disk creation." + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "Disabled", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Optional. Policy for controlling export on the disk." + } + }, + "acceleratedNetwork": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. True if the image from which the OS disk is created supports accelerated networking." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the availability set resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "variables": { + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Data Operator for Managed Disks": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '959f8984-c045-4866-89c7-12bf9737be2e')]", + "Disk Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24')]", + "Disk Pool Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840')]", + "Disk Restore Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "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-disk.{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" + } + } + } + } + }, + "disk": { + "type": "Microsoft.Compute/disks", + "apiVersion": "2022-07-02", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('sku')]" + }, + "properties": { + "burstingEnabled": "[parameters('burstingEnabled')]", + "completionPercent": "[parameters('completionPercent')]", + "creationData": { + "createOption": "[parameters('createOption')]", + "imageReference": "[if(not(equals(parameters('createOption'), 'FromImage')), null(), createObject('id', parameters('imageReferenceId')))]", + "logicalSectorSize": "[if(contains(parameters('sku'), 'Ultra'), parameters('logicalSectorSize'), null())]", + "securityDataUri": "[if(equals(parameters('createOption'), 'ImportSecure'), parameters('securityDataUri'), null())]", + "sourceResourceId": "[if(equals(parameters('createOption'), 'Copy'), parameters('sourceResourceId'), null())]", + "sourceUri": "[if(equals(parameters('createOption'), 'Import'), parameters('sourceUri'), null())]", + "storageAccountId": "[if(equals(parameters('createOption'), 'Import'), parameters('storageAccountId'), null())]", + "uploadSizeBytes": "[if(equals(parameters('createOption'), 'Upload'), parameters('uploadSizeBytes'), null())]" + }, + "diskIOPSReadWrite": "[if(contains(parameters('sku'), 'Ultra'), parameters('diskIOPSReadWrite'), null())]", + "diskMBpsReadWrite": "[if(contains(parameters('sku'), 'Ultra'), parameters('diskMBpsReadWrite'), null())]", + "diskSizeGB": "[if(equals(parameters('createOption'), 'Empty'), parameters('diskSizeGB'), null())]", + "hyperVGeneration": "[if(empty(parameters('osType')), null(), parameters('hyperVGeneration'))]", + "maxShares": "[parameters('maxShares')]", + "networkAccessPolicy": "[parameters('networkAccessPolicy')]", + "optimizedForFrequentAttach": "[parameters('optimizedForFrequentAttach')]", + "osType": "[if(empty(parameters('osType')), null(), parameters('osType'))]", + "publicNetworkAccess": "[parameters('publicNetworkAccess')]", + "supportedCapabilities": "[if(empty(parameters('osType')), createObject(), createObject('acceleratedNetwork', parameters('acceleratedNetwork'), 'architecture', if(empty(parameters('architecture')), null(), parameters('architecture'))))]" + } + }, + "disk_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/disks/{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": [ + "disk" + ] + }, + "disk_roleAssignments": { + "copy": { + "name": "disk_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Compute/disks/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Compute/disks', 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": [ + "disk" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the disk was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the disk." + }, + "value": "[resourceId('Microsoft.Compute/disks', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the disk." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('disk', '2022-07-02', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep b/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..cb89afcd7a --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,47 @@ +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.disk-${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 = 'cdmin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-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 + sku: 'Standard_LRS' + diskSizeGB: 1 + } +}] diff --git a/avm/res/compute/disk/tests/e2e/image/dependencies.bicep b/avm/res/compute/disk/tests/e2e/image/dependencies.bicep new file mode 100644 index 0000000000..616cf219fe --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/image/dependencies.bicep @@ -0,0 +1,13 @@ +@description('Optional. The location to deploy resources 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/disk/tests/e2e/image/main.test.bicep b/avm/res/compute/disk/tests/e2e/image/main.test.bicep new file mode 100644 index 0000000000..096d8eed74 --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/image/main.test.bicep @@ -0,0 +1,79 @@ +targetScope = 'subscription' + +metadata name = 'Using an image' +metadata description = 'This instance deploys the module with an image reference.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.disks-${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 = 'cdimg' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-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 + sku: 'Standard_LRS' + createOption: 'FromImage' + imageReferenceId: '${subscription().id}/Providers/Microsoft.Compute/Locations/westeurope/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer/Skus/2022-datacenter-azure-edition/Versions/20348.1006.220908' + 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/disk/tests/e2e/import/dependencies.bicep b/avm/res/compute/disk/tests/e2e/import/dependencies.bicep new file mode 100644 index 0000000000..adaf509a2d --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/import/dependencies.bicep @@ -0,0 +1,152 @@ +@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 + +@description('Required. The name of the Storage Account to create and to copy the VHD into.') +param storageAccountName string + +@description('Required. The name prefix of the Image Template to create.') +param imageTemplateNamePrefix string + +@description('Generated. Do not provide a value! This date value is used to generate a unique image template name.') +param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') + +@description('Required. The name of the Deployment Script to create for triggering the image creation.') +param triggerImageDeploymentScriptName string + +@description('Required. The name of the Deployment Script to copy the VHD to a destination storage account.') +param copyVhdDeploymentScriptName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = { + name: storageAccountName + location: location + kind: 'StorageV2' + sku: { + name: 'Standard_LRS' + } + properties: { + allowBlobPublicAccess: false + } + resource blobServices 'blobServices@2022-09-01' = { + name: 'default' + resource container 'containers@2022-09-01' = { + name: 'vhds' + properties: { + publicAccess: 'None' + } + } + } +} + +module roleAssignment 'dependencies_rbac.bicep' = { + name: '${deployment().name}-MSI-roleAssignment' + scope: subscription() + params: { + managedIdentityPrincipalId: managedIdentity.properties.principalId + managedIdentityResourceId: managedIdentity.id + } +} + +// Deploy image template +resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2022-02-14' = { + name: '${imageTemplateNamePrefix}-${baseTime}' + location: location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + buildTimeoutInMinutes: 0 + vmProfile: { + vmSize: 'Standard_D2s_v3' + osDiskSizeGB: 127 + } + source: { + type: 'PlatformImage' + publisher: 'MicrosoftWindowsDesktop' + offer: 'Windows-11' + sku: 'win11-21h2-avd' + version: 'latest' + } + distribute: [ + { + type: 'VHD' + runOutputName: '${imageTemplateNamePrefix}-VHD' + artifactTags: {} + } + ] + customize: [ + { + restartTimeout: '30m' + type: 'WindowsRestart' + } + ] + } +} + +// Trigger VHD creation +resource triggerImageDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: triggerImageDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '8.0' + retentionInterval: 'P1D' + arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\"' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/.scripts/Start-ImageTemplate.ps1') + cleanupPreference: 'OnSuccess' + forceUpdateTag: baseTime + } + dependsOn: [ + roleAssignment + ] +} + +// Copy VHD to destination storage account +resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: copyVhdDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '8.0' + retentionInterval: 'P1D' + arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\" -DestinationStorageAccountName \\"${storageAccount.name}\\" -VhdName \\"${imageTemplateNamePrefix}\\" -WaitForComplete' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/.scripts/Copy-VhdToStorageAccount.ps1') + cleanupPreference: 'OnSuccess' + forceUpdateTag: baseTime + } + dependsOn: [ triggerImageDeploymentScript ] +} + +@description('The URI of the created VHD.') +output vhdUri string = 'https://${storageAccount.name}.blob.${environment().suffixes.storage}/vhds/${imageTemplateNamePrefix}.vhd' + +@description('The resource ID of the created Storage Account.') +output storageAccountResourceId string = storageAccount.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id diff --git a/avm/res/compute/disk/tests/e2e/import/dependencies_rbac.bicep b/avm/res/compute/disk/tests/e2e/import/dependencies_rbac.bicep new file mode 100644 index 0000000000..cdca1b63bd --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/import/dependencies_rbac.bicep @@ -0,0 +1,16 @@ +targetScope = 'subscription' + +@description('Required. The resource ID of the created Managed Identity.') +param managedIdentityResourceId string + +@description('Required. The principal ID of the created Managed Identity.') +param managedIdentityPrincipalId string + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(subscription().subscriptionId, 'Contributor', managedIdentityResourceId) + properties: { + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalId: managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } +} diff --git a/avm/res/compute/disk/tests/e2e/import/main.test.bicep b/avm/res/compute/disk/tests/e2e/import/main.test.bicep new file mode 100644 index 0000000000..e677ae61dc --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/import/main.test.bicep @@ -0,0 +1,84 @@ +targetScope = 'subscription' + +metadata name = 'Using an imported image' +metadata description = 'This instance deploys the module with a custom image that is imported from a VHD in a storage account.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.disks-${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 = 'cdimp' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-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 + storageAccountName: 'dep${namePrefix}sa${serviceShort}01' + imageTemplateNamePrefix: 'dep-${namePrefix}-imgt-${serviceShort}' + triggerImageDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}-triggerImageTemplate' + copyVhdDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}-copyVhdToStorage' + } +} + +// ============== // +// 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 + sku: 'Standard_LRS' + createOption: 'Import' + 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' + } + ] + sourceUri: nestedDependencies.outputs.vhdUri + storageAccountId: nestedDependencies.outputs.storageAccountResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/compute/disk/tests/e2e/max/dependencies.bicep b/avm/res/compute/disk/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..616cf219fe --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/max/dependencies.bicep @@ -0,0 +1,13 @@ +@description('Optional. The location to deploy resources 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/disk/tests/e2e/max/main.test.bicep b/avm/res/compute/disk/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..523619915c --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/max/main.test.bicep @@ -0,0 +1,87 @@ +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.disks-${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 = 'cdmax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-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 + sku: 'UltraSSD_LRS' + diskIOPSReadWrite: 500 + diskMBpsReadWrite: 60 + diskSizeGB: 128 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + logicalSectorSize: 512 + osType: 'Windows' + publicNetworkAccess: 'Enabled' + 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/disk/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..df88b86a47 --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,61 @@ +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.disks-${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 = 'cdwaf' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-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 + sku: 'UltraSSD_LRS' + diskIOPSReadWrite: 500 + diskMBpsReadWrite: 60 + diskSizeGB: 128 + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + logicalSectorSize: 512 + osType: 'Windows' + publicNetworkAccess: 'Enabled' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/compute/disk/version.json b/avm/res/compute/disk/version.json new file mode 100644 index 0000000000..7fa401bdf7 --- /dev/null +++ b/avm/res/compute/disk/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} From b7b9b54c67a7d71ad5fefff863e8a37ef886aded Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 12 Jan 2024 20:40:36 +1000 Subject: [PATCH 02/13] codeowners --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index baf9bd2b2c..704d0f8a66 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -22,7 +22,7 @@ #/avm/res/cdn/profile/ @Azure/avm-res-cdn-profile-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/cognitive-services/account/ @Azure/avm-res-cognitiveservices-account-module-owners-bicep @Azure/avm-core-team-technical-bicep #/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/ @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/image/ @Azure/avm-res-compute-image-module-owners-bicep @Azure/avm-core-team-technical-bicep From ae5b32384e3e45b96104d899202d0fed03d4adfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Fri, 12 Jan 2024 20:44:12 +1000 Subject: [PATCH 03/13] Update .github/workflows/avm.res.compute.disk.yml Co-authored-by: Alexander Sehr --- .github/workflows/avm.res.compute.disk.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/avm.res.compute.disk.yml b/.github/workflows/avm.res.compute.disk.yml index 719f7dbbb8..14bf616de0 100644 --- a/.github/workflows/avm.res.compute.disk.yml +++ b/.github/workflows/avm.res.compute.disk.yml @@ -33,7 +33,7 @@ on: - "!*/**/README.md" env: - modulePath: "avm/res/network/network-security-group" + modulePath: "avm/res/compute/disk" workflowPath: ".github/workflows/avm.res.compute.disk.yml" concurrency: From 2feafb337aab71d03cbd66c2024e2a1a8e744c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:20:21 +1000 Subject: [PATCH 04/13] Update avm/res/compute/disk/main.bicep Co-authored-by: Alexander Sehr --- avm/res/compute/disk/main.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/compute/disk/main.bicep b/avm/res/compute/disk/main.bicep index 16630825ae..9028134769 100644 --- a/avm/res/compute/disk/main.bicep +++ b/avm/res/compute/disk/main.bicep @@ -127,7 +127,7 @@ param roleAssignments roleAssignmentType @description('Optional. Tags of the availability set resource.') param tags object? -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +@description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true var builtInRoleNames = { From 4ce522f284077a207a25ecdea04946c31bc9f493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:20:29 +1000 Subject: [PATCH 05/13] Update avm/res/compute/disk/main.bicep Co-authored-by: Alexander Sehr --- avm/res/compute/disk/main.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/compute/disk/main.bicep b/avm/res/compute/disk/main.bicep index 9028134769..d55082cbe8 100644 --- a/avm/res/compute/disk/main.bicep +++ b/avm/res/compute/disk/main.bicep @@ -190,7 +190,7 @@ resource disk 'Microsoft.Compute/disks@2022-07-02' = { maxShares: maxShares networkAccessPolicy: networkAccessPolicy optimizedForFrequentAttach: optimizedForFrequentAttach - osType: empty(osType) ? any(null) : osType + osType: !empty(osType) ? osType : any(null) publicNetworkAccess: publicNetworkAccess supportedCapabilities: empty(osType) ? {} : { acceleratedNetwork: acceleratedNetwork From 9a925e21af8d07dc05628114fcaaad0830c46369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:20:36 +1000 Subject: [PATCH 06/13] Update avm/res/compute/disk/main.bicep Co-authored-by: Alexander Sehr --- avm/res/compute/disk/main.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/compute/disk/main.bicep b/avm/res/compute/disk/main.bicep index d55082cbe8..6c8ab67e46 100644 --- a/avm/res/compute/disk/main.bicep +++ b/avm/res/compute/disk/main.bicep @@ -186,7 +186,7 @@ resource disk 'Microsoft.Compute/disks@2022-07-02' = { diskIOPSReadWrite: contains(sku, 'Ultra') ? diskIOPSReadWrite : null diskMBpsReadWrite: contains(sku, 'Ultra') ? diskMBpsReadWrite : null diskSizeGB: createOption == 'Empty' ? diskSizeGB : null - hyperVGeneration: empty(osType) ? null : hyperVGeneration + hyperVGeneration: !empty(osType) ? hyperVGeneration : null maxShares: maxShares networkAccessPolicy: networkAccessPolicy optimizedForFrequentAttach: optimizedForFrequentAttach From 8b6a697df5b3c12175d966595f73f3cf2cf9e670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:20:49 +1000 Subject: [PATCH 07/13] Update avm/res/compute/disk/main.bicep Co-authored-by: Alexander Sehr --- avm/res/compute/disk/main.bicep | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/avm/res/compute/disk/main.bicep b/avm/res/compute/disk/main.bicep index 6c8ab67e46..f2cab40424 100644 --- a/avm/res/compute/disk/main.bicep +++ b/avm/res/compute/disk/main.bicep @@ -173,9 +173,9 @@ resource disk 'Microsoft.Compute/disks@2022-07-02' = { completionPercent: completionPercent creationData: { createOption: createOption - imageReference: createOption != 'FromImage' ? null : { + imageReference: createOption == 'FromImage' ? { id: imageReferenceId - } + } : null logicalSectorSize: contains(sku, 'Ultra') ? logicalSectorSize : null securityDataUri: createOption == 'ImportSecure' ? securityDataUri : null sourceResourceId: createOption == 'Copy' ? sourceResourceId : null From 0b4a7e79df301bd397840f4aecd0e81453470f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:21:03 +1000 Subject: [PATCH 08/13] Update avm/res/compute/disk/main.bicep Co-authored-by: Alexander Sehr --- avm/res/compute/disk/main.bicep | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/avm/res/compute/disk/main.bicep b/avm/res/compute/disk/main.bicep index f2cab40424..00701ce256 100644 --- a/avm/res/compute/disk/main.bicep +++ b/avm/res/compute/disk/main.bicep @@ -192,10 +192,10 @@ resource disk 'Microsoft.Compute/disks@2022-07-02' = { optimizedForFrequentAttach: optimizedForFrequentAttach osType: !empty(osType) ? osType : any(null) publicNetworkAccess: publicNetworkAccess - supportedCapabilities: empty(osType) ? {} : { + supportedCapabilities: !empty(osType) ? { acceleratedNetwork: acceleratedNetwork - architecture: empty(architecture) ? null : architecture - } + architecture: !empty(architecture) ? architecture : null + } : {} } } From 106d9b60f8b830ebcd40e27d56e719520874b812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:21:15 +1000 Subject: [PATCH 09/13] Update avm/res/compute/disk/tests/e2e/import/main.test.bicep Co-authored-by: Alexander Sehr --- .../disk/tests/e2e/import/main.test.bicep | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/avm/res/compute/disk/tests/e2e/import/main.test.bicep b/avm/res/compute/disk/tests/e2e/import/main.test.bicep index e677ae61dc..092b23bdda 100644 --- a/avm/res/compute/disk/tests/e2e/import/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/import/main.test.bicep @@ -56,23 +56,6 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' location: location sku: 'Standard_LRS' createOption: 'Import' - 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' - } - ] sourceUri: nestedDependencies.outputs.vhdUri storageAccountId: nestedDependencies.outputs.storageAccountResourceId tags: { From f52e76e3910f649402230ce40d257203a5c1685f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:21:53 +1000 Subject: [PATCH 10/13] Update avm/res/compute/disk/tests/e2e/import/main.test.bicep Co-authored-by: Alexander Sehr --- avm/res/compute/disk/tests/e2e/import/main.test.bicep | 5 ----- 1 file changed, 5 deletions(-) diff --git a/avm/res/compute/disk/tests/e2e/import/main.test.bicep b/avm/res/compute/disk/tests/e2e/import/main.test.bicep index 092b23bdda..c711a56c34 100644 --- a/avm/res/compute/disk/tests/e2e/import/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/import/main.test.bicep @@ -58,10 +58,5 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' createOption: 'Import' sourceUri: nestedDependencies.outputs.vhdUri storageAccountId: nestedDependencies.outputs.storageAccountResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } } }] From 033c4a445576a570d1ceb25da8c038106fe3b3c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:22:00 +1000 Subject: [PATCH 11/13] Update avm/res/compute/disk/tests/e2e/image/main.test.bicep Co-authored-by: Alexander Sehr --- .../disk/tests/e2e/image/main.test.bicep | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/avm/res/compute/disk/tests/e2e/image/main.test.bicep b/avm/res/compute/disk/tests/e2e/image/main.test.bicep index 096d8eed74..5ad6af75e7 100644 --- a/avm/res/compute/disk/tests/e2e/image/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/image/main.test.bicep @@ -53,27 +53,5 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' sku: 'Standard_LRS' createOption: 'FromImage' imageReferenceId: '${subscription().id}/Providers/Microsoft.Compute/Locations/westeurope/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer/Skus/2022-datacenter-azure-edition/Versions/20348.1006.220908' - 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' - } } }] From 24d54366e700e515610f1b4b9d73347dd7ff168d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:22:12 +1000 Subject: [PATCH 12/13] Update .github/workflows/avm.res.compute.disk.yml Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- .github/workflows/avm.res.compute.disk.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/avm.res.compute.disk.yml b/.github/workflows/avm.res.compute.disk.yml index 14bf616de0..655ecd505f 100644 --- a/.github/workflows/avm.res.compute.disk.yml +++ b/.github/workflows/avm.res.compute.disk.yml @@ -44,7 +44,7 @@ jobs: # Initialize pipeline # ########################### job_initialize_pipeline: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest name: "Initialize pipeline" steps: - name: "Checkout" From 4c5178c317f45be719edf9f3bbf266e1178c0a82 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Mon, 15 Jan 2024 14:18:57 +1000 Subject: [PATCH 13/13] . --- avm/res/compute/disk/README.md | 107 ++---------------- avm/res/compute/disk/main.json | 12 +- .../disk/tests/e2e/import/dependencies.bicep | 14 +-- .../disk/tests/e2e/import/main.test.bicep | 5 +- 4 files changed, 24 insertions(+), 114 deletions(-) diff --git a/avm/res/compute/disk/README.md b/avm/res/compute/disk/README.md index c8c16ea0f6..1ceb237340 100644 --- a/avm/res/compute/disk/README.md +++ b/avm/res/compute/disk/README.md @@ -29,7 +29,7 @@ The following section provides usage examples for the module, which were used to - [Using only defaults](#example-1-using-only-defaults) - [Using an image](#example-2-using-an-image) -- [Import](#example-3-import) +- [Using an imported image](#example-3-using-an-imported-image) - [Using large parameter set](#example-4-using-large-parameter-set) - [WAF-aligned](#example-5-waf-aligned) @@ -109,28 +109,6 @@ module disk 'br/public:avm/res/compute/disk:' = { createOption: 'FromImage' imageReferenceId: '' location: '' - 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' - } } } ``` @@ -163,32 +141,6 @@ module disk 'br/public:avm/res/compute/disk:' = { }, "location": { "value": "" - }, - "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" - } } } } @@ -197,7 +149,10 @@ module disk 'br/public:avm/res/compute/disk:' = {

-### Example 3: _Import_ +### Example 3: _Using an imported image_ + +This instance deploys the module with a custom image that is imported from a VHD in a storage account. +

@@ -213,30 +168,8 @@ module disk 'br/public:avm/res/compute/disk:' = { // Non-required parameters createOption: 'Import' location: '' - roleAssignments: [ - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Owner' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: '' - } - ] sourceUri: '' storageAccountId: '' - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } } } ``` @@ -267,37 +200,11 @@ module disk 'br/public:avm/res/compute/disk:' = { "location": { "value": "" }, - "roleAssignments": { - "value": [ - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Owner" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "" - } - ] - }, "sourceUri": { "value": "" }, "storageAccountId": { "value": "" - }, - "tags": { - "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } } } } @@ -566,7 +473,7 @@ module disk 'br/public:avm/res/compute/disk:' = { | [`createOption`](#parameter-createoption) | string | Sources of a disk creation. | | [`diskIOPSReadWrite`](#parameter-diskiopsreadwrite) | int | The number of IOPS allowed for this disk; only settable for UltraSSD disks. | | [`diskMBpsReadWrite`](#parameter-diskmbpsreadwrite) | int | The bandwidth allowed for this disk; only settable for UltraSSD disks. | -| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`hyperVGeneration`](#parameter-hypervgeneration) | string | The hypervisor generation of the Virtual Machine. Applicable to OS disks only. | | [`imageReferenceId`](#parameter-imagereferenceid) | string | A relative uri containing either a Platform Image Repository or user image reference. | | [`location`](#parameter-location) | string | Resource location. | @@ -707,7 +614,7 @@ The bandwidth allowed for this disk; only settable for UltraSSD disks. ### Parameter: `enableTelemetry` -Enable telemetry via a Globally Unique Identifier (GUID). +Enable/Disable usage telemetry for module. - Required: No - Type: bool diff --git a/avm/res/compute/disk/main.json b/avm/res/compute/disk/main.json index 00f6a47fb8..4744d1356b 100644 --- a/avm/res/compute/disk/main.json +++ b/avm/res/compute/disk/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.24.24.22086", - "templateHash": "11182999004742950700" + "templateHash": "8032560098908563077" }, "name": "Compute Disks", "description": "This module deploys a Compute Disk", @@ -339,7 +339,7 @@ "type": "bool", "defaultValue": true, "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + "description": "Optional. Enable/Disable usage telemetry for module." } } }, @@ -392,7 +392,7 @@ "completionPercent": "[parameters('completionPercent')]", "creationData": { "createOption": "[parameters('createOption')]", - "imageReference": "[if(not(equals(parameters('createOption'), 'FromImage')), null(), createObject('id', parameters('imageReferenceId')))]", + "imageReference": "[if(equals(parameters('createOption'), 'FromImage'), createObject('id', parameters('imageReferenceId')), null())]", "logicalSectorSize": "[if(contains(parameters('sku'), 'Ultra'), parameters('logicalSectorSize'), null())]", "securityDataUri": "[if(equals(parameters('createOption'), 'ImportSecure'), parameters('securityDataUri'), null())]", "sourceResourceId": "[if(equals(parameters('createOption'), 'Copy'), parameters('sourceResourceId'), null())]", @@ -403,13 +403,13 @@ "diskIOPSReadWrite": "[if(contains(parameters('sku'), 'Ultra'), parameters('diskIOPSReadWrite'), null())]", "diskMBpsReadWrite": "[if(contains(parameters('sku'), 'Ultra'), parameters('diskMBpsReadWrite'), null())]", "diskSizeGB": "[if(equals(parameters('createOption'), 'Empty'), parameters('diskSizeGB'), null())]", - "hyperVGeneration": "[if(empty(parameters('osType')), null(), parameters('hyperVGeneration'))]", + "hyperVGeneration": "[if(not(empty(parameters('osType'))), parameters('hyperVGeneration'), null())]", "maxShares": "[parameters('maxShares')]", "networkAccessPolicy": "[parameters('networkAccessPolicy')]", "optimizedForFrequentAttach": "[parameters('optimizedForFrequentAttach')]", - "osType": "[if(empty(parameters('osType')), null(), parameters('osType'))]", + "osType": "[if(not(empty(parameters('osType'))), parameters('osType'), null())]", "publicNetworkAccess": "[parameters('publicNetworkAccess')]", - "supportedCapabilities": "[if(empty(parameters('osType')), createObject(), createObject('acceleratedNetwork', parameters('acceleratedNetwork'), 'architecture', if(empty(parameters('architecture')), null(), parameters('architecture'))))]" + "supportedCapabilities": "[if(not(empty(parameters('osType'))), createObject('acceleratedNetwork', parameters('acceleratedNetwork'), 'architecture', if(not(empty(parameters('architecture'))), parameters('architecture'), null())), createObject())]" } }, "disk_lock": { diff --git a/avm/res/compute/disk/tests/e2e/import/dependencies.bicep b/avm/res/compute/disk/tests/e2e/import/dependencies.bicep index adaf509a2d..038eb6f8ac 100644 --- a/avm/res/compute/disk/tests/e2e/import/dependencies.bicep +++ b/avm/res/compute/disk/tests/e2e/import/dependencies.bicep @@ -8,7 +8,7 @@ param managedIdentityName string param storageAccountName string @description('Required. The name prefix of the Image Template to create.') -param imageTemplateNamePrefix string +param imageTemplateName string @description('Generated. Do not provide a value! This date value is used to generate a unique image template name.') param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') @@ -56,7 +56,7 @@ module roleAssignment 'dependencies_rbac.bicep' = { // Deploy image template resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2022-02-14' = { - name: '${imageTemplateNamePrefix}-${baseTime}' + name: imageTemplateName location: location identity: { type: 'UserAssigned' @@ -80,7 +80,7 @@ resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2022-02-14 distribute: [ { type: 'VHD' - runOutputName: '${imageTemplateNamePrefix}-VHD' + runOutputName: '${imageTemplateName}-VHD' artifactTags: {} } ] @@ -108,7 +108,7 @@ resource triggerImageDeploymentScript 'Microsoft.Resources/deploymentScripts@202 azPowerShellVersion: '8.0' retentionInterval: 'P1D' arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\"' - scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/.scripts/Start-ImageTemplate.ps1') + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Start-ImageTemplate.ps1') cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } @@ -131,8 +131,8 @@ resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10- properties: { azPowerShellVersion: '8.0' retentionInterval: 'P1D' - arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\" -DestinationStorageAccountName \\"${storageAccount.name}\\" -VhdName \\"${imageTemplateNamePrefix}\\" -WaitForComplete' - scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/.scripts/Copy-VhdToStorageAccount.ps1') + arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\" -DestinationStorageAccountName \\"${storageAccount.name}\\" -VhdName \\"${imageTemplateName}\\" -WaitForComplete' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Copy-VhdToStorageAccount.ps1') cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } @@ -140,7 +140,7 @@ resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10- } @description('The URI of the created VHD.') -output vhdUri string = 'https://${storageAccount.name}.blob.${environment().suffixes.storage}/vhds/${imageTemplateNamePrefix}.vhd' +output vhdUri string = 'https://${storageAccount.name}.blob.${environment().suffixes.storage}/vhds/${imageTemplateName}.vhd' @description('The resource ID of the created Storage Account.') output storageAccountResourceId string = storageAccount.id diff --git a/avm/res/compute/disk/tests/e2e/import/main.test.bicep b/avm/res/compute/disk/tests/e2e/import/main.test.bicep index c711a56c34..1b0783ff7b 100644 --- a/avm/res/compute/disk/tests/e2e/import/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/import/main.test.bicep @@ -17,6 +17,9 @@ 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 = 'cdimp' +@description('Generated. Do not provide a value! This date value is used to generate a unique image template name.') +param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') + @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' @@ -38,7 +41,7 @@ module nestedDependencies 'dependencies.bicep' = { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' location: location storageAccountName: 'dep${namePrefix}sa${serviceShort}01' - imageTemplateNamePrefix: 'dep-${namePrefix}-imgt-${serviceShort}' + imageTemplateName: 'dep-${namePrefix}-imgt-${serviceShort}-${baseTime}' triggerImageDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}-triggerImageTemplate' copyVhdDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}-copyVhdToStorage' }