From 57956521d11adcac74d6842b5822a503ccf7eb25 Mon Sep 17 00:00:00 2001 From: moisesjgomez <51566179+moisesjgomez@users.noreply.github.com> Date: Fri, 2 Feb 2024 11:50:40 -0600 Subject: [PATCH] feat: `avm/res/desktop-virtualization/application-group` (#832) ## Description Closes avm/res/desktop-virtualization/application-group #146 [![avm.res.desktop-virtualization.application-group](https://github.com/moisesjgomez/bicep-registry-modules/actions/workflows/avm.res.desktop-virtualization.application-group.yml/badge.svg?branch=application-group)](https://github.com/moisesjgomez/bicep-registry-modules/actions/workflows/avm.res.desktop-virtualization.application-group.yml) ## Adding a new module - [x] A proposal has been submitted and approved. - [x] I have included "Closes #{module_proposal_issue_number}" in the PR description. - [ ] I have run `brm validate` locally to verify the module files. - [x] I have run deployment tests locally to ensure the module is deployable. --------- Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> Co-authored-by: Alexander Sehr --- .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/avm_module_issue.yml | 2 +- ...sktop-virtualization.application-group.yml | 83 +++ .../application-group/README.md | 686 ++++++++++++++++++ .../application-group/application/README.md | 145 ++++ .../application-group/application/main.bicep | 66 ++ .../application-group/application/main.json | 127 ++++ .../application-group/main.bicep | 240 ++++++ .../application-group/main.json | 602 +++++++++++++++ .../tests/e2e/defaults/dependencies.bicep | 18 + .../tests/e2e/defaults/main.test.bicep | 54 ++ .../tests/e2e/max/dependencies.bicep | 29 + .../tests/e2e/max/main.test.bicep | 129 ++++ .../tests/e2e/waf-aligned/dependencies.bicep | 18 + .../tests/e2e/waf-aligned/main.test.bicep | 81 +++ .../application-group/version.json | 7 + 16 files changed, 2287 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/avm.res.desktop-virtualization.application-group.yml create mode 100644 avm/res/desktop-virtualization/application-group/README.md create mode 100644 avm/res/desktop-virtualization/application-group/application/README.md create mode 100644 avm/res/desktop-virtualization/application-group/application/main.bicep create mode 100644 avm/res/desktop-virtualization/application-group/application/main.json create mode 100644 avm/res/desktop-virtualization/application-group/main.bicep create mode 100644 avm/res/desktop-virtualization/application-group/main.json create mode 100644 avm/res/desktop-virtualization/application-group/tests/e2e/defaults/dependencies.bicep create mode 100644 avm/res/desktop-virtualization/application-group/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/desktop-virtualization/application-group/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/desktop-virtualization/application-group/tests/e2e/max/main.test.bicep create mode 100644 avm/res/desktop-virtualization/application-group/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/desktop-virtualization/application-group/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/desktop-virtualization/application-group/version.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f33ca58664..6a536fcca5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -40,7 +40,7 @@ /avm/res/data-protection/backup-vault/ @Azure/avm-res-dataprotection-backupvault-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/db-for-my-sql/flexible-server/ @Azure/avm-res-dbformysql-flexibleserver-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/db-for-postgre-sql/flexible-server/ @Azure/avm-res-dbforpostgresql-flexibleserver-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/desktop-virtualization/application-group/ @Azure/avm-res-desktopvirtualization-applicationgroup-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/desktop-virtualization/application-group/ @Azure/avm-res-desktopvirtualization-applicationgroup-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/desktop-virtualization/host-pool/ @Azure/avm-res-desktopvirtualization-hostpool-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/desktop-virtualization/scaling-plan/ @Azure/avm-res-desktopvirtualization-scalingplan-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/desktop-virtualization/workspace/ @Azure/avm-res-desktopvirtualization-workspace-module-owners-bicep @Azure/avm-core-team-technical-bicep diff --git a/.github/ISSUE_TEMPLATE/avm_module_issue.yml b/.github/ISSUE_TEMPLATE/avm_module_issue.yml index 58013c13b8..9f2c9bf5d6 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -74,7 +74,7 @@ body: - "avm/res/databricks/workspace" - "avm/res/db-for-my-sql/flexible-server" - "avm/res/db-for-postgre-sql/flexible-server" - # - "avm/res/desktop-virtualization/application-group" + - "avm/res/desktop-virtualization/application-group" # - "avm/res/desktop-virtualization/host-pool" - "avm/res/desktop-virtualization/scaling-plan" # - "avm/res/desktop-virtualization/workspace" diff --git a/.github/workflows/avm.res.desktop-virtualization.application-group.yml b/.github/workflows/avm.res.desktop-virtualization.application-group.yml new file mode 100644 index 0000000000..b3e2624566 --- /dev/null +++ b/.github/workflows/avm.res.desktop-virtualization.application-group.yml @@ -0,0 +1,83 @@ +name: "avm.res.desktop-virtualization.application-group" + +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.desktop-virtualization.application-group.yml" + - "avm/res/desktop-virtualization/application-group/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/desktop-virtualization/application-group" + workflowPath: ".github/workflows/avm.res.desktop-virtualization.application-group.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + 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/desktop-virtualization/application-group/README.md b/avm/res/desktop-virtualization/application-group/README.md new file mode 100644 index 0000000000..5ca1a8e2e6 --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/README.md @@ -0,0 +1,686 @@ +# Azure Virtual Desktop Application Group `[Microsoft.DesktopVirtualization/applicationGroups]` + +This module deploys an Azure Virtual Desktop Application Group. + +## 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.DesktopVirtualization/applicationGroups` | [2023-09-05](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2023-09-05/applicationGroups) | +| `Microsoft.DesktopVirtualization/applicationGroups/applications` | [2023-09-05](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2023-09-05/applicationGroups/applications) | +| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | + +## 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/desktop-virtualization/application-group:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [WAF-aligned](#example-3-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep +module applicationGroup 'br/public:avm/res/desktop-virtualization/application-group:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-dvagmin' + params: { + // Required parameters + applicationGroupType: 'Desktop' + hostpoolName: '' + name: 'dvagmin002' + // Non-required parameters + location: '' + } +} +``` + +
+

+ +

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

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

+ +via Bicep module + +```bicep +module applicationGroup 'br/public:avm/res/desktop-virtualization/application-group:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-dvagmax' + params: { + // Required parameters + applicationGroupType: 'RemoteApp' + hostpoolName: '' + name: 'dvagmax002' + // Non-required parameters + applications: [ + { + commandLineArguments: '' + commandLineSetting: 'DoNotAllow' + description: 'Notepad by ARM template' + filePath: 'C:\\Windows\\System32\\notepad.exe' + friendlyName: 'Notepad' + iconIndex: 0 + iconPath: 'C:\\Windows\\System32\\notepad.exe' + name: 'notepad' + showInPortal: true + } + { + filePath: 'C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe' + friendlyName: 'Wordpad' + name: 'wordpad' + } + ] + description: 'myDescription' + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "applicationGroupType": { + "value": "RemoteApp" + }, + "hostpoolName": { + "value": "" + }, + "name": { + "value": "dvagmax002" + }, + // Non-required parameters + "applications": { + "value": [ + { + "commandLineArguments": "", + "commandLineSetting": "DoNotAllow", + "description": "Notepad by ARM template", + "filePath": "C:\\Windows\\System32\\notepad.exe", + "friendlyName": "Notepad", + "iconIndex": 0, + "iconPath": "C:\\Windows\\System32\\notepad.exe", + "name": "notepad", + "showInPortal": true + }, + { + "filePath": "C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe", + "friendlyName": "Wordpad", + "name": "wordpad" + } + ] + }, + "description": { + "value": "myDescription" + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "logCategoriesAndGroups": [ + { + "categoryGroup": "allLogs" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module applicationGroup 'br/public:avm/res/desktop-virtualization/application-group:' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-dvagwaf' + params: { + // Required parameters + applicationGroupType: 'Desktop' + hostpoolName: '' + name: 'dvagwaf002' + // Non-required parameters + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + location: '' + tags: { + Environment: 'Non-Prod' + 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 + "applicationGroupType": { + "value": "Desktop" + }, + "hostpoolName": { + "value": "" + }, + "name": { + "value": "dvagwaf002" + }, + // Non-required parameters + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "location": { + "value": "" + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`applicationGroupType`](#parameter-applicationgrouptype) | string | The type of the Application Group to be created. Allowed values: RemoteApp or Desktop. | +| [`hostpoolName`](#parameter-hostpoolname) | string | Name of the Host Pool to be linked to this Application Group. | +| [`name`](#parameter-name) | string | Name of the Application Group. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`applications`](#parameter-applications) | array | List of applications to be created in the Application Group. | +| [`description`](#parameter-description) | string | Description of the application group. | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`friendlyName`](#parameter-friendlyname) | string | The friendly name of the Application Group to be created. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | + +### Parameter: `applicationGroupType` + +The type of the Application Group to be created. Allowed values: RemoteApp or Desktop. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Desktop' + 'RemoteApp' + ] + ``` + +### Parameter: `hostpoolName` + +Name of the Host Pool to be linked to this Application Group. + +- Required: Yes +- Type: string + +### Parameter: `name` + +Name of the Application Group. + +- Required: Yes +- Type: string + +### Parameter: `applications` + +List of applications to be created in the Application Group. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `description` + +Description of the application group. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `diagnosticSettings` + +The diagnostic settings of the service. + +- Required: No +- Type: array + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`eventHubAuthorizationRuleResourceId`](#parameter-diagnosticsettingseventhubauthorizationruleresourceid) | string | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| [`eventHubName`](#parameter-diagnosticsettingseventhubname) | string | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | +| [`logAnalyticsDestinationType`](#parameter-diagnosticsettingsloganalyticsdestinationtype) | string | A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. | +| [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. | +| [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | string | Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | +| [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | string | Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | + +### Parameter: `diagnosticSettings.eventHubAuthorizationRuleResourceId` + +Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.eventHubName` + +Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.logAnalyticsDestinationType` + +A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AzureDiagnostics' + 'Dedicated' + ] + ``` + +### Parameter: `diagnosticSettings.logCategoriesAndGroups` + +The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. + +- Required: No +- Type: array + +### Parameter: `diagnosticSettings.marketplacePartnerResourceId` + +The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.name` + +The name of diagnostic setting. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.storageAccountResourceId` + +Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.workspaceResourceId` + +Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `friendlyName` + +The friendly name of the Application Group to be created. + +- Required: No +- Type: string +- Default: `[parameters('name')]` + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `lock` + +The lock settings of the service. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | +| [`name`](#parameter-lockname) | string | Specify the name of lock. | + +### Parameter: `lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `roleAssignments` + +Array of role 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: `tags` + +Tags of the resource. + +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location of the scaling plan. | +| `name` | string | The name of the scaling plan. | +| `resourceGroupName` | string | The name of the resource group the scaling plan was created in. | +| `resourceId` | string | The resource ID of the scaling plan. | + +## 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/desktop-virtualization/application-group/application/README.md b/avm/res/desktop-virtualization/application-group/application/README.md new file mode 100644 index 0000000000..a4f0e30f2c --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/application/README.md @@ -0,0 +1,145 @@ +# Azure Virtual Desktop Application Group Application `[Microsoft.DesktopVirtualization/applicationGroups/applications]` + +This module deploys an Azure Virtual Desktop Application Group Application. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DesktopVirtualization/applicationGroups/applications` | [2023-09-05](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DesktopVirtualization/2023-09-05/applicationGroups/applications) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`filePath`](#parameter-filepath) | string | Specifies a path for the executable file for the application. | +| [`friendlyName`](#parameter-friendlyname) | string | Friendly name of Application.. | +| [`name`](#parameter-name) | string | Name of the Application to be created in the Application Group. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`applicationGroupName`](#parameter-applicationgroupname) | string | The name of the parent Application Group to create the application(s) in. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`commandLineArguments`](#parameter-commandlinearguments) | string | Command-Line Arguments for Application. | +| [`commandLineSetting`](#parameter-commandlinesetting) | string | Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all. | +| [`description`](#parameter-description) | string | Description of Application.. | +| [`iconIndex`](#parameter-iconindex) | int | Index of the icon. | +| [`iconPath`](#parameter-iconpath) | string | Path to icon. | +| [`showInPortal`](#parameter-showinportal) | bool | Specifies whether to show the RemoteApp program in the RD Web Access server. | + +### Parameter: `filePath` + +Specifies a path for the executable file for the application. + +- Required: Yes +- Type: string + +### Parameter: `friendlyName` + +Friendly name of Application.. + +- Required: Yes +- Type: string + +### Parameter: `name` + +Name of the Application to be created in the Application Group. + +- Required: Yes +- Type: string + +### Parameter: `applicationGroupName` + +The name of the parent Application Group to create the application(s) in. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `commandLineArguments` + +Command-Line Arguments for Application. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `commandLineSetting` + +Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all. + +- Required: No +- Type: string +- Default: `'DoNotAllow'` +- Allowed: + ```Bicep + [ + 'Allow' + 'DoNotAllow' + 'Require' + ] + ``` + +### Parameter: `description` + +Description of Application.. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `iconIndex` + +Index of the icon. + +- Required: No +- Type: int +- Default: `0` + +### Parameter: `iconPath` + +Path to icon. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `showInPortal` + +Specifies whether to show the RemoteApp program in the RD Web Access server. + +- Required: No +- Type: bool +- Default: `False` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the application. | +| `resourceGroupName` | string | The name of the resource group the application was created in. | +| `resourceId` | string | The resource ID of the application. | + +## 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/desktop-virtualization/application-group/application/main.bicep b/avm/res/desktop-virtualization/application-group/application/main.bicep new file mode 100644 index 0000000000..0f5b2f40e7 --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/application/main.bicep @@ -0,0 +1,66 @@ +metadata name = 'Azure Virtual Desktop Application Group Application' +metadata description = 'This module deploys an Azure Virtual Desktop Application Group Application.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Conditional. The name of the parent Application Group to create the application(s) in. Required if the template is used in a standalone deployment.') +param applicationGroupName string + +@sys.description('Required. Name of the Application to be created in the Application Group.') +param name string + +@sys.description('Optional. Description of Application..') +param description string = '' + +@sys.description('Required. Friendly name of Application..') +param friendlyName string + +@sys.description('Required. Specifies a path for the executable file for the application.') +param filePath string + +@allowed([ + 'Allow' + 'DoNotAllow' + 'Require' +]) +@sys.description('Optional. Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all.') +param commandLineSetting string = 'DoNotAllow' + +@sys.description('Optional. Command-Line Arguments for Application.') +param commandLineArguments string = '' + +@sys.description('Optional. Specifies whether to show the RemoteApp program in the RD Web Access server.') +param showInPortal bool = false + +@sys.description('Optional. Path to icon.') +param iconPath string = '' + +@sys.description('Optional. Index of the icon.') +param iconIndex int = 0 + +resource appGroup 'Microsoft.DesktopVirtualization/applicationGroups@2023-09-05' existing = { + name: applicationGroupName +} + +resource application 'Microsoft.DesktopVirtualization/applicationGroups/applications@2023-09-05' = { + name: name + parent: appGroup + properties: { + description: description + friendlyName: friendlyName + filePath: filePath + commandLineSetting: commandLineSetting + commandLineArguments: commandLineArguments + showInPortal: showInPortal + iconPath: iconPath + iconIndex: iconIndex + } +} + +@sys.description('The resource ID of the application.') +output resourceId string = application.id + +@sys.description('The name of the resource group the application was created in.') +output resourceGroupName string = resourceGroup().name + +@sys.description('The name of the application.') +output name string = application.name diff --git a/avm/res/desktop-virtualization/application-group/application/main.json b/avm/res/desktop-virtualization/application-group/application/main.json new file mode 100644 index 0000000000..b5447c1186 --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/application/main.json @@ -0,0 +1,127 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "16966262699054894958" + }, + "name": "Azure Virtual Desktop Application Group Application", + "description": "This module deploys an Azure Virtual Desktop Application Group Application.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "applicationGroupName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Application Group to create the application(s) in. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Application to be created in the Application Group." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of Application.." + } + }, + "friendlyName": { + "type": "string", + "metadata": { + "description": "Required. Friendly name of Application.." + } + }, + "filePath": { + "type": "string", + "metadata": { + "description": "Required. Specifies a path for the executable file for the application." + } + }, + "commandLineSetting": { + "type": "string", + "defaultValue": "DoNotAllow", + "allowedValues": [ + "Allow", + "DoNotAllow", + "Require" + ], + "metadata": { + "description": "Optional. Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all." + } + }, + "commandLineArguments": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Command-Line Arguments for Application." + } + }, + "showInPortal": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether to show the RemoteApp program in the RD Web Access server." + } + }, + "iconPath": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Path to icon." + } + }, + "iconIndex": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. Index of the icon." + } + } + }, + "resources": [ + { + "type": "Microsoft.DesktopVirtualization/applicationGroups/applications", + "apiVersion": "2023-09-05", + "name": "[format('{0}/{1}', parameters('applicationGroupName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "friendlyName": "[parameters('friendlyName')]", + "filePath": "[parameters('filePath')]", + "commandLineSetting": "[parameters('commandLineSetting')]", + "commandLineArguments": "[parameters('commandLineArguments')]", + "showInPortal": "[parameters('showInPortal')]", + "iconPath": "[parameters('iconPath')]", + "iconIndex": "[parameters('iconIndex')]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the application." + }, + "value": "[resourceId('Microsoft.DesktopVirtualization/applicationGroups/applications', parameters('applicationGroupName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the application was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the application." + }, + "value": "[parameters('name')]" + } + } +} \ No newline at end of file diff --git a/avm/res/desktop-virtualization/application-group/main.bicep b/avm/res/desktop-virtualization/application-group/main.bicep new file mode 100644 index 0000000000..bfc6102ad1 --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/main.bicep @@ -0,0 +1,240 @@ +metadata name = 'Azure Virtual Desktop Application Group' +metadata description = 'This module deploys an Azure Virtual Desktop Application Group.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Required. Name of the Application Group.') +@minLength(3) +param name string + +@sys.description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@sys.description('Required. The type of the Application Group to be created. Allowed values: RemoteApp or Desktop.') +@allowed([ + 'RemoteApp' + 'Desktop' +]) +param applicationGroupType string + +@sys.description('Required. Name of the Host Pool to be linked to this Application Group.') +param hostpoolName string + +@sys.description('Optional. The friendly name of the Application Group to be created.') +param friendlyName string = name + +@sys.description('Optional. Description of the application group.') +param description string = '' + +@sys.description('Optional. List of applications to be created in the Application Group.') +param applications array = [] + +@sys.description('Optional. Tags of the resource.') +param tags object? + +@sys.description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@sys.description('Optional. The lock settings of the service.') +param lock lockType + +@sys.description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +@sys.description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +var builtInRoleNames = { + Owner: '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' + Contributor: '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c' + Reader: '/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7' + 'Role Based Access Control Administrator (Preview)': '/providers/Microsoft.Authorization/roleDefinitions/f58310d9-a9f6-439a-9e8d-f62e7b41a168' + 'User Access Administrator': '/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + 'Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b' + 'Desktop Virtualization Application Group Contributor': '/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8' + 'Desktop Virtualization Application Group Reader': '/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55' + 'Desktop Virtualization Contributor': '/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387' + 'Desktop Virtualization Host Pool Contributor': '/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc' + 'Desktop Virtualization Host Pool Reader': '/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822' + 'Desktop Virtualization Power On Off Contributor': '/providers/Microsoft.Authorization/roleDefinitions/40c5ff49-9181-41f8-ae61-143b0e78555e' + 'Desktop Virtualization Reader': '/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868' + 'Desktop Virtualization Session Host Operator': '/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408' + 'Desktop Virtualization User': '/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63' + 'Desktop Virtualization User Session Operator': '/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6' + 'Desktop Virtualization Virtual Machine Contributor': '/providers/Microsoft.Authorization/roleDefinitions/a959dbd1-f747-45e3-8ba6-dd80f235f97c' + 'Desktop Virtualization Workspace Contributor': '/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b' + 'Desktop Virtualization Workspace Reader': '/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d' + 'Managed Application Contributor Role': '/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e' + 'Managed Application Operator Role': '/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae' + 'Managed Applications Reader': '/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44' +} + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.desktopvirtualization-appgroup.${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 appGroup_hostpool 'Microsoft.DesktopVirtualization/hostPools@2022-09-09' existing = { + name: hostpoolName +} + +resource appGroup 'Microsoft.DesktopVirtualization/applicationGroups@2023-09-05' = { + name: name + location: location + tags: tags + properties: { + hostPoolArmPath: appGroup_hostpool.id + friendlyName: friendlyName + description: description + applicationGroupType: applicationGroupType + } +} + +module appGroup_applications 'application/main.bicep' = [for (application, index) in applications: { + name: '${uniqueString(deployment().name, location)}-AppGroup-App-${index}' + params: { + name: application.name + applicationGroupName: appGroup.name + description: contains(application, 'description') ? application.description : '' + friendlyName: contains(application, 'friendlyName') ? application.friendlyName : appGroup.name + filePath: application.filePath + commandLineSetting: contains(application, 'commandLineSetting') ? application.commandLineSetting : 'DoNotAllow' + commandLineArguments: contains(application, 'commandLineArguments') ? application.commandLineArguments : '' + showInPortal: contains(application, 'showInPortal') ? application.showInPortal : false + iconPath: contains(application, 'iconPath') ? application.iconPath : application.filePath + iconIndex: contains(application, 'iconIndex') ? application.iconIndex : 0 + } +}] + +resource appGroup_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: appGroup +} + +resource appGroup_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(appGroup.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 + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: appGroup +}] + +resource appGroup_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + logs: diagnosticSetting.?logCategoriesAndGroups ?? [ + { + categoryGroup: 'allLogs' + enabled: true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: appGroup +}] + +@sys.description('The resource ID of the scaling plan.') +output resourceId string = appGroup.id + +@sys.description('The name of the resource group the scaling plan was created in.') +output resourceGroupName string = resourceGroup().name + +@sys.description('The name of the scaling plan.') +output name string = appGroup.name + +@sys.description('The location of the scaling plan.') +output location string = appGroup.location + +// ================ // +// Definitions // +// ================ // + +type lockType = { + @sys.description('Optional. Specify the name of lock.') + name: string? + + @sys.description('Optional. Specify the type of lock.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None')? +}? + +type roleAssignmentType = { + @sys.description('Required. The 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 + + @sys.description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @sys.description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @sys.description('Optional. The description of the role assignment.') + description: string? + + @sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') + condition: string? + + @sys.description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @sys.description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? + +type diagnosticSettingType = { + @sys.description('Optional. The name of diagnostic setting.') + name: string? + + @sys.description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + logCategoriesAndGroups: { + @sys.description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') + category: string? + + @sys.description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to \'AllLogs\' to collect all logs.') + categoryGroup: string? + }[]? + + @sys.description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') + logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? + + @sys.description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + workspaceResourceId: string? + + @sys.description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + storageAccountResourceId: string? + + @sys.description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') + eventHubAuthorizationRuleResourceId: string? + + @sys.description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + eventHubName: string? + + @sys.description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') + marketplacePartnerResourceId: string? +}[]? diff --git a/avm/res/desktop-virtualization/application-group/main.json b/avm/res/desktop-virtualization/application-group/main.json new file mode 100644 index 0000000000..1b50b9f0b4 --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/main.json @@ -0,0 +1,602 @@ +{ + "$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": "2654703443312844248" + }, + "name": "Azure Virtual Desktop Application Group", + "description": "This module deploys an Azure Virtual Desktop Application Group.", + "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 + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to 'AllLogs' to collect all logs." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 3, + "metadata": { + "description": "Required. Name of the Application Group." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "applicationGroupType": { + "type": "string", + "allowedValues": [ + "RemoteApp", + "Desktop" + ], + "metadata": { + "description": "Required. The type of the Application Group to be created. Allowed values: RemoteApp or Desktop." + } + }, + "hostpoolName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Host Pool to be linked to this Application Group." + } + }, + "friendlyName": { + "type": "string", + "defaultValue": "[parameters('name')]", + "metadata": { + "description": "Optional. The friendly name of the Application Group to be created." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of the application group." + } + }, + "applications": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of applications to be created in the Application Group." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + } + }, + "variables": { + "builtInRoleNames": { + "Owner": "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", + "Contributor": "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c", + "Reader": "/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7", + "Role Based Access Control Administrator (Preview)": "/providers/Microsoft.Authorization/roleDefinitions/f58310d9-a9f6-439a-9e8d-f62e7b41a168", + "User Access Administrator": "/providers/Microsoft.Authorization/roleDefinitions/18d7d88d-d35e-4fb5-a5c3-7773c20a72d9", + "Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/ca6382a4-1721-4bcf-a114-ff0c70227b6b", + "Desktop Virtualization Application Group Contributor": "/providers/Microsoft.Authorization/roleDefinitions/86240b0e-9422-4c43-887b-b61143f32ba8", + "Desktop Virtualization Application Group Reader": "/providers/Microsoft.Authorization/roleDefinitions/aebf23d0-b568-4e86-b8f9-fe83a2c6ab55", + "Desktop Virtualization Contributor": "/providers/Microsoft.Authorization/roleDefinitions/082f0a83-3be5-4ba1-904c-961cca79b387", + "Desktop Virtualization Host Pool Contributor": "/providers/Microsoft.Authorization/roleDefinitions/e307426c-f9b6-4e81-87de-d99efb3c32bc", + "Desktop Virtualization Host Pool Reader": "/providers/Microsoft.Authorization/roleDefinitions/ceadfde2-b300-400a-ab7b-6143895aa822", + "Desktop Virtualization Power On Off Contributor": "/providers/Microsoft.Authorization/roleDefinitions/40c5ff49-9181-41f8-ae61-143b0e78555e", + "Desktop Virtualization Reader": "/providers/Microsoft.Authorization/roleDefinitions/49a72310-ab8d-41df-bbb0-79b649203868", + "Desktop Virtualization Session Host Operator": "/providers/Microsoft.Authorization/roleDefinitions/2ad6aaab-ead9-4eaa-8ac5-da422f562408", + "Desktop Virtualization User": "/providers/Microsoft.Authorization/roleDefinitions/1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63", + "Desktop Virtualization User Session Operator": "/providers/Microsoft.Authorization/roleDefinitions/ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6", + "Desktop Virtualization Virtual Machine Contributor": "/providers/Microsoft.Authorization/roleDefinitions/a959dbd1-f747-45e3-8ba6-dd80f235f97c", + "Desktop Virtualization Workspace Contributor": "/providers/Microsoft.Authorization/roleDefinitions/21efdde3-836f-432b-bf3d-3e8e734d4b2b", + "Desktop Virtualization Workspace Reader": "/providers/Microsoft.Authorization/roleDefinitions/0fa44ee9-7a7d-466b-9bb2-2bf446b1204d", + "Managed Application Contributor Role": "/providers/Microsoft.Authorization/roleDefinitions/641177b8-a67a-45b9-a033-47bc880bb21e", + "Managed Application Operator Role": "/providers/Microsoft.Authorization/roleDefinitions/c7393b34-138c-406f-901b-d8cf2b17e6ae", + "Managed Applications Reader": "/providers/Microsoft.Authorization/roleDefinitions/b9331d33-8a36-4f8c-b097-4f54124fdb44" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.desktopvirtualization-appgroup.{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" + } + } + } + } + }, + "appGroup_hostpool": { + "existing": true, + "type": "Microsoft.DesktopVirtualization/hostPools", + "apiVersion": "2022-09-09", + "name": "[parameters('hostpoolName')]" + }, + "appGroup": { + "type": "Microsoft.DesktopVirtualization/applicationGroups", + "apiVersion": "2023-09-05", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "hostPoolArmPath": "[resourceId('Microsoft.DesktopVirtualization/hostPools', parameters('hostpoolName'))]", + "friendlyName": "[parameters('friendlyName')]", + "description": "[parameters('description')]", + "applicationGroupType": "[parameters('applicationGroupType')]" + }, + "dependsOn": [ + "appGroup_hostpool" + ] + }, + "appGroup_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.DesktopVirtualization/applicationGroups/{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": [ + "appGroup" + ] + }, + "appGroup_roleAssignments": { + "copy": { + "name": "appGroup_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.DesktopVirtualization/applicationGroups/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.DesktopVirtualization/applicationGroups', 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": [ + "appGroup" + ] + }, + "appGroup_diagnosticSettings": { + "copy": { + "name": "appGroup_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.DesktopVirtualization/applicationGroups/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "logs": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs', 'enabled', true())))]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "appGroup" + ] + }, + "appGroup_applications": { + "copy": { + "name": "appGroup_applications", + "count": "[length(parameters('applications'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AppGroup-App-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('applications')[copyIndex()].name]" + }, + "applicationGroupName": { + "value": "[parameters('name')]" + }, + "description": "[if(contains(parameters('applications')[copyIndex()], 'description'), createObject('value', parameters('applications')[copyIndex()].description), createObject('value', ''))]", + "friendlyName": "[if(contains(parameters('applications')[copyIndex()], 'friendlyName'), createObject('value', parameters('applications')[copyIndex()].friendlyName), createObject('value', parameters('name')))]", + "filePath": { + "value": "[parameters('applications')[copyIndex()].filePath]" + }, + "commandLineSetting": "[if(contains(parameters('applications')[copyIndex()], 'commandLineSetting'), createObject('value', parameters('applications')[copyIndex()].commandLineSetting), createObject('value', 'DoNotAllow'))]", + "commandLineArguments": "[if(contains(parameters('applications')[copyIndex()], 'commandLineArguments'), createObject('value', parameters('applications')[copyIndex()].commandLineArguments), createObject('value', ''))]", + "showInPortal": "[if(contains(parameters('applications')[copyIndex()], 'showInPortal'), createObject('value', parameters('applications')[copyIndex()].showInPortal), createObject('value', false()))]", + "iconPath": "[if(contains(parameters('applications')[copyIndex()], 'iconPath'), createObject('value', parameters('applications')[copyIndex()].iconPath), createObject('value', parameters('applications')[copyIndex()].filePath))]", + "iconIndex": "[if(contains(parameters('applications')[copyIndex()], 'iconIndex'), createObject('value', parameters('applications')[copyIndex()].iconIndex), createObject('value', 0))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "16966262699054894958" + }, + "name": "Azure Virtual Desktop Application Group Application", + "description": "This module deploys an Azure Virtual Desktop Application Group Application.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "applicationGroupName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Application Group to create the application(s) in. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Application to be created in the Application Group." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of Application.." + } + }, + "friendlyName": { + "type": "string", + "metadata": { + "description": "Required. Friendly name of Application.." + } + }, + "filePath": { + "type": "string", + "metadata": { + "description": "Required. Specifies a path for the executable file for the application." + } + }, + "commandLineSetting": { + "type": "string", + "defaultValue": "DoNotAllow", + "allowedValues": [ + "Allow", + "DoNotAllow", + "Require" + ], + "metadata": { + "description": "Optional. Specifies whether this published application can be launched with command-line arguments provided by the client, command-line arguments specified at publish time, or no command-line arguments at all." + } + }, + "commandLineArguments": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Command-Line Arguments for Application." + } + }, + "showInPortal": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether to show the RemoteApp program in the RD Web Access server." + } + }, + "iconPath": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Path to icon." + } + }, + "iconIndex": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. Index of the icon." + } + } + }, + "resources": [ + { + "type": "Microsoft.DesktopVirtualization/applicationGroups/applications", + "apiVersion": "2023-09-05", + "name": "[format('{0}/{1}', parameters('applicationGroupName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "friendlyName": "[parameters('friendlyName')]", + "filePath": "[parameters('filePath')]", + "commandLineSetting": "[parameters('commandLineSetting')]", + "commandLineArguments": "[parameters('commandLineArguments')]", + "showInPortal": "[parameters('showInPortal')]", + "iconPath": "[parameters('iconPath')]", + "iconIndex": "[parameters('iconIndex')]" + } + } + ], + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the application." + }, + "value": "[resourceId('Microsoft.DesktopVirtualization/applicationGroups/applications', parameters('applicationGroupName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the application was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the application." + }, + "value": "[parameters('name')]" + } + } + } + }, + "dependsOn": [ + "appGroup" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the scaling plan." + }, + "value": "[resourceId('Microsoft.DesktopVirtualization/applicationGroups', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the scaling plan was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the scaling plan." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location of the scaling plan." + }, + "value": "[reference('appGroup', '2023-09-05', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/desktop-virtualization/application-group/tests/e2e/defaults/dependencies.bicep b/avm/res/desktop-virtualization/application-group/tests/e2e/defaults/dependencies.bicep new file mode 100644 index 0000000000..a78bd0236f --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/tests/e2e/defaults/dependencies.bicep @@ -0,0 +1,18 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Host Pool to create.') +param hostPoolName string + +resource hostPool 'Microsoft.DesktopVirtualization/hostPools@2022-09-09' = { + name: hostPoolName + location: location + properties: { + hostPoolType: 'Pooled' + loadBalancerType: 'BreadthFirst' + preferredAppGroupType: 'Desktop' + } +} + +@description('The name of the created Host Pool.') +output hostPoolName string = hostPool.name diff --git a/avm/res/desktop-virtualization/application-group/tests/e2e/defaults/main.test.bicep b/avm/res/desktop-virtualization/application-group/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..081ad4e594 --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,54 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-desktopvirtualization.applicationgroup-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation 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 = 'dvagmin' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= + +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + hostPoolName: 'dep-${namePrefix}-hp-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceLocation + applicationGroupType: 'Desktop' + hostpoolName: nestedDependencies.outputs.hostPoolName + } +}] diff --git a/avm/res/desktop-virtualization/application-group/tests/e2e/max/dependencies.bicep b/avm/res/desktop-virtualization/application-group/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..0f75ef2327 --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/tests/e2e/max/dependencies.bicep @@ -0,0 +1,29 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Host Pool to create.') +param hostPoolName string + +@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 +} + +resource hostPool 'Microsoft.DesktopVirtualization/hostPools@2022-09-09' = { + name: hostPoolName + location: location + properties: { + hostPoolType: 'Pooled' + loadBalancerType: 'BreadthFirst' + preferredAppGroupType: 'RailApplications' + } +} + +@description('The name of the created Host Pool.') +output hostPoolName string = hostPool.name + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/desktop-virtualization/application-group/tests/e2e/max/main.test.bicep b/avm/res/desktop-virtualization/application-group/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..3f2d0a2e02 --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/tests/e2e/max/main.test.bicep @@ -0,0 +1,129 @@ +targetScope = 'subscription' + +metadata name = 'Using large parameter set' +metadata description = 'This instance deploys the module with most of its features enabled.' + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-desktopvirtualization.applicationgroup-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation 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 = 'dvagmax' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= + +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + hostPoolName: 'dep-${namePrefix}-hp-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// Diagnostics +// =========== + +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-diagnosticDependencies' + params: { + storageAccountName: substring('dep${uniqueString(deployment().name, resourceLocation)}${serviceShort}03', 0, 24) + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}01' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}01' + location: resourceLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceLocation + applicationGroupType: 'RemoteApp' + applications: [ + { + commandLineArguments: '' + commandLineSetting: 'DoNotAllow' + description: 'Notepad by ARM template' + filePath: 'C:\\Windows\\System32\\notepad.exe' + friendlyName: 'Notepad' + iconIndex: 0 + iconPath: 'C:\\Windows\\System32\\notepad.exe' + name: 'notepad' + showInPortal: true + } + { + filePath: 'C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe' + friendlyName: 'Wordpad' + name: 'wordpad' + } + ] + description: 'myDescription' + hostpoolName: nestedDependencies.outputs.hostPoolName + diagnosticSettings: [ + { + name: 'customSetting' + logCategoriesAndGroups: [ + { + categoryGroup: 'allLogs' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + 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/desktop-virtualization/application-group/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/desktop-virtualization/application-group/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..a78bd0236f --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,18 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Host Pool to create.') +param hostPoolName string + +resource hostPool 'Microsoft.DesktopVirtualization/hostPools@2022-09-09' = { + name: hostPoolName + location: location + properties: { + hostPoolType: 'Pooled' + loadBalancerType: 'BreadthFirst' + preferredAppGroupType: 'Desktop' + } +} + +@description('The name of the created Host Pool.') +output hostPoolName string = hostPool.name diff --git a/avm/res/desktop-virtualization/application-group/tests/e2e/waf-aligned/main.test.bicep b/avm/res/desktop-virtualization/application-group/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..df480ca807 --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,81 @@ +targetScope = 'subscription' + +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-practices of the Well-Architected Framework.' + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-desktopvirtualization.applicationgroup-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation 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 = 'dvagwaf' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= + +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + location: resourceLocation + hostPoolName: 'dep-${namePrefix}-hp-${serviceShort}' + } +} + +// Diagnostics +// =========== + +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-diagnosticDependencies' + params: { + storageAccountName: substring('dep${uniqueString(deployment().name, resourceLocation)}${serviceShort}03', 0, 24) + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}01' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}01' + location: resourceLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}002' + location: resourceLocation + applicationGroupType: 'Desktop' + hostpoolName: nestedDependencies.outputs.hostPoolName + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/desktop-virtualization/application-group/version.json b/avm/res/desktop-virtualization/application-group/version.json new file mode 100644 index 0000000000..7245f14872 --- /dev/null +++ b/avm/res/desktop-virtualization/application-group/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] + } \ No newline at end of file