From bcdcf23f8b5545f9410d72594be5310d077e91e4 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Tue, 5 Dec 2023 20:57:57 +1000 Subject: [PATCH 01/33] . --- .../avm.res.resources.resource-group.yml | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 .github/workflows/avm.res.resources.resource-group.yml diff --git a/.github/workflows/avm.res.resources.resource-group.yml b/.github/workflows/avm.res.resources.resource-group.yml new file mode 100644 index 0000000000..09f62a9174 --- /dev/null +++ b/.github/workflows/avm.res.resources.resource-group.yml @@ -0,0 +1,83 @@ +name: "avm.res.resources.resource-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.resources.resource-group.yml" + - "avm/res/resources/resource-group/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/resources/resource-group" + workflowPath: ".github/workflows/avm.res.resources.resource-group.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: "Module" + 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 From 620ca0ae2802d1670e447ab2d25a1715b52e1b70 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 21 Dec 2023 15:25:45 +1000 Subject: [PATCH 02/33] feat: 11 carml modules --- .github/CODEOWNERS | 4 +- .../avm.res.analysis-services.server.yml | 83 + .github/workflows/avm.res.cache.redis.yml | 83 + .github/workflows/avm.res.compute.disk.yml | 83 + .github/workflows/avm.res.compute.image.yml | 83 + .../workflows/avm.res.consumption.budget.yml | 83 + .../avm.res.data-protection.backup-vault.yml | 83 + .../avm.res.databricks.access-connector.yml | 83 + .../avm.res.databricks.workspace.yml | 83 + .../avm.res.db-for-my-sql.flexible-server.yml | 83 + .../avm.res.health-bot.health-bot.yml | 83 + .../avm.res.net-app.net-app-account.yml | 83 + avm/res/analysis-services/server/README.md | 727 ++++++++ avm/res/analysis-services/server/main.bicep | 209 +++ avm/res/analysis-services/server/main.json | 419 +++++ .../server/tests/e2e/defaults/main.test.bicep | 49 + .../server/tests/e2e/max/dependencies.bicep | 13 + .../server/tests/e2e/max/main.test.bicep | 131 ++ .../tests/e2e/waf-aligned/dependencies.bicep | 13 + .../tests/e2e/waf-aligned/main.test.bicep | 114 ++ avm/res/analysis-services/server/version.json | 7 + avm/res/backup-vault/README.md | 969 +++++++++++ avm/res/backup-vault/backup-policy/README.md | 217 +++ avm/res/backup-vault/backup-policy/main.bicep | 46 + avm/res/backup-vault/backup-policy/main.json | 88 + .../backup-vault/backup-policy/version.json | 7 + avm/res/backup-vault/main.bicep | 195 +++ avm/res/backup-vault/main.json | 470 ++++++ .../tests/e2e/defaults/main.test.bicep | 49 + .../tests/e2e/max/dependencies.bicep | 16 + .../tests/e2e/max/main.test.bicep | 149 ++ .../tests/e2e/waf-aligned/dependencies.bicep | 16 + .../tests/e2e/waf-aligned/main.test.bicep | 132 ++ avm/res/backup-vault/version.json | 7 + avm/res/cache/redis/README.md | 1226 ++++++++++++++ avm/res/cache/redis/main.bicep | 410 +++++ avm/res/cache/redis/main.json | 1397 ++++++++++++++++ .../redis/tests/e2e/defaults/main.test.bicep | 48 + .../redis/tests/e2e/max/dependencies.bicep | 60 + .../cache/redis/tests/e2e/max/main.test.bicep | 121 ++ .../tests/e2e/waf-aligned/dependencies.bicep | 60 + .../tests/e2e/waf-aligned/main.test.bicep | 121 ++ avm/res/cache/redis/version.json | 7 + avm/res/compute/disk/README.md | 990 +++++++++++ avm/res/compute/disk/main.bicep | 264 +++ avm/res/compute/disk/main.json | 476 ++++++ .../disk/tests/e2e/defaults/main.test.bicep | 50 + .../disk/tests/e2e/image/dependencies.bicep | 13 + .../disk/tests/e2e/image/main.test.bicep | 78 + .../disk/tests/e2e/import/dependencies.bicep | 152 ++ .../tests/e2e/import/dependencies_rbac.bicep | 16 + .../disk/tests/e2e/import/main.test.bicep | 83 + .../disk/tests/e2e/max/dependencies.bicep | 13 + .../disk/tests/e2e/max/main.test.bicep | 89 + .../tests/e2e/waf-aligned/dependencies.bicep | 13 + .../tests/e2e/waf-aligned/main.test.bicep | 72 + avm/res/compute/disk/version.json | 7 + avm/res/compute/image/README.md | 537 ++++++ avm/res/compute/image/main.bicep | 170 ++ avm/res/compute/image/main.json | 320 ++++ .../image/tests/e2e/max/dependencies.bicep | 218 +++ .../tests/e2e/max/dependencies_rbac.bicep | 16 + .../image/tests/e2e/max/main.test.bicep | 97 ++ .../tests/e2e/waf-aligned/dependencies.bicep | 218 +++ .../e2e/waf-aligned/dependencies_rbac.bicep | 16 + .../tests/e2e/waf-aligned/main.test.bicep | 80 + avm/res/compute/image/version.json | 7 + avm/res/consumption/budget/README.md | 405 +++++ avm/res/consumption/budget/main.bicep | 111 ++ avm/res/consumption/budget/main.json | 193 +++ .../budget/tests/e2e/defaults/main.test.bicep | 34 + .../budget/tests/e2e/max/main.test.bicep | 41 + .../tests/e2e/waf-aligned/main.test.bicep | 41 + avm/res/consumption/budget/version.json | 7 + avm/res/databricks/access-connector/README.md | 509 ++++++ .../databricks/access-connector/main.bicep | 140 ++ avm/res/databricks/access-connector/main.json | 287 ++++ .../tests/e2e/defaults/main.test.bicep | 49 + .../tests/e2e/max/dependencies.bicep | 16 + .../tests/e2e/max/main.test.bicep | 90 + .../tests/e2e/waf-aligned/dependencies.bicep | 16 + .../tests/e2e/waf-aligned/main.test.bicep | 73 + .../databricks/access-connector/version.json | 7 + avm/res/databricks/workspace/README.md | 1463 +++++++++++++++++ avm/res/databricks/workspace/main.bicep | 487 ++++++ avm/res/databricks/workspace/main.json | 1439 ++++++++++++++++ .../tests/e2e/defaults/main.test.bicep | 49 + .../tests/e2e/max/dependencies.bicep | 368 +++++ .../workspace/tests/e2e/max/main.test.bicep | 167 ++ .../tests/e2e/waf-aligned/dependencies.bicep | 368 +++++ .../tests/e2e/waf-aligned/main.test.bicep | 150 ++ avm/res/databricks/workspace/version.json | 7 + avm/res/flexible-server/README.md | 1286 +++++++++++++++ .../flexible-server/administrator/README.md | 105 ++ .../flexible-server/administrator/main.bicep | 61 + .../flexible-server/administrator/main.json | 112 ++ .../administrator/version.json | 7 + avm/res/flexible-server/database/README.md | 98 ++ avm/res/flexible-server/database/main.bicep | 55 + avm/res/flexible-server/database/main.json | 104 ++ avm/res/flexible-server/database/version.json | 7 + .../flexible-server/firewall-rule/README.md | 87 + .../flexible-server/firewall-rule/main.bicep | 52 + .../flexible-server/firewall-rule/main.json | 95 ++ .../firewall-rule/version.json | 7 + avm/res/flexible-server/main.bicep | 459 ++++++ avm/res/flexible-server/main.json | 1177 +++++++++++++ .../tests/e2e/defaults/main.test.bicep | 57 + .../tests/e2e/private/dependencies.bicep | 74 + .../tests/e2e/private/main.test.bicep | 144 ++ .../tests/e2e/public/dependencies1.bicep | 46 + .../tests/e2e/public/dependencies2.bicep | 120 ++ .../tests/e2e/public/main.test.bicep | 179 ++ avm/res/flexible-server/version.json | 7 + avm/res/health-bot/health-bot/README.md | 516 ++++++ avm/res/health-bot/health-bot/main.bicep | 145 ++ avm/res/health-bot/health-bot/main.json | 286 ++++ .../tests/e2e/defaults/main.test.bicep | 50 + .../tests/e2e/max/dependencies.bicep | 16 + .../health-bot/tests/e2e/max/main.test.bicep | 89 + .../tests/e2e/waf-aligned/dependencies.bicep | 16 + .../tests/e2e/waf-aligned/main.test.bicep | 72 + avm/res/health-bot/health-bot/version.json | 7 + avm/res/net-app/net-app-account/README.md | 849 ++++++++++ .../net-app-account/capacity-pool/README.md | 257 +++ .../net-app-account/capacity-pool/main.bicep | 164 ++ .../net-app-account/capacity-pool/main.json | 609 +++++++ .../capacity-pool/version.json | 7 + .../capacity-pool/volume/README.md | 241 +++ .../capacity-pool/volume/main.bicep | 141 ++ .../capacity-pool/volume/main.json | 278 ++++ .../capacity-pool/volume/version.json | 7 + avm/res/net-app/net-app-account/main.bicep | 189 +++ avm/res/net-app/net-app-account/main.json | 987 +++++++++++ .../tests/e2e/defaults/main.test.bicep | 48 + .../tests/e2e/nfs3/dependencies.bicep | 49 + .../tests/e2e/nfs3/main.test.bicep | 146 ++ .../tests/e2e/nfs41/dependencies.bicep | 52 + .../tests/e2e/nfs41/main.test.bicep | 157 ++ avm/res/net-app/net-app-account/version.json | 7 + 140 files changed, 28644 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/avm.res.analysis-services.server.yml create mode 100644 .github/workflows/avm.res.cache.redis.yml create mode 100644 .github/workflows/avm.res.compute.disk.yml create mode 100644 .github/workflows/avm.res.compute.image.yml create mode 100644 .github/workflows/avm.res.consumption.budget.yml create mode 100644 .github/workflows/avm.res.data-protection.backup-vault.yml create mode 100644 .github/workflows/avm.res.databricks.access-connector.yml create mode 100644 .github/workflows/avm.res.databricks.workspace.yml create mode 100644 .github/workflows/avm.res.db-for-my-sql.flexible-server.yml create mode 100644 .github/workflows/avm.res.health-bot.health-bot.yml create mode 100644 .github/workflows/avm.res.net-app.net-app-account.yml create mode 100644 avm/res/analysis-services/server/README.md create mode 100644 avm/res/analysis-services/server/main.bicep create mode 100644 avm/res/analysis-services/server/main.json create mode 100644 avm/res/analysis-services/server/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/analysis-services/server/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/analysis-services/server/tests/e2e/max/main.test.bicep create mode 100644 avm/res/analysis-services/server/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/analysis-services/server/version.json create mode 100644 avm/res/backup-vault/README.md create mode 100644 avm/res/backup-vault/backup-policy/README.md create mode 100644 avm/res/backup-vault/backup-policy/main.bicep create mode 100644 avm/res/backup-vault/backup-policy/main.json create mode 100644 avm/res/backup-vault/backup-policy/version.json create mode 100644 avm/res/backup-vault/main.bicep create mode 100644 avm/res/backup-vault/main.json create mode 100644 avm/res/backup-vault/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/backup-vault/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/backup-vault/tests/e2e/max/main.test.bicep create mode 100644 avm/res/backup-vault/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/backup-vault/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/backup-vault/version.json create mode 100644 avm/res/cache/redis/README.md create mode 100644 avm/res/cache/redis/main.bicep create mode 100644 avm/res/cache/redis/main.json create mode 100644 avm/res/cache/redis/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/cache/redis/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/cache/redis/tests/e2e/max/main.test.bicep create mode 100644 avm/res/cache/redis/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/cache/redis/version.json 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/dependencies.bicep create mode 100644 avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/compute/disk/version.json create mode 100644 avm/res/compute/image/README.md create mode 100644 avm/res/compute/image/main.bicep create mode 100644 avm/res/compute/image/main.json create mode 100644 avm/res/compute/image/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/compute/image/tests/e2e/max/dependencies_rbac.bicep create mode 100644 avm/res/compute/image/tests/e2e/max/main.test.bicep create mode 100644 avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/compute/image/tests/e2e/waf-aligned/dependencies_rbac.bicep create mode 100644 avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/compute/image/version.json create mode 100644 avm/res/consumption/budget/README.md create mode 100644 avm/res/consumption/budget/main.bicep create mode 100644 avm/res/consumption/budget/main.json create mode 100644 avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/consumption/budget/tests/e2e/max/main.test.bicep create mode 100644 avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/consumption/budget/version.json create mode 100644 avm/res/databricks/access-connector/README.md create mode 100644 avm/res/databricks/access-connector/main.bicep create mode 100644 avm/res/databricks/access-connector/main.json create mode 100644 avm/res/databricks/access-connector/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/databricks/access-connector/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/databricks/access-connector/tests/e2e/max/main.test.bicep create mode 100644 avm/res/databricks/access-connector/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/databricks/access-connector/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/databricks/access-connector/version.json create mode 100644 avm/res/databricks/workspace/README.md create mode 100644 avm/res/databricks/workspace/main.bicep create mode 100644 avm/res/databricks/workspace/main.json create mode 100644 avm/res/databricks/workspace/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/databricks/workspace/tests/e2e/max/main.test.bicep create mode 100644 avm/res/databricks/workspace/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/databricks/workspace/version.json create mode 100644 avm/res/flexible-server/README.md create mode 100644 avm/res/flexible-server/administrator/README.md create mode 100644 avm/res/flexible-server/administrator/main.bicep create mode 100644 avm/res/flexible-server/administrator/main.json create mode 100644 avm/res/flexible-server/administrator/version.json create mode 100644 avm/res/flexible-server/database/README.md create mode 100644 avm/res/flexible-server/database/main.bicep create mode 100644 avm/res/flexible-server/database/main.json create mode 100644 avm/res/flexible-server/database/version.json create mode 100644 avm/res/flexible-server/firewall-rule/README.md create mode 100644 avm/res/flexible-server/firewall-rule/main.bicep create mode 100644 avm/res/flexible-server/firewall-rule/main.json create mode 100644 avm/res/flexible-server/firewall-rule/version.json create mode 100644 avm/res/flexible-server/main.bicep create mode 100644 avm/res/flexible-server/main.json create mode 100644 avm/res/flexible-server/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/flexible-server/tests/e2e/private/dependencies.bicep create mode 100644 avm/res/flexible-server/tests/e2e/private/main.test.bicep create mode 100644 avm/res/flexible-server/tests/e2e/public/dependencies1.bicep create mode 100644 avm/res/flexible-server/tests/e2e/public/dependencies2.bicep create mode 100644 avm/res/flexible-server/tests/e2e/public/main.test.bicep create mode 100644 avm/res/flexible-server/version.json create mode 100644 avm/res/health-bot/health-bot/README.md create mode 100644 avm/res/health-bot/health-bot/main.bicep create mode 100644 avm/res/health-bot/health-bot/main.json create mode 100644 avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/health-bot/health-bot/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep create mode 100644 avm/res/health-bot/health-bot/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/health-bot/health-bot/version.json create mode 100644 avm/res/net-app/net-app-account/README.md create mode 100644 avm/res/net-app/net-app-account/capacity-pool/README.md create mode 100644 avm/res/net-app/net-app-account/capacity-pool/main.bicep create mode 100644 avm/res/net-app/net-app-account/capacity-pool/main.json create mode 100644 avm/res/net-app/net-app-account/capacity-pool/version.json create mode 100644 avm/res/net-app/net-app-account/capacity-pool/volume/README.md create mode 100644 avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep create mode 100644 avm/res/net-app/net-app-account/capacity-pool/volume/main.json create mode 100644 avm/res/net-app/net-app-account/capacity-pool/volume/version.json create mode 100644 avm/res/net-app/net-app-account/main.bicep create mode 100644 avm/res/net-app/net-app-account/main.json create mode 100644 avm/res/net-app/net-app-account/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/net-app/net-app-account/tests/e2e/nfs3/dependencies.bicep create mode 100644 avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep create mode 100644 avm/res/net-app/net-app-account/tests/e2e/nfs41/dependencies.bicep create mode 100644 avm/res/net-app/net-app-account/tests/e2e/nfs41/main.test.bicep create mode 100644 avm/res/net-app/net-app-account/version.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8b095bf930..ffd02702cf 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 @@ -30,7 +30,7 @@ /avm/res/compute/ssh-public-key/ @Azure/avm-res-compute-sshpublickey-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/compute/virtual-machine/ @Azure/avm-res-compute-virtualmachine-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/compute/virtual-machine-scale-set/ @Azure/avm-res-compute-virtualmachinescaleset-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/consumption/budget/ @Azure/avm-res-consumption-budget-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/consumption/budget/ @Azure/avm-res-consumption-budget-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/container-instance/container-group/ @Azure/avm-res-containerinstance-containergroup-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/container-registry/registry/ @Azure/avm-res-containerregistry-registry-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/container-service/managed-cluster/ @Azure/avm-res-containerservice-managedcluster-module-owners-bicep @Azure/avm-core-team-technical-bicep diff --git a/.github/workflows/avm.res.analysis-services.server.yml b/.github/workflows/avm.res.analysis-services.server.yml new file mode 100644 index 0000000000..5e52fd311b --- /dev/null +++ b/.github/workflows/avm.res.analysis-services.server.yml @@ -0,0 +1,83 @@ +name: "avm.res.analysis-services.server" + +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.analysis-services.server.yml" + - "avm/res/analysis-services/server/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/analysis-services/server" + workflowPath: ".github/workflows/avm.res.analysis-services.server.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/.github/workflows/avm.res.cache.redis.yml b/.github/workflows/avm.res.cache.redis.yml new file mode 100644 index 0000000000..fa9268c58d --- /dev/null +++ b/.github/workflows/avm.res.cache.redis.yml @@ -0,0 +1,83 @@ +name: "avm.res.cache.redis" + +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.cache.redis.yml" + - "avm/res/cache/redis/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/cache/redis" + workflowPath: ".github/workflows/avm.res.cache.redis.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/.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/.github/workflows/avm.res.compute.image.yml b/.github/workflows/avm.res.compute.image.yml new file mode 100644 index 0000000000..2957b5a5c4 --- /dev/null +++ b/.github/workflows/avm.res.compute.image.yml @@ -0,0 +1,83 @@ +name: "avm.res.compute.image" + +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.image.yml" + - "avm/res/compute/image/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/compute/image" + workflowPath: ".github/workflows/avm.res.compute.image.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/.github/workflows/avm.res.consumption.budget.yml b/.github/workflows/avm.res.consumption.budget.yml new file mode 100644 index 0000000000..08682eb0e0 --- /dev/null +++ b/.github/workflows/avm.res.consumption.budget.yml @@ -0,0 +1,83 @@ +name: "avm.res.consumption.budget" + +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.consumption.budget.yml" + - "avm/res/consumption/budget/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/consumption/budget" + workflowPath: ".github/workflows/avm.res.consumption.budget.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/.github/workflows/avm.res.data-protection.backup-vault.yml b/.github/workflows/avm.res.data-protection.backup-vault.yml new file mode 100644 index 0000000000..c96c595cc2 --- /dev/null +++ b/.github/workflows/avm.res.data-protection.backup-vault.yml @@ -0,0 +1,83 @@ +name: "avm.res.data-protection.backup-vault" + +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.data-protection/backup-vault.yml" + - "avm/res/data-protection/backup-vault/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/data-protection/backup-vault" + workflowPath: ".github/workflows/avm.res.data-protection/backup-vault.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/.github/workflows/avm.res.databricks.access-connector.yml b/.github/workflows/avm.res.databricks.access-connector.yml new file mode 100644 index 0000000000..1621066c20 --- /dev/null +++ b/.github/workflows/avm.res.databricks.access-connector.yml @@ -0,0 +1,83 @@ +name: "avm.res.databricks.access-connector" + +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.databricks/access-connector.yml" + - "avm/res/databricks/access-connector/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/databricks/access-connector" + workflowPath: ".github/workflows/avm.res.databricks/access-connector.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/.github/workflows/avm.res.databricks.workspace.yml b/.github/workflows/avm.res.databricks.workspace.yml new file mode 100644 index 0000000000..58e0e93390 --- /dev/null +++ b/.github/workflows/avm.res.databricks.workspace.yml @@ -0,0 +1,83 @@ +name: "avm.res.databricks.workspace" + +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.databricks/workspace.yml" + - "avm/res/databricks/workspace/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/databricks/workspace" + workflowPath: ".github/workflows/avm.res.databricks/workspace.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/.github/workflows/avm.res.db-for-my-sql.flexible-server.yml b/.github/workflows/avm.res.db-for-my-sql.flexible-server.yml new file mode 100644 index 0000000000..eb1a40e796 --- /dev/null +++ b/.github/workflows/avm.res.db-for-my-sql.flexible-server.yml @@ -0,0 +1,83 @@ +name: "avm.res.db-for-my-sql.flexible-server" + +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.db-for-my-sql/flexible-server.yml" + - "avm/res/db-for-my-sql/flexible-server/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/db-for-my-sql/flexible-server" + workflowPath: ".github/workflows/avm.res.db-for-my-sql/flexible-server.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/.github/workflows/avm.res.health-bot.health-bot.yml b/.github/workflows/avm.res.health-bot.health-bot.yml new file mode 100644 index 0000000000..a4d65b00bd --- /dev/null +++ b/.github/workflows/avm.res.health-bot.health-bot.yml @@ -0,0 +1,83 @@ +name: "avm.res.health-bot.health-bot" + +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.health-bot/health-bot.yml" + - "avm/res/health-bot/health-bot/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/health-bot/health-bot" + workflowPath: ".github/workflows/avm.res.health-bot/health-bot.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/.github/workflows/avm.res.net-app.net-app-account.yml b/.github/workflows/avm.res.net-app.net-app-account.yml new file mode 100644 index 0000000000..8bc8f3b70b --- /dev/null +++ b/.github/workflows/avm.res.net-app.net-app-account.yml @@ -0,0 +1,83 @@ +name: "avm.res.net-app.net-app-account" + +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.net-app/net-app-account.yml" + - "avm/res/net-app/net-app-account/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/net-app/net-app-account" + workflowPath: ".github/workflows/avm.res.net-app/net-app-account.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/analysis-services/server/README.md b/avm/res/analysis-services/server/README.md new file mode 100644 index 0000000000..e98e2db197 --- /dev/null +++ b/avm/res/analysis-services/server/README.md @@ -0,0 +1,727 @@ +# Analysis Services Servers `[Microsoft.AnalysisServices/servers]` + +This module deploys an Analysis Services Server. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.AnalysisServices/servers` | [2017-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.AnalysisServices/2017-08-01/servers) | +| `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.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:bicep/modules/analysis-services.server:1.0.0`. + +- [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 server 'br:bicep/modules/analysis-services.server:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-assmin' + params: { + // Required parameters + name: 'assmin' + // Non-required parameters + enableDefaultTelemetry: '' + } +} +``` + +
+

+ +

+ +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": "assmin" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module server 'br:bicep/modules/analysis-services.server:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-assmax' + params: { + // Required parameters + name: 'assmax' + // Non-required parameters + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + logCategoriesAndGroups: [ + { + category: 'Engine' + } + { + category: 'Service' + } + ] + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + enableDefaultTelemetry: '' + firewallSettings: { + enablePowerBIService: true + firewallRules: [ + { + firewallRuleName: 'AllowFromAll' + rangeEnd: '255.255.255.255' + rangeStart: '0.0.0.0' + } + ] + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + skuCapacity: 1 + skuName: 'S0' + 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": "assmax" + }, + // Non-required parameters + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "logCategoriesAndGroups": [ + { + "category": "Engine" + }, + { + "category": "Service" + } + ], + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "enableDefaultTelemetry": { + "value": "" + }, + "firewallSettings": { + "value": { + "enablePowerBIService": true, + "firewallRules": [ + { + "firewallRuleName": "AllowFromAll", + "rangeEnd": "255.255.255.255", + "rangeStart": "0.0.0.0" + } + ] + } + }, + "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": "" + } + ] + }, + "skuCapacity": { + "value": 1 + }, + "skuName": { + "value": "S0" + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module server 'br:bicep/modules/analysis-services.server:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-asswaf' + params: { + // Required parameters + name: 'asswaf' + // Non-required parameters + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + logCategoriesAndGroups: [ + { + category: 'Engine' + } + { + category: 'Service' + } + ] + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + enableDefaultTelemetry: '' + firewallSettings: { + enablePowerBIService: true + firewallRules: [ + { + firewallRuleName: 'AllowFromAll' + rangeEnd: '255.255.255.255' + rangeStart: '0.0.0.0' + } + ] + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + skuCapacity: 1 + skuName: 'S0' + 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": "asswaf" + }, + // Non-required parameters + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "logCategoriesAndGroups": [ + { + "category": "Engine" + }, + { + "category": "Service" + } + ], + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "enableDefaultTelemetry": { + "value": "" + }, + "firewallSettings": { + "value": { + "enablePowerBIService": true, + "firewallRules": [ + { + "firewallRuleName": "AllowFromAll", + "rangeEnd": "255.255.255.255", + "rangeStart": "0.0.0.0" + } + ] + } + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "skuCapacity": { + "value": 1 + }, + "skuName": { + "value": "S0" + }, + "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 Azure Analysis Services server to create. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`firewallSettings`](#parameter-firewallsettings) | object | The inbound firewall rules to define on the server. If not specified, firewall is disabled. | +| [`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. | +| [`skuCapacity`](#parameter-skucapacity) | int | The total number of query replica scale-out instances. | +| [`skuName`](#parameter-skuname) | string | The SKU name of the Azure Analysis Services server to create. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | + +### Parameter: `name` + +The name of the Azure Analysis Services server to create. + +- Required: Yes +- Type: string + +### 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. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. | +| [`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.metricCategories` + +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.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: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `firewallSettings` + +The inbound firewall rules to define on the server. If not specified, firewall is disabled. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enablePowerBIService: true + firewallRules: [ + { + firewallRuleName: 'AllowFromAll' + rangeEnd: '255.255.255.255' + rangeStart: '0.0.0.0' + } + ] + } + ``` + +### 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: `skuCapacity` + +The total number of query replica scale-out instances. + +- Required: No +- Type: int +- Default: `1` + +### Parameter: `skuName` + +The SKU name of the Azure Analysis Services server to create. + +- Required: No +- Type: string +- Default: `'S0'` + +### Parameter: `tags` + +Tags of the resource. + +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the analysis service. | +| `resourceGroupName` | string | The resource group the analysis service was deployed into. | +| `resourceId` | string | The resource ID of the analysis service. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/analysis-services/server/main.bicep b/avm/res/analysis-services/server/main.bicep new file mode 100644 index 0000000000..0d4d966a3b --- /dev/null +++ b/avm/res/analysis-services/server/main.bicep @@ -0,0 +1,209 @@ +metadata name = 'Analysis Services Servers' +metadata description = 'This module deploys an Analysis Services Server.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the Azure Analysis Services server to create.') +param name string + +@description('Optional. The SKU name of the Azure Analysis Services server to create.') +param skuName string = 'S0' + +@description('Optional. The total number of query replica scale-out instances.') +param skuCapacity int = 1 + +@description('Optional. The inbound firewall rules to define on the server. If not specified, firewall is disabled.') +param firewallSettings object = { + firewallRules: [ + { + firewallRuleName: 'AllowFromAll' + rangeStart: '0.0.0.0' + rangeEnd: '255.255.255.255' + } + ] + enablePowerBIService: true +} + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +@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 resource.') +param tags object? + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource server 'Microsoft.AnalysisServices/servers@2017-08-01' = { + name: name + location: location + tags: tags + sku: { + name: skuName + capacity: skuCapacity + } + properties: { + ipV4FirewallSettings: firewallSettings + } +} + +resource server_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: server +} + +resource server_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 + metrics: diagnosticSetting.?metricCategories ?? [ + { + category: 'AllMetrics' + timeGrain: null + enabled: true + } + ] + logs: diagnosticSetting.?logCategoriesAndGroups ?? [ + { + categoryGroup: 'AllLogs' + enabled: true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: server +}] + +resource server_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(server.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: server +}] + +@description('The name of the analysis service.') +output name string = server.name + +@description('The resource ID of the analysis service.') +output resourceId string = server.id + +@description('The resource group the analysis service was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = server.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? +}[]? + +type diagnosticSettingType = { + @description('Optional. The name of diagnostic setting.') + name: string? + + @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: { + @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? + + @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? + }[]? + + @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + metricCategories: { + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to \'AllMetrics\' to collect all metrics.') + category: string + }[]? + + @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')? + + @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? + + @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? + + @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? + + @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? + + @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/analysis-services/server/main.json b/avm/res/analysis-services/server/main.json new file mode 100644 index 0000000000..b3e4158662 --- /dev/null +++ b/avm/res/analysis-services/server/main.json @@ -0,0 +1,419 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "1605417065240868452" + }, + "name": "Analysis Services Servers", + "description": "This module deploys an Analysis Services Server.", + "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." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to 'AllMetrics' to collect all metrics." + } + } + } + }, + "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", + "metadata": { + "description": "Required. The name of the Azure Analysis Services server to create." + } + }, + "skuName": { + "type": "string", + "defaultValue": "S0", + "metadata": { + "description": "Optional. The SKU name of the Azure Analysis Services server to create." + } + }, + "skuCapacity": { + "type": "int", + "defaultValue": 1, + "metadata": { + "description": "Optional. The total number of query replica scale-out instances." + } + }, + "firewallSettings": { + "type": "object", + "defaultValue": { + "firewallRules": [ + { + "firewallRuleName": "AllowFromAll", + "rangeStart": "0.0.0.0", + "rangeEnd": "255.255.255.255" + } + ], + "enablePowerBIService": true + }, + "metadata": { + "description": "Optional. The inbound firewall rules to define on the server. If not specified, firewall is disabled." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "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 resource." + } + }, + "enableDefaultTelemetry": { + "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')]", + "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": { + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "server": { + "type": "Microsoft.AnalysisServices/servers", + "apiVersion": "2017-08-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('skuName')]", + "capacity": "[parameters('skuCapacity')]" + }, + "properties": { + "ipV4FirewallSettings": "[parameters('firewallSettings')]" + } + }, + "server_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.AnalysisServices/servers/{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": [ + "server" + ] + }, + "server_diagnosticSettings": { + "copy": { + "name": "server_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.AnalysisServices/servers/{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')]", + "metrics": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics', 'timeGrain', null(), 'enabled', true())))]", + "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": [ + "server" + ] + }, + "server_roleAssignments": { + "copy": { + "name": "server_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.AnalysisServices/servers/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.AnalysisServices/servers', 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": [ + "server" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the analysis service." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the analysis service." + }, + "value": "[resourceId('Microsoft.AnalysisServices/servers', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the analysis service was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('server', '2017-08-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/analysis-services/server/tests/e2e/defaults/main.test.bicep b/avm/res/analysis-services/server/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..d068d9795e --- /dev/null +++ b/avm/res/analysis-services/server/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,49 @@ +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}-analysisservices.servers-${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 = 'assmin' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}' + } +}] diff --git a/avm/res/analysis-services/server/tests/e2e/max/dependencies.bicep b/avm/res/analysis-services/server/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..29b9641692 --- /dev/null +++ b/avm/res/analysis-services/server/tests/e2e/max/dependencies.bicep @@ -0,0 +1,13 @@ +@description('Required. The name of the managed identity to create.') +param managedIdentityName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +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/analysis-services/server/tests/e2e/max/main.test.bicep b/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..93bfb2efaa --- /dev/null +++ b/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep @@ -0,0 +1,131 @@ +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}-analysisservices.servers-${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 = 'assmax' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}azsa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${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: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + skuName: 'S0' + skuCapacity: 1 + firewallSettings: { + firewallRules: [ + { + firewallRuleName: 'AllowFromAll' + rangeStart: '0.0.0.0' + rangeEnd: '255.255.255.255' + } + ] + enablePowerBIService: true + } + 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' + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + logCategoriesAndGroups: [ + { + category: 'Engine' + } + { + category: 'Service' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/analysis-services/server/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/analysis-services/server/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..29b9641692 --- /dev/null +++ b/avm/res/analysis-services/server/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,13 @@ +@description('Required. The name of the managed identity to create.') +param managedIdentityName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +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/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep b/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..705eaf124d --- /dev/null +++ b/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,114 @@ +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}-analysisservices.servers-${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 = 'asswaf' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}azsa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${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: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + skuName: 'S0' + skuCapacity: 1 + firewallSettings: { + firewallRules: [ + { + firewallRuleName: 'AllowFromAll' + rangeStart: '0.0.0.0' + rangeEnd: '255.255.255.255' + } + ] + enablePowerBIService: true + } + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + logCategoriesAndGroups: [ + { + category: 'Engine' + } + { + category: 'Service' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/analysis-services/server/version.json b/avm/res/analysis-services/server/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/analysis-services/server/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/backup-vault/README.md b/avm/res/backup-vault/README.md new file mode 100644 index 0000000000..3744f13387 --- /dev/null +++ b/avm/res/backup-vault/README.md @@ -0,0 +1,969 @@ +# Data Protection Backup Vaults `[Microsoft.DataProtection/backupVaults]` + +This module deploys a Data Protection Backup Vault. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Notes](#Notes) + +## 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.DataProtection/backupVaults` | [2023-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DataProtection/backupVaults) | +| `Microsoft.DataProtection/backupVaults/backupPolicies` | [2023-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DataProtection/backupVaults/backupPolicies) | + +## 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:bicep/modules/data-protection.backup-vault:1.0.0`. + +- [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 backupVault 'br:bicep/modules/data-protection.backup-vault:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-dpbvmin' + params: { + // Required parameters + name: 'dpbvmin001' + // Non-required parameters + enableDefaultTelemetry: '' + } +} +``` + +
+

+ +

+ +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": "dpbvmin001" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module backupVault 'br:bicep/modules/data-protection.backup-vault:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-dpbvmax' + params: { + // Required parameters + name: 'dpbvmax001' + // Non-required parameters + azureMonitorAlertSettingsAlertsForAllJobFailures: 'Disabled' + backupPolicies: [ + { + name: 'DefaultPolicy' + properties: { + datasourceTypes: [ + 'Microsoft.Compute/disks' + ] + objectType: 'BackupPolicy' + policyRules: [ + { + backupParameters: { + backupType: 'Incremental' + objectType: 'AzureBackupParams' + } + dataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + name: 'BackupDaily' + objectType: 'AzureBackupRule' + trigger: { + objectType: 'ScheduleBasedTriggerContext' + schedule: { + repeatingTimeIntervals: [ + 'R/2022-05-31T23:30:00+01:00/P1D' + ] + timeZone: 'W. Europe Standard Time' + } + taggingCriteria: [ + { + isDefault: true + taggingPriority: 99 + tagInfo: { + id: 'Default_' + tagName: 'Default' + } + } + ] + } + } + { + isDefault: true + lifecycles: [ + { + deleteAfter: { + duration: 'P7D' + objectType: 'AbsoluteDeleteOption' + } + sourceDataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + targetDataStoreCopySettings: [] + } + ] + name: 'Default' + objectType: 'AzureRetentionRule' + } + ] + } + } + ] + enableDefaultTelemetry: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + } + 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": "dpbvmax001" + }, + // Non-required parameters + "azureMonitorAlertSettingsAlertsForAllJobFailures": { + "value": "Disabled" + }, + "backupPolicies": { + "value": [ + { + "name": "DefaultPolicy", + "properties": { + "datasourceTypes": [ + "Microsoft.Compute/disks" + ], + "objectType": "BackupPolicy", + "policyRules": [ + { + "backupParameters": { + "backupType": "Incremental", + "objectType": "AzureBackupParams" + }, + "dataStore": { + "dataStoreType": "OperationalStore", + "objectType": "DataStoreInfoBase" + }, + "name": "BackupDaily", + "objectType": "AzureBackupRule", + "trigger": { + "objectType": "ScheduleBasedTriggerContext", + "schedule": { + "repeatingTimeIntervals": [ + "R/2022-05-31T23:30:00+01:00/P1D" + ], + "timeZone": "W. Europe Standard Time" + }, + "taggingCriteria": [ + { + "isDefault": true, + "taggingPriority": 99, + "tagInfo": { + "id": "Default_", + "tagName": "Default" + } + } + ] + } + }, + { + "isDefault": true, + "lifecycles": [ + { + "deleteAfter": { + "duration": "P7D", + "objectType": "AbsoluteDeleteOption" + }, + "sourceDataStore": { + "dataStoreType": "OperationalStore", + "objectType": "DataStoreInfoBase" + }, + "targetDataStoreCopySettings": [] + } + ], + "name": "Default", + "objectType": "AzureRetentionRule" + } + ] + } + } + ] + }, + "enableDefaultTelemetry": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module backupVault 'br:bicep/modules/data-protection.backup-vault:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-dpbvwaf' + params: { + // Required parameters + name: 'dpbvwaf001' + // Non-required parameters + azureMonitorAlertSettingsAlertsForAllJobFailures: 'Disabled' + backupPolicies: [ + { + name: 'DefaultPolicy' + properties: { + datasourceTypes: [ + 'Microsoft.Compute/disks' + ] + objectType: 'BackupPolicy' + policyRules: [ + { + backupParameters: { + backupType: 'Incremental' + objectType: 'AzureBackupParams' + } + dataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + name: 'BackupDaily' + objectType: 'AzureBackupRule' + trigger: { + objectType: 'ScheduleBasedTriggerContext' + schedule: { + repeatingTimeIntervals: [ + 'R/2022-05-31T23:30:00+01:00/P1D' + ] + timeZone: 'W. Europe Standard Time' + } + taggingCriteria: [ + { + isDefault: true + taggingPriority: 99 + tagInfo: { + id: 'Default_' + tagName: 'Default' + } + } + ] + } + } + { + isDefault: true + lifecycles: [ + { + deleteAfter: { + duration: 'P7D' + objectType: 'AbsoluteDeleteOption' + } + sourceDataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + targetDataStoreCopySettings: [] + } + ] + name: 'Default' + objectType: 'AzureRetentionRule' + } + ] + } + } + ] + enableDefaultTelemetry: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + } + 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": "dpbvwaf001" + }, + // Non-required parameters + "azureMonitorAlertSettingsAlertsForAllJobFailures": { + "value": "Disabled" + }, + "backupPolicies": { + "value": [ + { + "name": "DefaultPolicy", + "properties": { + "datasourceTypes": [ + "Microsoft.Compute/disks" + ], + "objectType": "BackupPolicy", + "policyRules": [ + { + "backupParameters": { + "backupType": "Incremental", + "objectType": "AzureBackupParams" + }, + "dataStore": { + "dataStoreType": "OperationalStore", + "objectType": "DataStoreInfoBase" + }, + "name": "BackupDaily", + "objectType": "AzureBackupRule", + "trigger": { + "objectType": "ScheduleBasedTriggerContext", + "schedule": { + "repeatingTimeIntervals": [ + "R/2022-05-31T23:30:00+01:00/P1D" + ], + "timeZone": "W. Europe Standard Time" + }, + "taggingCriteria": [ + { + "isDefault": true, + "taggingPriority": 99, + "tagInfo": { + "id": "Default_", + "tagName": "Default" + } + } + ] + } + }, + { + "isDefault": true, + "lifecycles": [ + { + "deleteAfter": { + "duration": "P7D", + "objectType": "AbsoluteDeleteOption" + }, + "sourceDataStore": { + "dataStoreType": "OperationalStore", + "objectType": "DataStoreInfoBase" + }, + "targetDataStoreCopySettings": [] + } + ], + "name": "Default", + "objectType": "AzureRetentionRule" + } + ] + } + } + ] + }, + "enableDefaultTelemetry": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true + } + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Backup Vault. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`azureMonitorAlertSettingsAlertsForAllJobFailures`](#parameter-azuremonitoralertsettingsalertsforalljobfailures) | string | Settings for Azure Monitor based alerts for job failures. | +| [`backupPolicies`](#parameter-backuppolicies) | array | List of all backup policies. | +| [`dataStoreType`](#parameter-datastoretype) | string | The datastore type to use. ArchiveStore does not support ZoneRedundancy. | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`featureSettings`](#parameter-featuresettings) | object | Feature settings for the backup vault. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`securitySettings`](#parameter-securitysettings) | object | Security settings for the backup vault. | +| [`tags`](#parameter-tags) | object | Tags of the Recovery Service Vault resource. | +| [`type`](#parameter-type) | string | The vault redundancy level to use. | + +### Parameter: `name` + +Name of the Backup Vault. + +- Required: Yes +- Type: string + +### Parameter: `azureMonitorAlertSettingsAlertsForAllJobFailures` + +Settings for Azure Monitor based alerts for job failures. + +- Required: No +- Type: string +- Default: `'Enabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `backupPolicies` + +List of all backup policies. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `dataStoreType` + +The datastore type to use. ArchiveStore does not support ZoneRedundancy. + +- Required: No +- Type: string +- Default: `'VaultStore'` +- Allowed: + ```Bicep + [ + 'ArchiveStore' + 'OperationalStore' + 'VaultStore' + ] + ``` + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `featureSettings` + +Feature settings for the backup vault. + +- Required: No +- Type: object +- Default: `{}` + +### 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: `managedIdentities` + +The managed identity definition for this resource. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | + +### Parameter: `managedIdentities.systemAssigned` + +Enables system assigned managed identity on the resource. + +- Required: No +- Type: bool + +### 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: `securitySettings` + +Security settings for the backup vault. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `tags` + +Tags of the Recovery Service Vault resource. + +- Required: No +- Type: object + +### Parameter: `type` + +The vault redundancy level to use. + +- Required: No +- Type: string +- Default: `'GeoRedundant'` +- Allowed: + ```Bicep + [ + 'GeoRedundant' + 'LocallyRedundant' + 'ZoneRedundant' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The Name of the backup vault. | +| `resourceGroupName` | string | The name of the resource group the recovery services vault was created in. | +| `resourceId` | string | The resource ID of the backup vault. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | + +## Cross-referenced modules + +_None_ + +## Notes + +### Parameter Usage: `backupPolicies` + +Create backup policies in the backupvault. + +

+ +Parameter JSON format +```json + "backupPolicies": { + "value": [ + { + "name": "DefaultPolicy", + "properties": { + "policyRules": [ + { + "backupParameters": { + "backupType": "Incremental", + "objectType": "AzureBackupParams" + }, + "trigger": { + "schedule": { + "repeatingTimeIntervals": [ + "R/2022-05-31T23:30:00+01:00/P1D" + ], + "timeZone": "W. Europe Standard Time" + }, + "taggingCriteria": [ + { + "tagInfo": { + "tagName": "Default", + "id": "Default_" + }, + "taggingPriority": 99, + "isDefault": true + } + ], + "objectType": "ScheduleBasedTriggerContext" + }, + "dataStore": { + "dataStoreType": "OperationalStore", + "objectType": "DataStoreInfoBase" + }, + "name": "BackupDaily", + "objectType": "AzureBackupRule" + }, + { + "lifecycles": [ + { + "deleteAfter": { + "objectType": "AbsoluteDeleteOption", + "duration": "P7D" + }, + "targetDataStoreCopySettings": [], + "sourceDataStore": { + "dataStoreType": "OperationalStore", + "objectType": "DataStoreInfoBase" + } + } + ], + "isDefault": true, + "name": "Default", + "objectType": "AzureRetentionRule" + } + ], + "datasourceTypes": [ + "Microsoft.Compute/disks" + ], + "objectType": "BackupPolicy" + } + } + ] +} +``` + +
+ +
+ +Bicep format + +```bicep +backupPolicies: [ + { + name: 'DefaultPolicy' + properties: { + policyRules: [ + { + backupParameters: { + backupType: 'Incremental' + objectType: 'AzureBackupParams' + } + trigger: { + schedule: { + repeatingTimeIntervals: [ + 'R/2022-05-31T23:30:00+01:00/P1D' + ] + timeZone: 'W. Europe Standard Time' + } + taggingCriteria: [ + { + tagInfo: { + tagName: 'Default' + id: 'Default_' + } + taggingPriority: 99 + isDefault: true + } + ] + objectType: 'ScheduleBasedTriggerContext' + } + dataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + name: 'BackupDaily' + objectType: 'AzureBackupRule' + } + { + lifecycles: [ + { + deleteAfter: { + objectType: 'AbsoluteDeleteOption' + duration: 'P7D' + } + targetDataStoreCopySettings: [] + sourceDataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + } + ] + isDefault: true + name: 'Default' + objectType: 'AzureRetentionRule' + } + ] + datasourceTypes: [ + 'Microsoft.Compute/disks' + ] + objectType: 'BackupPolicy' + } + } +] +``` + +
diff --git a/avm/res/backup-vault/backup-policy/README.md b/avm/res/backup-vault/backup-policy/README.md new file mode 100644 index 0000000000..990af9e3de --- /dev/null +++ b/avm/res/backup-vault/backup-policy/README.md @@ -0,0 +1,217 @@ +# Data Protection Backup Vault Backup Policies `[Microsoft.DataProtection/backupVaults/backupPolicies]` + +This module deploys a Data Protection Backup Vault Backup Policy. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Notes](#Notes) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DataProtection/backupVaults/backupPolicies` | [2023-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DataProtection/backupVaults/backupPolicies) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`backupVaultName`](#parameter-backupvaultname) | string | The name of the backup vault. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`name`](#parameter-name) | string | The name of the backup policy. | +| [`properties`](#parameter-properties) | object | The properties of the backup policy. | + +### Parameter: `backupVaultName` + +The name of the backup vault. + +- Required: Yes +- Type: string + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `name` + +The name of the backup policy. + +- Required: No +- Type: string +- Default: `'DefaultPolicy'` + +### Parameter: `properties` + +The properties of the backup policy. + +- Required: No +- Type: object +- Default: `{}` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the backup policy. | +| `resourceGroupName` | string | The name of the resource group the backup policy was created in. | +| `resourceId` | string | The resource ID of the backup policy. | + +## Cross-referenced modules + +_None_ + +## Notes + +### Parameter Usage: `properties` + +Create a backup policy. + +
+ +Parameter JSON format + +```json + "properties": { + "value": { + "policyRules": [ + { + "backupParameters": { + "backupType": "Incremental", + "objectType": "AzureBackupParams" + }, + "trigger": { + "schedule": { + "repeatingTimeIntervals": [ + "R/2022-05-31T23:30:00+01:00/P1D" + ], + "timeZone": "W. Europe Standard Time" + }, + "taggingCriteria": [ + { + "tagInfo": { + "tagName": "Default", + "id": "Default_" + }, + "taggingPriority": 99, + "isDefault": true + } + ], + "objectType": "ScheduleBasedTriggerContext" + }, + "dataStore": { + "dataStoreType": "OperationalStore", + "objectType": "DataStoreInfoBase" + }, + "name": "BackupDaily", + "objectType": "AzureBackupRule" + }, + { + "lifecycles": [ + { + "deleteAfter": { + "objectType": "AbsoluteDeleteOption", + "duration": "P7D" + }, + "targetDataStoreCopySettings": [], + "sourceDataStore": { + "dataStoreType": "OperationalStore", + "objectType": "DataStoreInfoBase" + } + } + ], + "isDefault": true, + "name": "Default", + "objectType": "AzureRetentionRule" + } + ], + "datasourceTypes": [ + "Microsoft.Compute/disks" + ], + "objectType": "BackupPolicy" + } +} +``` + +
+ +
+ +Bicep format + +```bicep +properties: { + policyRules: [ + { + backupParameters: { + backupType: 'Incremental' + objectType: 'AzureBackupParams' + } + trigger: { + schedule: { + repeatingTimeIntervals: [ + 'R/2022-05-31T23:30:00+01:00/P1D' + ] + timeZone: 'W. Europe Standard Time' + } + taggingCriteria: [ + { + tagInfo: { + tagName: 'Default' + id: 'Default_' + } + taggingPriority: 99 + isDefault: true + } + ] + objectType: 'ScheduleBasedTriggerContext' + } + dataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + name: 'BackupDaily' + objectType: 'AzureBackupRule' + } + { + lifecycles: [ + { + deleteAfter: { + objectType: 'AbsoluteDeleteOption' + duration: 'P7D' + } + targetDataStoreCopySettings: [] + sourceDataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + } + ] + isDefault: true + name: 'Default' + objectType: 'AzureRetentionRule' + } + ] + datasourceTypes: [ + 'Microsoft.Compute/disks' + ] + objectType: 'BackupPolicy' +} +``` + +
diff --git a/avm/res/backup-vault/backup-policy/main.bicep b/avm/res/backup-vault/backup-policy/main.bicep new file mode 100644 index 0000000000..b3b28ca62a --- /dev/null +++ b/avm/res/backup-vault/backup-policy/main.bicep @@ -0,0 +1,46 @@ +metadata name = 'Data Protection Backup Vault Backup Policies' +metadata description = 'This module deploys a Data Protection Backup Vault Backup Policy.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the backup vault.') +param backupVaultName string + +@description('Optional. The name of the backup policy.') +param name string = 'DefaultPolicy' + +@description('Optional. The properties of the backup policy.') +param properties object = {} + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource backupVault 'Microsoft.DataProtection/backupVaults@2023-05-01' existing = { + name: backupVaultName +} + +resource backupPolicy 'Microsoft.DataProtection/backupVaults/backupPolicies@2023-05-01' = { + name: name + parent: backupVault + properties: properties +} + +@description('The name of the backup policy.') +output name string = backupPolicy.name + +@description('The resource ID of the backup policy.') +output resourceId string = backupPolicy.id + +@description('The name of the resource group the backup policy was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/backup-vault/backup-policy/main.json b/avm/res/backup-vault/backup-policy/main.json new file mode 100644 index 0000000000..f3a79705fc --- /dev/null +++ b/avm/res/backup-vault/backup-policy/main.json @@ -0,0 +1,88 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "3378438498887899064" + }, + "name": "Data Protection Backup Vault Backup Policies", + "description": "This module deploys a Data Protection Backup Vault Backup Policy.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "backupVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the backup vault." + } + }, + "name": { + "type": "string", + "defaultValue": "DefaultPolicy", + "metadata": { + "description": "Optional. The name of the backup policy." + } + }, + "properties": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The properties of the backup policy." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.DataProtection/backupVaults/backupPolicies", + "apiVersion": "2023-05-01", + "name": "[format('{0}/{1}', parameters('backupVaultName'), parameters('name'))]", + "properties": "[parameters('properties')]" + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the backup policy." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the backup policy." + }, + "value": "[resourceId('Microsoft.DataProtection/backupVaults/backupPolicies', parameters('backupVaultName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the backup policy was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/backup-vault/backup-policy/version.json b/avm/res/backup-vault/backup-policy/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/backup-vault/backup-policy/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/backup-vault/main.bicep b/avm/res/backup-vault/main.bicep new file mode 100644 index 0000000000..f337814938 --- /dev/null +++ b/avm/res/backup-vault/main.bicep @@ -0,0 +1,195 @@ +metadata name = 'Data Protection Backup Vaults' +metadata description = 'This module deploys a Data Protection Backup Vault.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the Backup Vault.') +param name string + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +@description('Optional. Tags of the Recovery Service Vault resource.') +param tags object? + +@description('Optional. The datastore type to use. ArchiveStore does not support ZoneRedundancy.') +@allowed([ + 'ArchiveStore' + 'VaultStore' + 'OperationalStore' +]) +param dataStoreType string = 'VaultStore' + +@description('Optional. The vault redundancy level to use.') +@allowed([ + 'LocallyRedundant' + 'GeoRedundant' + 'ZoneRedundant' +]) +param type string = 'GeoRedundant' + +@allowed([ + 'Disabled' + 'Enabled' +]) +@description('Optional. Settings for Azure Monitor based alerts for job failures.') +param azureMonitorAlertSettingsAlertsForAllJobFailures string = 'Enabled' + +@description('Optional. List of all backup policies.') +param backupPolicies array = [] + +@description('Optional. Security settings for the backup vault.') +param securitySettings object = {} + +@description('Optional. Feature settings for the backup vault.') +param featureSettings object = {} + +var identity = !empty(managedIdentities) ? { + type: (managedIdentities.?systemAssigned ?? false) ? 'SystemAssigned' : null +} : null + +var enableReferencedModulesTelemetry = false + +var builtInRoleNames = { + 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') + 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') + 'Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912') + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource backupVault 'Microsoft.DataProtection/backupVaults@2023-05-01' = { + name: name + location: location + tags: tags + identity: identity + properties: { + monitoringSettings: { + azureMonitorAlertSettings: { + alertsForAllJobFailures: azureMonitorAlertSettingsAlertsForAllJobFailures + } + } + storageSettings: [ + { + type: type + datastoreType: dataStoreType + } + ] + featureSettings: featureSettings + securitySettings: securitySettings + } +} + +module backupVault_backupPolicies 'backup-policy/main.bicep' = [for (backupPolicy, index) in backupPolicies: { + name: '${uniqueString(deployment().name, location)}-BV-BackupPolicy-${index}' + params: { + backupVaultName: backupVault.name + name: backupPolicy.name + properties: backupPolicy.properties + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +resource backupVault_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: backupVault +} + +resource backupVault_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(backupVault.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: backupVault +}] + +@description('The resource ID of the backup vault.') +output resourceId string = backupVault.id + +@description('The name of the resource group the recovery services vault was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The Name of the backup vault.') +output name string = backupVault.name + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string = (managedIdentities.?systemAssigned ?? false) && contains(backupVault.identity, 'principalId') ? backupVault.identity.principalId : '' + +@description('The location the resource was deployed into.') +output location string = backupVault.location + +// =============== // +// Definitions // +// =============== // + +type managedIdentitiesType = { + @description('Optional. Enables system assigned managed identity on the resource.') + systemAssigned: bool? +}? + +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/backup-vault/main.json b/avm/res/backup-vault/main.json new file mode 100644 index 0000000000..487583bb38 --- /dev/null +++ b/avm/res/backup-vault/main.json @@ -0,0 +1,470 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "11737453267233569722" + }, + "name": "Data Protection Backup Vaults", + "description": "This module deploys a Data Protection Backup Vault.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + } + }, + "nullable": true + }, + "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. Name of the Backup Vault." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "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." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the Recovery Service Vault resource." + } + }, + "dataStoreType": { + "type": "string", + "defaultValue": "VaultStore", + "allowedValues": [ + "ArchiveStore", + "VaultStore", + "OperationalStore" + ], + "metadata": { + "description": "Optional. The datastore type to use. ArchiveStore does not support ZoneRedundancy." + } + }, + "type": { + "type": "string", + "defaultValue": "GeoRedundant", + "allowedValues": [ + "LocallyRedundant", + "GeoRedundant", + "ZoneRedundant" + ], + "metadata": { + "description": "Optional. The vault redundancy level to use." + } + }, + "azureMonitorAlertSettingsAlertsForAllJobFailures": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Optional. Settings for Azure Monitor based alerts for job failures." + } + }, + "backupPolicies": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of all backup policies." + } + }, + "securitySettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Security settings for the backup vault." + } + }, + "featureSettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Feature settings for the backup vault." + } + } + }, + "variables": { + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), 'SystemAssigned', null())), null())]", + "enableReferencedModulesTelemetry": false, + "builtInRoleNames": { + "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", + "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", + "Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a795c7a0-d4a2-40c1-ae25-d81f01202912')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "backupVault": { + "type": "Microsoft.DataProtection/backupVaults", + "apiVersion": "2023-05-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "properties": { + "monitoringSettings": { + "azureMonitorAlertSettings": { + "alertsForAllJobFailures": "[parameters('azureMonitorAlertSettingsAlertsForAllJobFailures')]" + } + }, + "storageSettings": [ + { + "type": "[parameters('type')]", + "datastoreType": "[parameters('dataStoreType')]" + } + ], + "featureSettings": "[parameters('featureSettings')]", + "securitySettings": "[parameters('securitySettings')]" + } + }, + "backupVault_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.DataProtection/backupVaults/{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": [ + "backupVault" + ] + }, + "backupVault_roleAssignments": { + "copy": { + "name": "backupVault_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.DataProtection/backupVaults/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.DataProtection/backupVaults', 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": [ + "backupVault" + ] + }, + "backupVault_backupPolicies": { + "copy": { + "name": "backupVault_backupPolicies", + "count": "[length(parameters('backupPolicies'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-BV-BackupPolicy-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "backupVaultName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('backupPolicies')[copyIndex()].name]" + }, + "properties": { + "value": "[parameters('backupPolicies')[copyIndex()].properties]" + }, + "enableDefaultTelemetry": { + "value": "[variables('enableReferencedModulesTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "3378438498887899064" + }, + "name": "Data Protection Backup Vault Backup Policies", + "description": "This module deploys a Data Protection Backup Vault Backup Policy.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "backupVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the backup vault." + } + }, + "name": { + "type": "string", + "defaultValue": "DefaultPolicy", + "metadata": { + "description": "Optional. The name of the backup policy." + } + }, + "properties": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The properties of the backup policy." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.DataProtection/backupVaults/backupPolicies", + "apiVersion": "2023-05-01", + "name": "[format('{0}/{1}', parameters('backupVaultName'), parameters('name'))]", + "properties": "[parameters('properties')]" + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the backup policy." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the backup policy." + }, + "value": "[resourceId('Microsoft.DataProtection/backupVaults/backupPolicies', parameters('backupVaultName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the backup policy was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "backupVault" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the backup vault." + }, + "value": "[resourceId('Microsoft.DataProtection/backupVaults', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the recovery services vault was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The Name of the backup vault." + }, + "value": "[parameters('name')]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[if(and(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), contains(reference('backupVault', '2023-05-01', 'full').identity, 'principalId')), reference('backupVault', '2023-05-01', 'full').identity.principalId, '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('backupVault', '2023-05-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/backup-vault/tests/e2e/defaults/main.test.bicep b/avm/res/backup-vault/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..eb6dd485a2 --- /dev/null +++ b/avm/res/backup-vault/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,49 @@ +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}-dataprotection.backupvaults-${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 = 'dpbvmin' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + } +}] diff --git a/avm/res/backup-vault/tests/e2e/max/dependencies.bicep b/avm/res/backup-vault/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..0f0755a6f4 --- /dev/null +++ b/avm/res/backup-vault/tests/e2e/max/dependencies.bicep @@ -0,0 +1,16 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id diff --git a/avm/res/backup-vault/tests/e2e/max/main.test.bicep b/avm/res/backup-vault/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..588b2e0c20 --- /dev/null +++ b/avm/res/backup-vault/tests/e2e/max/main.test.bicep @@ -0,0 +1,149 @@ +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}-dataprotection.backupvaults-${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 = 'dpbvmax' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + 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' + } + ] + azureMonitorAlertSettingsAlertsForAllJobFailures: 'Disabled' + managedIdentities: { + systemAssigned: true + } + backupPolicies: [ + { + name: 'DefaultPolicy' + properties: { + datasourceTypes: [ + 'Microsoft.Compute/disks' + ] + objectType: 'BackupPolicy' + policyRules: [ + { + backupParameters: { + backupType: 'Incremental' + objectType: 'AzureBackupParams' + } + dataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + name: 'BackupDaily' + objectType: 'AzureBackupRule' + trigger: { + objectType: 'ScheduleBasedTriggerContext' + schedule: { + repeatingTimeIntervals: [ + 'R/2022-05-31T23:30:00+01:00/P1D' + ] + timeZone: 'W. Europe Standard Time' + } + taggingCriteria: [ + { + isDefault: true + taggingPriority: 99 + tagInfo: { + id: 'Default_' + tagName: 'Default' + } + } + ] + } + } + { + isDefault: true + lifecycles: [ + { + deleteAfter: { + duration: 'P7D' + objectType: 'AbsoluteDeleteOption' + } + sourceDataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + targetDataStoreCopySettings: [] + } + ] + name: 'Default' + objectType: 'AzureRetentionRule' + } + ] + } + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/backup-vault/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/backup-vault/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..0f0755a6f4 --- /dev/null +++ b/avm/res/backup-vault/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,16 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id diff --git a/avm/res/backup-vault/tests/e2e/waf-aligned/main.test.bicep b/avm/res/backup-vault/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..1bcb119964 --- /dev/null +++ b/avm/res/backup-vault/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,132 @@ +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}-dataprotection.backupvaults-${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 = 'dpbvwaf' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + azureMonitorAlertSettingsAlertsForAllJobFailures: 'Disabled' + managedIdentities: { + systemAssigned: true + } + backupPolicies: [ + { + name: 'DefaultPolicy' + properties: { + datasourceTypes: [ + 'Microsoft.Compute/disks' + ] + objectType: 'BackupPolicy' + policyRules: [ + { + backupParameters: { + backupType: 'Incremental' + objectType: 'AzureBackupParams' + } + dataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + name: 'BackupDaily' + objectType: 'AzureBackupRule' + trigger: { + objectType: 'ScheduleBasedTriggerContext' + schedule: { + repeatingTimeIntervals: [ + 'R/2022-05-31T23:30:00+01:00/P1D' + ] + timeZone: 'W. Europe Standard Time' + } + taggingCriteria: [ + { + isDefault: true + taggingPriority: 99 + tagInfo: { + id: 'Default_' + tagName: 'Default' + } + } + ] + } + } + { + isDefault: true + lifecycles: [ + { + deleteAfter: { + duration: 'P7D' + objectType: 'AbsoluteDeleteOption' + } + sourceDataStore: { + dataStoreType: 'OperationalStore' + objectType: 'DataStoreInfoBase' + } + targetDataStoreCopySettings: [] + } + ] + name: 'Default' + objectType: 'AzureRetentionRule' + } + ] + } + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/backup-vault/version.json b/avm/res/backup-vault/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/backup-vault/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/cache/redis/README.md b/avm/res/cache/redis/README.md new file mode 100644 index 0000000000..5f026c7c76 --- /dev/null +++ b/avm/res/cache/redis/README.md @@ -0,0 +1,1226 @@ +# Redis Cache `[Microsoft.Cache/redis]` + +This module deploys a Redis Cache. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Notes](#Notes) + +## 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.Cache/redis` | [2022-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Cache/2022-06-01/redis) | +| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | +| `Microsoft.Network/privateEndpoints` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints) | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints/privateDnsZoneGroups) | + +## 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:bicep/modules/cache.redis:1.0.0`. + +- [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 redis 'br:bicep/modules/cache.redis:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-crmin' + params: { + // Required parameters + name: 'crmin001' + // Non-required parameters + enableDefaultTelemetry: '' + } +} +``` + +
+

+ +

+ +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": "crmin001" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module redis 'br:bicep/modules/cache.redis:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-crmax' + params: { + // Required parameters + name: 'crmax001' + // Non-required parameters + capacity: 2 + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + enableDefaultTelemetry: '' + enableNonSslPort: true + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + minimumTlsVersion: '1.2' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + ] + publicNetworkAccess: 'Enabled' + redisVersion: '6' + shardCount: 1 + skuName: 'Premium' + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Redis Cache' + } + zoneRedundant: true + zones: [ + 1 + 2 + ] + } +} +``` + +
+

+ +

+ +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": "crmax001" + }, + // Non-required parameters + "capacity": { + "value": 2 + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "enableDefaultTelemetry": { + "value": "" + }, + "enableNonSslPort": { + "value": true + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "minimumTlsVersion": { + "value": "1.2" + }, + "privateEndpoints": { + "value": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + ] + }, + "publicNetworkAccess": { + "value": "Enabled" + }, + "redisVersion": { + "value": "6" + }, + "shardCount": { + "value": 1 + }, + "skuName": { + "value": "Premium" + }, + "tags": { + "value": { + "hidden-title": "This is visible in the resource name", + "resourceType": "Redis Cache" + } + }, + "zoneRedundant": { + "value": true + }, + "zones": { + "value": [ + 1, + 2 + ] + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module redis 'br:bicep/modules/cache.redis:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-crwaf' + params: { + // Required parameters + name: 'crwaf001' + // Non-required parameters + capacity: 2 + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + enableDefaultTelemetry: '' + enableNonSslPort: true + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + minimumTlsVersion: '1.2' + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + ] + publicNetworkAccess: 'Enabled' + redisVersion: '6' + shardCount: 1 + skuName: 'Premium' + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Redis Cache' + } + zoneRedundant: true + zones: [ + 1 + 2 + ] + } +} +``` + +
+

+ +

+ +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": "crwaf001" + }, + // Non-required parameters + "capacity": { + "value": 2 + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "enableDefaultTelemetry": { + "value": "" + }, + "enableNonSslPort": { + "value": true + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "minimumTlsVersion": { + "value": "1.2" + }, + "privateEndpoints": { + "value": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + ] + }, + "publicNetworkAccess": { + "value": "Enabled" + }, + "redisVersion": { + "value": "6" + }, + "shardCount": { + "value": 1 + }, + "skuName": { + "value": "Premium" + }, + "tags": { + "value": { + "hidden-title": "This is visible in the resource name", + "resourceType": "Redis Cache" + } + }, + "zoneRedundant": { + "value": true + }, + "zones": { + "value": [ + 1, + 2 + ] + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the Redis cache resource. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`capacity`](#parameter-capacity) | int | The size of the Redis cache to deploy. Valid values: for C (Basic/Standard) family (0, 1, 2, 3, 4, 5, 6), for P (Premium) family (1, 2, 3, 4). | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`enableNonSslPort`](#parameter-enablenonsslport) | bool | Specifies whether the non-ssl Redis server port (6379) is enabled. | +| [`location`](#parameter-location) | string | The location to deploy the Redis cache service. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | +| [`minimumTlsVersion`](#parameter-minimumtlsversion) | string | Requires clients to use a specified TLS version (or higher) to connect. | +| [`privateEndpoints`](#parameter-privateendpoints) | array | Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. | +| [`publicNetworkAccess`](#parameter-publicnetworkaccess) | string | Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set. | +| [`redisConfiguration`](#parameter-redisconfiguration) | object | All Redis Settings. Few possible keys: rdb-backup-enabled,rdb-storage-connection-string,rdb-backup-frequency,maxmemory-delta,maxmemory-policy,notify-keyspace-events,maxmemory-samples,slowlog-log-slower-than,slowlog-max-len,list-max-ziplist-entries,list-max-ziplist-value,hash-max-ziplist-entries,hash-max-ziplist-value,set-max-intset-entries,zset-max-ziplist-entries,zset-max-ziplist-value etc. | +| [`redisVersion`](#parameter-redisversion) | string | Redis version. Only major version will be used in PUT/PATCH request with current valid values: (4, 6). | +| [`replicasPerMaster`](#parameter-replicaspermaster) | int | The number of replicas to be created per primary. | +| [`replicasPerPrimary`](#parameter-replicasperprimary) | int | The number of replicas to be created per primary. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`shardCount`](#parameter-shardcount) | int | The number of shards to be created on a Premium Cluster Cache. | +| [`skuName`](#parameter-skuname) | string | The type of Redis cache to deploy. | +| [`staticIP`](#parameter-staticip) | string | Static IP address. Optionally, may be specified when deploying a Redis cache inside an existing Azure Virtual Network; auto assigned by default. | +| [`subnetId`](#parameter-subnetid) | string | The full resource ID of a subnet in a virtual network to deploy the Redis cache in. Example format: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/Microsoft.{Network|ClassicNetwork}/VirtualNetworks/vnet1/subnets/subnet1. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | +| [`tenantSettings`](#parameter-tenantsettings) | object | A dictionary of tenant settings. | +| [`zoneRedundant`](#parameter-zoneredundant) | bool | When true, replicas will be provisioned in availability zones specified in the zones parameter. | +| [`zones`](#parameter-zones) | array | If the zoneRedundant parameter is true, replicas will be provisioned in the availability zones specified here. Otherwise, the service will choose where replicas are deployed. | + +### Parameter: `name` + +The name of the Redis cache resource. + +- Required: Yes +- Type: string + +### Parameter: `capacity` + +The size of the Redis cache to deploy. Valid values: for C (Basic/Standard) family (0, 1, 2, 3, 4, 5, 6), for P (Premium) family (1, 2, 3, 4). + +- Required: No +- Type: int +- Default: `1` +- Allowed: + ```Bicep + [ + 0 + 1 + 2 + 3 + 4 + 5 + 6 + ] + ``` + +### 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. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. | +| [`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.metricCategories` + +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.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: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `enableNonSslPort` + +Specifies whether the non-ssl Redis server port (6379) is enabled. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `location` + +The location to deploy the Redis cache service. + +- 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: `managedIdentities` + +The managed identity definition for this resource. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | + +### Parameter: `managedIdentities.systemAssigned` + +Enables system assigned managed identity on the resource. + +- Required: No +- Type: bool + +### Parameter: `managedIdentities.userAssignedResourceIds` + +The resource ID(s) to assign to the resource. + +- Required: No +- Type: array + +### Parameter: `minimumTlsVersion` + +Requires clients to use a specified TLS version (or higher) to connect. + +- Required: No +- Type: string +- Default: `'1.2'` +- Allowed: + ```Bicep + [ + '1.0' + '1.1' + '1.2' + ] + ``` + +### Parameter: `privateEndpoints` + +Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the private endpoint IP configuration is included. | +| [`customDnsConfigs`](#parameter-privateendpointscustomdnsconfigs) | array | Custom DNS configurations. | +| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | +| [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | +| [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | +| [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | +| [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | +| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. | +| [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | array | The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | +| [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | +| [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | +| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | + +### Parameter: `privateEndpoints.subnetResourceId` + +Resource ID of the subnet where the endpoint needs to be created. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` + +Application security groups in which the private endpoint IP configuration is included. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.customDnsConfigs` + +Custom DNS configurations. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.customNetworkInterfaceName` + +The custom name of the network interface attached to the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool + +### Parameter: `privateEndpoints.ipConfigurations` + +A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.location` + +The location to deploy the private endpoint to. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.lock` + +Specify the type of lock. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-privateendpointslockkind) | string | Specify the type of lock. | +| [`name`](#parameter-privateendpointslockname) | string | Specify the name of lock. | + +### Parameter: `privateEndpoints.lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `privateEndpoints.lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.manualPrivateLinkServiceConnections` + +Manual PrivateLink Service Connections. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.name` + +The name of the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneGroupName` + +The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneResourceIds` + +The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-privateendpointsroleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-privateendpointsroleassignmentsroledefinitionidorname) | 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-privateendpointsroleassignmentscondition) | 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-privateendpointsroleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-privateendpointsroleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-privateendpointsroleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-privateendpointsroleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `privateEndpoints.roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.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: `privateEndpoints.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: `privateEndpoints.roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `privateEndpoints.roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `privateEndpoints.service` + +The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.tags` + +Tags to be applied on all resources/resource groups in this deployment. + +- Required: No +- Type: object + +### Parameter: `publicNetworkAccess` + +Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `redisConfiguration` + +All Redis Settings. Few possible keys: rdb-backup-enabled,rdb-storage-connection-string,rdb-backup-frequency,maxmemory-delta,maxmemory-policy,notify-keyspace-events,maxmemory-samples,slowlog-log-slower-than,slowlog-max-len,list-max-ziplist-entries,list-max-ziplist-value,hash-max-ziplist-entries,hash-max-ziplist-value,set-max-intset-entries,zset-max-ziplist-entries,zset-max-ziplist-value etc. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `redisVersion` + +Redis version. Only major version will be used in PUT/PATCH request with current valid values: (4, 6). + +- Required: No +- Type: string +- Default: `'6'` +- Allowed: + ```Bicep + [ + '4' + '6' + ] + ``` + +### Parameter: `replicasPerMaster` + +The number of replicas to be created per primary. + +- Required: No +- Type: int +- Default: `1` + +### Parameter: `replicasPerPrimary` + +The number of replicas to be created per primary. + +- Required: No +- Type: int +- Default: `1` + +### 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: `shardCount` + +The number of shards to be created on a Premium Cluster Cache. + +- Required: No +- Type: int +- Default: `1` + +### Parameter: `skuName` + +The type of Redis cache to deploy. + +- Required: No +- Type: string +- Default: `'Basic'` +- Allowed: + ```Bicep + [ + 'Basic' + 'Premium' + 'Standard' + ] + ``` + +### Parameter: `staticIP` + +Static IP address. Optionally, may be specified when deploying a Redis cache inside an existing Azure Virtual Network; auto assigned by default. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `subnetId` + +The full resource ID of a subnet in a virtual network to deploy the Redis cache in. Example format: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/Microsoft.{Network|ClassicNetwork}/VirtualNetworks/vnet1/subnets/subnet1. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `tags` + +Tags of the resource. + +- Required: No +- Type: object + +### Parameter: `tenantSettings` + +A dictionary of tenant settings. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `zoneRedundant` + +When true, replicas will be provisioned in availability zones specified in the zones parameter. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `zones` + +If the zoneRedundant parameter is true, replicas will be provisioned in the availability zones specified here. Otherwise, the service will choose where replicas are deployed. + +- Required: No +- Type: array +- Default: `[]` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `hostName` | string | Redis hostname. | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the Redis Cache. | +| `resourceGroupName` | string | The name of the resource group the Redis Cache was created in. | +| `resourceId` | string | The resource ID of the Redis Cache. | +| `sslPort` | int | Redis SSL port. | +| `subnetId` | string | The full resource ID of a subnet in a virtual network where the Redis Cache was deployed in. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other CARML modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `modules/network/private-endpoint` | Local reference | + +## Notes + +### Parameter Usage: `redisConfiguration` + +All Redis Settings. Few possible keys: rdb-backup-enabled,rdb-storage-connection-string,rdb-backup-frequency,maxmemory-delta,maxmemory-policy,notify-keyspace-events,maxmemory-samples,slowlog-log-slower-than,slowlog-max-len,list-max-ziplist-entries,list-max-ziplist-value,hash-max-ziplist-entries,hash-max-ziplist-value,set-max-intset-entries,zset-max-ziplist-entries,zset-max-ziplist-value etc.. + +Name | Description | Value +---------|----------|--------- +aof-storage-connection-string-0 | First storage account connection string | string +aof-storage-connection-string-1 | Second storage account connection string | string +maxfragmentationmemory-reserved | Value in megabytes reserved for fragmentation per shard | string +maxmemory-delta | Value in megabytes reserved for non-cache usage per shard e.g. failover. | string +maxmemory-policy | The eviction strategy used when your data won't fit within its memory limit. | string +maxmemory-reserved | Value in megabytes reserved for non-cache usage per shard e.g. failover. | string +rdb-backup-enabled | Specifies whether the rdb backup is enabled | string +rdb-backup-frequency | Specifies the frequency for creating rdb backup | string +rdb-backup-max-snapshot-count | Specifies the maximum number of snapshots for rdb backup | string +rdb-storage-connection-string | The storage account connection string for storing rdb file | string + +For more details visit [Microsoft.Cache redis reference](https://learn.microsoft.com/en-us/azure/templates/microsoft.cache/redis?tabs=bicep) + +

+ +Bicep format + +```bicep +userAssignedIdentities: { + '/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001': {} + '/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002': {} +} +``` + +
+

diff --git a/avm/res/cache/redis/main.bicep b/avm/res/cache/redis/main.bicep new file mode 100644 index 0000000000..4a34e577ce --- /dev/null +++ b/avm/res/cache/redis/main.bicep @@ -0,0 +1,410 @@ +metadata name = 'Redis Cache' +metadata description = 'This module deploys a Redis Cache.' +metadata owner = 'Azure/module-maintainers' + +@description('Optional. The location to deploy the Redis cache service.') +param location string = resourceGroup().location + +@description('Required. The name of the Redis cache resource.') +param name string + +@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 resource.') +param tags object? + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +@description('Optional. Specifies whether the non-ssl Redis server port (6379) is enabled.') +param enableNonSslPort bool = false + +@allowed([ + '1.0' + '1.1' + '1.2' +]) +@description('Optional. Requires clients to use a specified TLS version (or higher) to connect.') +param minimumTlsVersion string = '1.2' + +@description('Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set.') +@allowed([ + '' + 'Enabled' + 'Disabled' +]) +param publicNetworkAccess string = '' + +@description('Optional. All Redis Settings. Few possible keys: rdb-backup-enabled,rdb-storage-connection-string,rdb-backup-frequency,maxmemory-delta,maxmemory-policy,notify-keyspace-events,maxmemory-samples,slowlog-log-slower-than,slowlog-max-len,list-max-ziplist-entries,list-max-ziplist-value,hash-max-ziplist-entries,hash-max-ziplist-value,set-max-intset-entries,zset-max-ziplist-entries,zset-max-ziplist-value etc.') +param redisConfiguration object = {} + +@allowed([ + '4' + '6' +]) +@description('Optional. Redis version. Only major version will be used in PUT/PATCH request with current valid values: (4, 6).') +param redisVersion string = '6' + +@minValue(1) +@description('Optional. The number of replicas to be created per primary.') +param replicasPerMaster int = 1 + +@minValue(1) +@description('Optional. The number of replicas to be created per primary.') +param replicasPerPrimary int = 1 + +@minValue(1) +@description('Optional. The number of shards to be created on a Premium Cluster Cache.') +param shardCount int = 1 + +@allowed([ + 0 + 1 + 2 + 3 + 4 + 5 + 6 +]) +@description('Optional. The size of the Redis cache to deploy. Valid values: for C (Basic/Standard) family (0, 1, 2, 3, 4, 5, 6), for P (Premium) family (1, 2, 3, 4).') +param capacity int = 1 + +@allowed([ + 'Basic' + 'Premium' + 'Standard' +]) +@description('Optional. The type of Redis cache to deploy.') +param skuName string = 'Basic' + +@description('Optional. Static IP address. Optionally, may be specified when deploying a Redis cache inside an existing Azure Virtual Network; auto assigned by default.') +param staticIP string = '' + +@description('Optional. The full resource ID of a subnet in a virtual network to deploy the Redis cache in. Example format: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/Microsoft.{Network|ClassicNetwork}/VirtualNetworks/vnet1/subnets/subnet1.') +param subnetId string = '' + +@description('Optional. A dictionary of tenant settings.') +param tenantSettings object = {} + +@description('Optional. When true, replicas will be provisioned in availability zones specified in the zones parameter.') +param zoneRedundant bool = true + +@description('Optional. If the zoneRedundant parameter is true, replicas will be provisioned in the availability zones specified here. Otherwise, the service will choose where replicas are deployed.') +param zones array = [] + +@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints privateEndpointType + +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +var availabilityZones = skuName == 'Premium' ? zoneRedundant ? !empty(zones) ? zones : pickZones('Microsoft.Cache', 'redis', location, 3) : [] : [] + +var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } + +var identity = !empty(managedIdentities) ? { + type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +var enableReferencedModulesTelemetry = false + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Redis Cache Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17') + '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 defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource redis 'Microsoft.Cache/redis@2022-06-01' = { + name: name + location: location + tags: tags + identity: identity + properties: { + enableNonSslPort: enableNonSslPort + minimumTlsVersion: minimumTlsVersion + publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) ? 'Disabled' : null) + redisConfiguration: !empty(redisConfiguration) ? redisConfiguration : null + redisVersion: redisVersion + replicasPerMaster: skuName == 'Premium' ? replicasPerMaster : null + replicasPerPrimary: skuName == 'Premium' ? replicasPerPrimary : null + shardCount: skuName == 'Premium' ? shardCount : null // Not supported in free tier + sku: { + capacity: capacity + family: skuName == 'Premium' ? 'P' : 'C' + name: skuName + } + staticIP: !empty(staticIP) ? staticIP : null + subnetId: !empty(subnetId) ? subnetId : null + tenantSettings: tenantSettings + } + zones: availabilityZones +} + +resource redis_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: redis +} + +resource redis_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 + metrics: diagnosticSetting.?metricCategories ?? [ + { + category: 'AllMetrics' + timeGrain: null + enabled: true + } + ] + logs: diagnosticSetting.?logCategoriesAndGroups ?? [ + { + categoryGroup: 'AllLogs' + enabled: true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: redis +}] + +resource redis_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(redis.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: redis +}] + +module redis_privateEndpoints '../../network/private-endpoint/main.bicep' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-redis-PrivateEndpoint-${index}' + params: { + groupIds: [ + privateEndpoint.?service ?? 'redisCache' + ] + name: privateEndpoint.?name ?? 'pep-${last(split(redis.id, '/'))}-${privateEndpoint.?service ?? 'redisCache'}-${index}' + serviceResourceId: redis.id + subnetResourceId: privateEndpoint.subnetResourceId + enableDefaultTelemetry: privateEndpoint.?enableDefaultTelemetry ?? enableReferencedModulesTelemetry + location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } +}] + +@description('The name of the Redis Cache.') +output name string = redis.name + +@description('The resource ID of the Redis Cache.') +output resourceId string = redis.id + +@description('The name of the resource group the Redis Cache was created in.') +output resourceGroupName string = resourceGroup().name + +@description('Redis hostname.') +output hostName string = redis.properties.hostName + +@description('Redis SSL port.') +output sslPort int = redis.properties.sslPort + +@description('The full resource ID of a subnet in a virtual network where the Redis Cache was deployed in.') +output subnetId string = !empty(subnetId) ? redis.properties.subnetId : '' + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string = (managedIdentities.?systemAssigned ?? false) && contains(redis.identity, 'principalId') ? redis.identity.principalId : '' + +@description('The location the resource was deployed into.') +output location string = redis.location + +// =============== // +// Definitions // +// =============== // + +type managedIdentitiesType = { + @description('Optional. Enables system assigned managed identity on the resource.') + systemAssigned: bool? + + @description('Optional. The resource ID(s) to assign to the resource.') + userAssignedResourceIds: string[]? +}? + +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? +}[]? + +type privateEndpointType = { + @description('Optional. The name of the private endpoint.') + name: string? + + @description('Optional. The location to deploy the private endpoint to.') + location: string? + + @description('Optional. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob".') + service: string? + + @description('Required. Resource ID of the subnet where the endpoint needs to be created.') + subnetResourceId: string + + @description('Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided.') + privateDnsZoneGroupName: string? + + @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') + privateDnsZoneResourceIds: string[]? + + @description('Optional. Custom DNS configurations.') + customDnsConfigs: { + @description('Required. Fqdn that resolves to private endpoint ip address.') + fqdn: string? + + @description('Required. A list of private ip addresses of the private endpoint.') + ipAddresses: string[] + }[]? + + @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') + ipConfigurations: { + @description('Required. The name of the resource that is unique within a resource group.') + name: string + + @description('Required. Properties of private endpoint IP configurations.') + properties: { + @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') + groupId: string + + @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') + memberName: string + + @description('Required. A private ip address obtained from the private endpoint\'s subnet.') + privateIPAddress: string + } + }[]? + + @description('Optional. Application security groups in which the private endpoint IP configuration is included.') + applicationSecurityGroupResourceIds: string[]? + + @description('Optional. The custom name of the network interface attached to the private endpoint.') + customNetworkInterfaceName: string? + + @description('Optional. Specify the type of lock.') + lock: lockType + + @description('Optional. Array of role assignments to create.') + roleAssignments: roleAssignmentType + + @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') + tags: object? + + @description('Optional. Manual PrivateLink Service Connections.') + manualPrivateLinkServiceConnections: array? + + @description('Optional. Enable/Disable usage telemetry for module.') + enableTelemetry: bool? +}[]? + +type diagnosticSettingType = { + @description('Optional. The name of diagnostic setting.') + name: string? + + @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: { + @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? + + @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? + }[]? + + @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + metricCategories: { + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to \'AllMetrics\' to collect all metrics.') + category: string + }[]? + + @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')? + + @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? + + @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? + + @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? + + @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? + + @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/cache/redis/main.json b/avm/res/cache/redis/main.json new file mode 100644 index 0000000000..90b5617b8a --- /dev/null +++ b/avm/res/cache/redis/main.json @@ -0,0 +1,1397 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "10455754336377427456" + }, + "name": "Redis Cache", + "description": "This module deploys a Redis Cache.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "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 + }, + "privateEndpointType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The service (sub-) type to deploy the private endpoint for. For example \"vault\" or \"blob\"." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided." + } + }, + "privateDnsZoneResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint ip address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private ip addresses of the private endpoint." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private ip address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "manualPrivateLinkServiceConnections": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Manual PrivateLink Service Connections." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + } + }, + "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." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to 'AllMetrics' to collect all metrics." + } + } + } + }, + "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": { + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location to deploy the Redis cache service." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Redis cache resource." + } + }, + "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 resource." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + }, + "enableNonSslPort": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether the non-ssl Redis server port (6379) is enabled." + } + }, + "minimumTlsVersion": { + "type": "string", + "defaultValue": "1.2", + "allowedValues": [ + "1.0", + "1.1", + "1.2" + ], + "metadata": { + "description": "Optional. Requires clients to use a specified TLS version (or higher) to connect." + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set." + } + }, + "redisConfiguration": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. All Redis Settings. Few possible keys: rdb-backup-enabled,rdb-storage-connection-string,rdb-backup-frequency,maxmemory-delta,maxmemory-policy,notify-keyspace-events,maxmemory-samples,slowlog-log-slower-than,slowlog-max-len,list-max-ziplist-entries,list-max-ziplist-value,hash-max-ziplist-entries,hash-max-ziplist-value,set-max-intset-entries,zset-max-ziplist-entries,zset-max-ziplist-value etc." + } + }, + "redisVersion": { + "type": "string", + "defaultValue": "6", + "allowedValues": [ + "4", + "6" + ], + "metadata": { + "description": "Optional. Redis version. Only major version will be used in PUT/PATCH request with current valid values: (4, 6)." + } + }, + "replicasPerMaster": { + "type": "int", + "defaultValue": 1, + "minValue": 1, + "metadata": { + "description": "Optional. The number of replicas to be created per primary." + } + }, + "replicasPerPrimary": { + "type": "int", + "defaultValue": 1, + "minValue": 1, + "metadata": { + "description": "Optional. The number of replicas to be created per primary." + } + }, + "shardCount": { + "type": "int", + "defaultValue": 1, + "minValue": 1, + "metadata": { + "description": "Optional. The number of shards to be created on a Premium Cluster Cache." + } + }, + "capacity": { + "type": "int", + "defaultValue": 1, + "allowedValues": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "metadata": { + "description": "Optional. The size of the Redis cache to deploy. Valid values: for C (Basic/Standard) family (0, 1, 2, 3, 4, 5, 6), for P (Premium) family (1, 2, 3, 4)." + } + }, + "skuName": { + "type": "string", + "defaultValue": "Basic", + "allowedValues": [ + "Basic", + "Premium", + "Standard" + ], + "metadata": { + "description": "Optional. The type of Redis cache to deploy." + } + }, + "staticIP": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Static IP address. Optionally, may be specified when deploying a Redis cache inside an existing Azure Virtual Network; auto assigned by default." + } + }, + "subnetId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The full resource ID of a subnet in a virtual network to deploy the Redis cache in. Example format: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/Microsoft.{Network|ClassicNetwork}/VirtualNetworks/vnet1/subnets/subnet1." + } + }, + "tenantSettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. A dictionary of tenant settings." + } + }, + "zoneRedundant": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. When true, replicas will be provisioned in availability zones specified in the zones parameter." + } + }, + "zones": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. If the zoneRedundant parameter is true, replicas will be provisioned in the availability zones specified here. Otherwise, the service will choose where replicas are deployed." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "variables": { + "availabilityZones": "[if(equals(parameters('skuName'), 'Premium'), if(parameters('zoneRedundant'), if(not(empty(parameters('zones'))), parameters('zones'), pickZones('Microsoft.Cache', 'redis', parameters('location'), 3)), createArray()), createArray())]", + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null())), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "enableReferencedModulesTelemetry": false, + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Redis Cache Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e0f68234-74aa-48ed-b826-c38b57376e17')]", + "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": { + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "redis": { + "type": "Microsoft.Cache/redis", + "apiVersion": "2022-06-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "properties": { + "enableNonSslPort": "[parameters('enableNonSslPort')]", + "minimumTlsVersion": "[parameters('minimumTlsVersion')]", + "publicNetworkAccess": "[if(not(empty(parameters('publicNetworkAccess'))), parameters('publicNetworkAccess'), if(not(empty(parameters('privateEndpoints'))), 'Disabled', null()))]", + "redisConfiguration": "[if(not(empty(parameters('redisConfiguration'))), parameters('redisConfiguration'), null())]", + "redisVersion": "[parameters('redisVersion')]", + "replicasPerMaster": "[if(equals(parameters('skuName'), 'Premium'), parameters('replicasPerMaster'), null())]", + "replicasPerPrimary": "[if(equals(parameters('skuName'), 'Premium'), parameters('replicasPerPrimary'), null())]", + "shardCount": "[if(equals(parameters('skuName'), 'Premium'), parameters('shardCount'), null())]", + "sku": { + "capacity": "[parameters('capacity')]", + "family": "[if(equals(parameters('skuName'), 'Premium'), 'P', 'C')]", + "name": "[parameters('skuName')]" + }, + "staticIP": "[if(not(empty(parameters('staticIP'))), parameters('staticIP'), null())]", + "subnetId": "[if(not(empty(parameters('subnetId'))), parameters('subnetId'), null())]", + "tenantSettings": "[parameters('tenantSettings')]" + }, + "zones": "[variables('availabilityZones')]" + }, + "redis_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.Cache/redis/{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": [ + "redis" + ] + }, + "redis_diagnosticSettings": { + "copy": { + "name": "redis_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Cache/redis/{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')]", + "metrics": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics', 'timeGrain', null(), 'enabled', true())))]", + "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": [ + "redis" + ] + }, + "redis_roleAssignments": { + "copy": { + "name": "redis_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Cache/redis/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Cache/redis', 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": [ + "redis" + ] + }, + "redis_privateEndpoints": { + "copy": { + "name": "redis_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-redis-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "groupIds": { + "value": [ + "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'redisCache')]" + ] + }, + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Cache/redis', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'redisCache'), copyIndex()))]" + }, + "serviceResourceId": { + "value": "[resourceId('Microsoft.Cache/redis', parameters('name'))]" + }, + "subnetResourceId": { + "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" + }, + "enableDefaultTelemetry": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableDefaultTelemetry'), variables('enableReferencedModulesTelemetry'))]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "lock": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" + }, + "privateDnsZoneGroupName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroupName')]" + }, + "privateDnsZoneResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneResourceIds')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "manualPrivateLinkServiceConnections": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections')]" + }, + "customDnsConfigs": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" + }, + "ipConfigurations": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'ipConfigurations')]" + }, + "applicationSecurityGroupResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'applicationSecurityGroupResourceIds')]" + }, + "customNetworkInterfaceName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "6873008238043407177" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "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 + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private ip address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint ip address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private ip addresses of the private endpoint." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "serviceResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the resource that needs to be connected to the network." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to." + } + }, + "privateDnsZoneGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided." + } + }, + "privateDnsZoneResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Manual PrivateLink Service Connections." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "enableReferencedModulesTelemetry": false, + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "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')]" + } + }, + "resources": { + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" + } + } + ], + "customDnsConfigs": "[parameters('customDnsConfigs')]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": [ + { + "name": "[parameters('name')]", + "properties": { + "privateLinkServiceId": "[parameters('serviceResourceId')]", + "groupIds": "[parameters('groupIds')]" + } + } + ], + "subnet": { + "id": "[parameters('subnetResourceId')]" + } + } + }, + "privateEndpoint_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.Network/privateEndpoints/{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": [ + "privateEndpoint" + ] + }, + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', 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], 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": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneResourceIds')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('privateDnsZoneGroupName'), 'default')]" + }, + "privateDNSResourceIds": { + "value": "[coalesce(parameters('privateDnsZoneResourceIds'), createArray())]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + }, + "enableDefaultTelemetry": { + "value": "[variables('enableReferencedModulesTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "17578977753131828304" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDNSResourceIds": { + "type": "array", + "minLength": 1, + "maxLength": 5, + "metadata": { + "description": "Required. Array of private DNS zone resource IDs. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(parameters('privateDNSResourceIds'))]", + "input": { + "name": "[last(split(parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigs')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint DNS zone group." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "redis" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the Redis Cache." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Redis Cache." + }, + "value": "[resourceId('Microsoft.Cache/redis', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Redis Cache was created in." + }, + "value": "[resourceGroup().name]" + }, + "hostName": { + "type": "string", + "metadata": { + "description": "Redis hostname." + }, + "value": "[reference('redis').hostName]" + }, + "sslPort": { + "type": "int", + "metadata": { + "description": "Redis SSL port." + }, + "value": "[reference('redis').sslPort]" + }, + "subnetId": { + "type": "string", + "metadata": { + "description": "The full resource ID of a subnet in a virtual network where the Redis Cache was deployed in." + }, + "value": "[if(not(empty(parameters('subnetId'))), reference('redis').subnetId, '')]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[if(and(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), contains(reference('redis', '2022-06-01', 'full').identity, 'principalId')), reference('redis', '2022-06-01', 'full').identity.principalId, '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('redis', '2022-06-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep b/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..4c8ef85da3 --- /dev/null +++ b/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,48 @@ +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}-cache.redis-${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 = 'crmin' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + } +} diff --git a/avm/res/cache/redis/tests/e2e/max/dependencies.bicep b/avm/res/cache/redis/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..8218e0c1ad --- /dev/null +++ b/avm/res/cache/redis/tests/e2e/max/dependencies.bicep @@ -0,0 +1,60 @@ +@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 + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.redis.cache.windows.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/avm/res/cache/redis/tests/e2e/max/main.test.bicep b/avm/res/cache/redis/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..dd1a06da7d --- /dev/null +++ b/avm/res/cache/redis/tests/e2e/max/main.test.bicep @@ -0,0 +1,121 @@ +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}-cache.redis-${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 = 'crmax' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' + location: location + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + capacity: 2 + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + enableNonSslPort: true + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + minimumTlsVersion: '1.2' + zoneRedundant: true + zones: [ 1, 2 ] + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + publicNetworkAccess: 'Enabled' + redisVersion: '6' + shardCount: 1 + skuName: 'Premium' + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Redis Cache' + } + } +} diff --git a/avm/res/cache/redis/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/cache/redis/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..8218e0c1ad --- /dev/null +++ b/avm/res/cache/redis/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,60 @@ +@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 + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.redis.cache.windows.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..01f1338b3d --- /dev/null +++ b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,121 @@ +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}-cache.redis-${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 = 'crwaf' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' + location: location + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + capacity: 2 + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + enableNonSslPort: true + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + minimumTlsVersion: '1.2' + zoneRedundant: true + zones: [ 1, 2 ] + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + publicNetworkAccess: 'Enabled' + redisVersion: '6' + shardCount: 1 + skuName: 'Premium' + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'Redis Cache' + } + } +} diff --git a/avm/res/cache/redis/version.json b/avm/res/cache/redis/version.json new file mode 100644 index 0000000000..04a0dd1a80 --- /dev/null +++ b/avm/res/cache/redis/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.5", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/compute/disk/README.md b/avm/res/compute/disk/README.md new file mode 100644 index 0000000000..3bc00fac1b --- /dev/null +++ b/avm/res/compute/disk/README.md @@ -0,0 +1,990 @@ +# 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) + +## 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:bicep/modules/compute.disk:1.0.0`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Image](#example-2-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:bicep/modules/compute.disk:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-cdmin' + params: { + // Required parameters + name: 'cdmin001' + sku: 'Standard_LRS' + // Non-required parameters + diskSizeGB: 1 + enableDefaultTelemetry: '' + } +} +``` + +
+

+ +

+ +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 + }, + "enableDefaultTelemetry": { + "value": "" + } + } +} +``` + +
+

+ +### Example 2: _Image_ + +

+ +via Bicep module + +```bicep +module disk 'br:bicep/modules/compute.disk:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-cdimg' + params: { + // Required parameters + name: 'cdimg001' + sku: 'Standard_LRS' + // Non-required parameters + createOption: 'FromImage' + enableDefaultTelemetry: '' + imageReferenceId: '' + 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" + }, + "enableDefaultTelemetry": { + "value": "" + }, + "imageReferenceId": { + "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:bicep/modules/compute.disk:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-cdimp' + params: { + // Required parameters + name: 'cdimp001' + sku: 'Standard_LRS' + // Non-required parameters + createOption: 'Import' + enableDefaultTelemetry: '' + 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" + }, + "enableDefaultTelemetry": { + "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:bicep/modules/compute.disk:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-cdmax' + params: { + // Required parameters + name: 'cdmax001' + sku: 'UltraSSD_LRS' + // Non-required parameters + diskIOPSReadWrite: 500 + diskMBpsReadWrite: 60 + diskSizeGB: 128 + enableDefaultTelemetry: '' + 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 + }, + "enableDefaultTelemetry": { + "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:bicep/modules/compute.disk:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-cdwaf' + params: { + // Required parameters + name: 'cdwaf001' + sku: 'UltraSSD_LRS' + // Non-required parameters + diskIOPSReadWrite: 500 + diskMBpsReadWrite: 60 + diskSizeGB: 128 + enableDefaultTelemetry: '' + 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 + }, + "enableDefaultTelemetry": { + "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. | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | 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: `enableDefaultTelemetry` + +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_ diff --git a/avm/res/compute/disk/main.bicep b/avm/res/compute/disk/main.bicep new file mode 100644 index 0000000000..7989977bb4 --- /dev/null +++ b/avm/res/compute/disk/main.bicep @@ -0,0 +1,264 @@ +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 enableDefaultTelemetry 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 defaultTelemetry 'Microsoft.Resources/deployments@2022-09-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +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..37e7361de7 --- /dev/null +++ b/avm/res/compute/disk/main.json @@ -0,0 +1,476 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "8419179965275134660" + }, + "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." + } + }, + "enableDefaultTelemetry": { + "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": { + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "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..95b44f7771 --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,50 @@ +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.images-${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. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@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: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}-${serviceShort}001' + 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..67fd259073 --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/image/main.test.bicep @@ -0,0 +1,78 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.images-${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. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@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}' + } +} + +// ============== // +// Test Execution // +// ============== // +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}-${serviceShort}001' + 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..aa2912f2ec --- /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('../../../../../.shared/.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('../../../../../.shared/.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..0622d78455 --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/import/main.test.bicep @@ -0,0 +1,83 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.images-${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. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@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}' + 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: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}-${serviceShort}001' + 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..25ab818edd --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/max/main.test.bicep @@ -0,0 +1,89 @@ +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.images-${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. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@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}' + } +} + +// ============== // +// Test Execution // +// ============== // +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}-${serviceShort}001' + 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/dependencies.bicep b/avm/res/compute/disk/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..616cf219fe --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/waf-aligned/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/waf-aligned/main.test.bicep b/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..e22035fb5e --- /dev/null +++ b/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,72 @@ +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.images-${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. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@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}' + } +} + +// ============== // +// Test Execution // +// ============== // +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}-${serviceShort}001' + 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..96236a61ba --- /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.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/compute/image/README.md b/avm/res/compute/image/README.md new file mode 100644 index 0000000000..dbfd145add --- /dev/null +++ b/avm/res/compute/image/README.md @@ -0,0 +1,537 @@ +# Images `[Microsoft.Compute/images]` + +This module deploys a Compute Image. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.Compute/images` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-11-01/images) | + +## Usage examples + +The following section provides usage examples for the module, which were used to validate and deploy the module successfully. For a full reference, please review the module's test folder in its repository. + +>**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +>**Note**: To reference the module, please use the following syntax `br:bicep/modules/compute.image:1.0.0`. + +- [Using large parameter set](#example-1-using-large-parameter-set) +- [WAF-aligned](#example-2-waf-aligned) + +### Example 1: _Using large parameter set_ + +This instance deploys the module with most of its features enabled. + + +

+ +via Bicep module + +```bicep +module image 'br:bicep/modules/compute.image:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-cimax' + params: { + // Required parameters + name: 'cimax001' + osAccountType: 'Premium_LRS' + osDiskBlobUri: '' + osDiskCaching: 'ReadWrite' + osType: 'Windows' + // Non-required parameters + diskEncryptionSetResourceId: '' + diskSizeGB: 128 + enableDefaultTelemetry: '' + hyperVGeneration: 'V1' + osState: 'Generalized' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + tagA: 'You\'re it' + tagB: 'Player' + } + zoneResilient: true + } +} +``` + +
+

+ +

+ +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": "cimax001" + }, + "osAccountType": { + "value": "Premium_LRS" + }, + "osDiskBlobUri": { + "value": "" + }, + "osDiskCaching": { + "value": "ReadWrite" + }, + "osType": { + "value": "Windows" + }, + // Non-required parameters + "diskEncryptionSetResourceId": { + "value": "" + }, + "diskSizeGB": { + "value": 128 + }, + "enableDefaultTelemetry": { + "value": "" + }, + "hyperVGeneration": { + "value": "V1" + }, + "osState": { + "value": "Generalized" + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "hidden-title": "This is visible in the resource name", + "tagA": "You\"re it", + "tagB": "Player" + } + }, + "zoneResilient": { + "value": true + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module image 'br:bicep/modules/compute.image:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-ciwaf' + params: { + // Required parameters + name: 'ciwaf001' + osAccountType: 'Premium_LRS' + osDiskBlobUri: '' + osDiskCaching: 'ReadWrite' + osType: 'Windows' + // Non-required parameters + diskEncryptionSetResourceId: '' + diskSizeGB: 128 + enableDefaultTelemetry: '' + hyperVGeneration: 'V1' + osState: 'Generalized' + tags: { + 'hidden-title': 'This is visible in the resource name' + tagA: 'You\'re it' + tagB: 'Player' + } + zoneResilient: true + } +} +``` + +
+

+ +

+ +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": "ciwaf001" + }, + "osAccountType": { + "value": "Premium_LRS" + }, + "osDiskBlobUri": { + "value": "" + }, + "osDiskCaching": { + "value": "ReadWrite" + }, + "osType": { + "value": "Windows" + }, + // Non-required parameters + "diskEncryptionSetResourceId": { + "value": "" + }, + "diskSizeGB": { + "value": 128 + }, + "enableDefaultTelemetry": { + "value": "" + }, + "hyperVGeneration": { + "value": "V1" + }, + "osState": { + "value": "Generalized" + }, + "tags": { + "value": { + "hidden-title": "This is visible in the resource name", + "tagA": "You\"re it", + "tagB": "Player" + } + }, + "zoneResilient": { + "value": true + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the image. | +| [`osDiskBlobUri`](#parameter-osdiskbloburi) | string | The Virtual Hard Disk. | +| [`osType`](#parameter-ostype) | string | This property allows you to specify the type of the OS that is included in the disk if creating a VM from a custom image. - Windows or Linux. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`dataDisks`](#parameter-datadisks) | array | Specifies the parameters that are used to add a data disk to a virtual machine. | +| [`diskEncryptionSetResourceId`](#parameter-diskencryptionsetresourceid) | string | Specifies the customer managed disk encryption set resource ID for the managed image disk. | +| [`diskSizeGB`](#parameter-disksizegb) | int | Specifies the size of empty data disks in gigabytes. This element can be used to overwrite the name of the disk in a virtual machine image. This value cannot be larger than 1023 GB. | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`extendedLocation`](#parameter-extendedlocation) | object | The extended location of the Image. | +| [`hyperVGeneration`](#parameter-hypervgeneration) | string | Gets the HyperVGenerationType of the VirtualMachine created from the image. - V1 or V2. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`managedDiskResourceId`](#parameter-manageddiskresourceid) | string | The managedDisk. | +| [`osAccountType`](#parameter-osaccounttype) | string | Specifies the storage account type for the managed disk. NOTE: UltraSSD_LRS can only be used with data disks, it cannot be used with OS Disk. - Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS. | +| [`osDiskCaching`](#parameter-osdiskcaching) | string | Specifies the caching requirements. Default: None for Standard storage. ReadOnly for Premium storage. - None, ReadOnly, ReadWrite. | +| [`osState`](#parameter-osstate) | string | The OS State. For managed images, use Generalized. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`snapshotResourceId`](#parameter-snapshotresourceid) | string | The snapshot resource ID. | +| [`sourceVirtualMachineResourceId`](#parameter-sourcevirtualmachineresourceid) | string | The source virtual machine from which Image is created. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | +| [`zoneResilient`](#parameter-zoneresilient) | bool | Default is false. Specifies whether an image is zone resilient or not. Zone resilient images can be created only in regions that provide Zone Redundant Storage (ZRS). | + +### Parameter: `name` + +The name of the image. + +- Required: Yes +- Type: string + +### Parameter: `osDiskBlobUri` + +The Virtual Hard Disk. + +- Required: Yes +- Type: string + +### Parameter: `osType` + +This property allows you to specify the type of the OS that is included in the disk if creating a VM from a custom image. - Windows or Linux. + +- Required: Yes +- Type: string + +### Parameter: `dataDisks` + +Specifies the parameters that are used to add a data disk to a virtual machine. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `diskEncryptionSetResourceId` + +Specifies the customer managed disk encryption set resource ID for the managed image disk. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `diskSizeGB` + +Specifies the size of empty data disks in gigabytes. This element can be used to overwrite the name of the disk in a virtual machine image. This value cannot be larger than 1023 GB. + +- Required: No +- Type: int +- Default: `128` + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `extendedLocation` + +The extended location of the Image. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `hyperVGeneration` + +Gets the HyperVGenerationType of the VirtualMachine created from the image. - V1 or V2. + +- Required: No +- Type: string +- Default: `'V1'` + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `managedDiskResourceId` + +The managedDisk. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `osAccountType` + +Specifies the storage account type for the managed disk. NOTE: UltraSSD_LRS can only be used with data disks, it cannot be used with OS Disk. - Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS. + +- Required: Yes +- Type: string + +### Parameter: `osDiskCaching` + +Specifies the caching requirements. Default: None for Standard storage. ReadOnly for Premium storage. - None, ReadOnly, ReadWrite. + +- Required: Yes +- Type: string + +### Parameter: `osState` + +The OS State. For managed images, use Generalized. + +- Required: No +- Type: string +- Default: `'Generalized'` +- Allowed: + ```Bicep + [ + 'Generalized' + 'Specialized' + ] + ``` + +### 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: `snapshotResourceId` + +The snapshot resource ID. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `sourceVirtualMachineResourceId` + +The source virtual machine from which Image is created. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `tags` + +Tags of the resource. + +- Required: No +- Type: object + +### Parameter: `zoneResilient` + +Default is false. Specifies whether an image is zone resilient or not. Zone resilient images can be created only in regions that provide Zone Redundant Storage (ZRS). + +- Required: No +- Type: bool +- Default: `False` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the image. | +| `resourceGroupName` | string | The resource group the image was deployed into. | +| `resourceId` | string | The resource ID of the image. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/compute/image/main.bicep b/avm/res/compute/image/main.bicep new file mode 100644 index 0000000000..20e3e6ea11 --- /dev/null +++ b/avm/res/compute/image/main.bicep @@ -0,0 +1,170 @@ +metadata name = 'Images' +metadata description = 'This module deploys a Compute Image.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the image.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. The Virtual Hard Disk.') +param osDiskBlobUri string + +@description('Required. This property allows you to specify the type of the OS that is included in the disk if creating a VM from a custom image. - Windows or Linux.') +param osType string + +@description('Optional. Specifies the caching requirements. Default: None for Standard storage. ReadOnly for Premium storage. - None, ReadOnly, ReadWrite.') +param osDiskCaching string + +@description('Optional. Specifies the storage account type for the managed disk. NOTE: UltraSSD_LRS can only be used with data disks, it cannot be used with OS Disk. - Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS.') +param osAccountType string + +@description('Optional. Default is false. Specifies whether an image is zone resilient or not. Zone resilient images can be created only in regions that provide Zone Redundant Storage (ZRS).') +param zoneResilient bool = false + +@description('Optional. Gets the HyperVGenerationType of the VirtualMachine created from the image. - V1 or V2.') +param hyperVGeneration string = 'V1' + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. The extended location of the Image.') +param extendedLocation object = {} + +@description('Optional. The source virtual machine from which Image is created.') +param sourceVirtualMachineResourceId string = '' + +@description('Optional. Specifies the customer managed disk encryption set resource ID for the managed image disk.') +param diskEncryptionSetResourceId string = '' + +@description('Optional. The managedDisk.') +param managedDiskResourceId string = '' + +@description('Optional. Specifies the size of empty data disks in gigabytes. This element can be used to overwrite the name of the disk in a virtual machine image. This value cannot be larger than 1023 GB.') +param diskSizeGB int = 128 + +@description('Optional. The OS State. For managed images, use Generalized.') +@allowed([ + 'Generalized' + 'Specialized' +]) +param osState string = 'Generalized' + +@description('Optional. The snapshot resource ID.') +param snapshotResourceId string = '' + +@description('Optional. Specifies the parameters that are used to add a data disk to a virtual machine.') +param dataDisks array = [] + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2022-09-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource image 'Microsoft.Compute/images@2022-11-01' = { + name: name + location: location + tags: tags + extendedLocation: !empty(extendedLocation) ? extendedLocation : null + properties: { + storageProfile: { + osDisk: { + osType: osType + blobUri: osDiskBlobUri + caching: osDiskCaching + storageAccountType: osAccountType + osState: osState + diskEncryptionSet: !empty(diskEncryptionSetResourceId) ? { + id: diskEncryptionSetResourceId + } : null + diskSizeGB: diskSizeGB + managedDisk: !empty(managedDiskResourceId) ? { + id: managedDiskResourceId + } : null + snapshot: !empty(snapshotResourceId) ? { + id: snapshotResourceId + } : null + } + dataDisks: dataDisks + zoneResilient: zoneResilient + } + hyperVGeneration: hyperVGeneration + sourceVirtualMachine: !empty(sourceVirtualMachineResourceId) ? { + id: sourceVirtualMachineResourceId + } : null + } +} + +resource image_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(image.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: image +}] + +@description('The resource ID of the image.') +output resourceId string = image.id + +@description('The resource group the image was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the image.') +output name string = image.name + +@description('The location the resource was deployed into.') +output location string = image.location +// =============== // +// Definitions // +// =============== // + +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/image/main.json b/avm/res/compute/image/main.json new file mode 100644 index 0000000000..b3099a9dec --- /dev/null +++ b/avm/res/compute/image/main.json @@ -0,0 +1,320 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "6473488393825855372" + }, + "name": "Images", + "description": "This module deploys a Compute Image.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "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 image." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "osDiskBlobUri": { + "type": "string", + "metadata": { + "description": "Required. The Virtual Hard Disk." + } + }, + "osType": { + "type": "string", + "metadata": { + "description": "Required. This property allows you to specify the type of the OS that is included in the disk if creating a VM from a custom image. - Windows or Linux." + } + }, + "osDiskCaching": { + "type": "string", + "metadata": { + "description": "Optional. Specifies the caching requirements. Default: None for Standard storage. ReadOnly for Premium storage. - None, ReadOnly, ReadWrite." + } + }, + "osAccountType": { + "type": "string", + "metadata": { + "description": "Optional. Specifies the storage account type for the managed disk. NOTE: UltraSSD_LRS can only be used with data disks, it cannot be used with OS Disk. - Standard_LRS, Premium_LRS, StandardSSD_LRS, UltraSSD_LRS." + } + }, + "zoneResilient": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Default is false. Specifies whether an image is zone resilient or not. Zone resilient images can be created only in regions that provide Zone Redundant Storage (ZRS)." + } + }, + "hyperVGeneration": { + "type": "string", + "defaultValue": "V1", + "metadata": { + "description": "Optional. Gets the HyperVGenerationType of the VirtualMachine created from the image. - V1 or V2." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "extendedLocation": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The extended location of the Image." + } + }, + "sourceVirtualMachineResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The source virtual machine from which Image is created." + } + }, + "diskEncryptionSetResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the customer managed disk encryption set resource ID for the managed image disk." + } + }, + "managedDiskResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The managedDisk." + } + }, + "diskSizeGB": { + "type": "int", + "defaultValue": 128, + "metadata": { + "description": "Optional. Specifies the size of empty data disks in gigabytes. This element can be used to overwrite the name of the disk in a virtual machine image. This value cannot be larger than 1023 GB." + } + }, + "osState": { + "type": "string", + "defaultValue": "Generalized", + "allowedValues": [ + "Generalized", + "Specialized" + ], + "metadata": { + "description": "Optional. The OS State. For managed images, use Generalized." + } + }, + "snapshotResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The snapshot resource ID." + } + }, + "dataDisks": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies the parameters that are used to add a data disk to a virtual machine." + } + }, + "enableDefaultTelemetry": { + "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')]", + "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": { + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "image": { + "type": "Microsoft.Compute/images", + "apiVersion": "2022-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "extendedLocation": "[if(not(empty(parameters('extendedLocation'))), parameters('extendedLocation'), null())]", + "properties": { + "storageProfile": { + "osDisk": { + "osType": "[parameters('osType')]", + "blobUri": "[parameters('osDiskBlobUri')]", + "caching": "[parameters('osDiskCaching')]", + "storageAccountType": "[parameters('osAccountType')]", + "osState": "[parameters('osState')]", + "diskEncryptionSet": "[if(not(empty(parameters('diskEncryptionSetResourceId'))), createObject('id', parameters('diskEncryptionSetResourceId')), null())]", + "diskSizeGB": "[parameters('diskSizeGB')]", + "managedDisk": "[if(not(empty(parameters('managedDiskResourceId'))), createObject('id', parameters('managedDiskResourceId')), null())]", + "snapshot": "[if(not(empty(parameters('snapshotResourceId'))), createObject('id', parameters('snapshotResourceId')), null())]" + }, + "dataDisks": "[parameters('dataDisks')]", + "zoneResilient": "[parameters('zoneResilient')]" + }, + "hyperVGeneration": "[parameters('hyperVGeneration')]", + "sourceVirtualMachine": "[if(not(empty(parameters('sourceVirtualMachineResourceId'))), createObject('id', parameters('sourceVirtualMachineResourceId')), null())]" + } + }, + "image_roleAssignments": { + "copy": { + "name": "image_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Compute/images/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Compute/images', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "image" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the image." + }, + "value": "[resourceId('Microsoft.Compute/images', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the image was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the image." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('image', '2022-11-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/compute/image/tests/e2e/max/dependencies.bicep b/avm/res/compute/image/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..2a31d8730b --- /dev/null +++ b/avm/res/compute/image/tests/e2e/max/dependencies.bicep @@ -0,0 +1,218 @@ +@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 of the Disk Encryption Set to create.') +param diskEncryptionSetName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName 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' = { + #disable-next-line use-stable-resource-identifiers + 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('../../../../../.shared/.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('../../../../../.shared/.scripts/Copy-VhdToStorageAccount.ps1') + cleanupPreference: 'OnSuccess' + forceUpdateTag: baseTime + } + dependsOn: [ triggerImageDeploymentScript ] +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: true // Required for encrption to work + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'encryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Reader-RoleAssignment') + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2022-07-02' = { + name: diskEncryptionSetName + location: location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + activeKey: { + sourceVault: { + id: keyVault.id + } + keyUrl: keyVault::key.properties.keyUriWithVersion + } + encryptionType: 'EncryptionAtRestWithCustomerKey' + } + dependsOn: [ + keyPermissions + ] +} + +@description('The URI of the created VHD.') +output vhdUri string = 'https://${storageAccount.name}.blob.${environment().suffixes.storage}/vhds/${imageTemplateNamePrefix}.vhd' + +@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 + +@description('The resource ID of the created Disk Encryption Set.') +output diskEncryptionSetResourceId string = diskEncryptionSet.id diff --git a/avm/res/compute/image/tests/e2e/max/dependencies_rbac.bicep b/avm/res/compute/image/tests/e2e/max/dependencies_rbac.bicep new file mode 100644 index 0000000000..cdca1b63bd --- /dev/null +++ b/avm/res/compute/image/tests/e2e/max/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/image/tests/e2e/max/main.test.bicep b/avm/res/compute/image/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..4ef529aeea --- /dev/null +++ b/avm/res/compute/image/tests/e2e/max/main.test.bicep @@ -0,0 +1,97 @@ +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.images-${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 = 'cimax' + +@description('Generated. Used as a basis for unique resource names.') +param baseTime string = utcNow('u') + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@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}' + // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + diskEncryptionSetName: 'dep-${namePrefix}-des-${serviceShort}' + 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: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + osAccountType: 'Premium_LRS' + osDiskBlobUri: nestedDependencies.outputs.vhdUri + osDiskCaching: 'ReadWrite' + osType: 'Windows' + hyperVGeneration: 'V1' + 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' + } + ] + zoneResilient: true + diskEncryptionSetResourceId: nestedDependencies.outputs.diskEncryptionSetResourceId + osState: 'Generalized' + diskSizeGB: 128 + tags: { + 'hidden-title': 'This is visible in the resource name' + tagA: 'You\'re it' + tagB: 'Player' + } + } +}] diff --git a/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..2a31d8730b --- /dev/null +++ b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,218 @@ +@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 of the Disk Encryption Set to create.') +param diskEncryptionSetName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName 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' = { + #disable-next-line use-stable-resource-identifiers + 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('../../../../../.shared/.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('../../../../../.shared/.scripts/Copy-VhdToStorageAccount.ps1') + cleanupPreference: 'OnSuccess' + forceUpdateTag: baseTime + } + dependsOn: [ triggerImageDeploymentScript ] +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: true // Required for encrption to work + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'encryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Reader-RoleAssignment') + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2022-07-02' = { + name: diskEncryptionSetName + location: location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + activeKey: { + sourceVault: { + id: keyVault.id + } + keyUrl: keyVault::key.properties.keyUriWithVersion + } + encryptionType: 'EncryptionAtRestWithCustomerKey' + } + dependsOn: [ + keyPermissions + ] +} + +@description('The URI of the created VHD.') +output vhdUri string = 'https://${storageAccount.name}.blob.${environment().suffixes.storage}/vhds/${imageTemplateNamePrefix}.vhd' + +@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 + +@description('The resource ID of the created Disk Encryption Set.') +output diskEncryptionSetResourceId string = diskEncryptionSet.id diff --git a/avm/res/compute/image/tests/e2e/waf-aligned/dependencies_rbac.bicep b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies_rbac.bicep new file mode 100644 index 0000000000..cdca1b63bd --- /dev/null +++ b/avm/res/compute/image/tests/e2e/waf-aligned/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/image/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..ee4dfe3db0 --- /dev/null +++ b/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,80 @@ +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.images-${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 = 'ciwaf' + +@description('Generated. Used as a basis for unique resource names.') +param baseTime string = utcNow('u') + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@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}' + // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + diskEncryptionSetName: 'dep-${namePrefix}-des-${serviceShort}' + 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: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + osAccountType: 'Premium_LRS' + osDiskBlobUri: nestedDependencies.outputs.vhdUri + osDiskCaching: 'ReadWrite' + osType: 'Windows' + hyperVGeneration: 'V1' + zoneResilient: true + diskEncryptionSetResourceId: nestedDependencies.outputs.diskEncryptionSetResourceId + osState: 'Generalized' + diskSizeGB: 128 + tags: { + 'hidden-title': 'This is visible in the resource name' + tagA: 'You\'re it' + tagB: 'Player' + } + } +}] diff --git a/avm/res/compute/image/version.json b/avm/res/compute/image/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/compute/image/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/consumption/budget/README.md b/avm/res/consumption/budget/README.md new file mode 100644 index 0000000000..27a7dbedeb --- /dev/null +++ b/avm/res/consumption/budget/README.md @@ -0,0 +1,405 @@ +# Consumption Budgets `[Microsoft.Consumption/budgets]` + +This module deploys a Consumption Budget for Subscriptions. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Consumption/budgets` | [2021-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Consumption/2021-10-01/budgets) | + +## 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:bicep/modules/consumption.budget:1.0.0`. + +- [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 budget 'br:bicep/modules/consumption.budget:1.0.0' = { + name: '${uniqueString(deployment().name)}-test-cbmin' + params: { + // Required parameters + amount: 500 + name: 'cbmin001' + // Non-required parameters + contactEmails: [ + 'dummy@contoso.com' + ] + enableDefaultTelemetry: '' + } +} +``` + +
+

+ +

+ +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 + "amount": { + "value": 500 + }, + "name": { + "value": "cbmin001" + }, + // Non-required parameters + "contactEmails": { + "value": [ + "dummy@contoso.com" + ] + }, + "enableDefaultTelemetry": { + "value": "" + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module budget 'br:bicep/modules/consumption.budget:1.0.0' = { + name: '${uniqueString(deployment().name)}-test-cbmax' + params: { + // Required parameters + amount: 500 + name: 'cbmax001' + // Non-required parameters + contactEmails: [ + 'dummy@contoso.com' + ] + enableDefaultTelemetry: '' + thresholds: [ + 50 + 75 + 90 + 100 + 110 + ] + } +} +``` + +
+

+ +

+ +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 + "amount": { + "value": 500 + }, + "name": { + "value": "cbmax001" + }, + // Non-required parameters + "contactEmails": { + "value": [ + "dummy@contoso.com" + ] + }, + "enableDefaultTelemetry": { + "value": "" + }, + "thresholds": { + "value": [ + 50, + 75, + 90, + 100, + 110 + ] + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module budget 'br:bicep/modules/consumption.budget:1.0.0' = { + name: '${uniqueString(deployment().name)}-test-cbwaf' + params: { + // Required parameters + amount: 500 + name: 'cbwaf001' + // Non-required parameters + contactEmails: [ + 'dummy@contoso.com' + ] + enableDefaultTelemetry: '' + thresholds: [ + 50 + 75 + 90 + 100 + 110 + ] + } +} +``` + +
+

+ +

+ +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 + "amount": { + "value": 500 + }, + "name": { + "value": "cbwaf001" + }, + // Non-required parameters + "contactEmails": { + "value": [ + "dummy@contoso.com" + ] + }, + "enableDefaultTelemetry": { + "value": "" + }, + "thresholds": { + "value": [ + 50, + 75, + 90, + 100, + 110 + ] + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`amount`](#parameter-amount) | int | The total amount of cost or usage to track with the budget. | +| [`name`](#parameter-name) | string | The name of the budget. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`actionGroups`](#parameter-actiongroups) | array | List of action group resource IDs that will receive the alert. Required if neither `contactEmails` nor `contactEmails` was provided. | +| [`contactEmails`](#parameter-contactemails) | array | The list of email addresses to send the budget notification to when the thresholds are exceeded. Required if neither `contactRoles` nor `actionGroups` was provided. | +| [`contactRoles`](#parameter-contactroles) | array | The list of contact roles to send the budget notification to when the thresholds are exceeded. Required if neither `contactEmails` nor `actionGroups` was provided. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`category`](#parameter-category) | string | The category of the budget, whether the budget tracks cost or usage. | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`endDate`](#parameter-enddate) | string | The end date for the budget. If not provided, it will default to 10 years from the start date. | +| [`location`](#parameter-location) | string | Location deployment metadata. | +| [`resetPeriod`](#parameter-resetperiod) | string | The time covered by a budget. Tracking of the amount will be reset based on the time grain. BillingMonth, BillingQuarter, and BillingAnnual are only supported by WD customers. | +| [`startDate`](#parameter-startdate) | string | The start date for the budget. Start date should be the first day of the month and cannot be in the past (except for the current month). | +| [`thresholds`](#parameter-thresholds) | array | Percent thresholds of budget for when to get a notification. Can be up to 5 thresholds, where each must be between 1 and 1000. | + +### Parameter: `amount` + +The total amount of cost or usage to track with the budget. + +- Required: Yes +- Type: int + +### Parameter: `name` + +The name of the budget. + +- Required: Yes +- Type: string + +### Parameter: `actionGroups` + +List of action group resource IDs that will receive the alert. Required if neither `contactEmails` nor `contactEmails` was provided. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `contactEmails` + +The list of email addresses to send the budget notification to when the thresholds are exceeded. Required if neither `contactRoles` nor `actionGroups` was provided. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `contactRoles` + +The list of contact roles to send the budget notification to when the thresholds are exceeded. Required if neither `contactEmails` nor `actionGroups` was provided. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `category` + +The category of the budget, whether the budget tracks cost or usage. + +- Required: No +- Type: string +- Default: `'Cost'` +- Allowed: + ```Bicep + [ + 'Cost' + 'Usage' + ] + ``` + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `endDate` + +The end date for the budget. If not provided, it will default to 10 years from the start date. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `location` + +Location deployment metadata. + +- Required: No +- Type: string +- Default: `[deployment().location]` + +### Parameter: `resetPeriod` + +The time covered by a budget. Tracking of the amount will be reset based on the time grain. BillingMonth, BillingQuarter, and BillingAnnual are only supported by WD customers. + +- Required: No +- Type: string +- Default: `'Monthly'` +- Allowed: + ```Bicep + [ + 'Annually' + 'BillingAnnual' + 'BillingMonth' + 'BillingQuarter' + 'Monthly' + 'Quarterly' + ] + ``` + +### Parameter: `startDate` + +The start date for the budget. Start date should be the first day of the month and cannot be in the past (except for the current month). + +- Required: No +- Type: string +- Default: `[format('{0}-{1}-01T00:00:00Z', utcNow('yyyy'), utcNow('MM'))]` + +### Parameter: `thresholds` + +Percent thresholds of budget for when to get a notification. Can be up to 5 thresholds, where each must be between 1 and 1000. + +- Required: No +- Type: array +- Default: + ```Bicep + [ + 50 + 75 + 90 + 100 + 110 + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the budget. | +| `resourceId` | string | The resource ID of the budget. | +| `subscriptionName` | string | The subscription the budget was deployed into. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/consumption/budget/main.bicep b/avm/res/consumption/budget/main.bicep new file mode 100644 index 0000000000..853e144964 --- /dev/null +++ b/avm/res/consumption/budget/main.bicep @@ -0,0 +1,111 @@ +metadata name = 'Consumption Budgets' +metadata description = 'This module deploys a Consumption Budget for Subscriptions.' +metadata owner = 'Azure/module-maintainers' + +targetScope = 'subscription' + +@description('Required. The name of the budget.') +param name string + +@allowed([ + 'Cost' + 'Usage' +]) +@description('Optional. The category of the budget, whether the budget tracks cost or usage.') +param category string = 'Cost' + +@description('Required. The total amount of cost or usage to track with the budget.') +param amount int + +@allowed([ + 'Monthly' + 'Quarterly' + 'Annually' + 'BillingMonth' + 'BillingQuarter' + 'BillingAnnual' +]) +@description('Optional. The time covered by a budget. Tracking of the amount will be reset based on the time grain. BillingMonth, BillingQuarter, and BillingAnnual are only supported by WD customers.') +param resetPeriod string = 'Monthly' + +@description('Optional. The start date for the budget. Start date should be the first day of the month and cannot be in the past (except for the current month).') +param startDate string = '${utcNow('yyyy')}-${utcNow('MM')}-01T00:00:00Z' + +@description('Optional. The end date for the budget. If not provided, it will default to 10 years from the start date.') +param endDate string = '' + +@maxLength(5) +@description('Optional. Percent thresholds of budget for when to get a notification. Can be up to 5 thresholds, where each must be between 1 and 1000.') +param thresholds array = [ + 50 + 75 + 90 + 100 + 110 +] + +@description('Conditional. The list of email addresses to send the budget notification to when the thresholds are exceeded. Required if neither `contactRoles` nor `actionGroups` was provided.') +param contactEmails array = [] + +@description('Conditional. The list of contact roles to send the budget notification to when the thresholds are exceeded. Required if neither `contactEmails` nor `actionGroups` was provided.') +param contactRoles array = [] + +@description('Conditional. List of action group resource IDs that will receive the alert. Required if neither `contactEmails` nor `contactEmails` was provided.') +param actionGroups array = [] + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@sys.description('Optional. Location deployment metadata.') +param location string = deployment().location + +var notificationsArray = [for threshold in thresholds: { + 'Actual_GreaterThan_${threshold}_Percentage': { + enabled: true + operator: 'GreaterThan' + threshold: threshold + contactEmails: empty(contactEmails) ? null : array(contactEmails) + contactRoles: empty(contactRoles) ? null : array(contactRoles) + contactGroups: empty(actionGroups) ? null : array(actionGroups) + thresholdType: 'Actual' + } +}] + +var notifications = json(replace(replace(replace(string(notificationsArray), '[{', '{'), '}]', '}'), '}},{', '},')) + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + location: location + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource budget 'Microsoft.Consumption/budgets@2021-10-01' = { + name: name + properties: { + category: category + amount: amount + timeGrain: resetPeriod + timePeriod: { + startDate: startDate + endDate: endDate + } + filter: {} + notifications: notifications + } +} + +@description('The name of the budget.') +output name string = budget.name + +@description('The resource ID of the budget.') +output resourceId string = budget.id + +@description('The subscription the budget was deployed into.') +output subscriptionName string = subscription().displayName diff --git a/avm/res/consumption/budget/main.json b/avm/res/consumption/budget/main.json new file mode 100644 index 0000000000..31a5523934 --- /dev/null +++ b/avm/res/consumption/budget/main.json @@ -0,0 +1,193 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "10861664842554589267" + }, + "name": "Consumption Budgets", + "description": "This module deploys a Consumption Budget for Subscriptions.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the budget." + } + }, + "category": { + "type": "string", + "defaultValue": "Cost", + "allowedValues": [ + "Cost", + "Usage" + ], + "metadata": { + "description": "Optional. The category of the budget, whether the budget tracks cost or usage." + } + }, + "amount": { + "type": "int", + "metadata": { + "description": "Required. The total amount of cost or usage to track with the budget." + } + }, + "resetPeriod": { + "type": "string", + "defaultValue": "Monthly", + "allowedValues": [ + "Monthly", + "Quarterly", + "Annually", + "BillingMonth", + "BillingQuarter", + "BillingAnnual" + ], + "metadata": { + "description": "Optional. The time covered by a budget. Tracking of the amount will be reset based on the time grain. BillingMonth, BillingQuarter, and BillingAnnual are only supported by WD customers." + } + }, + "startDate": { + "type": "string", + "defaultValue": "[format('{0}-{1}-01T00:00:00Z', utcNow('yyyy'), utcNow('MM'))]", + "metadata": { + "description": "Optional. The start date for the budget. Start date should be the first day of the month and cannot be in the past (except for the current month)." + } + }, + "endDate": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The end date for the budget. If not provided, it will default to 10 years from the start date." + } + }, + "thresholds": { + "type": "array", + "defaultValue": [ + 50, + 75, + 90, + 100, + 110 + ], + "maxLength": 5, + "metadata": { + "description": "Optional. Percent thresholds of budget for when to get a notification. Can be up to 5 thresholds, where each must be between 1 and 1000." + } + }, + "contactEmails": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Conditional. The list of email addresses to send the budget notification to when the thresholds are exceeded. Required if neither `contactRoles` nor `actionGroups` was provided." + } + }, + "contactRoles": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Conditional. The list of contact roles to send the budget notification to when the thresholds are exceeded. Required if neither `contactEmails` nor `actionGroups` was provided." + } + }, + "actionGroups": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Conditional. List of action group resource IDs that will receive the alert. Required if neither `contactEmails` nor `contactEmails` was provided." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location deployment metadata." + } + } + }, + "variables": { + "copy": [ + { + "name": "notificationsArray", + "count": "[length(parameters('thresholds'))]", + "input": { + "[format('Actual_GreaterThan_{0}_Percentage', parameters('thresholds')[copyIndex('notificationsArray')])]": { + "enabled": true, + "operator": "GreaterThan", + "threshold": "[parameters('thresholds')[copyIndex('notificationsArray')]]", + "contactEmails": "[if(empty(parameters('contactEmails')), null(), array(parameters('contactEmails')))]", + "contactRoles": "[if(empty(parameters('contactRoles')), null(), array(parameters('contactRoles')))]", + "contactGroups": "[if(empty(parameters('actionGroups')), null(), array(parameters('actionGroups')))]", + "thresholdType": "Actual" + } + } + } + ], + "notifications": "[json(replace(replace(replace(string(variables('notificationsArray')), '[{', '{'), '}]', '}'), '}},{', '},'))]" + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "location": "[parameters('location')]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Consumption/budgets", + "apiVersion": "2021-10-01", + "name": "[parameters('name')]", + "properties": { + "category": "[parameters('category')]", + "amount": "[parameters('amount')]", + "timeGrain": "[parameters('resetPeriod')]", + "timePeriod": { + "startDate": "[parameters('startDate')]", + "endDate": "[parameters('endDate')]" + }, + "filter": {}, + "notifications": "[variables('notifications')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the budget." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the budget." + }, + "value": "[subscriptionResourceId('Microsoft.Consumption/budgets', parameters('name'))]" + }, + "subscriptionName": { + "type": "string", + "metadata": { + "description": "The subscription the budget was deployed into." + }, + "value": "[subscription().displayName]" + } + } +} \ No newline at end of file diff --git a/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep b/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..44789640d2 --- /dev/null +++ b/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,34 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@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 = 'cbmin' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + amount: 500 + contactEmails: [ + 'dummy@contoso.com' + ] + } +}] diff --git a/avm/res/consumption/budget/tests/e2e/max/main.test.bicep b/avm/res/consumption/budget/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..15fa49855c --- /dev/null +++ b/avm/res/consumption/budget/tests/e2e/max/main.test.bicep @@ -0,0 +1,41 @@ +targetScope = 'subscription' + +metadata name = 'Using large parameter set' +metadata description = 'This instance deploys the module with most of its features enabled.' + +// ========== // +// Parameters // +// ========== // + +@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 = 'cbmax' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + amount: 500 + contactEmails: [ + 'dummy@contoso.com' + ] + thresholds: [ + 50 + 75 + 90 + 100 + 110 + ] + } +}] diff --git a/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep b/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..0d2260e7d8 --- /dev/null +++ b/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,41 @@ +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. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'cbwaf' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + amount: 500 + contactEmails: [ + 'dummy@contoso.com' + ] + thresholds: [ + 50 + 75 + 90 + 100 + 110 + ] + } +}] diff --git a/avm/res/consumption/budget/version.json b/avm/res/consumption/budget/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/consumption/budget/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/databricks/access-connector/README.md b/avm/res/databricks/access-connector/README.md new file mode 100644 index 0000000000..ba68a44a37 --- /dev/null +++ b/avm/res/databricks/access-connector/README.md @@ -0,0 +1,509 @@ +# Azure Databricks Access Connectors `[Microsoft.Databricks/accessConnectors]` + +This module deploys an Azure Databricks Access Connector. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.Databricks/accessConnectors` | [2022-10-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Databricks/2022-10-01-preview/accessConnectors) | + +## 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:bicep/modules/databricks.access-connector:1.0.0`. + +- [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 accessConnector 'br:bicep/modules/databricks.access-connector:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-dacmin' + params: { + // Required parameters + name: 'dacmin001' + // Non-required parameters + enableDefaultTelemetry: '' + } +} +``` + +
+

+ +

+ +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": "dacmin001" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module accessConnector 'br:bicep/modules/databricks.access-connector:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-dacmax' + params: { + // Required parameters + name: 'dacmax001' + // Non-required parameters + enableDefaultTelemetry: '' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + 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": "dacmax001" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module accessConnector 'br:bicep/modules/databricks.access-connector:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-dacwaf' + params: { + // Required parameters + name: 'dacwaf001' + // Non-required parameters + enableDefaultTelemetry: '' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + 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": "dacwaf001" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "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 Azure Databricks access connector to create. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`location`](#parameter-location) | string | Location for all Resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | + +### Parameter: `name` + +The name of the Azure Databricks access connector to create. + +- Required: Yes +- Type: string + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### 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: `managedIdentities` + +The managed identity definition for this resource. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | + +### Parameter: `managedIdentities.systemAssigned` + +Enables system assigned managed identity on the resource. + +- Required: No +- Type: bool + +### Parameter: `managedIdentities.userAssignedResourceIds` + +The resource ID(s) to assign to the resource. + +- Required: No +- Type: array + +### 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 the resource was deployed into. | +| `name` | string | The name of the deployed access connector. | +| `resourceGroupName` | string | The resource group of the deployed access connector. | +| `resourceId` | string | The resource ID of the deployed access connector. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/databricks/access-connector/main.bicep b/avm/res/databricks/access-connector/main.bicep new file mode 100644 index 0000000000..53ba92c2c2 --- /dev/null +++ b/avm/res/databricks/access-connector/main.bicep @@ -0,0 +1,140 @@ +metadata name = 'Azure Databricks Access Connectors' +metadata description = 'This module deploys an Azure Databricks Access Connector.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the Azure Databricks access connector to create.') +param name string + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } + +var identity = !empty(managedIdentities) ? { + type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource accessConnector 'Microsoft.Databricks/accessConnectors@2022-10-01-preview' = { + name: name + location: location + tags: tags + identity: identity + properties: {} +} + +resource accessConnector_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: accessConnector +} + +resource accessConnector_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(accessConnector.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: accessConnector +}] + +@description('The name of the deployed access connector.') +output name string = accessConnector.name + +@description('The resource ID of the deployed access connector.') +output resourceId string = accessConnector.id + +@description('The resource group of the deployed access connector.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string = (managedIdentities.?systemAssigned ?? false) && contains(accessConnector.identity, 'principalId') ? accessConnector.identity.principalId : '' + +@description('The location the resource was deployed into.') +output location string = accessConnector.location + +// =============== // +// Definitions // +// =============== // + +type managedIdentitiesType = { + @description('Optional. Enables system assigned managed identity on the resource.') + systemAssigned: bool? + + @description('Optional. The resource ID(s) to assign to the resource.') + userAssignedResourceIds: string[]? +}? + +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/databricks/access-connector/main.json b/avm/res/databricks/access-connector/main.json new file mode 100644 index 0000000000..dce724ef4b --- /dev/null +++ b/avm/res/databricks/access-connector/main.json @@ -0,0 +1,287 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "3245638906962144809" + }, + "name": "Azure Databricks Access Connectors", + "description": "This module deploys an Azure Databricks Access Connector.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "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 Azure Databricks access connector to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "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." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "variables": { + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null())), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "accessConnector": { + "type": "Microsoft.Databricks/accessConnectors", + "apiVersion": "2022-10-01-preview", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "properties": {} + }, + "accessConnector_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.Databricks/accessConnectors/{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": [ + "accessConnector" + ] + }, + "accessConnector_roleAssignments": { + "copy": { + "name": "accessConnector_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Databricks/accessConnectors/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Databricks/accessConnectors', 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": [ + "accessConnector" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed access connector." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed access connector." + }, + "value": "[resourceId('Microsoft.Databricks/accessConnectors', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed access connector." + }, + "value": "[resourceGroup().name]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[if(and(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), contains(reference('accessConnector', '2022-10-01-preview', 'full').identity, 'principalId')), reference('accessConnector', '2022-10-01-preview', 'full').identity.principalId, '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('accessConnector', '2022-10-01-preview', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/databricks/access-connector/tests/e2e/defaults/main.test.bicep b/avm/res/databricks/access-connector/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..17bf07d2fc --- /dev/null +++ b/avm/res/databricks/access-connector/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,49 @@ +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}-databricks.accessconnectors-${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 = 'dacmin' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + } +}] diff --git a/avm/res/databricks/access-connector/tests/e2e/max/dependencies.bicep b/avm/res/databricks/access-connector/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..b20bc53e8f --- /dev/null +++ b/avm/res/databricks/access-connector/tests/e2e/max/dependencies.bicep @@ -0,0 +1,16 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: managedIdentityName + location: location +} + +@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/databricks/access-connector/tests/e2e/max/main.test.bicep b/avm/res/databricks/access-connector/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..586cd17f0c --- /dev/null +++ b/avm/res/databricks/access-connector/tests/e2e/max/main.test.bicep @@ -0,0 +1,90 @@ +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}-databricks.accessconnectors-${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 = 'dacmax' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + 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' + } + location: resourceGroup.location + } +}] diff --git a/avm/res/databricks/access-connector/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/databricks/access-connector/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..b20bc53e8f --- /dev/null +++ b/avm/res/databricks/access-connector/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,16 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: managedIdentityName + location: location +} + +@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/databricks/access-connector/tests/e2e/waf-aligned/main.test.bicep b/avm/res/databricks/access-connector/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..64b4f1b6ab --- /dev/null +++ b/avm/res/databricks/access-connector/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,73 @@ +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}-databricks.accessconnectors-${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 = 'dacwaf' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + location: resourceGroup.location + } +}] diff --git a/avm/res/databricks/access-connector/version.json b/avm/res/databricks/access-connector/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/databricks/access-connector/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/databricks/workspace/README.md b/avm/res/databricks/workspace/README.md new file mode 100644 index 0000000000..a6502ad9f6 --- /dev/null +++ b/avm/res/databricks/workspace/README.md @@ -0,0 +1,1463 @@ +# Azure Databricks Workspaces `[Microsoft.Databricks/workspaces]` + +This module deploys an Azure Databricks Workspace. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Notes](#Notes) + +## 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.Databricks/workspaces` | [2023-02-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Databricks/2023-02-01/workspaces) | +| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | +| `Microsoft.Network/privateEndpoints` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints) | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints/privateDnsZoneGroups) | + +## 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:bicep/modules/databricks.workspace:1.0.0`. + +- [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 workspace 'br:bicep/modules/databricks.workspace:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-dwmin' + params: { + // Required parameters + name: 'dwmin001' + // Non-required parameters + enableDefaultTelemetry: '' + } +} +``` + +
+

+ +

+ +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": "dwmin001" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module workspace 'br:bicep/modules/databricks.workspace:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-dwmax' + params: { + // Required parameters + name: 'dwmax001' + // Non-required parameters + amlWorkspaceResourceId: '' + customerManagedKey: { + keyName: '' + keyVaultResourceId: '' + } + customerManagedKeyManagedDisk: { + keyName: '' + keyVaultResourceId: '' + rotationToLatestKeyVersionEnabled: true + } + customPrivateSubnetName: '' + customPublicSubnetName: '' + customVirtualNetworkResourceId: '' + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + logCategoriesAndGroups: [ + { + category: 'jobs' + } + { + category: 'notebook' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + disablePublicIp: true + enableDefaultTelemetry: '' + loadBalancerBackendPoolName: '' + loadBalancerResourceId: '' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedResourceGroupResourceId: '' + natGatewayName: 'nat-gateway' + prepareEncryption: true + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + publicIpName: 'nat-gw-public-ip' + publicNetworkAccess: 'Disabled' + requiredNsgRules: 'NoAzureDatabricksRules' + requireInfrastructureEncryption: true + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + skuName: 'premium' + storageAccountName: 'sadwmax001' + storageAccountSkuName: 'Standard_ZRS' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + vnetAddressPrefix: '10.100' + } +} +``` + +
+

+ +

+ +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": "dwmax001" + }, + // Non-required parameters + "amlWorkspaceResourceId": { + "value": "" + }, + "customerManagedKey": { + "value": { + "keyName": "", + "keyVaultResourceId": "" + } + }, + "customerManagedKeyManagedDisk": { + "value": { + "keyName": "", + "keyVaultResourceId": "", + "rotationToLatestKeyVersionEnabled": true + } + }, + "customPrivateSubnetName": { + "value": "" + }, + "customPublicSubnetName": { + "value": "" + }, + "customVirtualNetworkResourceId": { + "value": "" + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "logCategoriesAndGroups": [ + { + "category": "jobs" + }, + { + "category": "notebook" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "disablePublicIp": { + "value": true + }, + "enableDefaultTelemetry": { + "value": "" + }, + "loadBalancerBackendPoolName": { + "value": "" + }, + "loadBalancerResourceId": { + "value": "" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedResourceGroupResourceId": { + "value": "" + }, + "natGatewayName": { + "value": "nat-gateway" + }, + "prepareEncryption": { + "value": true + }, + "privateEndpoints": { + "value": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "Role": "DeploymentValidation" + } + } + ] + }, + "publicIpName": { + "value": "nat-gw-public-ip" + }, + "publicNetworkAccess": { + "value": "Disabled" + }, + "requiredNsgRules": { + "value": "NoAzureDatabricksRules" + }, + "requireInfrastructureEncryption": { + "value": true + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "skuName": { + "value": "premium" + }, + "storageAccountName": { + "value": "sadwmax001" + }, + "storageAccountSkuName": { + "value": "Standard_ZRS" + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "vnetAddressPrefix": { + "value": "10.100" + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module workspace 'br:bicep/modules/databricks.workspace:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-dwwaf' + params: { + // Required parameters + name: 'dwwaf001' + // Non-required parameters + amlWorkspaceResourceId: '' + customerManagedKey: { + keyName: '' + keyVaultResourceId: '' + } + customerManagedKeyManagedDisk: { + keyName: '' + keyVaultResourceId: '' + rotationToLatestKeyVersionEnabled: true + } + customPrivateSubnetName: '' + customPublicSubnetName: '' + customVirtualNetworkResourceId: '' + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + logCategoriesAndGroups: [ + { + category: 'jobs' + } + { + category: 'notebook' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + disablePublicIp: true + enableDefaultTelemetry: '' + loadBalancerBackendPoolName: '' + loadBalancerResourceId: '' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedResourceGroupResourceId: '' + natGatewayName: 'nat-gateway' + prepareEncryption: true + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + publicIpName: 'nat-gw-public-ip' + publicNetworkAccess: 'Disabled' + requiredNsgRules: 'NoAzureDatabricksRules' + requireInfrastructureEncryption: true + skuName: 'premium' + storageAccountName: 'sadwwaf001' + storageAccountSkuName: 'Standard_ZRS' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + vnetAddressPrefix: '10.100' + } +} +``` + +
+

+ +

+ +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": "dwwaf001" + }, + // Non-required parameters + "amlWorkspaceResourceId": { + "value": "" + }, + "customerManagedKey": { + "value": { + "keyName": "", + "keyVaultResourceId": "" + } + }, + "customerManagedKeyManagedDisk": { + "value": { + "keyName": "", + "keyVaultResourceId": "", + "rotationToLatestKeyVersionEnabled": true + } + }, + "customPrivateSubnetName": { + "value": "" + }, + "customPublicSubnetName": { + "value": "" + }, + "customVirtualNetworkResourceId": { + "value": "" + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "logCategoriesAndGroups": [ + { + "category": "jobs" + }, + { + "category": "notebook" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "disablePublicIp": { + "value": true + }, + "enableDefaultTelemetry": { + "value": "" + }, + "loadBalancerBackendPoolName": { + "value": "" + }, + "loadBalancerResourceId": { + "value": "" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedResourceGroupResourceId": { + "value": "" + }, + "natGatewayName": { + "value": "nat-gateway" + }, + "prepareEncryption": { + "value": true + }, + "privateEndpoints": { + "value": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "Role": "DeploymentValidation" + } + } + ] + }, + "publicIpName": { + "value": "nat-gw-public-ip" + }, + "publicNetworkAccess": { + "value": "Disabled" + }, + "requiredNsgRules": { + "value": "NoAzureDatabricksRules" + }, + "requireInfrastructureEncryption": { + "value": true + }, + "skuName": { + "value": "premium" + }, + "storageAccountName": { + "value": "sadwwaf001" + }, + "storageAccountSkuName": { + "value": "Standard_ZRS" + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "vnetAddressPrefix": { + "value": "10.100" + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the Azure Databricks workspace to create. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`amlWorkspaceResourceId`](#parameter-amlworkspaceresourceid) | string | The resource ID of a Azure Machine Learning workspace to link with Databricks workspace. | +| [`customerManagedKey`](#parameter-customermanagedkey) | object | The customer managed key definition to use for the managed service. | +| [`customerManagedKeyManagedDisk`](#parameter-customermanagedkeymanageddisk) | object | The customer managed key definition to use for the managed disk. | +| [`customPrivateSubnetName`](#parameter-customprivatesubnetname) | string | The name of the Private Subnet within the Virtual Network. | +| [`customPublicSubnetName`](#parameter-custompublicsubnetname) | string | The name of a Public Subnet within the Virtual Network. | +| [`customVirtualNetworkResourceId`](#parameter-customvirtualnetworkresourceid) | string | The resource ID of a Virtual Network where this Databricks Cluster should be created. | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`disablePublicIp`](#parameter-disablepublicip) | bool | Disable Public IP. | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`loadBalancerBackendPoolName`](#parameter-loadbalancerbackendpoolname) | string | Name of the outbound Load Balancer Backend Pool for Secure Cluster Connectivity (No Public IP). | +| [`loadBalancerResourceId`](#parameter-loadbalancerresourceid) | string | Resource URI of Outbound Load balancer for Secure Cluster Connectivity (No Public IP) workspace. | +| [`location`](#parameter-location) | string | Location for all Resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`managedResourceGroupResourceId`](#parameter-managedresourcegroupresourceid) | string | The managed resource group ID. It is created by the module as per the to-be resource ID you provide. | +| [`natGatewayName`](#parameter-natgatewayname) | string | Name of the NAT gateway for Secure Cluster Connectivity (No Public IP) workspace subnets. | +| [`prepareEncryption`](#parameter-prepareencryption) | bool | Prepare the workspace for encryption. Enables the Managed Identity for managed storage account. | +| [`privateEndpoints`](#parameter-privateendpoints) | array | Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. | +| [`publicIpName`](#parameter-publicipname) | string | Name of the Public IP for No Public IP workspace with managed vNet. | +| [`publicNetworkAccess`](#parameter-publicnetworkaccess) | string | The network access type for accessing workspace. Set value to disabled to access workspace only via private link. | +| [`requiredNsgRules`](#parameter-requirednsgrules) | string | Gets or sets a value indicating whether data plane (clusters) to control plane communication happen over private endpoint. | +| [`requireInfrastructureEncryption`](#parameter-requireinfrastructureencryption) | bool | A boolean indicating whether or not the DBFS root file system will be enabled with secondary layer of encryption with platform managed keys for data at rest. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`skuName`](#parameter-skuname) | string | The pricing tier of workspace. | +| [`storageAccountName`](#parameter-storageaccountname) | string | Default DBFS storage account name. | +| [`storageAccountSkuName`](#parameter-storageaccountskuname) | string | Storage account SKU name. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | +| [`vnetAddressPrefix`](#parameter-vnetaddressprefix) | string | Address prefix for Managed virtual network. | + +### Parameter: `name` + +The name of the Azure Databricks workspace to create. + +- Required: Yes +- Type: string + +### Parameter: `amlWorkspaceResourceId` + +The resource ID of a Azure Machine Learning workspace to link with Databricks workspace. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `customerManagedKey` + +The customer managed key definition to use for the managed service. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`keyName`](#parameter-customermanagedkeykeyname) | string | The name of the customer managed key to use for encryption. | +| [`keyVaultResourceId`](#parameter-customermanagedkeykeyvaultresourceid) | string | The resource ID of a key vault to reference a customer managed key for encryption from. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`keyVersion`](#parameter-customermanagedkeykeyversion) | string | The version of the customer managed key to reference for encryption. If not provided, using 'latest'. | +| [`userAssignedIdentityResourceId`](#parameter-customermanagedkeyuserassignedidentityresourceid) | string | User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use. | + +### Parameter: `customerManagedKey.keyName` + +The name of the customer managed key to use for encryption. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKey.keyVaultResourceId` + +The resource ID of a key vault to reference a customer managed key for encryption from. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKey.keyVersion` + +The version of the customer managed key to reference for encryption. If not provided, using 'latest'. + +- Required: No +- Type: string + +### Parameter: `customerManagedKey.userAssignedIdentityResourceId` + +User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use. + +- Required: No +- Type: string + +### Parameter: `customerManagedKeyManagedDisk` + +The customer managed key definition to use for the managed disk. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`keyName`](#parameter-customermanagedkeymanageddiskkeyname) | string | The name of the customer managed key to use for encryption. | +| [`keyVaultResourceId`](#parameter-customermanagedkeymanageddiskkeyvaultresourceid) | string | The resource ID of a key vault to reference a customer managed key for encryption from. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`keyVersion`](#parameter-customermanagedkeymanageddiskkeyversion) | string | The version of the customer managed key to reference for encryption. If not provided, using 'latest'. | +| [`rotationToLatestKeyVersionEnabled`](#parameter-customermanagedkeymanageddiskrotationtolatestkeyversionenabled) | bool | Indicate whether the latest key version should be automatically used for Managed Disk Encryption. Enabled by default. | +| [`userAssignedIdentityResourceId`](#parameter-customermanagedkeymanageddiskuserassignedidentityresourceid) | string | User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use. | + +### Parameter: `customerManagedKeyManagedDisk.keyName` + +The name of the customer managed key to use for encryption. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKeyManagedDisk.keyVaultResourceId` + +The resource ID of a key vault to reference a customer managed key for encryption from. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKeyManagedDisk.keyVersion` + +The version of the customer managed key to reference for encryption. If not provided, using 'latest'. + +- Required: No +- Type: string + +### Parameter: `customerManagedKeyManagedDisk.rotationToLatestKeyVersionEnabled` + +Indicate whether the latest key version should be automatically used for Managed Disk Encryption. Enabled by default. + +- Required: No +- Type: bool + +### Parameter: `customerManagedKeyManagedDisk.userAssignedIdentityResourceId` + +User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use. + +- Required: No +- Type: string + +### Parameter: `customPrivateSubnetName` + +The name of the Private Subnet within the Virtual Network. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `customPublicSubnetName` + +The name of a Public Subnet within the Virtual Network. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `customVirtualNetworkResourceId` + +The resource ID of a Virtual Network where this Databricks Cluster should be created. + +- 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: `disablePublicIp` + +Disable Public IP. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `loadBalancerBackendPoolName` + +Name of the outbound Load Balancer Backend Pool for Secure Cluster Connectivity (No Public IP). + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `loadBalancerResourceId` + +Resource URI of Outbound Load balancer for Secure Cluster Connectivity (No Public IP) workspace. + +- Required: No +- Type: string +- Default: `''` + +### 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: `managedResourceGroupResourceId` + +The managed resource group ID. It is created by the module as per the to-be resource ID you provide. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `natGatewayName` + +Name of the NAT gateway for Secure Cluster Connectivity (No Public IP) workspace subnets. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `prepareEncryption` + +Prepare the workspace for encryption. Enables the Managed Identity for managed storage account. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `privateEndpoints` + +Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | array | Application security groups in which the private endpoint IP configuration is included. | +| [`customDnsConfigs`](#parameter-privateendpointscustomdnsconfigs) | array | Custom DNS configurations. | +| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | +| [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | +| [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | +| [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | +| [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | +| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. | +| [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | array | The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | +| [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | +| [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | +| [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | + +### Parameter: `privateEndpoints.subnetResourceId` + +Resource ID of the subnet where the endpoint needs to be created. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` + +Application security groups in which the private endpoint IP configuration is included. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.customDnsConfigs` + +Custom DNS configurations. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.customNetworkInterfaceName` + +The custom name of the network interface attached to the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool + +### Parameter: `privateEndpoints.ipConfigurations` + +A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.location` + +The location to deploy the private endpoint to. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.lock` + +Specify the type of lock. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-privateendpointslockkind) | string | Specify the type of lock. | +| [`name`](#parameter-privateendpointslockname) | string | Specify the name of lock. | + +### Parameter: `privateEndpoints.lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `privateEndpoints.lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.manualPrivateLinkServiceConnections` + +Manual PrivateLink Service Connections. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.name` + +The name of the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneGroupName` + +The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneResourceIds` + +The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-privateendpointsroleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-privateendpointsroleassignmentsroledefinitionidorname) | 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-privateendpointsroleassignmentscondition) | 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-privateendpointsroleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-privateendpointsroleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-privateendpointsroleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-privateendpointsroleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `privateEndpoints.roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.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: `privateEndpoints.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: `privateEndpoints.roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `privateEndpoints.roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `privateEndpoints.service` + +The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.tags` + +Tags to be applied on all resources/resource groups in this deployment. + +- Required: No +- Type: object + +### Parameter: `publicIpName` + +Name of the Public IP for No Public IP workspace with managed vNet. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `publicNetworkAccess` + + The network access type for accessing workspace. Set value to disabled to access workspace only via private link. + +- Required: No +- Type: string +- Default: `'Enabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `requiredNsgRules` + +Gets or sets a value indicating whether data plane (clusters) to control plane communication happen over private endpoint. + +- Required: No +- Type: string +- Default: `'AllRules'` +- Allowed: + ```Bicep + [ + 'AllRules' + 'NoAzureDatabricksRules' + ] + ``` + +### Parameter: `requireInfrastructureEncryption` + +A boolean indicating whether or not the DBFS root file system will be enabled with secondary layer of encryption with platform managed keys for data at rest. + +- Required: No +- Type: bool +- Default: `False` + +### 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: `skuName` + +The pricing tier of workspace. + +- Required: No +- Type: string +- Default: `'premium'` +- Allowed: + ```Bicep + [ + 'premium' + 'standard' + 'trial' + ] + ``` + +### Parameter: `storageAccountName` + +Default DBFS storage account name. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `storageAccountSkuName` + +Storage account SKU name. + +- Required: No +- Type: string +- Default: `'Standard_GRS'` + +### Parameter: `tags` + +Tags of the resource. + +- Required: No +- Type: object + +### Parameter: `vnetAddressPrefix` + +Address prefix for Managed virtual network. + +- Required: No +- Type: string +- Default: `'10.139'` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the deployed databricks workspace. | +| `resourceGroupName` | string | The resource group of the deployed databricks workspace. | +| `resourceId` | string | The resource ID of the deployed databricks workspace. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other CARML modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `modules/network/private-endpoint` | Local reference | + +## Notes + +### Parameter Usage: `customPublicSubnetName` and `customPrivateSubnetName` + +- Require Network Security Groups attached to the subnets (Note: Rule don't have to be set, they are set through the deployment) + +- The two subnets also need the delegation to service `Microsoft.Databricks/workspaces` + +### Parameter Usage: `parameters` + +- Include only those elements (e.g. amlWorkspaceId) as object if specified, otherwise remove it. + +

+ +Parameter JSON format + +```json +"parameters": { + "value": { + "amlWorkspaceId": { + "value": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.MachineLearningServices/workspaces/xxx" + }, + "customVirtualNetworkId": { + "value": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworks/xxx" + }, + "customPublicSubnetName": { + "value": "xxx" + }, + "customPrivateSubnetName": { + "value": "xxx" + }, + "enableNoPublicIp": { + "value": true + } + } +} +``` + +
+ +
+ +Bicep format + +```bicep +parameters: { + amlWorkspaceId: { + value: '/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.MachineLearningServices/workspaces/xxx' + } + customVirtualNetworkId: { + value: '/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworks/xxx' + } + customPublicSubnetName: { + value: 'xxx' + } + customPrivateSubnetName: { + value: 'xxx' + } + enableNoPublicIp: { + value: true + } +} +``` + +
+

diff --git a/avm/res/databricks/workspace/main.bicep b/avm/res/databricks/workspace/main.bicep new file mode 100644 index 0000000000..0d7e6cdb19 --- /dev/null +++ b/avm/res/databricks/workspace/main.bicep @@ -0,0 +1,487 @@ +metadata name = 'Azure Databricks Workspaces' +metadata description = 'This module deploys an Azure Databricks Workspace.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the Azure Databricks workspace to create.') +param name string + +@description('Optional. The managed resource group ID. It is created by the module as per the to-be resource ID you provide.') +param managedResourceGroupResourceId string = '' + +@description('Optional. The pricing tier of workspace.') +@allowed([ + 'trial' + 'standard' + 'premium' +]) +param skuName string = 'premium' + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The resource ID of a Virtual Network where this Databricks Cluster should be created.') +param customVirtualNetworkResourceId string = '' + +@description('Optional. The resource ID of a Azure Machine Learning workspace to link with Databricks workspace.') +param amlWorkspaceResourceId string = '' + +@description('Optional. The name of the Private Subnet within the Virtual Network.') +param customPrivateSubnetName string = '' + +@description('Optional. The name of a Public Subnet within the Virtual Network.') +param customPublicSubnetName string = '' + +@description('Optional. Disable Public IP.') +param disablePublicIp bool = false + +@description('Optional. The customer managed key definition to use for the managed service.') +param customerManagedKey customerManagedKeyType + +@description('Optional. The customer managed key definition to use for the managed disk.') +param customerManagedKeyManagedDisk customerManagedKeyManagedDiskType + +@description('Optional. Name of the outbound Load Balancer Backend Pool for Secure Cluster Connectivity (No Public IP).') +param loadBalancerBackendPoolName string = '' + +@description('Optional. Resource URI of Outbound Load balancer for Secure Cluster Connectivity (No Public IP) workspace.') +param loadBalancerResourceId string = '' + +@description('Optional. Name of the NAT gateway for Secure Cluster Connectivity (No Public IP) workspace subnets.') +param natGatewayName string = '' + +@description('Optional. Prepare the workspace for encryption. Enables the Managed Identity for managed storage account.') +param prepareEncryption bool = false + +@description('Optional. Name of the Public IP for No Public IP workspace with managed vNet.') +param publicIpName string = '' + +@description('Optional. A boolean indicating whether or not the DBFS root file system will be enabled with secondary layer of encryption with platform managed keys for data at rest.') +param requireInfrastructureEncryption bool = false + +@description('Optional. Default DBFS storage account name.') +param storageAccountName string = '' + +@description('Optional. Storage account SKU name.') +param storageAccountSkuName string = 'Standard_GRS' + +@description('Optional. Address prefix for Managed virtual network.') +param vnetAddressPrefix string = '10.139' + +@description('Optional. The network access type for accessing workspace. Set value to disabled to access workspace only via private link.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param publicNetworkAccess string = 'Enabled' + +@description('Optional. Gets or sets a value indicating whether data plane (clusters) to control plane communication happen over private endpoint.') +@allowed([ + 'AllRules' + 'NoAzureDatabricksRules' +]) +param requiredNsgRules string = 'AllRules' + +@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints privateEndpointType + +var enableReferencedModulesTelemetry = false + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) + + resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } +} + +resource cMKManagedDiskKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKeyManagedDisk.?keyVaultResourceId)) { + name: last(split((customerManagedKeyManagedDisk.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup(split((customerManagedKeyManagedDisk.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKeyManagedDisk.?keyVaultResourceId ?? '////'), '/')[4]) + + resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKeyManagedDisk.?keyVaultResourceId) && !empty(customerManagedKeyManagedDisk.?keyName)) { + name: customerManagedKeyManagedDisk.?keyName ?? 'dummyKey' + } +} + +resource workspace 'Microsoft.Databricks/workspaces@2023-02-01' = { + name: name + location: location + tags: tags + sku: { + name: skuName + } + properties: { + managedResourceGroupId: !empty(managedResourceGroupResourceId) ? managedResourceGroupResourceId : '${subscription().id}/resourceGroups/${name}-rg' + parameters: union( + // Always added parameters + { + enableNoPublicIp: { + value: disablePublicIp + } + prepareEncryption: { + value: prepareEncryption + } + vnetAddressPrefix: { + value: vnetAddressPrefix + } + requireInfrastructureEncryption: { + value: requireInfrastructureEncryption + } + }, + // Parameters only added if not empty + !empty(customVirtualNetworkResourceId) ? { + customVirtualNetworkId: { + value: customVirtualNetworkResourceId + } + } : {}, + !empty(amlWorkspaceResourceId) ? { + amlWorkspaceId: { + value: amlWorkspaceResourceId + } + } : {}, + !empty(customPrivateSubnetName) ? { + customPrivateSubnetName: { + value: customPrivateSubnetName + } + } : {}, + !empty(customPublicSubnetName) ? { + customPublicSubnetName: { + value: customPublicSubnetName + } + } : {}, + !empty(loadBalancerBackendPoolName) ? { + loadBalancerBackendPoolName: { + value: loadBalancerBackendPoolName + } + } : {}, + !empty(loadBalancerResourceId) ? { + loadBalancerId: { + value: loadBalancerResourceId + } + } : {}, + !empty(natGatewayName) ? { + natGatewayName: { + value: natGatewayName + } + } : {}, + !empty(publicIpName) ? { + publicIpName: { + value: publicIpName + } + } : {}, + !empty(storageAccountName) ? { + storageAccountName: { + value: storageAccountName + } + } : {}, + !empty(storageAccountSkuName) ? { + storageAccountSkuName: { + value: storageAccountSkuName + } + } : {}) + publicNetworkAccess: publicNetworkAccess + requiredNsgRules: requiredNsgRules + encryption: !empty(customerManagedKey) || !empty(customerManagedKeyManagedDisk) ? { + entities: { + managedServices: !empty(customerManagedKey) ? { + keySource: 'Microsoft.Keyvault' + keyVaultProperties: { + keyVaultUri: cMKKeyVault.properties.vaultUri + keyName: customerManagedKey!.keyName + keyVersion: !empty(customerManagedKey.?keyVersion ?? '') ? customerManagedKey!.keyVersion : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) + } + } : null + managedDisk: !empty(customerManagedKeyManagedDisk) ? { + keySource: 'Microsoft.Keyvault' + keyVaultProperties: { + keyVaultUri: cMKManagedDiskKeyVault.properties.vaultUri + keyName: customerManagedKeyManagedDisk!.keyName + keyVersion: !empty(customerManagedKeyManagedDisk.?keyVersion ?? '') ? customerManagedKeyManagedDisk!.keyVersion : last(split(cMKManagedDiskKeyVault::cMKKey.properties.keyUriWithVersion, '/')) + } + rotationToLatestKeyVersionEnabled: customerManagedKeyManagedDisk.?rotationToLatestKeyVersionEnabled ?? true + } : null + } + } : null + } +} + +resource workspace_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: workspace +} + +// Note: Diagnostic Settings are only supported by the premium tier +resource workspace_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: workspace +}] + +resource workspace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(workspace.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: workspace +}] + +module workspace_privateEndpoints '../../network/private-endpoint/main.bicep' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-workspace-PrivateEndpoint-${index}' + params: { + groupIds: [ + privateEndpoint.?service ?? 'databricks_ui_api' + ] + name: privateEndpoint.?name ?? 'pep-${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'databricks_ui_api'}-${index}' + serviceResourceId: workspace.id + subnetResourceId: privateEndpoint.subnetResourceId + enableDefaultTelemetry: privateEndpoint.?enableDefaultTelemetry ?? enableReferencedModulesTelemetry + location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } +}] + +@description('The name of the deployed databricks workspace.') +output name string = workspace.name + +@description('The resource ID of the deployed databricks workspace.') +output resourceId string = workspace.id + +@description('The resource group of the deployed databricks workspace.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = workspace.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? +}[]? + +type privateEndpointType = { + @description('Optional. The name of the private endpoint.') + name: string? + + @description('Optional. The location to deploy the private endpoint to.') + location: string? + + @description('Optional. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob".') + service: string? + + @description('Required. Resource ID of the subnet where the endpoint needs to be created.') + subnetResourceId: string + + @description('Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided.') + privateDnsZoneGroupName: string? + + @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') + privateDnsZoneResourceIds: string[]? + + @description('Optional. Custom DNS configurations.') + customDnsConfigs: { + @description('Required. Fqdn that resolves to private endpoint ip address.') + fqdn: string? + + @description('Required. A list of private ip addresses of the private endpoint.') + ipAddresses: string[] + }[]? + + @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') + ipConfigurations: { + @description('Required. The name of the resource that is unique within a resource group.') + name: string + + @description('Required. Properties of private endpoint IP configurations.') + properties: { + @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') + groupId: string + + @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') + memberName: string + + @description('Required. A private ip address obtained from the private endpoint\'s subnet.') + privateIPAddress: string + } + }[]? + + @description('Optional. Application security groups in which the private endpoint IP configuration is included.') + applicationSecurityGroupResourceIds: string[]? + + @description('Optional. The custom name of the network interface attached to the private endpoint.') + customNetworkInterfaceName: string? + + @description('Optional. Specify the type of lock.') + lock: lockType + + @description('Optional. Array of role assignments to create.') + roleAssignments: roleAssignmentType + + @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') + tags: object? + + @description('Optional. Manual PrivateLink Service Connections.') + manualPrivateLinkServiceConnections: array? + + @description('Optional. Enable/Disable usage telemetry for module.') + enableTelemetry: bool? +}[]? + +type diagnosticSettingType = { + @description('Optional. The name of diagnostic setting.') + name: string? + + @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: { + @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? + + @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? + }[]? + + @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')? + + @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? + + @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? + + @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? + + @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? + + @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') + marketplacePartnerResourceId: string? +}[]? + +type customerManagedKeyType = { + @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') + keyVaultResourceId: string + + @description('Required. The name of the customer managed key to use for encryption.') + keyName: string + + @description('Optional. The version of the customer managed key to reference for encryption. If not provided, using \'latest\'.') + keyVersion: string? + + @description('Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use.') + userAssignedIdentityResourceId: string? +}? + +type customerManagedKeyManagedDiskType = { + @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') + keyVaultResourceId: string + + @description('Required. The name of the customer managed key to use for encryption.') + keyName: string + + @description('Optional. The version of the customer managed key to reference for encryption. If not provided, using \'latest\'.') + keyVersion: string? + + @description('Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use.') + userAssignedIdentityResourceId: string? + + @description('Optional. Indicate whether the latest key version should be automatically used for Managed Disk Encryption. Enabled by default.') + rotationToLatestKeyVersionEnabled: bool? +}? diff --git a/avm/res/databricks/workspace/main.json b/avm/res/databricks/workspace/main.json new file mode 100644 index 0000000000..47a19aa465 --- /dev/null +++ b/avm/res/databricks/workspace/main.json @@ -0,0 +1,1439 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "17678709403904494263" + }, + "name": "Azure Databricks Workspaces", + "description": "This module deploys an Azure Databricks Workspace.", + "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 + }, + "privateEndpointType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The service (sub-) type to deploy the private endpoint for. For example \"vault\" or \"blob\"." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided." + } + }, + "privateDnsZoneResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint ip address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private ip addresses of the private endpoint." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private ip address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "manualPrivateLinkServiceConnections": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Manual PrivateLink Service Connections." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + } + }, + "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 + }, + "customerManagedKeyType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + } + }, + "nullable": true + }, + "customerManagedKeyManagedDiskType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + }, + "rotationToLatestKeyVersionEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Indicate whether the latest key version should be automatically used for Managed Disk Encryption. Enabled by default." + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Azure Databricks workspace to create." + } + }, + "managedResourceGroupResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The managed resource group ID. It is created by the module as per the to-be resource ID you provide." + } + }, + "skuName": { + "type": "string", + "defaultValue": "premium", + "allowedValues": [ + "trial", + "standard", + "premium" + ], + "metadata": { + "description": "Optional. The pricing tier of workspace." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + }, + "customVirtualNetworkResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The resource ID of a Virtual Network where this Databricks Cluster should be created." + } + }, + "amlWorkspaceResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The resource ID of a Azure Machine Learning workspace to link with Databricks workspace." + } + }, + "customPrivateSubnetName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the Private Subnet within the Virtual Network." + } + }, + "customPublicSubnetName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of a Public Subnet within the Virtual Network." + } + }, + "disablePublicIp": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Disable Public IP." + } + }, + "customerManagedKey": { + "$ref": "#/definitions/customerManagedKeyType", + "metadata": { + "description": "Optional. The customer managed key definition to use for the managed service." + } + }, + "customerManagedKeyManagedDisk": { + "$ref": "#/definitions/customerManagedKeyManagedDiskType", + "metadata": { + "description": "Optional. The customer managed key definition to use for the managed disk." + } + }, + "loadBalancerBackendPoolName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the outbound Load Balancer Backend Pool for Secure Cluster Connectivity (No Public IP)." + } + }, + "loadBalancerResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource URI of Outbound Load balancer for Secure Cluster Connectivity (No Public IP) workspace." + } + }, + "natGatewayName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the NAT gateway for Secure Cluster Connectivity (No Public IP) workspace subnets." + } + }, + "prepareEncryption": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Prepare the workspace for encryption. Enables the Managed Identity for managed storage account." + } + }, + "publicIpName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the Public IP for No Public IP workspace with managed vNet." + } + }, + "requireInfrastructureEncryption": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. A boolean indicating whether or not the DBFS root file system will be enabled with secondary layer of encryption with platform managed keys for data at rest." + } + }, + "storageAccountName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Default DBFS storage account name." + } + }, + "storageAccountSkuName": { + "type": "string", + "defaultValue": "Standard_GRS", + "metadata": { + "description": "Optional. Storage account SKU name." + } + }, + "vnetAddressPrefix": { + "type": "string", + "defaultValue": "10.139", + "metadata": { + "description": "Optional. Address prefix for Managed virtual network." + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Optional. \tThe network access type for accessing workspace. Set value to disabled to access workspace only via private link." + } + }, + "requiredNsgRules": { + "type": "string", + "defaultValue": "AllRules", + "allowedValues": [ + "AllRules", + "NoAzureDatabricksRules" + ], + "metadata": { + "description": "Optional. Gets or sets a value indicating whether data plane (clusters) to control plane communication happen over private endpoint." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." + } + } + }, + "variables": { + "enableReferencedModulesTelemetry": false, + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "cMKKeyVault::cMKKey": { + "condition": "[and(not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'))), and(not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'))), not(empty(tryGet(parameters('customerManagedKey'), 'keyName')))))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[format('{0}/{1}', last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/')), coalesce(tryGet(parameters('customerManagedKey'), 'keyName'), 'dummyKey'))]", + "dependsOn": [ + "cMKKeyVault" + ] + }, + "cMKManagedDiskKeyVault::cMKKey": { + "condition": "[and(not(empty(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'))), and(not(empty(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'))), not(empty(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyName')))))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[format('{0}/{1}', last(split(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'), 'dummyVault'), '/')), coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyName'), 'dummyKey'))]", + "dependsOn": [ + "cMKManagedDiskKeyVault" + ] + }, + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "cMKKeyVault": { + "condition": "[not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId')))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/'))]" + }, + "cMKManagedDiskKeyVault": { + "condition": "[not(empty(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId')))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVaultResourceId'), 'dummyVault'), '/'))]" + }, + "workspace": { + "type": "Microsoft.Databricks/workspaces", + "apiVersion": "2023-02-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('skuName')]" + }, + "properties": { + "managedResourceGroupId": "[if(not(empty(parameters('managedResourceGroupResourceId'))), parameters('managedResourceGroupResourceId'), format('{0}/resourceGroups/{1}-rg', subscription().id, parameters('name')))]", + "parameters": "[union(createObject('enableNoPublicIp', createObject('value', parameters('disablePublicIp')), 'prepareEncryption', createObject('value', parameters('prepareEncryption')), 'vnetAddressPrefix', createObject('value', parameters('vnetAddressPrefix')), 'requireInfrastructureEncryption', createObject('value', parameters('requireInfrastructureEncryption'))), if(not(empty(parameters('customVirtualNetworkResourceId'))), createObject('customVirtualNetworkId', createObject('value', parameters('customVirtualNetworkResourceId'))), createObject()), if(not(empty(parameters('amlWorkspaceResourceId'))), createObject('amlWorkspaceId', createObject('value', parameters('amlWorkspaceResourceId'))), createObject()), if(not(empty(parameters('customPrivateSubnetName'))), createObject('customPrivateSubnetName', createObject('value', parameters('customPrivateSubnetName'))), createObject()), if(not(empty(parameters('customPublicSubnetName'))), createObject('customPublicSubnetName', createObject('value', parameters('customPublicSubnetName'))), createObject()), if(not(empty(parameters('loadBalancerBackendPoolName'))), createObject('loadBalancerBackendPoolName', createObject('value', parameters('loadBalancerBackendPoolName'))), createObject()), if(not(empty(parameters('loadBalancerResourceId'))), createObject('loadBalancerId', createObject('value', parameters('loadBalancerResourceId'))), createObject()), if(not(empty(parameters('natGatewayName'))), createObject('natGatewayName', createObject('value', parameters('natGatewayName'))), createObject()), if(not(empty(parameters('publicIpName'))), createObject('publicIpName', createObject('value', parameters('publicIpName'))), createObject()), if(not(empty(parameters('storageAccountName'))), createObject('storageAccountName', createObject('value', parameters('storageAccountName'))), createObject()), if(not(empty(parameters('storageAccountSkuName'))), createObject('storageAccountSkuName', createObject('value', parameters('storageAccountSkuName'))), createObject()))]", + "publicNetworkAccess": "[parameters('publicNetworkAccess')]", + "requiredNsgRules": "[parameters('requiredNsgRules')]", + "encryption": "[if(or(not(empty(parameters('customerManagedKey'))), not(empty(parameters('customerManagedKeyManagedDisk')))), createObject('entities', createObject('managedServices', if(not(empty(parameters('customerManagedKey'))), createObject('keySource', 'Microsoft.Keyvault', 'keyVaultProperties', createObject('keyVaultUri', reference('cMKKeyVault').vaultUri, 'keyName', parameters('customerManagedKey').keyName, 'keyVersion', if(not(empty(coalesce(tryGet(parameters('customerManagedKey'), 'keyVersion'), ''))), parameters('customerManagedKey').keyVersion, last(split(reference('cMKKeyVault::cMKKey').keyUriWithVersion, '/'))))), null()), 'managedDisk', if(not(empty(parameters('customerManagedKeyManagedDisk'))), createObject('keySource', 'Microsoft.Keyvault', 'keyVaultProperties', createObject('keyVaultUri', reference('cMKManagedDiskKeyVault').vaultUri, 'keyName', parameters('customerManagedKeyManagedDisk').keyName, 'keyVersion', if(not(empty(coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'keyVersion'), ''))), parameters('customerManagedKeyManagedDisk').keyVersion, last(split(reference('cMKManagedDiskKeyVault::cMKKey').keyUriWithVersion, '/')))), 'rotationToLatestKeyVersionEnabled', coalesce(tryGet(parameters('customerManagedKeyManagedDisk'), 'rotationToLatestKeyVersionEnabled'), true())), null()))), null())]" + }, + "dependsOn": [ + "cMKKeyVault", + "cMKManagedDiskKeyVault" + ] + }, + "workspace_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.Databricks/workspaces/{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": [ + "workspace" + ] + }, + "workspace_diagnosticSettings": { + "copy": { + "name": "workspace_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Databricks/workspaces/{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": [ + "workspace" + ] + }, + "workspace_roleAssignments": { + "copy": { + "name": "workspace_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Databricks/workspaces/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Databricks/workspaces', 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": [ + "workspace" + ] + }, + "workspace_privateEndpoints": { + "copy": { + "name": "workspace_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-workspace-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "groupIds": { + "value": [ + "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'databricks_ui_api')]" + ] + }, + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Databricks/workspaces', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'databricks_ui_api'), copyIndex()))]" + }, + "serviceResourceId": { + "value": "[resourceId('Microsoft.Databricks/workspaces', parameters('name'))]" + }, + "subnetResourceId": { + "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" + }, + "enableDefaultTelemetry": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableDefaultTelemetry'), variables('enableReferencedModulesTelemetry'))]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "lock": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" + }, + "privateDnsZoneGroupName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroupName')]" + }, + "privateDnsZoneResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneResourceIds')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "manualPrivateLinkServiceConnections": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections')]" + }, + "customDnsConfigs": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" + }, + "ipConfigurations": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'ipConfigurations')]" + }, + "applicationSecurityGroupResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'applicationSecurityGroupResourceIds')]" + }, + "customNetworkInterfaceName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "6873008238043407177" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "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 + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private ip address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint ip address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private ip addresses of the private endpoint." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "serviceResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the resource that needs to be connected to the network." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to." + } + }, + "privateDnsZoneGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided." + } + }, + "privateDnsZoneResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Manual PrivateLink Service Connections." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "enableReferencedModulesTelemetry": false, + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "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')]" + } + }, + "resources": { + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" + } + } + ], + "customDnsConfigs": "[parameters('customDnsConfigs')]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": [ + { + "name": "[parameters('name')]", + "properties": { + "privateLinkServiceId": "[parameters('serviceResourceId')]", + "groupIds": "[parameters('groupIds')]" + } + } + ], + "subnet": { + "id": "[parameters('subnetResourceId')]" + } + } + }, + "privateEndpoint_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.Network/privateEndpoints/{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": [ + "privateEndpoint" + ] + }, + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', 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], 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": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneResourceIds')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('privateDnsZoneGroupName'), 'default')]" + }, + "privateDNSResourceIds": { + "value": "[coalesce(parameters('privateDnsZoneResourceIds'), createArray())]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + }, + "enableDefaultTelemetry": { + "value": "[variables('enableReferencedModulesTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "17578977753131828304" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDNSResourceIds": { + "type": "array", + "minLength": 1, + "maxLength": 5, + "metadata": { + "description": "Required. Array of private DNS zone resource IDs. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(parameters('privateDNSResourceIds'))]", + "input": { + "name": "[last(split(parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigs')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint DNS zone group." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "workspace" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed databricks workspace." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed databricks workspace." + }, + "value": "[resourceId('Microsoft.Databricks/workspaces', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed databricks workspace." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('workspace', '2023-02-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/databricks/workspace/tests/e2e/defaults/main.test.bicep b/avm/res/databricks/workspace/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..8c3002937e --- /dev/null +++ b/avm/res/databricks/workspace/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,49 @@ +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}-databricks.workspaces-${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 = 'dwmin' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + } +}] diff --git a/avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep b/avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..4c074d6ae8 --- /dev/null +++ b/avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep @@ -0,0 +1,368 @@ +@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 Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Key Vault for Disk Encryption to create.') +param keyVaultDiskName string + +@description('Required. The name of the Azure Machine Learning Workspace to create.') +param amlWorkspaceName string + +@description('Required. The name of the Load Balancer to create.') +param loadBalancerName string + +@description('Required. The name of the Network Security Group to create.') +param networkSecurityGroupName string + +@description('Required. The name of the Storage Account to create.') +param storageAccountName string + +@description('Required. The name of the Application Insights Instanec to create.') +param applicationInsightsName string + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +var addressPrefix = '10.0.0.0/16' + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: true // Required by batch account + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource keyVaultDisk 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultDiskName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: true // Required by batch account + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKeyDisk' + properties: { + kty: 'RSA' + } + } +} + +resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Key-Vault-Crypto-User-RoleAssignment') + scope: keyVault::key + properties: { + principalId: '5167ea7a-355a-466f-ae8b-8ea60f718b35' // AzureDatabricks Enterprise Application Object Id + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +resource amlPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${keyVault.id}-${location}-${managedIdentity.id}-Key-Vault-Contributor') + scope: keyVault + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_ZRS' + } + kind: 'StorageV2' + properties: {} +} + +resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { + name: applicationInsightsName + location: location + kind: 'web' + properties: { + Application_Type: 'web' + } +} + +resource machineLearningWorkspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' = { + name: amlWorkspaceName + location: location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + storageAccount: storageAccount.id + keyVault: keyVault.id + applicationInsights: applicationInsights.id + primaryUserAssignedIdentity: managedIdentity.id + } +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2023-04-01' = { + name: loadBalancerName + location: location + properties: { + backendAddressPools: [ + { + name: 'default' + } + ] + frontendIPConfigurations: [ + { + name: 'privateIPConfig1' + properties: { + subnet: { + id: virtualNetwork.properties.subnets[0].id + } + } + } + ] + } +} + +resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2023-04-01' = { + name: networkSecurityGroupName + location: location + properties: { + securityRules: [ + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-inbound' + properties: { + description: 'Required for worker nodes communication within a cluster.' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 100 + direction: 'Inbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-databricks-webapp' + properties: { + description: 'Required for workers communication with Databricks Webapp.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'AzureDatabricks' + access: 'Allow' + priority: 100 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-sql' + properties: { + description: 'Required for workers communication with Azure SQL services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '3306' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Sql' + access: 'Allow' + priority: 101 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-storage' + properties: { + description: 'Required for workers communication with Azure Storage services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Storage' + access: 'Allow' + priority: 102 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-outbound' + properties: { + description: 'Required for worker nodes communication within a cluster.' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 103 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-eventhub' + properties: { + description: 'Required for worker communication with Azure Eventhub services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '9093' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'EventHub' + access: 'Allow' + priority: 104 + direction: 'Outbound' + } + } + ] + } +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 0) + } + } + { + name: 'custom-public-subnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 1) + networkSecurityGroup: { + id: networkSecurityGroup.id + } + delegations: [ + { + name: 'databricksDelegation' + properties: { + serviceName: 'Microsoft.Databricks/workspaces' + } + } + ] + } + } + { + name: 'custom-private-subnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 2) + networkSecurityGroup: { + id: networkSecurityGroup.id + } + delegations: [ + { + name: 'databricksDelegation' + properties: { + serviceName: 'Microsoft.Databricks/workspaces' + } + } + ] + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.azuredatabricks.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +@description('The resource ID of the created Virtual Network Default Subnet.') +output defaultSubnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The name of the created Virtual Network Public Subnet.') +output customPublicSubnetName string = virtualNetwork.properties.subnets[1].name + +@description('The name of the created Virtual Network Private Subnet.') +output customPrivateSubnetName string = virtualNetwork.properties.subnets[2].name + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = virtualNetwork.id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id + +@description('The resource ID of the created Azure Machine Learning Workspace.') +output machineLearningWorkspaceResourceId string = machineLearningWorkspace.id + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The resource ID of the created Disk Key Vault.') +output keyVaultDiskResourceId string = keyVaultDisk.id + +@description('The resource ID of the created Load Balancer.') +output loadBalancerResourceId string = loadBalancer.id + +@description('The name of the created Load Balancer Backend Pool.') +output loadBalancerBackendPoolName string = loadBalancer.properties.backendAddressPools[0].name + +@description('The name of the created Key Vault encryption key.') +output keyVaultKeyName string = keyVault::key.name + +@description('The name of the created Key Vault Disk encryption key.') +output keyVaultDiskKeyName string = keyVaultDisk::key.name + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep b/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..5656e772da --- /dev/null +++ b/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep @@ -0,0 +1,167 @@ +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}-databricks.workspaces-${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 = 'dwmax' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Generated. Used as a basis for unique resource names.') +param baseTime string = utcNow('u') + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + amlWorkspaceName: 'dep-${namePrefix}-aml-${serviceShort}' + applicationInsightsName: 'dep-${namePrefix}-appi-${serviceShort}' + loadBalancerName: 'dep-${namePrefix}-lb-${serviceShort}' + storageAccountName: 'dep${namePrefix}sa${serviceShort}' + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + networkSecurityGroupName: 'dep-${namePrefix}-nsg-${serviceShort}' + // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + keyVaultDiskName: 'dep-${namePrefix}-kve-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${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: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + logCategoriesAndGroups: [ + { + category: 'jobs' + } + { + category: 'notebook' + + } + ] + } + ] + 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' + } + customerManagedKey: { + keyName: nestedDependencies.outputs.keyVaultKeyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + } + customerManagedKeyManagedDisk: { + keyName: nestedDependencies.outputs.keyVaultDiskKeyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultDiskResourceId + rotationToLatestKeyVersionEnabled: true + } + storageAccountName: 'sa${namePrefix}${serviceShort}001' + storageAccountSkuName: 'Standard_ZRS' + publicIpName: 'nat-gw-public-ip' + natGatewayName: 'nat-gateway' + prepareEncryption: true + requiredNsgRules: 'NoAzureDatabricksRules' + skuName: 'premium' + amlWorkspaceResourceId: nestedDependencies.outputs.machineLearningWorkspaceResourceId + customPrivateSubnetName: nestedDependencies.outputs.customPrivateSubnetName + customPublicSubnetName: nestedDependencies.outputs.customPublicSubnetName + publicNetworkAccess: 'Disabled' + disablePublicIp: true + loadBalancerResourceId: nestedDependencies.outputs.loadBalancerResourceId + loadBalancerBackendPoolName: nestedDependencies.outputs.loadBalancerBackendPoolName + customVirtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.defaultSubnetResourceId + tags: { + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + managedResourceGroupResourceId: '${subscription().id}/resourceGroups/rg-${resourceGroupName}-managed' + requireInfrastructureEncryption: true + vnetAddressPrefix: '10.100' + location: resourceGroup.location + } +}] diff --git a/avm/res/databricks/workspace/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/databricks/workspace/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..4c074d6ae8 --- /dev/null +++ b/avm/res/databricks/workspace/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,368 @@ +@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 Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Key Vault for Disk Encryption to create.') +param keyVaultDiskName string + +@description('Required. The name of the Azure Machine Learning Workspace to create.') +param amlWorkspaceName string + +@description('Required. The name of the Load Balancer to create.') +param loadBalancerName string + +@description('Required. The name of the Network Security Group to create.') +param networkSecurityGroupName string + +@description('Required. The name of the Storage Account to create.') +param storageAccountName string + +@description('Required. The name of the Application Insights Instanec to create.') +param applicationInsightsName string + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +var addressPrefix = '10.0.0.0/16' + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: true // Required by batch account + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource keyVaultDisk 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultDiskName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: true // Required by batch account + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKeyDisk' + properties: { + kty: 'RSA' + } + } +} + +resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Key-Vault-Crypto-User-RoleAssignment') + scope: keyVault::key + properties: { + principalId: '5167ea7a-355a-466f-ae8b-8ea60f718b35' // AzureDatabricks Enterprise Application Object Id + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +resource amlPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${keyVault.id}-${location}-${managedIdentity.id}-Key-Vault-Contributor') + scope: keyVault + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_ZRS' + } + kind: 'StorageV2' + properties: {} +} + +resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { + name: applicationInsightsName + location: location + kind: 'web' + properties: { + Application_Type: 'web' + } +} + +resource machineLearningWorkspace 'Microsoft.MachineLearningServices/workspaces@2023-04-01' = { + name: amlWorkspaceName + location: location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + storageAccount: storageAccount.id + keyVault: keyVault.id + applicationInsights: applicationInsights.id + primaryUserAssignedIdentity: managedIdentity.id + } +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2023-04-01' = { + name: loadBalancerName + location: location + properties: { + backendAddressPools: [ + { + name: 'default' + } + ] + frontendIPConfigurations: [ + { + name: 'privateIPConfig1' + properties: { + subnet: { + id: virtualNetwork.properties.subnets[0].id + } + } + } + ] + } +} + +resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2023-04-01' = { + name: networkSecurityGroupName + location: location + properties: { + securityRules: [ + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-inbound' + properties: { + description: 'Required for worker nodes communication within a cluster.' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 100 + direction: 'Inbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-databricks-webapp' + properties: { + description: 'Required for workers communication with Databricks Webapp.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'AzureDatabricks' + access: 'Allow' + priority: 100 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-sql' + properties: { + description: 'Required for workers communication with Azure SQL services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '3306' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Sql' + access: 'Allow' + priority: 101 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-storage' + properties: { + description: 'Required for workers communication with Azure Storage services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'Storage' + access: 'Allow' + priority: 102 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-worker-outbound' + properties: { + description: 'Required for worker nodes communication within a cluster.' + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 103 + direction: 'Outbound' + } + } + { + name: 'Microsoft.Databricks-workspaces_UseOnly_databricks-worker-to-eventhub' + properties: { + description: 'Required for worker communication with Azure Eventhub services.' + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '9093' + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'EventHub' + access: 'Allow' + priority: 104 + direction: 'Outbound' + } + } + ] + } +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 0) + } + } + { + name: 'custom-public-subnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 1) + networkSecurityGroup: { + id: networkSecurityGroup.id + } + delegations: [ + { + name: 'databricksDelegation' + properties: { + serviceName: 'Microsoft.Databricks/workspaces' + } + } + ] + } + } + { + name: 'custom-private-subnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 2) + networkSecurityGroup: { + id: networkSecurityGroup.id + } + delegations: [ + { + name: 'databricksDelegation' + properties: { + serviceName: 'Microsoft.Databricks/workspaces' + } + } + ] + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.azuredatabricks.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +@description('The resource ID of the created Virtual Network Default Subnet.') +output defaultSubnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The name of the created Virtual Network Public Subnet.') +output customPublicSubnetName string = virtualNetwork.properties.subnets[1].name + +@description('The name of the created Virtual Network Private Subnet.') +output customPrivateSubnetName string = virtualNetwork.properties.subnets[2].name + +@description('The resource ID of the created Virtual Network.') +output virtualNetworkResourceId string = virtualNetwork.id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id + +@description('The resource ID of the created Azure Machine Learning Workspace.') +output machineLearningWorkspaceResourceId string = machineLearningWorkspace.id + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The resource ID of the created Disk Key Vault.') +output keyVaultDiskResourceId string = keyVaultDisk.id + +@description('The resource ID of the created Load Balancer.') +output loadBalancerResourceId string = loadBalancer.id + +@description('The name of the created Load Balancer Backend Pool.') +output loadBalancerBackendPoolName string = loadBalancer.properties.backendAddressPools[0].name + +@description('The name of the created Key Vault encryption key.') +output keyVaultKeyName string = keyVault::key.name + +@description('The name of the created Key Vault Disk encryption key.') +output keyVaultDiskKeyName string = keyVaultDisk::key.name + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..66928e1121 --- /dev/null +++ b/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,150 @@ +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}-databricks.workspaces-${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 = 'dwwaf' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Generated. Used as a basis for unique resource names.') +param baseTime string = utcNow('u') + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + amlWorkspaceName: 'dep-${namePrefix}-aml-${serviceShort}' + applicationInsightsName: 'dep-${namePrefix}-appi-${serviceShort}' + loadBalancerName: 'dep-${namePrefix}-lb-${serviceShort}' + storageAccountName: 'dep${namePrefix}sa${serviceShort}' + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + networkSecurityGroupName: 'dep-${namePrefix}-nsg-${serviceShort}' + // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + keyVaultDiskName: 'dep-${namePrefix}-kve-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${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: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + diagnosticSettings: [ + { + name: 'customSetting' + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + logCategoriesAndGroups: [ + { + category: 'jobs' + } + { + category: 'notebook' + + } + ] + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + customerManagedKey: { + keyName: nestedDependencies.outputs.keyVaultKeyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + } + customerManagedKeyManagedDisk: { + keyName: nestedDependencies.outputs.keyVaultDiskKeyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultDiskResourceId + rotationToLatestKeyVersionEnabled: true + } + storageAccountName: 'sa${namePrefix}${serviceShort}001' + storageAccountSkuName: 'Standard_ZRS' + publicIpName: 'nat-gw-public-ip' + natGatewayName: 'nat-gateway' + prepareEncryption: true + requiredNsgRules: 'NoAzureDatabricksRules' + skuName: 'premium' + amlWorkspaceResourceId: nestedDependencies.outputs.machineLearningWorkspaceResourceId + customPrivateSubnetName: nestedDependencies.outputs.customPrivateSubnetName + customPublicSubnetName: nestedDependencies.outputs.customPublicSubnetName + publicNetworkAccess: 'Disabled' + disablePublicIp: true + loadBalancerResourceId: nestedDependencies.outputs.loadBalancerResourceId + loadBalancerBackendPoolName: nestedDependencies.outputs.loadBalancerBackendPoolName + customVirtualNetworkResourceId: nestedDependencies.outputs.virtualNetworkResourceId + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.defaultSubnetResourceId + tags: { + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + managedResourceGroupResourceId: '${subscription().id}/resourceGroups/rg-${resourceGroupName}-managed' + requireInfrastructureEncryption: true + vnetAddressPrefix: '10.100' + location: resourceGroup.location + } +}] diff --git a/avm/res/databricks/workspace/version.json b/avm/res/databricks/workspace/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/databricks/workspace/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/flexible-server/README.md b/avm/res/flexible-server/README.md new file mode 100644 index 0000000000..bdbfbf4aa1 --- /dev/null +++ b/avm/res/flexible-server/README.md @@ -0,0 +1,1286 @@ +# DBforMySQL Flexible Servers `[Microsoft.DBforMySQL/flexibleServers]` + +This module deploys a DBforMySQL Flexible Server. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.DBforMySQL/flexibleServers` | [2022-09-30-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DBforMySQL/2022-09-30-preview/flexibleServers) | +| `Microsoft.DBforMySQL/flexibleServers/administrators` | [2022-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DBforMySQL/2022-01-01/flexibleServers/administrators) | +| `Microsoft.DBforMySQL/flexibleServers/databases` | [2022-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DBforMySQL/2022-01-01/flexibleServers/databases) | +| `Microsoft.DBforMySQL/flexibleServers/firewallRules` | [2022-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DBforMySQL/2022-01-01/flexibleServers/firewallRules) | +| `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:bicep/modules/db-for-my-sql.flexible-server:1.0.0`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Private](#example-2-private) +- [Public](#example-3-public) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-dfmsfsmin' + params: { + // Required parameters + name: 'dfmsfsmin001' + skuName: 'Standard_B1ms' + tier: 'Burstable' + // Non-required parameters + administratorLogin: 'adminUserName' + administratorLoginPassword: '' + enableDefaultTelemetry: '' + } +} +``` + +
+

+ +

+ +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": "dfmsfsmin001" + }, + "skuName": { + "value": "Standard_B1ms" + }, + "tier": { + "value": "Burstable" + }, + // Non-required parameters + "administratorLogin": { + "value": "adminUserName" + }, + "administratorLoginPassword": { + "value": "" + }, + "enableDefaultTelemetry": { + "value": "" + } + } +} +``` + +
+

+ +### Example 2: _Private_ + +

+ +via Bicep module + +```bicep +module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-dfmsfspvt' + params: { + // Required parameters + name: 'dfmsfspvt001' + skuName: 'Standard_D2ds_v4' + tier: 'GeneralPurpose' + // Non-required parameters + administratorLogin: 'adminUserName' + administratorLoginPassword: '' + administrators: [ + { + identityResourceId: '' + login: '' + sid: '' + } + ] + backupRetentionDays: 10 + databases: [ + { + name: 'testdb1' + } + ] + delegatedSubnetResourceId: '' + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + enableDefaultTelemetry: '' + highAvailability: 'SameZone' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + userAssignedResourceIds: [ + '' + ] + } + privateDnsZoneResourceId: '' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + storageAutoGrow: 'Enabled' + storageAutoIoScaling: 'Enabled' + storageIOPS: 400 + storageSizeGB: 64 + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'MySQL Flexible Server' + serverName: 'dfmsfspvt001' + } + } +} +``` + +
+

+ +

+ +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": "dfmsfspvt001" + }, + "skuName": { + "value": "Standard_D2ds_v4" + }, + "tier": { + "value": "GeneralPurpose" + }, + // Non-required parameters + "administratorLogin": { + "value": "adminUserName" + }, + "administratorLoginPassword": { + "value": "" + }, + "administrators": { + "value": [ + { + "identityResourceId": "", + "login": "", + "sid": "" + } + ] + }, + "backupRetentionDays": { + "value": 10 + }, + "databases": { + "value": [ + { + "name": "testdb1" + } + ] + }, + "delegatedSubnetResourceId": { + "value": "" + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "enableDefaultTelemetry": { + "value": "" + }, + "highAvailability": { + "value": "SameZone" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "userAssignedResourceIds": [ + "" + ] + } + }, + "privateDnsZoneResourceId": { + "value": "" + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "storageAutoGrow": { + "value": "Enabled" + }, + "storageAutoIoScaling": { + "value": "Enabled" + }, + "storageIOPS": { + "value": 400 + }, + "storageSizeGB": { + "value": 64 + }, + "tags": { + "value": { + "hidden-title": "This is visible in the resource name", + "resourceType": "MySQL Flexible Server", + "serverName": "dfmsfspvt001" + } + } + } +} +``` + +
+

+ +### Example 3: _Public_ + +

+ +via Bicep module + +```bicep +module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-dfmsfsp' + params: { + // Required parameters + name: 'dfmsfsp001' + skuName: 'Standard_D2ds_v4' + tier: 'GeneralPurpose' + // Non-required parameters + administratorLogin: 'adminUserName' + administratorLoginPassword: '' + availabilityZone: '1' + backupRetentionDays: 20 + customerManagedKey: { + keyName: '' + keyVaultResourceId: '' + userAssignedIdentityResourceId: '' + } + customerManagedKeyGeo: { + keyName: '' + keyVaultResourceId: '' + userAssignedIdentityResourceId: '' + } + databases: [ + { + name: 'testdb1' + } + { + charset: 'ascii' + collation: 'ascii_general_ci' + name: 'testdb2' + } + ] + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + enableDefaultTelemetry: '' + firewallRules: [ + { + endIpAddress: '0.0.0.0' + name: 'AllowAllWindowsAzureIps' + startIpAddress: '0.0.0.0' + } + { + endIpAddress: '10.10.10.10' + name: 'test-rule1' + startIpAddress: '10.10.10.1' + } + { + endIpAddress: '100.100.100.10' + name: 'test-rule2' + startIpAddress: '100.100.100.1' + } + ] + geoRedundantBackup: 'Enabled' + highAvailability: 'SameZone' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + userAssignedResourceIds: [ + '' + '' + ] + } + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + storageAutoGrow: 'Enabled' + storageAutoIoScaling: 'Enabled' + storageIOPS: 400 + storageSizeGB: 32 + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'MySQL Flexible Server' + serverName: 'dfmsfsp001' + } + version: '8.0.21' + } +} +``` + +
+

+ +

+ +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": "dfmsfsp001" + }, + "skuName": { + "value": "Standard_D2ds_v4" + }, + "tier": { + "value": "GeneralPurpose" + }, + // Non-required parameters + "administratorLogin": { + "value": "adminUserName" + }, + "administratorLoginPassword": { + "value": "" + }, + "availabilityZone": { + "value": "1" + }, + "backupRetentionDays": { + "value": 20 + }, + "customerManagedKey": { + "value": { + "keyName": "", + "keyVaultResourceId": "", + "userAssignedIdentityResourceId": "" + } + }, + "customerManagedKeyGeo": { + "value": { + "keyName": "", + "keyVaultResourceId": "", + "userAssignedIdentityResourceId": "" + } + }, + "databases": { + "value": [ + { + "name": "testdb1" + }, + { + "charset": "ascii", + "collation": "ascii_general_ci", + "name": "testdb2" + } + ] + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "enableDefaultTelemetry": { + "value": "" + }, + "firewallRules": { + "value": [ + { + "endIpAddress": "0.0.0.0", + "name": "AllowAllWindowsAzureIps", + "startIpAddress": "0.0.0.0" + }, + { + "endIpAddress": "10.10.10.10", + "name": "test-rule1", + "startIpAddress": "10.10.10.1" + }, + { + "endIpAddress": "100.100.100.10", + "name": "test-rule2", + "startIpAddress": "100.100.100.1" + } + ] + }, + "geoRedundantBackup": { + "value": "Enabled" + }, + "highAvailability": { + "value": "SameZone" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "userAssignedResourceIds": [ + "", + "" + ] + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + }, + "storageAutoGrow": { + "value": "Enabled" + }, + "storageAutoIoScaling": { + "value": "Enabled" + }, + "storageIOPS": { + "value": 400 + }, + "storageSizeGB": { + "value": 32 + }, + "tags": { + "value": { + "hidden-title": "This is visible in the resource name", + "resourceType": "MySQL Flexible Server", + "serverName": "dfmsfsp001" + } + }, + "version": { + "value": "8.0.21" + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the MySQL flexible server. | +| [`skuName`](#parameter-skuname) | string | The name of the sku, typically, tier + family + cores, e.g. Standard_D4s_v3. | +| [`tier`](#parameter-tier) | string | The tier of the particular SKU. Tier must align with the "skuName" property. Example, tier cannot be "Burstable" if skuName is "Standard_D4s_v3". | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. Required if 'customerManagedKey' is not empty. | +| [`privateDnsZoneResourceId`](#parameter-privatednszoneresourceid) | string | Private dns zone arm resource ID. Used when the desired connectivity mode is "Private Access". Required if "delegatedSubnetResourceId" is used and the Private DNS Zone name must end with mysql.database.azure.com in order to be linked to the MySQL Flexible Server. | +| [`restorePointInTime`](#parameter-restorepointintime) | string | Restore point creation time (ISO8601 format), specifying the time to restore from. Required if "createMode" is set to "PointInTimeRestore". | +| [`sourceServerResourceId`](#parameter-sourceserverresourceid) | string | The source MySQL server ID. Required if "createMode" is set to "PointInTimeRestore". | +| [`storageAutoGrow`](#parameter-storageautogrow) | string | Enable Storage Auto Grow or not. Storage auto-growth prevents a server from running out of storage and becoming read-only. Required if "highAvailability" is not "Disabled". | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`administratorLogin`](#parameter-administratorlogin) | string | The administrator login name of a server. Can only be specified when the MySQL server is being created. | +| [`administratorLoginPassword`](#parameter-administratorloginpassword) | securestring | The administrator login password. | +| [`administrators`](#parameter-administrators) | array | The Azure AD administrators when AAD authentication enabled. | +| [`availabilityZone`](#parameter-availabilityzone) | string | Availability zone information of the server. Default will have no preference set. | +| [`backupRetentionDays`](#parameter-backupretentiondays) | int | Backup retention days for the server. | +| [`createMode`](#parameter-createmode) | string | The mode to create a new MySQL server. | +| [`customerManagedKey`](#parameter-customermanagedkey) | object | The customer managed key definition to use for the managed service. | +| [`customerManagedKeyGeo`](#parameter-customermanagedkeygeo) | object | The customer managed key definition to use when geoRedundantBackup is "Enabled". | +| [`databases`](#parameter-databases) | array | The databases to create in the server. | +| [`delegatedSubnetResourceId`](#parameter-delegatedsubnetresourceid) | string | Delegated subnet arm resource ID. Used when the desired connectivity mode is "Private Access" - virtual network integration. Delegation must be enabled on the subnet for MySQL Flexible Servers and subnet CIDR size is /29. | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`firewallRules`](#parameter-firewallrules) | array | The firewall rules to create in the MySQL flexible server. | +| [`geoRedundantBackup`](#parameter-georedundantbackup) | string | A value indicating whether Geo-Redundant backup is enabled on the server. If "Enabled" and "cMKKeyName" is not empty, then "geoBackupCMKKeyVaultResourceId" and "cMKUserAssignedIdentityResourceId" are also required. | +| [`highAvailability`](#parameter-highavailability) | string | The mode for High Availability (HA). It is not supported for the Burstable pricing tier and Zone redundant HA can only be set during server provisioning. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`maintenanceWindow`](#parameter-maintenancewindow) | object | Properties for the maintenence window. If provided, "customWindow" property must exist and set to "Enabled". | +| [`replicationRole`](#parameter-replicationrole) | string | The replication role. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignment objects that contain the "roleDefinitionIdOrName" and "principalId" to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11". | +| [`storageAutoIoScaling`](#parameter-storageautoioscaling) | string | Enable IO Auto Scaling or not. The server scales IOPs up or down automatically depending on your workload needs. | +| [`storageIOPS`](#parameter-storageiops) | int | Storage IOPS for a server. Max IOPS are determined by compute size. | +| [`storageSizeGB`](#parameter-storagesizegb) | int | Max storage allowed for a server. In all compute tiers, the minimum storage supported is 20 GiB and maximum is 16 TiB. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | +| [`version`](#parameter-version) | string | MySQL Server version. | + +### Parameter: `name` + +The name of the MySQL flexible server. + +- Required: Yes +- Type: string + +### Parameter: `skuName` + +The name of the sku, typically, tier + family + cores, e.g. Standard_D4s_v3. + +- Required: Yes +- Type: string + +### Parameter: `tier` + +The tier of the particular SKU. Tier must align with the "skuName" property. Example, tier cannot be "Burstable" if skuName is "Standard_D4s_v3". + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Burstable' + 'GeneralPurpose' + 'MemoryOptimized' + ] + ``` + +### Parameter: `managedIdentities` + +The managed identity definition for this resource. Required if 'customerManagedKey' is not empty. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | + +### Parameter: `managedIdentities.userAssignedResourceIds` + +The resource ID(s) to assign to the resource. + +- Required: Yes +- Type: array + +### Parameter: `privateDnsZoneResourceId` + +Private dns zone arm resource ID. Used when the desired connectivity mode is "Private Access". Required if "delegatedSubnetResourceId" is used and the Private DNS Zone name must end with mysql.database.azure.com in order to be linked to the MySQL Flexible Server. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `restorePointInTime` + +Restore point creation time (ISO8601 format), specifying the time to restore from. Required if "createMode" is set to "PointInTimeRestore". + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `sourceServerResourceId` + +The source MySQL server ID. Required if "createMode" is set to "PointInTimeRestore". + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `storageAutoGrow` + +Enable Storage Auto Grow or not. Storage auto-growth prevents a server from running out of storage and becoming read-only. Required if "highAvailability" is not "Disabled". + +- Required: No +- Type: string +- Default: `'Disabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `administratorLogin` + +The administrator login name of a server. Can only be specified when the MySQL server is being created. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `administratorLoginPassword` + +The administrator login password. + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `administrators` + +The Azure AD administrators when AAD authentication enabled. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `availabilityZone` + +Availability zone information of the server. Default will have no preference set. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + '1' + '2' + '3' + ] + ``` + +### Parameter: `backupRetentionDays` + +Backup retention days for the server. + +- Required: No +- Type: int +- Default: `7` + +### Parameter: `createMode` + +The mode to create a new MySQL server. + +- Required: No +- Type: string +- Default: `'Default'` +- Allowed: + ```Bicep + [ + 'Default' + 'GeoRestore' + 'PointInTimeRestore' + 'Replica' + ] + ``` + +### Parameter: `customerManagedKey` + +The customer managed key definition to use for the managed service. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`keyName`](#parameter-customermanagedkeykeyname) | string | The name of the customer managed key to use for encryption. | +| [`keyVaultResourceId`](#parameter-customermanagedkeykeyvaultresourceid) | string | The resource ID of a key vault to reference a customer managed key for encryption from. | +| [`userAssignedIdentityResourceId`](#parameter-customermanagedkeyuserassignedidentityresourceid) | string | User assigned identity to use when fetching the customer managed key. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`keyVersion`](#parameter-customermanagedkeykeyversion) | string | The version of the customer managed key to reference for encryption. If not provided, using 'latest'. | + +### Parameter: `customerManagedKey.keyName` + +The name of the customer managed key to use for encryption. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKey.keyVaultResourceId` + +The resource ID of a key vault to reference a customer managed key for encryption from. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKey.userAssignedIdentityResourceId` + +User assigned identity to use when fetching the customer managed key. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKey.keyVersion` + +The version of the customer managed key to reference for encryption. If not provided, using 'latest'. + +- Required: No +- Type: string + +### Parameter: `customerManagedKeyGeo` + +The customer managed key definition to use when geoRedundantBackup is "Enabled". + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`keyName`](#parameter-customermanagedkeygeokeyname) | string | The name of the customer managed key to use for encryption. | +| [`keyVaultResourceId`](#parameter-customermanagedkeygeokeyvaultresourceid) | string | The resource ID of a key vault to reference a customer managed key for encryption from. | +| [`userAssignedIdentityResourceId`](#parameter-customermanagedkeygeouserassignedidentityresourceid) | string | User assigned identity to use when fetching the customer managed key. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`keyVersion`](#parameter-customermanagedkeygeokeyversion) | string | The version of the customer managed key to reference for encryption. If not provided, using 'latest'. | + +### Parameter: `customerManagedKeyGeo.keyName` + +The name of the customer managed key to use for encryption. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKeyGeo.keyVaultResourceId` + +The resource ID of a key vault to reference a customer managed key for encryption from. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKeyGeo.userAssignedIdentityResourceId` + +User assigned identity to use when fetching the customer managed key. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKeyGeo.keyVersion` + +The version of the customer managed key to reference for encryption. If not provided, using 'latest'. + +- Required: No +- Type: string + +### Parameter: `databases` + +The databases to create in the server. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `delegatedSubnetResourceId` + +Delegated subnet arm resource ID. Used when the desired connectivity mode is "Private Access" - virtual network integration. Delegation must be enabled on the subnet for MySQL Flexible Servers and subnet CIDR size is /29. + +- 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. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. | +| [`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.metricCategories` + +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.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: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `firewallRules` + +The firewall rules to create in the MySQL flexible server. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `geoRedundantBackup` + +A value indicating whether Geo-Redundant backup is enabled on the server. If "Enabled" and "cMKKeyName" is not empty, then "geoBackupCMKKeyVaultResourceId" and "cMKUserAssignedIdentityResourceId" are also required. + +- Required: No +- Type: string +- Default: `'Disabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `highAvailability` + +The mode for High Availability (HA). It is not supported for the Burstable pricing tier and Zone redundant HA can only be set during server provisioning. + +- Required: No +- Type: string +- Default: `'Disabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'SameZone' + 'ZoneRedundant' + ] + ``` + +### 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: `maintenanceWindow` + +Properties for the maintenence window. If provided, "customWindow" property must exist and set to "Enabled". + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `replicationRole` + +The replication role. + +- Required: No +- Type: string +- Default: `'None'` +- Allowed: + ```Bicep + [ + 'None' + 'Replica' + 'Source' + ] + ``` + +### Parameter: `roleAssignments` + +Array of role assignment objects that contain the "roleDefinitionIdOrName" and "principalId" to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11". + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The 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: `storageAutoIoScaling` + +Enable IO Auto Scaling or not. The server scales IOPs up or down automatically depending on your workload needs. + +- Required: No +- Type: string +- Default: `'Disabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `storageIOPS` + +Storage IOPS for a server. Max IOPS are determined by compute size. + +- Required: No +- Type: int +- Default: `1000` + +### Parameter: `storageSizeGB` + +Max storage allowed for a server. In all compute tiers, the minimum storage supported is 20 GiB and maximum is 16 TiB. + +- Required: No +- Type: int +- Default: `64` +- Allowed: + ```Bicep + [ + 20 + 32 + 64 + 128 + 256 + 512 + 1024 + 2048 + 4096 + 8192 + 16384 + ] + ``` + +### Parameter: `tags` + +Tags of the resource. + +- Required: No +- Type: object + +### Parameter: `version` + +MySQL Server version. + +- Required: No +- Type: string +- Default: `'5.7'` +- Allowed: + ```Bicep + [ + '5.7' + '8.0.21' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the deployed MySQL Flexible server. | +| `resourceGroupName` | string | The resource group of the deployed MySQL Flexible server. | +| `resourceId` | string | The resource ID of the deployed MySQL Flexible server. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/flexible-server/administrator/README.md b/avm/res/flexible-server/administrator/README.md new file mode 100644 index 0000000000..827b434ef7 --- /dev/null +++ b/avm/res/flexible-server/administrator/README.md @@ -0,0 +1,105 @@ +# DBforMySQL Flexible Server Administrators `[Microsoft.DBforMySQL/flexibleServers/administrators]` + +This module deploys a DBforMySQL Flexible Server Administrator. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DBforMySQL/flexibleServers/administrators` | [2022-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DBforMySQL/2022-01-01/flexibleServers/administrators) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`identityResourceId`](#parameter-identityresourceid) | string | The resource ID of the identity used for AAD Authentication. | +| [`login`](#parameter-login) | string | Login name of the server administrator. | +| [`sid`](#parameter-sid) | string | SID (object ID) of the server administrator. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`flexibleServerName`](#parameter-flexibleservername) | string | The name of the parent DBforMySQL flexible server. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`tenantId`](#parameter-tenantid) | string | The tenantId of the Active Directory administrator. | + +### Parameter: `identityResourceId` + +The resource ID of the identity used for AAD Authentication. + +- Required: Yes +- Type: string + +### Parameter: `login` + +Login name of the server administrator. + +- Required: Yes +- Type: string + +### Parameter: `sid` + +SID (object ID) of the server administrator. + +- Required: Yes +- Type: string + +### Parameter: `flexibleServerName` + +The name of the parent DBforMySQL flexible server. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `tenantId` + +The tenantId of the Active Directory administrator. + +- Required: No +- Type: string +- Default: `[tenant().tenantId]` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed administrator. | +| `resourceGroupName` | string | The resource group of the deployed administrator. | +| `resourceId` | string | The resource ID of the deployed administrator. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/flexible-server/administrator/main.bicep b/avm/res/flexible-server/administrator/main.bicep new file mode 100644 index 0000000000..c5442f24ea --- /dev/null +++ b/avm/res/flexible-server/administrator/main.bicep @@ -0,0 +1,61 @@ +metadata name = 'DBforMySQL Flexible Server Administrators' +metadata description = 'This module deploys a DBforMySQL Flexible Server Administrator.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent DBforMySQL flexible server. Required if the template is used in a standalone deployment.') +param flexibleServerName string + +@description('Required. SID (object ID) of the server administrator.') +param sid string + +@description('Required. The resource ID of the identity used for AAD Authentication.') +param identityResourceId string + +@description('Required. Login name of the server administrator.') +param login string + +@description('Optional. The tenantId of the Active Directory administrator.') +param tenantId string = tenant().tenantId + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource flexibleServer 'Microsoft.DBforMySQL/flexibleServers@2022-01-01' existing = { + name: flexibleServerName +} + +resource administrator 'Microsoft.DBforMySQL/flexibleServers/administrators@2022-01-01' = { + name: 'ActiveDirectory' + parent: flexibleServer + properties: { + administratorType: 'ActiveDirectory' + identityResourceId: identityResourceId + login: login + sid: sid + tenantId: tenantId + } +} + +@description('The name of the deployed administrator.') +output name string = administrator.name + +@description('The resource ID of the deployed administrator.') +output resourceId string = administrator.id + +@description('The resource group of the deployed administrator.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/flexible-server/administrator/main.json b/avm/res/flexible-server/administrator/main.json new file mode 100644 index 0000000000..347c0a171f --- /dev/null +++ b/avm/res/flexible-server/administrator/main.json @@ -0,0 +1,112 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "8863151548145849170" + }, + "name": "DBforMySQL Flexible Server Administrators", + "description": "This module deploys a DBforMySQL Flexible Server Administrator.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "flexibleServerName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent DBforMySQL flexible server. Required if the template is used in a standalone deployment." + } + }, + "sid": { + "type": "string", + "metadata": { + "description": "Required. SID (object ID) of the server administrator." + } + }, + "identityResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the identity used for AAD Authentication." + } + }, + "login": { + "type": "string", + "metadata": { + "description": "Required. Login name of the server administrator." + } + }, + "tenantId": { + "type": "string", + "defaultValue": "[tenant().tenantId]", + "metadata": { + "description": "Optional. The tenantId of the Active Directory administrator." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.DBforMySQL/flexibleServers/administrators", + "apiVersion": "2022-01-01", + "name": "[format('{0}/{1}', parameters('flexibleServerName'), 'ActiveDirectory')]", + "properties": { + "administratorType": "ActiveDirectory", + "identityResourceId": "[parameters('identityResourceId')]", + "login": "[parameters('login')]", + "sid": "[parameters('sid')]", + "tenantId": "[parameters('tenantId')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed administrator." + }, + "value": "ActiveDirectory" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed administrator." + }, + "value": "[resourceId('Microsoft.DBforMySQL/flexibleServers/administrators', parameters('flexibleServerName'), 'ActiveDirectory')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed administrator." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/flexible-server/administrator/version.json b/avm/res/flexible-server/administrator/version.json new file mode 100644 index 0000000000..7fa401bdf7 --- /dev/null +++ b/avm/res/flexible-server/administrator/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/flexible-server/database/README.md b/avm/res/flexible-server/database/README.md new file mode 100644 index 0000000000..4bcb034a0b --- /dev/null +++ b/avm/res/flexible-server/database/README.md @@ -0,0 +1,98 @@ +# DBforMySQL Flexible Server Databases `[Microsoft.DBforMySQL/flexibleServers/databases]` + +This module deploys a DBforMySQL Flexible Server Database. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DBforMySQL/flexibleServers/databases` | [2022-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DBforMySQL/2022-01-01/flexibleServers/databases) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the database. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`flexibleServerName`](#parameter-flexibleservername) | string | The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`charset`](#parameter-charset) | string | The charset of the database. | +| [`collation`](#parameter-collation) | string | The collation of the database. | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`location`](#parameter-location) | string | Location for all resources. | + +### Parameter: `name` + +The name of the database. + +- Required: Yes +- Type: string + +### Parameter: `flexibleServerName` + +The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `charset` + +The charset of the database. + +- Required: No +- Type: string +- Default: `'utf8_general_ci'` + +### Parameter: `collation` + +The collation of the database. + +- Required: No +- Type: string +- Default: `'utf8'` + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed database. | +| `resourceGroupName` | string | The resource group of the deployed database. | +| `resourceId` | string | The resource ID of the deployed database. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/flexible-server/database/main.bicep b/avm/res/flexible-server/database/main.bicep new file mode 100644 index 0000000000..2c4fd62547 --- /dev/null +++ b/avm/res/flexible-server/database/main.bicep @@ -0,0 +1,55 @@ +metadata name = 'DBforMySQL Flexible Server Databases' +metadata description = 'This module deploys a DBforMySQL Flexible Server Database.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the database.') +param name string + +@description('Conditional. The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment.') +param flexibleServerName string + +@description('Optional. The collation of the database.') +param collation string = 'utf8' + +@description('Optional. The charset of the database.') +param charset string = 'utf8_general_ci' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2022-09-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource flexibleServer 'Microsoft.DBforMySQL/flexibleServers@2022-09-30-preview' existing = { + name: flexibleServerName +} + +resource database 'Microsoft.DBforMySQL/flexibleServers/databases@2022-01-01' = { + name: name + parent: flexibleServer + properties: { + collation: !empty(collation) ? collation : null + charset: !empty(charset) ? charset : null + } +} + +@description('The name of the deployed database.') +output name string = database.name + +@description('The resource ID of the deployed database.') +output resourceId string = database.id + +@description('The resource group of the deployed database.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/flexible-server/database/main.json b/avm/res/flexible-server/database/main.json new file mode 100644 index 0000000000..c7747c6684 --- /dev/null +++ b/avm/res/flexible-server/database/main.json @@ -0,0 +1,104 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "7585808247826533259" + }, + "name": "DBforMySQL Flexible Server Databases", + "description": "This module deploys a DBforMySQL Flexible Server Database.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the database." + } + }, + "flexibleServerName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment." + } + }, + "collation": { + "type": "string", + "defaultValue": "utf8", + "metadata": { + "description": "Optional. The collation of the database." + } + }, + "charset": { + "type": "string", + "defaultValue": "utf8_general_ci", + "metadata": { + "description": "Optional. The charset of the database." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.DBforMySQL/flexibleServers/databases", + "apiVersion": "2022-01-01", + "name": "[format('{0}/{1}', parameters('flexibleServerName'), parameters('name'))]", + "properties": { + "collation": "[if(not(empty(parameters('collation'))), parameters('collation'), null())]", + "charset": "[if(not(empty(parameters('charset'))), parameters('charset'), null())]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed database." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed database." + }, + "value": "[resourceId('Microsoft.DBforMySQL/flexibleServers/databases', parameters('flexibleServerName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed database." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/flexible-server/database/version.json b/avm/res/flexible-server/database/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/flexible-server/database/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/flexible-server/firewall-rule/README.md b/avm/res/flexible-server/firewall-rule/README.md new file mode 100644 index 0000000000..593969aa25 --- /dev/null +++ b/avm/res/flexible-server/firewall-rule/README.md @@ -0,0 +1,87 @@ +# DBforMySQL Flexible Server Firewall Rules `[Microsoft.DBforMySQL/flexibleServers/firewallRules]` + +This module deploys a DBforMySQL Flexible Server Firewall Rule. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.DBforMySQL/flexibleServers/firewallRules` | [2022-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.DBforMySQL/2022-01-01/flexibleServers/firewallRules) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`endIpAddress`](#parameter-endipaddress) | string | The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value '0.0.0.0' for all Azure-internal IP addresses. | +| [`name`](#parameter-name) | string | The name of the MySQL flexible server Firewall Rule. | +| [`startIpAddress`](#parameter-startipaddress) | string | The start IP address of the firewall rule. Must be IPv4 format. Use value '0.0.0.0' for all Azure-internal IP addresses. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`flexibleServerName`](#parameter-flexibleservername) | string | The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | + +### Parameter: `endIpAddress` + +The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value '0.0.0.0' for all Azure-internal IP addresses. + +- Required: Yes +- Type: string + +### Parameter: `name` + +The name of the MySQL flexible server Firewall Rule. + +- Required: Yes +- Type: string + +### Parameter: `startIpAddress` + +The start IP address of the firewall rule. Must be IPv4 format. Use value '0.0.0.0' for all Azure-internal IP addresses. + +- Required: Yes +- Type: string + +### Parameter: `flexibleServerName` + +The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed firewall rule. | +| `resourceGroupName` | string | The resource group of the deployed firewall rule. | +| `resourceId` | string | The resource ID of the deployed firewall rule. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/flexible-server/firewall-rule/main.bicep b/avm/res/flexible-server/firewall-rule/main.bicep new file mode 100644 index 0000000000..cba30a70e3 --- /dev/null +++ b/avm/res/flexible-server/firewall-rule/main.bicep @@ -0,0 +1,52 @@ +metadata name = 'DBforMySQL Flexible Server Firewall Rules' +metadata description = 'This module deploys a DBforMySQL Flexible Server Firewall Rule.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the MySQL flexible server Firewall Rule.') +param name string + +@description('Required. The start IP address of the firewall rule. Must be IPv4 format. Use value \'0.0.0.0\' for all Azure-internal IP addresses.') +param startIpAddress string + +@description('Required. The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value \'0.0.0.0\' for all Azure-internal IP addresses.') +param endIpAddress string + +@description('Conditional. The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment.') +param flexibleServerName string + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +resource defaultTelemetry 'Microsoft.Resources/deployments@2022-09-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource flexibleServer 'Microsoft.DBforMySQL/flexibleServers@2022-09-30-preview' existing = { + name: flexibleServerName +} + +resource firewallRule 'Microsoft.DBforMySQL/flexibleServers/firewallRules@2022-01-01' = { + name: name + parent: flexibleServer + properties: { + endIpAddress: endIpAddress + startIpAddress: startIpAddress + } +} + +@description('The name of the deployed firewall rule.') +output name string = firewallRule.name + +@description('The resource ID of the deployed firewall rule.') +output resourceId string = firewallRule.id + +@description('The resource group of the deployed firewall rule.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/flexible-server/firewall-rule/main.json b/avm/res/flexible-server/firewall-rule/main.json new file mode 100644 index 0000000000..c86c3c1a46 --- /dev/null +++ b/avm/res/flexible-server/firewall-rule/main.json @@ -0,0 +1,95 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "9889972221731602451" + }, + "name": "DBforMySQL Flexible Server Firewall Rules", + "description": "This module deploys a DBforMySQL Flexible Server Firewall Rule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the MySQL flexible server Firewall Rule." + } + }, + "startIpAddress": { + "type": "string", + "metadata": { + "description": "Required. The start IP address of the firewall rule. Must be IPv4 format. Use value '0.0.0.0' for all Azure-internal IP addresses." + } + }, + "endIpAddress": { + "type": "string", + "metadata": { + "description": "Required. The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value '0.0.0.0' for all Azure-internal IP addresses." + } + }, + "flexibleServerName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.DBforMySQL/flexibleServers/firewallRules", + "apiVersion": "2022-01-01", + "name": "[format('{0}/{1}', parameters('flexibleServerName'), parameters('name'))]", + "properties": { + "endIpAddress": "[parameters('endIpAddress')]", + "startIpAddress": "[parameters('startIpAddress')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed firewall rule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed firewall rule." + }, + "value": "[resourceId('Microsoft.DBforMySQL/flexibleServers/firewallRules', parameters('flexibleServerName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed firewall rule." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/flexible-server/firewall-rule/version.json b/avm/res/flexible-server/firewall-rule/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/flexible-server/firewall-rule/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/flexible-server/main.bicep b/avm/res/flexible-server/main.bicep new file mode 100644 index 0000000000..d89c29094a --- /dev/null +++ b/avm/res/flexible-server/main.bicep @@ -0,0 +1,459 @@ +metadata name = 'DBforMySQL Flexible Servers' +metadata description = 'This module deploys a DBforMySQL Flexible Server.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the MySQL flexible server.') +param name string + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. The administrator login name of a server. Can only be specified when the MySQL server is being created.') +param administratorLogin string = '' + +@description('Optional. The administrator login password.') +@secure() +param administratorLoginPassword string = '' + +@description('Optional. The Azure AD administrators when AAD authentication enabled.') +param administrators array = [] + +@description('Required. The name of the sku, typically, tier + family + cores, e.g. Standard_D4s_v3.') +param skuName string + +@allowed([ + 'GeneralPurpose' + 'Burstable' + 'MemoryOptimized' +]) +@description('Required. The tier of the particular SKU. Tier must align with the "skuName" property. Example, tier cannot be "Burstable" if skuName is "Standard_D4s_v3".') +param tier string + +@allowed([ + '' + '1' + '2' + '3' +]) +@description('Optional. Availability zone information of the server. Default will have no preference set.') +param availabilityZone string = '' + +@minValue(1) +@maxValue(35) +@description('Optional. Backup retention days for the server.') +param backupRetentionDays int = 7 + +@allowed([ + 'Disabled' + 'Enabled' +]) +@description('Optional. A value indicating whether Geo-Redundant backup is enabled on the server. If "Enabled" and "cMKKeyName" is not empty, then "geoBackupCMKKeyVaultResourceId" and "cMKUserAssignedIdentityResourceId" are also required.') +param geoRedundantBackup string = 'Disabled' + +@allowed([ + 'Default' + 'GeoRestore' + 'PointInTimeRestore' + 'Replica' +]) +@description('Optional. The mode to create a new MySQL server.') +param createMode string = 'Default' + +@description('Conditional. The managed identity definition for this resource. Required if \'customerManagedKey\' is not empty.') +param managedIdentities managedIdentitiesType + +@description('Optional. The customer managed key definition to use for the managed service.') +param customerManagedKey customerManagedKeyType + +@description('Optional. The customer managed key definition to use when geoRedundantBackup is "Enabled".') +param customerManagedKeyGeo customerManagedKeyType + +@allowed([ + 'Disabled' + 'SameZone' + 'ZoneRedundant' +]) +@description('Optional. The mode for High Availability (HA). It is not supported for the Burstable pricing tier and Zone redundant HA can only be set during server provisioning.') +param highAvailability string = 'Disabled' + +@description('Optional. Properties for the maintenence window. If provided, "customWindow" property must exist and set to "Enabled".') +param maintenanceWindow object = {} + +@description('Optional. Delegated subnet arm resource ID. Used when the desired connectivity mode is "Private Access" - virtual network integration. Delegation must be enabled on the subnet for MySQL Flexible Servers and subnet CIDR size is /29.') +param delegatedSubnetResourceId string = '' + +@description('Conditional. Private dns zone arm resource ID. Used when the desired connectivity mode is "Private Access". Required if "delegatedSubnetResourceId" is used and the Private DNS Zone name must end with mysql.database.azure.com in order to be linked to the MySQL Flexible Server.') +param privateDnsZoneResourceId string = '' + +@description('Conditional. Restore point creation time (ISO8601 format), specifying the time to restore from. Required if "createMode" is set to "PointInTimeRestore".') +param restorePointInTime string = '' + +@allowed([ + 'None' + 'Replica' + 'Source' +]) +@description('Optional. The replication role.') +param replicationRole string = 'None' + +@description('Conditional. The source MySQL server ID. Required if "createMode" is set to "PointInTimeRestore".') +param sourceServerResourceId string = '' + +@allowed([ + 'Disabled' + 'Enabled' +]) +@description('Conditional. Enable Storage Auto Grow or not. Storage auto-growth prevents a server from running out of storage and becoming read-only. Required if "highAvailability" is not "Disabled".') +param storageAutoGrow string = 'Disabled' + +@allowed([ + 'Disabled' + 'Enabled' +]) +@description('Optional. Enable IO Auto Scaling or not. The server scales IOPs up or down automatically depending on your workload needs.') +param storageAutoIoScaling string = 'Disabled' + +@minValue(360) +@maxValue(48000) +@description('Optional. Storage IOPS for a server. Max IOPS are determined by compute size.') +param storageIOPS int = 1000 + +@allowed([ + 20 + 32 + 64 + 128 + 256 + 512 + 1024 + 2048 + 4096 + 8192 + 16384 +]) +@description('Optional. Max storage allowed for a server. In all compute tiers, the minimum storage supported is 20 GiB and maximum is 16 TiB.') +param storageSizeGB int = 64 + +@allowed([ + '5.7' + '8.0.21' +]) +@description('Optional. MySQL Server version.') +param version string = '5.7' + +@description('Optional. The databases to create in the server.') +param databases array = [] + +@description('Optional. The firewall rules to create in the MySQL flexible server.') +param firewallRules array = [] + +@description('Optional. Array of role assignment objects that contain the "roleDefinitionIdOrName" and "principalId" to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11".') +param roleAssignments roleAssignmentType + +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } + +var identity = !empty(managedIdentities) ? { + type: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +var enableReferencedModulesTelemetry = false + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'MySQL Backup And Export Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd18ad5f3-1baf-4119-b49b-d944edb1f9d0') + 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 defaultTelemetry 'Microsoft.Resources/deployments@2022-09-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) + + resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } +} + +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup(split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4]) +} + +resource cMKGeoKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKeyGeo.?keyVaultResourceId)) { + name: last(split((customerManagedKeyGeo.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup(split((customerManagedKeyGeo.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKeyGeo.?keyVaultResourceId ?? '////'), '/')[4]) + + resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKeyGeo.?keyVaultResourceId) && !empty(customerManagedKeyGeo.?keyName)) { + name: customerManagedKeyGeo.?keyName ?? 'dummyKey' + } +} + +resource cMKGeoUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKeyGeo.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKeyGeo.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup(split((customerManagedKeyGeo.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKeyGeo.?userAssignedIdentityResourceId ?? '////'), '/')[4]) +} + +resource flexibleServer 'Microsoft.DBforMySQL/flexibleServers@2022-09-30-preview' = { + name: name + location: location + tags: tags + sku: { + name: skuName + tier: tier + } + identity: identity + properties: { + administratorLogin: !empty(administratorLogin) ? administratorLogin : null + administratorLoginPassword: !empty(administratorLoginPassword) ? administratorLoginPassword : null + availabilityZone: availabilityZone + backup: { + backupRetentionDays: backupRetentionDays + geoRedundantBackup: geoRedundantBackup + } + createMode: createMode + dataEncryption: !empty(customerManagedKey) ? { + type: 'AzureKeyVault' + geoBackupKeyURI: geoRedundantBackup == 'Enabled' ? (!empty(customerManagedKeyGeo.?keyVersion ?? '') ? '${cMKGeoKeyVault::cMKKey.properties.keyUri}/${customerManagedKeyGeo!.keyVersion}' : cMKGeoKeyVault::cMKKey.properties.keyUriWithVersion) : null + geoBackupUserAssignedIdentityId: geoRedundantBackup == 'Enabled' ? cMKGeoUserAssignedIdentity.id : null + primaryKeyURI: !empty(customerManagedKey.?keyVersion ?? '') ? '${cMKKeyVault::cMKKey.properties.keyUri}/${customerManagedKey!.keyVersion}' : cMKKeyVault::cMKKey.properties.keyUriWithVersion + primaryUserAssignedIdentityId: cMKUserAssignedIdentity.id + } : null + highAvailability: { + mode: highAvailability + standbyAvailabilityZone: highAvailability == 'SameZone' ? availabilityZone : null + } + maintenanceWindow: !empty(maintenanceWindow) ? { + customWindow: maintenanceWindow.customWindow + dayOfWeek: maintenanceWindow.customWindow == 'Enabled' ? maintenanceWindow.dayOfWeek : 0 + startHour: maintenanceWindow.customWindow == 'Enabled' ? maintenanceWindow.startHour : 0 + startMinute: maintenanceWindow.customWindow == 'Enabled' ? maintenanceWindow.startMinute : 0 + } : null + network: !empty(delegatedSubnetResourceId) && empty(firewallRules) ? { + delegatedSubnetResourceId: delegatedSubnetResourceId + privateDnsZoneResourceId: privateDnsZoneResourceId + } : null + replicationRole: replicationRole + restorePointInTime: restorePointInTime + sourceServerResourceId: !empty(sourceServerResourceId) ? sourceServerResourceId : null + storage: { + autoGrow: storageAutoGrow + autoIoScaling: storageAutoIoScaling + iops: storageIOPS + storageSizeGB: storageSizeGB + } + version: version + } +} + +resource flexibleServer_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: flexibleServer +} + +resource flexibleServer_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(flexibleServer.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: flexibleServer +}] + +module flexibleServer_databases 'database/main.bicep' = [for (database, index) in databases: { + name: '${uniqueString(deployment().name, location)}-MySQL-DB-${index}' + params: { + name: database.name + flexibleServerName: flexibleServer.name + collation: contains(database, 'collation') ? database.collation : '' + charset: contains(database, 'charset') ? database.charset : '' + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module flexibleServer_firewallRules 'firewall-rule/main.bicep' = [for (firewallRule, index) in firewallRules: { + name: '${uniqueString(deployment().name, location)}-MySQL-FirewallRules-${index}' + params: { + name: firewallRule.name + flexibleServerName: flexibleServer.name + startIpAddress: firewallRule.startIpAddress + endIpAddress: firewallRule.endIpAddress + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module flexibleServer_administrators 'administrator/main.bicep' = [for (administrator, index) in administrators: { + name: '${uniqueString(deployment().name, location)}-MySQL-Administrators-${index}' + params: { + flexibleServerName: flexibleServer.name + login: administrator.login + sid: administrator.sid + identityResourceId: administrator.identityResourceId + tenantId: contains(administrator, 'tenantId') ? administrator.tenantId : tenant().tenantId + } +}] + +resource flexibleServer_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 + metrics: diagnosticSetting.?metricCategories ?? [ + { + category: 'AllMetrics' + timeGrain: null + enabled: true + } + ] + logs: diagnosticSetting.?logCategoriesAndGroups ?? [ + { + categoryGroup: 'AllLogs' + enabled: true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: flexibleServer +}] + +@description('The name of the deployed MySQL Flexible server.') +output name string = flexibleServer.name + +@description('The resource ID of the deployed MySQL Flexible server.') +output resourceId string = flexibleServer.id + +@description('The resource group of the deployed MySQL Flexible server.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = flexibleServer.location + +// =============== // +// Definitions // +// =============== // + +type managedIdentitiesType = { + @description('Optional. The resource ID(s) to assign to the resource.') + userAssignedResourceIds: string[] +}? + +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? +}[]? + +type diagnosticSettingType = { + @description('Optional. The name of diagnostic setting.') + name: string? + + @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: { + @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? + + @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? + }[]? + + @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + metricCategories: { + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to \'AllMetrics\' to collect all metrics.') + category: string + }[]? + + @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')? + + @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? + + @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? + + @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? + + @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? + + @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') + marketplacePartnerResourceId: string? +}[]? + +type customerManagedKeyType = { + @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') + keyVaultResourceId: string + + @description('Required. The name of the customer managed key to use for encryption.') + keyName: string + + @description('Optional. The version of the customer managed key to reference for encryption. If not provided, using \'latest\'.') + keyVersion: string? + + @description('Required. User assigned identity to use when fetching the customer managed key.') + userAssignedIdentityResourceId: string +}? diff --git a/avm/res/flexible-server/main.json b/avm/res/flexible-server/main.json new file mode 100644 index 0000000000..5d63ee48ca --- /dev/null +++ b/avm/res/flexible-server/main.json @@ -0,0 +1,1177 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "13509958318011769977" + }, + "name": "DBforMySQL Flexible Servers", + "description": "This module deploys a DBforMySQL Flexible Server.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "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." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to 'AllMetrics' to collect all metrics." + } + } + } + }, + "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 + }, + "customerManagedKeyType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "metadata": { + "description": "Required. User assigned identity to use when fetching the customer managed key." + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the MySQL flexible server." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "administratorLogin": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The administrator login name of a server. Can only be specified when the MySQL server is being created." + } + }, + "administratorLoginPassword": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. The administrator login password." + } + }, + "administrators": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The Azure AD administrators when AAD authentication enabled." + } + }, + "skuName": { + "type": "string", + "metadata": { + "description": "Required. The name of the sku, typically, tier + family + cores, e.g. Standard_D4s_v3." + } + }, + "tier": { + "type": "string", + "allowedValues": [ + "GeneralPurpose", + "Burstable", + "MemoryOptimized" + ], + "metadata": { + "description": "Required. The tier of the particular SKU. Tier must align with the \"skuName\" property. Example, tier cannot be \"Burstable\" if skuName is \"Standard_D4s_v3\"." + } + }, + "availabilityZone": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "1", + "2", + "3" + ], + "metadata": { + "description": "Optional. Availability zone information of the server. Default will have no preference set." + } + }, + "backupRetentionDays": { + "type": "int", + "defaultValue": 7, + "minValue": 1, + "maxValue": 35, + "metadata": { + "description": "Optional. Backup retention days for the server." + } + }, + "geoRedundantBackup": { + "type": "string", + "defaultValue": "Disabled", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Optional. A value indicating whether Geo-Redundant backup is enabled on the server. If \"Enabled\" and \"cMKKeyName\" is not empty, then \"geoBackupCMKKeyVaultResourceId\" and \"cMKUserAssignedIdentityResourceId\" are also required." + } + }, + "createMode": { + "type": "string", + "defaultValue": "Default", + "allowedValues": [ + "Default", + "GeoRestore", + "PointInTimeRestore", + "Replica" + ], + "metadata": { + "description": "Optional. The mode to create a new MySQL server." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Conditional. The managed identity definition for this resource. Required if 'customerManagedKey' is not empty." + } + }, + "customerManagedKey": { + "$ref": "#/definitions/customerManagedKeyType", + "metadata": { + "description": "Optional. The customer managed key definition to use for the managed service." + } + }, + "customerManagedKeyGeo": { + "$ref": "#/definitions/customerManagedKeyType", + "metadata": { + "description": "Optional. The customer managed key definition to use when geoRedundantBackup is \"Enabled\"." + } + }, + "highAvailability": { + "type": "string", + "defaultValue": "Disabled", + "allowedValues": [ + "Disabled", + "SameZone", + "ZoneRedundant" + ], + "metadata": { + "description": "Optional. The mode for High Availability (HA). It is not supported for the Burstable pricing tier and Zone redundant HA can only be set during server provisioning." + } + }, + "maintenanceWindow": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Properties for the maintenence window. If provided, \"customWindow\" property must exist and set to \"Enabled\"." + } + }, + "delegatedSubnetResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Delegated subnet arm resource ID. Used when the desired connectivity mode is \"Private Access\" - virtual network integration. Delegation must be enabled on the subnet for MySQL Flexible Servers and subnet CIDR size is /29." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Conditional. Private dns zone arm resource ID. Used when the desired connectivity mode is \"Private Access\". Required if \"delegatedSubnetResourceId\" is used and the Private DNS Zone name must end with mysql.database.azure.com in order to be linked to the MySQL Flexible Server." + } + }, + "restorePointInTime": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Conditional. Restore point creation time (ISO8601 format), specifying the time to restore from. Required if \"createMode\" is set to \"PointInTimeRestore\"." + } + }, + "replicationRole": { + "type": "string", + "defaultValue": "None", + "allowedValues": [ + "None", + "Replica", + "Source" + ], + "metadata": { + "description": "Optional. The replication role." + } + }, + "sourceServerResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Conditional. The source MySQL server ID. Required if \"createMode\" is set to \"PointInTimeRestore\"." + } + }, + "storageAutoGrow": { + "type": "string", + "defaultValue": "Disabled", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Conditional. Enable Storage Auto Grow or not. Storage auto-growth prevents a server from running out of storage and becoming read-only. Required if \"highAvailability\" is not \"Disabled\"." + } + }, + "storageAutoIoScaling": { + "type": "string", + "defaultValue": "Disabled", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "metadata": { + "description": "Optional. Enable IO Auto Scaling or not. The server scales IOPs up or down automatically depending on your workload needs." + } + }, + "storageIOPS": { + "type": "int", + "defaultValue": 1000, + "minValue": 360, + "maxValue": 48000, + "metadata": { + "description": "Optional. Storage IOPS for a server. Max IOPS are determined by compute size." + } + }, + "storageSizeGB": { + "type": "int", + "defaultValue": 64, + "allowedValues": [ + 20, + 32, + 64, + 128, + 256, + 512, + 1024, + 2048, + 4096, + 8192, + 16384 + ], + "metadata": { + "description": "Optional. Max storage allowed for a server. In all compute tiers, the minimum storage supported is 20 GiB and maximum is 16 TiB." + } + }, + "version": { + "type": "string", + "defaultValue": "5.7", + "allowedValues": [ + "5.7", + "8.0.21" + ], + "metadata": { + "description": "Optional. MySQL Server version." + } + }, + "databases": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The databases to create in the server." + } + }, + "firewallRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The firewall rules to create in the MySQL flexible server." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignment objects that contain the \"roleDefinitionIdOrName\" and \"principalId\" to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \"/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\"." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "variables": { + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null()), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "enableReferencedModulesTelemetry": false, + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "MySQL Backup And Export Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd18ad5f3-1baf-4119-b49b-d944edb1f9d0')]", + "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": { + "cMKKeyVault::cMKKey": { + "condition": "[and(not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'))), and(not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'))), not(empty(tryGet(parameters('customerManagedKey'), 'keyName')))))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[format('{0}/{1}', last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/')), coalesce(tryGet(parameters('customerManagedKey'), 'keyName'), 'dummyKey'))]", + "dependsOn": [ + "cMKKeyVault" + ] + }, + "cMKGeoKeyVault::cMKKey": { + "condition": "[and(not(empty(tryGet(parameters('customerManagedKeyGeo'), 'keyVaultResourceId'))), and(not(empty(tryGet(parameters('customerManagedKeyGeo'), 'keyVaultResourceId'))), not(empty(tryGet(parameters('customerManagedKeyGeo'), 'keyName')))))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[format('{0}/{1}', last(split(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'keyVaultResourceId'), 'dummyVault'), '/')), coalesce(tryGet(parameters('customerManagedKeyGeo'), 'keyName'), 'dummyKey'))]", + "dependsOn": [ + "cMKGeoKeyVault" + ] + }, + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "cMKKeyVault": { + "condition": "[not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId')))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/'))]" + }, + "cMKUserAssignedIdentity": { + "condition": "[not(empty(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId')))]", + "existing": true, + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2023-01-31", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), 'dummyMsi'), '/'))]" + }, + "cMKGeoKeyVault": { + "condition": "[not(empty(tryGet(parameters('customerManagedKeyGeo'), 'keyVaultResourceId')))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'keyVaultResourceId'), 'dummyVault'), '/'))]" + }, + "cMKGeoUserAssignedIdentity": { + "condition": "[not(empty(tryGet(parameters('customerManagedKeyGeo'), 'userAssignedIdentityResourceId')))]", + "existing": true, + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2023-01-31", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'userAssignedIdentityResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'userAssignedIdentityResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'userAssignedIdentityResourceId'), 'dummyMsi'), '/'))]" + }, + "flexibleServer": { + "type": "Microsoft.DBforMySQL/flexibleServers", + "apiVersion": "2022-09-30-preview", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('skuName')]", + "tier": "[parameters('tier')]" + }, + "identity": "[variables('identity')]", + "properties": { + "administratorLogin": "[if(not(empty(parameters('administratorLogin'))), parameters('administratorLogin'), null())]", + "administratorLoginPassword": "[if(not(empty(parameters('administratorLoginPassword'))), parameters('administratorLoginPassword'), null())]", + "availabilityZone": "[parameters('availabilityZone')]", + "backup": { + "backupRetentionDays": "[parameters('backupRetentionDays')]", + "geoRedundantBackup": "[parameters('geoRedundantBackup')]" + }, + "createMode": "[parameters('createMode')]", + "dataEncryption": "[if(not(empty(parameters('customerManagedKey'))), createObject('type', 'AzureKeyVault', 'geoBackupKeyURI', if(equals(parameters('geoRedundantBackup'), 'Enabled'), if(not(empty(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'keyVersion'), ''))), format('{0}/{1}', reference('cMKGeoKeyVault::cMKKey').keyUri, parameters('customerManagedKeyGeo').keyVersion), reference('cMKGeoKeyVault::cMKKey').keyUriWithVersion), null()), 'geoBackupUserAssignedIdentityId', if(equals(parameters('geoRedundantBackup'), 'Enabled'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'userAssignedIdentityResourceId'), '//'), '/')[2], split(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'userAssignedIdentityResourceId'), '////'), '/')[4]), 'Microsoft.ManagedIdentity/userAssignedIdentities', last(split(coalesce(tryGet(parameters('customerManagedKeyGeo'), 'userAssignedIdentityResourceId'), 'dummyMsi'), '/'))), null()), 'primaryKeyURI', if(not(empty(coalesce(tryGet(parameters('customerManagedKey'), 'keyVersion'), ''))), format('{0}/{1}', reference('cMKKeyVault::cMKKey').keyUri, parameters('customerManagedKey').keyVersion), reference('cMKKeyVault::cMKKey').keyUriWithVersion), 'primaryUserAssignedIdentityId', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), '//'), '/')[2], split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), '////'), '/')[4]), 'Microsoft.ManagedIdentity/userAssignedIdentities', last(split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), 'dummyMsi'), '/')))), null())]", + "highAvailability": { + "mode": "[parameters('highAvailability')]", + "standbyAvailabilityZone": "[if(equals(parameters('highAvailability'), 'SameZone'), parameters('availabilityZone'), null())]" + }, + "maintenanceWindow": "[if(not(empty(parameters('maintenanceWindow'))), createObject('customWindow', parameters('maintenanceWindow').customWindow, 'dayOfWeek', if(equals(parameters('maintenanceWindow').customWindow, 'Enabled'), parameters('maintenanceWindow').dayOfWeek, 0), 'startHour', if(equals(parameters('maintenanceWindow').customWindow, 'Enabled'), parameters('maintenanceWindow').startHour, 0), 'startMinute', if(equals(parameters('maintenanceWindow').customWindow, 'Enabled'), parameters('maintenanceWindow').startMinute, 0)), null())]", + "network": "[if(and(not(empty(parameters('delegatedSubnetResourceId'))), empty(parameters('firewallRules'))), createObject('delegatedSubnetResourceId', parameters('delegatedSubnetResourceId'), 'privateDnsZoneResourceId', parameters('privateDnsZoneResourceId')), null())]", + "replicationRole": "[parameters('replicationRole')]", + "restorePointInTime": "[parameters('restorePointInTime')]", + "sourceServerResourceId": "[if(not(empty(parameters('sourceServerResourceId'))), parameters('sourceServerResourceId'), null())]", + "storage": { + "autoGrow": "[parameters('storageAutoGrow')]", + "autoIoScaling": "[parameters('storageAutoIoScaling')]", + "iops": "[parameters('storageIOPS')]", + "storageSizeGB": "[parameters('storageSizeGB')]" + }, + "version": "[parameters('version')]" + }, + "dependsOn": [ + "cMKGeoKeyVault", + "cMKGeoUserAssignedIdentity", + "cMKKeyVault", + "cMKUserAssignedIdentity" + ] + }, + "flexibleServer_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.DBforMySQL/flexibleServers/{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": [ + "flexibleServer" + ] + }, + "flexibleServer_roleAssignments": { + "copy": { + "name": "flexibleServer_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.DBforMySQL/flexibleServers/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.DBforMySQL/flexibleServers', 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": [ + "flexibleServer" + ] + }, + "flexibleServer_diagnosticSettings": { + "copy": { + "name": "flexibleServer_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.DBforMySQL/flexibleServers/{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')]", + "metrics": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics', 'timeGrain', null(), 'enabled', true())))]", + "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": [ + "flexibleServer" + ] + }, + "flexibleServer_databases": { + "copy": { + "name": "flexibleServer_databases", + "count": "[length(parameters('databases'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-MySQL-DB-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('databases')[copyIndex()].name]" + }, + "flexibleServerName": { + "value": "[parameters('name')]" + }, + "collation": "[if(contains(parameters('databases')[copyIndex()], 'collation'), createObject('value', parameters('databases')[copyIndex()].collation), createObject('value', ''))]", + "charset": "[if(contains(parameters('databases')[copyIndex()], 'charset'), createObject('value', parameters('databases')[copyIndex()].charset), createObject('value', ''))]", + "enableDefaultTelemetry": { + "value": "[variables('enableReferencedModulesTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "7585808247826533259" + }, + "name": "DBforMySQL Flexible Server Databases", + "description": "This module deploys a DBforMySQL Flexible Server Database.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the database." + } + }, + "flexibleServerName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment." + } + }, + "collation": { + "type": "string", + "defaultValue": "utf8", + "metadata": { + "description": "Optional. The collation of the database." + } + }, + "charset": { + "type": "string", + "defaultValue": "utf8_general_ci", + "metadata": { + "description": "Optional. The charset of the database." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.DBforMySQL/flexibleServers/databases", + "apiVersion": "2022-01-01", + "name": "[format('{0}/{1}', parameters('flexibleServerName'), parameters('name'))]", + "properties": { + "collation": "[if(not(empty(parameters('collation'))), parameters('collation'), null())]", + "charset": "[if(not(empty(parameters('charset'))), parameters('charset'), null())]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed database." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed database." + }, + "value": "[resourceId('Microsoft.DBforMySQL/flexibleServers/databases', parameters('flexibleServerName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed database." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "flexibleServer" + ] + }, + "flexibleServer_firewallRules": { + "copy": { + "name": "flexibleServer_firewallRules", + "count": "[length(parameters('firewallRules'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-MySQL-FirewallRules-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('firewallRules')[copyIndex()].name]" + }, + "flexibleServerName": { + "value": "[parameters('name')]" + }, + "startIpAddress": { + "value": "[parameters('firewallRules')[copyIndex()].startIpAddress]" + }, + "endIpAddress": { + "value": "[parameters('firewallRules')[copyIndex()].endIpAddress]" + }, + "enableDefaultTelemetry": { + "value": "[variables('enableReferencedModulesTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "9889972221731602451" + }, + "name": "DBforMySQL Flexible Server Firewall Rules", + "description": "This module deploys a DBforMySQL Flexible Server Firewall Rule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the MySQL flexible server Firewall Rule." + } + }, + "startIpAddress": { + "type": "string", + "metadata": { + "description": "Required. The start IP address of the firewall rule. Must be IPv4 format. Use value '0.0.0.0' for all Azure-internal IP addresses." + } + }, + "endIpAddress": { + "type": "string", + "metadata": { + "description": "Required. The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value '0.0.0.0' for all Azure-internal IP addresses." + } + }, + "flexibleServerName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.DBforMySQL/flexibleServers/firewallRules", + "apiVersion": "2022-01-01", + "name": "[format('{0}/{1}', parameters('flexibleServerName'), parameters('name'))]", + "properties": { + "endIpAddress": "[parameters('endIpAddress')]", + "startIpAddress": "[parameters('startIpAddress')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed firewall rule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed firewall rule." + }, + "value": "[resourceId('Microsoft.DBforMySQL/flexibleServers/firewallRules', parameters('flexibleServerName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed firewall rule." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "flexibleServer" + ] + }, + "flexibleServer_administrators": { + "copy": { + "name": "flexibleServer_administrators", + "count": "[length(parameters('administrators'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-MySQL-Administrators-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "flexibleServerName": { + "value": "[parameters('name')]" + }, + "login": { + "value": "[parameters('administrators')[copyIndex()].login]" + }, + "sid": { + "value": "[parameters('administrators')[copyIndex()].sid]" + }, + "identityResourceId": { + "value": "[parameters('administrators')[copyIndex()].identityResourceId]" + }, + "tenantId": "[if(contains(parameters('administrators')[copyIndex()], 'tenantId'), createObject('value', parameters('administrators')[copyIndex()].tenantId), createObject('value', tenant().tenantId))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "8863151548145849170" + }, + "name": "DBforMySQL Flexible Server Administrators", + "description": "This module deploys a DBforMySQL Flexible Server Administrator.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "flexibleServerName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent DBforMySQL flexible server. Required if the template is used in a standalone deployment." + } + }, + "sid": { + "type": "string", + "metadata": { + "description": "Required. SID (object ID) of the server administrator." + } + }, + "identityResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the identity used for AAD Authentication." + } + }, + "login": { + "type": "string", + "metadata": { + "description": "Required. Login name of the server administrator." + } + }, + "tenantId": { + "type": "string", + "defaultValue": "[tenant().tenantId]", + "metadata": { + "description": "Optional. The tenantId of the Active Directory administrator." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + { + "type": "Microsoft.DBforMySQL/flexibleServers/administrators", + "apiVersion": "2022-01-01", + "name": "[format('{0}/{1}', parameters('flexibleServerName'), 'ActiveDirectory')]", + "properties": { + "administratorType": "ActiveDirectory", + "identityResourceId": "[parameters('identityResourceId')]", + "login": "[parameters('login')]", + "sid": "[parameters('sid')]", + "tenantId": "[parameters('tenantId')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed administrator." + }, + "value": "ActiveDirectory" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed administrator." + }, + "value": "[resourceId('Microsoft.DBforMySQL/flexibleServers/administrators', parameters('flexibleServerName'), 'ActiveDirectory')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed administrator." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "flexibleServer" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed MySQL Flexible server." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed MySQL Flexible server." + }, + "value": "[resourceId('Microsoft.DBforMySQL/flexibleServers', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed MySQL Flexible server." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('flexibleServer', '2022-09-30-preview', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/flexible-server/tests/e2e/defaults/main.test.bicep b/avm/res/flexible-server/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..60b6289226 --- /dev/null +++ b/avm/res/flexible-server/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,57 @@ +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}-dbformysql.flexibleservers-${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 = 'dfmsfsmin' + +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@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: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + administratorLogin: 'adminUserName' + administratorLoginPassword: password + skuName: 'Standard_B1ms' + tier: 'Burstable' + } +}] diff --git a/avm/res/flexible-server/tests/e2e/private/dependencies.bicep b/avm/res/flexible-server/tests/e2e/private/dependencies.bicep new file mode 100644 index 0000000000..ca3c6ceec6 --- /dev/null +++ b/avm/res/flexible-server/tests/e2e/private/dependencies.bicep @@ -0,0 +1,74 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + delegations: [ + { + name: 'Microsoft.DBforMySQL.flexibleServers' + properties: { + serviceName: 'Microsoft.DBforMySQL/flexibleServers' + } + } + ] + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'private.mysql.database.azure.com' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id + +@description('The name of the created Managed Identity.') +output managedIdentityName string = managedIdentity.name + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/flexible-server/tests/e2e/private/main.test.bicep b/avm/res/flexible-server/tests/e2e/private/main.test.bicep new file mode 100644 index 0000000000..46a67b9445 --- /dev/null +++ b/avm/res/flexible-server/tests/e2e/private/main.test.bicep @@ -0,0 +1,144 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-dbformysql.flexibleservers-${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 = 'dfmsfspvt' + +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@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: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${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: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + location: resourceGroup.location + 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' + resourceType: 'MySQL Flexible Server' + serverName: '${namePrefix}${serviceShort}001' + } + administratorLogin: 'adminUserName' + administratorLoginPassword: password + skuName: 'Standard_D2ds_v4' + tier: 'GeneralPurpose' + delegatedSubnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceId: nestedDependencies.outputs.privateDNSZoneResourceId + storageAutoIoScaling: 'Enabled' + storageSizeGB: 64 + storageIOPS: 400 + backupRetentionDays: 10 + databases: [ + { + + name: 'testdb1' + } + ] + highAvailability: 'SameZone' + storageAutoGrow: 'Enabled' + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + administrators: [ + { + identityResourceId: nestedDependencies.outputs.managedIdentityResourceId + login: nestedDependencies.outputs.managedIdentityName + sid: nestedDependencies.outputs.managedIdentityPrincipalId + } + ] + } +}] diff --git a/avm/res/flexible-server/tests/e2e/public/dependencies1.bicep b/avm/res/flexible-server/tests/e2e/public/dependencies1.bicep new file mode 100644 index 0000000000..82fbab799d --- /dev/null +++ b/avm/res/flexible-server/tests/e2e/public/dependencies1.bicep @@ -0,0 +1,46 @@ +@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 + +@description('Required. The name of the Deployment Script to create to get the paired region name.') +param pairedRegionScriptName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: managedIdentityName + location: location +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${location}-${managedIdentity.id}-Reader-RoleAssignment') + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') // Reader + principalType: 'ServicePrincipal' + } +} + +resource getPairedRegionScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: pairedRegionScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '8.0' + retentionInterval: 'P1D' + arguments: '-Location \\"${location}\\"' + scriptContent: loadTextContent('../../../../../.shared/.scripts/Get-PairedRegion.ps1') + } + dependsOn: [ + roleAssignment + ] +} + +@description('The name of the paired region.') +output pairedRegionName string = getPairedRegionScript.properties.outputs.pairedRegionName diff --git a/avm/res/flexible-server/tests/e2e/public/dependencies2.bicep b/avm/res/flexible-server/tests/e2e/public/dependencies2.bicep new file mode 100644 index 0000000000..258d087ade --- /dev/null +++ b/avm/res/flexible-server/tests/e2e/public/dependencies2.bicep @@ -0,0 +1,120 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the geo backup Key Vault to create.') +param geoBackupKeyVaultName string + +@description('Required. The name of the geo backup Managed Identity to create.') +param geoBackupManagedIdentityName string + +@description('Required. The location to deploy geo backup resources to.') +param geoBackupLocation string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: managedIdentityName + location: location +} + +resource keyVault 'Microsoft.KeyVault/vaults@2023-02-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: true + softDeleteRetentionInDays: 90 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2023-02-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Reader-RoleAssignment') + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +resource geoBackupManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: geoBackupManagedIdentityName + location: geoBackupLocation +} + +resource geoBackupKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' = { + name: geoBackupKeyVaultName + location: geoBackupLocation + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: true + softDeleteRetentionInDays: 90 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2023-02-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource geoBackupKeyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${geoBackupKeyVault::key.id}-${geoBackupLocation}-${geoBackupManagedIdentity.id}-Key-Reader-RoleAssignment') + scope: geoBackupKeyVault::key + properties: { + principalId: geoBackupManagedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The name of the created encryption key.') +output keyName string = keyVault::key.name + +@description('The resource ID of the created geo backup Managed Identity.') +output geoBackupManagedIdentityResourceId string = geoBackupManagedIdentity.id + +@description('The resource ID of the created geo backup Key Vault.') +output geoBackupKeyVaultResourceId string = geoBackupKeyVault.id + +@description('The name of the created geo backup encryption key.') +output geoBackupKeyName string = geoBackupKeyVault::key.name diff --git a/avm/res/flexible-server/tests/e2e/public/main.test.bicep b/avm/res/flexible-server/tests/e2e/public/main.test.bicep new file mode 100644 index 0000000000..7f522933c1 --- /dev/null +++ b/avm/res/flexible-server/tests/e2e/public/main.test.bicep @@ -0,0 +1,179 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-dbformysql.flexibleservers-${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 = 'dfmsfsp' + +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + +@description('Generated. Used as a basis for unique resource names.') +param baseTime string = utcNow('u') + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@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 nestedDependencies1 'dependencies1.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies1' + params: { + // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) + location: location + managedIdentityName: 'dep-${namePrefix}-msi-ds-${serviceShort}' + pairedRegionScriptName: 'dep-${namePrefix}-ds-${serviceShort}' + } +} + +module nestedDependencies2 'dependencies2.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies2' + params: { + // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + geoBackupKeyVaultName: 'dep-${namePrefix}-kvp-${serviceShort}-${substring(uniqueString(baseTime), 0, 2)}' + geoBackupManagedIdentityName: 'dep-${namePrefix}-msip-${serviceShort}' + geoBackupLocation: nestedDependencies1.outputs.pairedRegionName + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${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: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + location: resourceGroup.location + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies2.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'MySQL Flexible Server' + serverName: '${namePrefix}${serviceShort}001' + } + administratorLogin: 'adminUserName' + administratorLoginPassword: password + skuName: 'Standard_D2ds_v4' + tier: 'GeneralPurpose' + storageAutoIoScaling: 'Enabled' + storageSizeGB: 32 + storageIOPS: 400 + backupRetentionDays: 20 + availabilityZone: '1' + databases: [ + { + + name: 'testdb1' + } + { + name: 'testdb2' + charset: 'ascii' + collation: 'ascii_general_ci' + } + ] + firewallRules: [ + { + endIpAddress: '0.0.0.0' + name: 'AllowAllWindowsAzureIps' + startIpAddress: '0.0.0.0' + } + { + endIpAddress: '10.10.10.10' + name: 'test-rule1' + startIpAddress: '10.10.10.1' + } + { + endIpAddress: '100.100.100.10' + name: 'test-rule2' + startIpAddress: '100.100.100.1' + } + ] + highAvailability: 'SameZone' + storageAutoGrow: 'Enabled' + version: '8.0.21' + customerManagedKey: { + keyName: nestedDependencies2.outputs.keyName + keyVaultResourceId: nestedDependencies2.outputs.keyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies2.outputs.managedIdentityResourceId + } + geoRedundantBackup: 'Enabled' + customerManagedKeyGeo: { + keyName: nestedDependencies2.outputs.geoBackupKeyName + keyVaultResourceId: nestedDependencies2.outputs.geoBackupKeyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies2.outputs.geoBackupManagedIdentityResourceId + } + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies2.outputs.managedIdentityResourceId + nestedDependencies2.outputs.geoBackupManagedIdentityResourceId + ] + } + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + } +}] diff --git a/avm/res/flexible-server/version.json b/avm/res/flexible-server/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/flexible-server/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/health-bot/health-bot/README.md b/avm/res/health-bot/health-bot/README.md new file mode 100644 index 0000000000..3b796cfb65 --- /dev/null +++ b/avm/res/health-bot/health-bot/README.md @@ -0,0 +1,516 @@ +# Azure Health Bots `[Microsoft.HealthBot/healthBots]` + +This module deploys an Azure Health Bot. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.HealthBot/healthBots` | [2022-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.HealthBot/2022-08-08/healthBots) | + +## 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:bicep/modules/health-bot.health-bot:1.0.0`. + +- [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 healthBot 'br:bicep/modules/health-bot.health-bot:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-hbhbmin' + params: { + // Required parameters + name: 'hbhbmin001' + sku: 'F0' + // Non-required parameters + enableDefaultTelemetry: '' + } +} +``` + +
+

+ +

+ +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": "hbhbmin001" + }, + "sku": { + "value": "F0" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module healthBot 'br:bicep/modules/health-bot.health-bot:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-hbhbmax' + params: { + // Required parameters + name: 'hbhbmax001' + sku: 'F0' + // Non-required parameters + enableDefaultTelemetry: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + userAssignedResourceIds: [ + '' + ] + } + 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": "hbhbmax001" + }, + "sku": { + "value": "F0" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "userAssignedResourceIds": [ + "" + ] + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module healthBot 'br:bicep/modules/health-bot.health-bot:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-hbhbwaf' + params: { + // Required parameters + name: 'hbhbwaf001' + sku: 'F0' + // Non-required parameters + enableDefaultTelemetry: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + userAssignedResourceIds: [ + '' + ] + } + 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": "hbhbwaf001" + }, + "sku": { + "value": "F0" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "userAssignedResourceIds": [ + "" + ] + } + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the resource. | +| [`sku`](#parameter-sku) | string | The name of the Azure Health Bot SKU. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | + +### Parameter: `name` + +Name of the resource. + +- Required: Yes +- Type: string + +### Parameter: `sku` + +The name of the Azure Health Bot SKU. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'C0' + 'F0' + 'S1' + ] + ``` + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### 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: `managedIdentities` + +The managed identity definition for this resource. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | + +### Parameter: `managedIdentities.userAssignedResourceIds` + +The resource ID(s) to assign to the resource. + +- Required: Yes +- Type: array + +### 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 the resource was deployed into. | +| `name` | string | The name of the health bot. | +| `resourceGroupName` | string | The resource group the health bot was deployed into. | +| `resourceId` | string | The resource ID of the health bot. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/health-bot/health-bot/main.bicep b/avm/res/health-bot/health-bot/main.bicep new file mode 100644 index 0000000000..bf0e08c90d --- /dev/null +++ b/avm/res/health-bot/health-bot/main.bicep @@ -0,0 +1,145 @@ +metadata name = 'Azure Health Bots' +metadata description = 'This module deploys an Azure Health Bot.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the resource.') +param name string + +@allowed([ + 'C0' + 'F0' + 'S1' +]) +@description('Required. The name of the Azure Health Bot SKU.') +param sku string + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@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 resource.') +param tags object? + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } + +var identity = !empty(managedIdentities) ? { + type: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource healthBot 'Microsoft.HealthBot/healthBots@2022-08-08' = { + name: name + location: location + tags: tags + identity: identity + sku: { + name: sku + } + properties: {} +} + +resource healthBot_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: healthBot +} + +resource healthBot_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(healthBot.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: healthBot +}] + +@description('The resource group the health bot was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the health bot.') +output name string = healthBot.name + +@description('The resource ID of the health bot.') +output resourceId string = healthBot.id + +@description('The location the resource was deployed into.') +output location string = healthBot.location + +// =============== // +// Definitions // +// =============== // + +type managedIdentitiesType = { + @description('Optional. The resource ID(s) to assign to the resource.') + userAssignedResourceIds: string[] +}? + +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/health-bot/health-bot/main.json b/avm/res/health-bot/health-bot/main.json new file mode 100644 index 0000000000..538d2d760a --- /dev/null +++ b/avm/res/health-bot/health-bot/main.json @@ -0,0 +1,286 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "582765600236650029" + }, + "name": "Azure Health Bots", + "description": "This module deploys an Azure Health Bot.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "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. Name of the resource." + } + }, + "sku": { + "type": "string", + "allowedValues": [ + "C0", + "F0", + "S1" + ], + "metadata": { + "description": "Required. The name of the Azure Health Bot SKU." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "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 resource." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "variables": { + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null()), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "healthBot": { + "type": "Microsoft.HealthBot/healthBots", + "apiVersion": "2022-08-08", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "sku": { + "name": "[parameters('sku')]" + }, + "properties": {} + }, + "healthBot_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.HealthBot/healthBots/{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": [ + "healthBot" + ] + }, + "healthBot_roleAssignments": { + "copy": { + "name": "healthBot_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.HealthBot/healthBots/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.HealthBot/healthBots', 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": [ + "healthBot" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the health bot was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the health bot." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the health bot." + }, + "value": "[resourceId('Microsoft.HealthBot/healthBots', parameters('name'))]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('healthBot', '2022-08-08', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..f2b46c90a3 --- /dev/null +++ b/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,50 @@ +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}-healthbot.healthbots-${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 = 'hbhbmin' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + sku: 'F0' + } +}] diff --git a/avm/res/health-bot/health-bot/tests/e2e/max/dependencies.bicep b/avm/res/health-bot/health-bot/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..539240be2b --- /dev/null +++ b/avm/res/health-bot/health-bot/tests/e2e/max/dependencies.bicep @@ -0,0 +1,16 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..d5e7889ab8 --- /dev/null +++ b/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep @@ -0,0 +1,89 @@ +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}-healthbot.healthbots-${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 = 'hbhbmax' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + 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' + } + sku: 'F0' + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + } +}] diff --git a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..539240be2b --- /dev/null +++ b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,16 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..4e5cb79986 --- /dev/null +++ b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,72 @@ +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}-healthbot.healthbots-${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 = 'hbhbwaf' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + sku: 'F0' + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + } +}] diff --git a/avm/res/health-bot/health-bot/version.json b/avm/res/health-bot/health-bot/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/health-bot/health-bot/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/net-app/net-app-account/README.md b/avm/res/net-app/net-app-account/README.md new file mode 100644 index 0000000000..c0fdd19a6e --- /dev/null +++ b/avm/res/net-app/net-app-account/README.md @@ -0,0 +1,849 @@ +# Azure NetApp Files `[Microsoft.NetApp/netAppAccounts]` + +This module deploys an Azure NetApp File. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.NetApp/netAppAccounts` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts) | +| `Microsoft.NetApp/netAppAccounts/capacityPools` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools) | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools/volumes) | + +## 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:bicep/modules/net-app.net-app-account:1.0.0`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Nfs3](#example-2-nfs3) +- [Nfs41](#example-3-nfs41) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-nanaamin' + params: { + // Required parameters + name: 'nanaamin001' + // Non-required parameters + enableDefaultTelemetry: '' + } +} +``` + +
+

+ +

+ +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": "nanaamin001" + }, + // Non-required parameters + "enableDefaultTelemetry": { + "value": "" + } + } +} +``` + +
+

+ +### Example 2: _Nfs3_ + +

+ +via Bicep module + +```bicep +module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-nanaanfs3' + params: { + // Required parameters + name: 'nanaanfs3001' + // Non-required parameters + capacityPools: [ + { + name: 'nanaanfs3-cp-001' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [ + { + exportPolicyRules: [ + { + allowedClients: '0.0.0.0/0' + nfsv3: true + nfsv41: false + ruleIndex: 1 + unixReadOnly: false + unixReadWrite: true + } + ] + name: 'nanaanfs3-vol-001' + protocolTypes: [ + 'NFSv3' + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + subnetResourceId: '' + usageThreshold: 107374182400 + } + { + name: 'nanaanfs3-vol-002' + protocolTypes: [ + 'NFSv3' + ] + subnetResourceId: '' + usageThreshold: 107374182400 + } + ] + } + { + name: 'nanaanfs3-cp-002' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [] + } + ] + enableDefaultTelemetry: '' + 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: { + Contact: 'test.user@testcompany.com' + CostCenter: '7890' + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + PurchaseOrder: '1234' + Role: 'DeploymentValidation' + ServiceName: '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": "nanaanfs3001" + }, + // Non-required parameters + "capacityPools": { + "value": [ + { + "name": "nanaanfs3-cp-001", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [ + { + "exportPolicyRules": [ + { + "allowedClients": "0.0.0.0/0", + "nfsv3": true, + "nfsv41": false, + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true + } + ], + "name": "nanaanfs3-vol-001", + "protocolTypes": [ + "NFSv3" + ], + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "subnetResourceId": "", + "usageThreshold": 107374182400 + }, + { + "name": "nanaanfs3-vol-002", + "protocolTypes": [ + "NFSv3" + ], + "subnetResourceId": "", + "usageThreshold": 107374182400 + } + ] + }, + { + "name": "nanaanfs3-cp-002", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [] + } + ] + }, + "enableDefaultTelemetry": { + "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": { + "Contact": "test.user@testcompany.com", + "CostCenter": "7890", + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "PurchaseOrder": "1234", + "Role": "DeploymentValidation", + "ServiceName": "DeploymentValidation" + } + } + } +} +``` + +
+

+ +### Example 3: _Nfs41_ + +

+ +via Bicep module + +```bicep +module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-nanaanfs41' + params: { + // Required parameters + name: 'nanaanfs41001' + // Non-required parameters + capacityPools: [ + { + name: 'nanaanfs41-cp-001' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [ + { + exportPolicyRules: [ + { + allowedClients: '0.0.0.0/0' + nfsv3: false + nfsv41: true + ruleIndex: 1 + unixReadOnly: false + unixReadWrite: true + } + ] + name: 'nanaanfs41-vol-001' + protocolTypes: [ + 'NFSv4.1' + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + subnetResourceId: '' + usageThreshold: 107374182400 + } + { + exportPolicyRules: [ + { + allowedClients: '0.0.0.0/0' + nfsv3: false + nfsv41: true + ruleIndex: 1 + unixReadOnly: false + unixReadWrite: true + } + ] + name: 'nanaanfs41-vol-002' + protocolTypes: [ + 'NFSv4.1' + ] + subnetResourceId: '' + usageThreshold: 107374182400 + } + ] + } + { + name: 'nanaanfs41-cp-002' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [] + } + ] + enableDefaultTelemetry: '' + managedIdentities: { + userAssignedResourceIds: [ + '' + ] + } + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Contact: 'test.user@testcompany.com' + CostCenter: '7890' + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + PurchaseOrder: '1234' + Role: 'DeploymentValidation' + ServiceName: '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": "nanaanfs41001" + }, + // Non-required parameters + "capacityPools": { + "value": [ + { + "name": "nanaanfs41-cp-001", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [ + { + "exportPolicyRules": [ + { + "allowedClients": "0.0.0.0/0", + "nfsv3": false, + "nfsv41": true, + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true + } + ], + "name": "nanaanfs41-vol-001", + "protocolTypes": [ + "NFSv4.1" + ], + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "subnetResourceId": "", + "usageThreshold": 107374182400 + }, + { + "exportPolicyRules": [ + { + "allowedClients": "0.0.0.0/0", + "nfsv3": false, + "nfsv41": true, + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true + } + ], + "name": "nanaanfs41-vol-002", + "protocolTypes": [ + "NFSv4.1" + ], + "subnetResourceId": "", + "usageThreshold": 107374182400 + } + ] + }, + { + "name": "nanaanfs41-cp-002", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [] + } + ] + }, + "enableDefaultTelemetry": { + "value": "" + }, + "managedIdentities": { + "value": { + "userAssignedResourceIds": [ + "" + ] + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Contact": "test.user@testcompany.com", + "CostCenter": "7890", + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "PurchaseOrder": "1234", + "Role": "DeploymentValidation", + "ServiceName": "DeploymentValidation" + } + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the NetApp account. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`capacityPools`](#parameter-capacitypools) | array | Capacity pools to create. | +| [`dnsServers`](#parameter-dnsservers) | string | Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed. | +| [`domainJoinOU`](#parameter-domainjoinou) | string | Used only if domainName is specified. LDAP Path for the Organization Unit (OU) where SMB Server machine accounts will be created (i.e. 'OU=SecondLevel,OU=FirstLevel'). | +| [`domainJoinPassword`](#parameter-domainjoinpassword) | securestring | Required if domainName is specified. Password of the user specified in domainJoinUser parameter. | +| [`domainJoinUser`](#parameter-domainjoinuser) | string | Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain. | +| [`domainName`](#parameter-domainname) | string | Fully Qualified Active Directory DNS Domain Name (e.g. 'contoso.com'). | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`smbServerNamePrefix`](#parameter-smbservernameprefix) | string | Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes. | +| [`tags`](#parameter-tags) | object | Tags for all resources. | + +### Parameter: `name` + +The name of the NetApp account. + +- Required: Yes +- Type: string + +### Parameter: `capacityPools` + +Capacity pools to create. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `dnsServers` + +Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `domainJoinOU` + +Used only if domainName is specified. LDAP Path for the Organization Unit (OU) where SMB Server machine accounts will be created (i.e. 'OU=SecondLevel,OU=FirstLevel'). + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `domainJoinPassword` + +Required if domainName is specified. Password of the user specified in domainJoinUser parameter. + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `domainJoinUser` + +Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `domainName` + +Fully Qualified Active Directory DNS Domain Name (e.g. 'contoso.com'). + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### 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: `managedIdentities` + +The managed identity definition for this resource. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | + +### Parameter: `managedIdentities.userAssignedResourceIds` + +The resource ID(s) to assign to the resource. + +- Required: Yes +- Type: array + +### 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: `smbServerNamePrefix` + +Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `tags` + +Tags for all resources. + +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the NetApp account. | +| `resourceGroupName` | string | The name of the Resource Group the NetApp account was created in. | +| `resourceId` | string | The Resource ID of the NetApp account. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/net-app/net-app-account/capacity-pool/README.md b/avm/res/net-app/net-app-account/capacity-pool/README.md new file mode 100644 index 0000000000..381674df79 --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/README.md @@ -0,0 +1,257 @@ +# Azure NetApp Files Capacity Pools `[Microsoft.NetApp/netAppAccounts/capacityPools]` + +This module deploys an Azure NetApp Files Capacity Pool. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.NetApp/netAppAccounts/capacityPools` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools) | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools/volumes) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the capacity pool. | +| [`size`](#parameter-size) | int | Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104). | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`netAppAccountName`](#parameter-netappaccountname) | string | The name of the parent NetApp account. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`coolAccess`](#parameter-coolaccess) | bool | If enabled (true) the pool can contain cool Access enabled volumes. | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`encryptionType`](#parameter-encryptiontype) | string | Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool. | +| [`location`](#parameter-location) | string | Location of the pool volume. | +| [`qosType`](#parameter-qostype) | string | The qos type of the pool. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`serviceLevel`](#parameter-servicelevel) | string | The pool service level. | +| [`tags`](#parameter-tags) | object | Tags for all resources. | +| [`volumes`](#parameter-volumes) | array | List of volumnes to create in the capacity pool. | + +### Parameter: `name` + +The name of the capacity pool. + +- Required: Yes +- Type: string + +### Parameter: `size` + +Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104). + +- Required: Yes +- Type: int + +### Parameter: `netAppAccountName` + +The name of the parent NetApp account. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `coolAccess` + +If enabled (true) the pool can contain cool Access enabled volumes. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `encryptionType` + +Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool. + +- Required: No +- Type: string +- Default: `'Single'` +- Allowed: + ```Bicep + [ + 'Double' + 'Single' + ] + ``` + +### Parameter: `location` + +Location of the pool volume. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `qosType` + +The qos type of the pool. + +- Required: No +- Type: string +- Default: `'Auto'` +- Allowed: + ```Bicep + [ + 'Auto' + 'Manual' + ] + ``` + +### 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: `serviceLevel` + +The pool service level. + +- Required: No +- Type: string +- Default: `'Standard'` +- Allowed: + ```Bicep + [ + 'Premium' + 'Standard' + 'StandardZRS' + 'Ultra' + ] + ``` + +### Parameter: `tags` + +Tags for all resources. + +- Required: No +- Type: object + +### Parameter: `volumes` + +List of volumnes to create in the capacity pool. + +- Required: No +- Type: array +- Default: `[]` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the Capacity Pool. | +| `resourceGroupName` | string | The name of the Resource Group the Capacity Pool was created in. | +| `resourceId` | string | The resource ID of the Capacity Pool. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/net-app/net-app-account/capacity-pool/main.bicep b/avm/res/net-app/net-app-account/capacity-pool/main.bicep new file mode 100644 index 0000000000..213245ba7e --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/main.bicep @@ -0,0 +1,164 @@ +metadata name = 'Azure NetApp Files Capacity Pools' +metadata description = 'This module deploys an Azure NetApp Files Capacity Pool.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment.') +param netAppAccountName string + +@description('Required. The name of the capacity pool.') +param name string + +@description('Optional. Location of the pool volume.') +param location string = resourceGroup().location + +@description('Optional. Tags for all resources.') +param tags object? + +@description('Optional. The pool service level.') +@allowed([ + 'Premium' + 'Standard' + 'StandardZRS' + 'Ultra' +]) +param serviceLevel string = 'Standard' + +@description('Required. Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104).') +param size int + +@description('Optional. The qos type of the pool.') +@allowed([ + 'Auto' + 'Manual' +]) +param qosType string = 'Auto' + +@description('Optional. List of volumnes to create in the capacity pool.') +param volumes array = [] + +@description('Optional. If enabled (true) the pool can contain cool Access enabled volumes.') +param coolAccess bool = false + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool.') +@allowed([ + 'Double' + 'Single' +]) +param encryptionType string = 'Single' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +var enableReferencedModulesTelemetry = false + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2022-11-01' existing = { + name: netAppAccountName +} + +resource capacityPool 'Microsoft.NetApp/netAppAccounts/capacityPools@2022-11-01' = { + name: name + parent: netAppAccount + location: location + tags: tags + properties: { + serviceLevel: serviceLevel + size: size + qosType: qosType + coolAccess: coolAccess + encryptionType: encryptionType + } +} + +@batchSize(1) +module capacityPool_volumes 'volume/main.bicep' = [for (volume, index) in volumes: { + name: '${deployment().name}-Vol-${index}' + params: { + netAppAccountName: netAppAccount.name + capacityPoolName: capacityPool.name + name: volume.name + location: location + serviceLevel: serviceLevel + creationToken: contains(volume, 'creationToken') ? volume.creationToken : volume.name + usageThreshold: volume.usageThreshold + protocolTypes: contains(volume, 'protocolTypes') ? volume.protocolTypes : [] + subnetResourceId: volume.subnetResourceId + exportPolicyRules: contains(volume, 'exportPolicyRules') ? volume.exportPolicyRules : [] + roleAssignments: contains(volume, 'roleAssignments') ? volume.roleAssignments : [] + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +resource capacityPool_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(capacityPool.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: capacityPool +}] + +@description('The name of the Capacity Pool.') +output name string = capacityPool.name + +@description('The resource ID of the Capacity Pool.') +output resourceId string = capacityPool.id + +@description('The name of the Resource Group the Capacity Pool was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = capacityPool.location +// =============== // +// Definitions // +// =============== // + +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/net-app/net-app-account/capacity-pool/main.json b/avm/res/net-app/net-app-account/capacity-pool/main.json new file mode 100644 index 0000000000..464a90fcd8 --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/main.json @@ -0,0 +1,609 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "15353329491336313807" + }, + "name": "Azure NetApp Files Capacity Pools", + "description": "This module deploys an Azure NetApp Files Capacity Pool.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "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": { + "netAppAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the capacity pool." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location of the pool volume." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all resources." + } + }, + "serviceLevel": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Premium", + "Standard", + "StandardZRS", + "Ultra" + ], + "metadata": { + "description": "Optional. The pool service level." + } + }, + "size": { + "type": "int", + "metadata": { + "description": "Required. Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104)." + } + }, + "qosType": { + "type": "string", + "defaultValue": "Auto", + "allowedValues": [ + "Auto", + "Manual" + ], + "metadata": { + "description": "Optional. The qos type of the pool." + } + }, + "volumes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of volumnes to create in the capacity pool." + } + }, + "coolAccess": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If enabled (true) the pool can contain cool Access enabled volumes." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "encryptionType": { + "type": "string", + "defaultValue": "Single", + "allowedValues": [ + "Double", + "Single" + ], + "metadata": { + "description": "Optional. Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "variables": { + "enableReferencedModulesTelemetry": false, + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "netAppAccount": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts", + "apiVersion": "2022-11-01", + "name": "[parameters('netAppAccountName')]" + }, + "capacityPool": { + "type": "Microsoft.NetApp/netAppAccounts/capacityPools", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "serviceLevel": "[parameters('serviceLevel')]", + "size": "[parameters('size')]", + "qosType": "[parameters('qosType')]", + "coolAccess": "[parameters('coolAccess')]", + "encryptionType": "[parameters('encryptionType')]" + }, + "dependsOn": [ + "netAppAccount" + ] + }, + "capacityPool_roleAssignments": { + "copy": { + "name": "capacityPool_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}/capacityPools/{1}', parameters('netAppAccountName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.NetApp/netAppAccounts/capacityPools', parameters('netAppAccountName'), 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": [ + "capacityPool" + ] + }, + "capacityPool_volumes": { + "copy": { + "name": "capacityPool_volumes", + "count": "[length(parameters('volumes'))]", + "mode": "serial", + "batchSize": 1 + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Vol-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "netAppAccountName": { + "value": "[parameters('netAppAccountName')]" + }, + "capacityPoolName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('volumes')[copyIndex()].name]" + }, + "location": { + "value": "[parameters('location')]" + }, + "serviceLevel": { + "value": "[parameters('serviceLevel')]" + }, + "creationToken": "[if(contains(parameters('volumes')[copyIndex()], 'creationToken'), createObject('value', parameters('volumes')[copyIndex()].creationToken), createObject('value', parameters('volumes')[copyIndex()].name))]", + "usageThreshold": { + "value": "[parameters('volumes')[copyIndex()].usageThreshold]" + }, + "protocolTypes": "[if(contains(parameters('volumes')[copyIndex()], 'protocolTypes'), createObject('value', parameters('volumes')[copyIndex()].protocolTypes), createObject('value', createArray()))]", + "subnetResourceId": { + "value": "[parameters('volumes')[copyIndex()].subnetResourceId]" + }, + "exportPolicyRules": "[if(contains(parameters('volumes')[copyIndex()], 'exportPolicyRules'), createObject('value', parameters('volumes')[copyIndex()].exportPolicyRules), createObject('value', createArray()))]", + "roleAssignments": "[if(contains(parameters('volumes')[copyIndex()], 'roleAssignments'), createObject('value', parameters('volumes')[copyIndex()].roleAssignments), createObject('value', createArray()))]", + "enableDefaultTelemetry": { + "value": "[variables('enableReferencedModulesTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "3662331312918191126" + }, + "name": "Azure NetApp Files Capacity Pool Volumes", + "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "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": { + "netAppAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment." + } + }, + "capacityPoolName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the pool volume." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location of the pool volume." + } + }, + "serviceLevel": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Premium", + "Standard", + "StandardZRS", + "Ultra" + ], + "metadata": { + "description": "Optional. The pool service level. Must match the one of the parent capacity pool." + } + }, + "creationToken": { + "type": "string", + "defaultValue": "[parameters('name')]", + "metadata": { + "description": "Optional. A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription." + } + }, + "usageThreshold": { + "type": "int", + "metadata": { + "description": "Required. Maximum storage quota allowed for a file system in bytes." + } + }, + "protocolTypes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Set of protocol types." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes." + } + }, + "exportPolicyRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Export policy rules." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "enableDefaultTelemetry": { + "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')]", + "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": { + "netAppAccount::capacityPool": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts/capacityPools", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('capacityPoolName'))]", + "dependsOn": [ + "netAppAccount" + ] + }, + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "netAppAccount": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts", + "apiVersion": "2022-11-01", + "name": "[parameters('netAppAccountName')]" + }, + "volume": { + "type": "Microsoft.NetApp/netAppAccounts/capacityPools/volumes", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "serviceLevel": "[parameters('serviceLevel')]", + "creationToken": "[parameters('creationToken')]", + "usageThreshold": "[parameters('usageThreshold')]", + "protocolTypes": "[parameters('protocolTypes')]", + "subnetId": "[parameters('subnetResourceId')]", + "exportPolicy": "[if(not(empty(parameters('exportPolicyRules'))), createObject('rules', parameters('exportPolicyRules')), null())]" + }, + "dependsOn": [ + "netAppAccount::capacityPool" + ] + }, + "volume_roleAssignments": { + "copy": { + "name": "volume_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}/capacityPools/{1}/volumes/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.NetApp/netAppAccounts/capacityPools/volumes', parameters('netAppAccountName'), parameters('capacityPoolName'), 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": [ + "volume" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the Volume." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the Volume." + }, + "value": "[resourceId('Microsoft.NetApp/netAppAccounts/capacityPools/volumes', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the Volume was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('volume', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "capacityPool", + "netAppAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the Capacity Pool." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Capacity Pool." + }, + "value": "[resourceId('Microsoft.NetApp/netAppAccounts/capacityPools', parameters('netAppAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the Capacity Pool was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('capacityPool', '2022-11-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/net-app/net-app-account/capacity-pool/version.json b/avm/res/net-app/net-app-account/capacity-pool/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/README.md b/avm/res/net-app/net-app-account/capacity-pool/volume/README.md new file mode 100644 index 0000000000..bf17feb0a2 --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/README.md @@ -0,0 +1,241 @@ +# Azure NetApp Files Capacity Pool Volumes `[Microsoft.NetApp/netAppAccounts/capacityPools/volumes]` + +This module deploys an Azure NetApp Files Capacity Pool Volume. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools/volumes) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the pool volume. | +| [`subnetResourceId`](#parameter-subnetresourceid) | string | The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes. | +| [`usageThreshold`](#parameter-usagethreshold) | int | Maximum storage quota allowed for a file system in bytes. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`capacityPoolName`](#parameter-capacitypoolname) | string | The name of the parent capacity pool. Required if the template is used in a standalone deployment. | +| [`netAppAccountName`](#parameter-netappaccountname) | string | The name of the parent NetApp account. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`creationToken`](#parameter-creationtoken) | string | A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription. | +| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`exportPolicyRules`](#parameter-exportpolicyrules) | array | Export policy rules. | +| [`location`](#parameter-location) | string | Location of the pool volume. | +| [`protocolTypes`](#parameter-protocoltypes) | array | Set of protocol types. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`serviceLevel`](#parameter-servicelevel) | string | The pool service level. Must match the one of the parent capacity pool. | + +### Parameter: `name` + +The name of the pool volume. + +- Required: Yes +- Type: string + +### Parameter: `subnetResourceId` + +The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes. + +- Required: Yes +- Type: string + +### Parameter: `usageThreshold` + +Maximum storage quota allowed for a file system in bytes. + +- Required: Yes +- Type: int + +### Parameter: `capacityPoolName` + +The name of the parent capacity pool. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `netAppAccountName` + +The name of the parent NetApp account. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `creationToken` + +A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription. + +- Required: No +- Type: string +- Default: `[parameters('name')]` + +### Parameter: `enableDefaultTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `exportPolicyRules` + +Export policy rules. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `location` + +Location of the pool volume. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `protocolTypes` + +Set of protocol types. + +- Required: No +- Type: array +- Default: `[]` + +### 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: `serviceLevel` + +The pool service level. Must match the one of the parent capacity pool. + +- Required: No +- Type: string +- Default: `'Standard'` +- Allowed: + ```Bicep + [ + 'Premium' + 'Standard' + 'StandardZRS' + 'Ultra' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the Volume. | +| `resourceGroupName` | string | The name of the Resource Group the Volume was created in. | +| `resourceId` | string | The Resource ID of the Volume. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep b/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep new file mode 100644 index 0000000000..5870382621 --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep @@ -0,0 +1,141 @@ +metadata name = 'Azure NetApp Files Capacity Pool Volumes' +metadata description = 'This module deploys an Azure NetApp Files Capacity Pool Volume.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment.') +param netAppAccountName string + +@description('Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment.') +param capacityPoolName string + +@description('Required. The name of the pool volume.') +param name string + +@description('Optional. Location of the pool volume.') +param location string = resourceGroup().location + +@description('Optional. The pool service level. Must match the one of the parent capacity pool.') +@allowed([ + 'Premium' + 'Standard' + 'StandardZRS' + 'Ultra' +]) +param serviceLevel string = 'Standard' + +@description('Optional. A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription.') +param creationToken string = name + +@description('Required. Maximum storage quota allowed for a file system in bytes.') +param usageThreshold int + +@description('Optional. Set of protocol types.') +param protocolTypes array = [] + +@description('Required. The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes.') +param subnetResourceId string + +@description('Optional. Export policy rules.') +param exportPolicyRules array = [] + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2022-11-01' existing = { + name: netAppAccountName + + resource capacityPool 'capacityPools@2022-11-01' existing = { + name: capacityPoolName + } +} + +resource volume 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes@2022-11-01' = { + name: name + parent: netAppAccount::capacityPool + location: location + properties: { + serviceLevel: serviceLevel + creationToken: creationToken + usageThreshold: usageThreshold + protocolTypes: protocolTypes + subnetId: subnetResourceId + exportPolicy: !empty(exportPolicyRules) ? { + rules: exportPolicyRules + } : null + } +} + +resource volume_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(volume.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: volume +}] + +@description('The name of the Volume.') +output name string = volume.name + +@description('The Resource ID of the Volume.') +output resourceId string = volume.id + +@description('The name of the Resource Group the Volume was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = volume.location +// =============== // +// Definitions // +// =============== // + +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/net-app/net-app-account/capacity-pool/volume/main.json b/avm/res/net-app/net-app-account/capacity-pool/volume/main.json new file mode 100644 index 0000000000..5e0f1b20ef --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/main.json @@ -0,0 +1,278 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "3662331312918191126" + }, + "name": "Azure NetApp Files Capacity Pool Volumes", + "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "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": { + "netAppAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment." + } + }, + "capacityPoolName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the pool volume." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location of the pool volume." + } + }, + "serviceLevel": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Premium", + "Standard", + "StandardZRS", + "Ultra" + ], + "metadata": { + "description": "Optional. The pool service level. Must match the one of the parent capacity pool." + } + }, + "creationToken": { + "type": "string", + "defaultValue": "[parameters('name')]", + "metadata": { + "description": "Optional. A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription." + } + }, + "usageThreshold": { + "type": "int", + "metadata": { + "description": "Required. Maximum storage quota allowed for a file system in bytes." + } + }, + "protocolTypes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Set of protocol types." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes." + } + }, + "exportPolicyRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Export policy rules." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "enableDefaultTelemetry": { + "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')]", + "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": { + "netAppAccount::capacityPool": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts/capacityPools", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('capacityPoolName'))]", + "dependsOn": [ + "netAppAccount" + ] + }, + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "netAppAccount": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts", + "apiVersion": "2022-11-01", + "name": "[parameters('netAppAccountName')]" + }, + "volume": { + "type": "Microsoft.NetApp/netAppAccounts/capacityPools/volumes", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "serviceLevel": "[parameters('serviceLevel')]", + "creationToken": "[parameters('creationToken')]", + "usageThreshold": "[parameters('usageThreshold')]", + "protocolTypes": "[parameters('protocolTypes')]", + "subnetId": "[parameters('subnetResourceId')]", + "exportPolicy": "[if(not(empty(parameters('exportPolicyRules'))), createObject('rules', parameters('exportPolicyRules')), null())]" + }, + "dependsOn": [ + "netAppAccount::capacityPool" + ] + }, + "volume_roleAssignments": { + "copy": { + "name": "volume_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}/capacityPools/{1}/volumes/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.NetApp/netAppAccounts/capacityPools/volumes', parameters('netAppAccountName'), parameters('capacityPoolName'), 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": [ + "volume" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the Volume." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the Volume." + }, + "value": "[resourceId('Microsoft.NetApp/netAppAccounts/capacityPools/volumes', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the Volume was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('volume', '2022-11-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/version.json b/avm/res/net-app/net-app-account/capacity-pool/volume/version.json new file mode 100644 index 0000000000..96236a61ba --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.4", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/net-app/net-app-account/main.bicep b/avm/res/net-app/net-app-account/main.bicep new file mode 100644 index 0000000000..2fc4c5833d --- /dev/null +++ b/avm/res/net-app/net-app-account/main.bicep @@ -0,0 +1,189 @@ +metadata name = 'Azure NetApp Files' +metadata description = 'This module deploys an Azure NetApp File.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the NetApp account.') +param name string + +@description('Optional. Fully Qualified Active Directory DNS Domain Name (e.g. \'contoso.com\').') +param domainName string = '' + +@description('Optional. Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain.') +param domainJoinUser string = '' + +@description('Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter.') +@secure() +param domainJoinPassword string = '' + +@description('Optional. Used only if domainName is specified. LDAP Path for the Organization Unit (OU) where SMB Server machine accounts will be created (i.e. \'OU=SecondLevel,OU=FirstLevel\').') +param domainJoinOU string = '' + +@description('Optional. Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed.') +param dnsServers string = '' + +@description('Optional. Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes.') +param smbServerNamePrefix string = '' + +@description('Optional. Capacity pools to create.') +param capacityPools array = [] + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Tags for all resources.') +param tags object? + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +var enableReferencedModulesTelemetry = false + +var activeDirectoryConnectionProperties = [ + { + username: !empty(domainName) ? domainJoinUser : null + password: !empty(domainName) ? domainJoinPassword : null + domain: !empty(domainName) ? domainName : null + dns: !empty(domainName) ? dnsServers : null + smbServerName: !empty(domainName) ? smbServerNamePrefix : null + organizationalUnit: !empty(domainJoinOU) ? domainJoinOU : null + } +] + +var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } + +var identity = !empty(managedIdentities) ? { + type: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2022-11-01' = { + name: name + tags: tags + identity: identity + location: location + properties: { + activeDirectories: !empty(domainName) ? activeDirectoryConnectionProperties : null + } +} + +resource netAppAccount_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: netAppAccount +} + +resource netAppAccount_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(netAppAccount.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: netAppAccount +}] + +module netAppAccount_capacityPools 'capacity-pool/main.bicep' = [for (capacityPool, index) in capacityPools: { + name: '${uniqueString(deployment().name, location)}-ANFAccount-CapPool-${index}' + params: { + netAppAccountName: netAppAccount.name + name: capacityPool.name + location: location + size: capacityPool.size + serviceLevel: contains(capacityPool, 'serviceLevel') ? capacityPool.serviceLevel : 'Standard' + qosType: contains(capacityPool, 'qosType') ? capacityPool.qosType : 'Auto' + volumes: contains(capacityPool, 'volumes') ? capacityPool.volumes : [] + coolAccess: contains(capacityPool, 'coolAccess') ? capacityPool.coolAccess : false + roleAssignments: contains(capacityPool, 'roleAssignments') ? capacityPool.roleAssignments : [] + encryptionType: contains(capacityPool, 'encryptionType') ? capacityPool.encryptionType : 'Single' + tags: capacityPool.?tags ?? tags + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +@description('The name of the NetApp account.') +output name string = netAppAccount.name + +@description('The Resource ID of the NetApp account.') +output resourceId string = netAppAccount.id + +@description('The name of the Resource Group the NetApp account was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = netAppAccount.location + +// =============== // +// Definitions // +// =============== // + +type managedIdentitiesType = { + @description('Optional. The resource ID(s) to assign to the resource.') + userAssignedResourceIds: string[] +}? + +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/net-app/net-app-account/main.json b/avm/res/net-app/net-app-account/main.json new file mode 100644 index 0000000000..862b3c67db --- /dev/null +++ b/avm/res/net-app/net-app-account/main.json @@ -0,0 +1,987 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "8081072067801758787" + }, + "name": "Azure NetApp Files", + "description": "This module deploys an Azure NetApp File.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "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 NetApp account." + } + }, + "domainName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Fully Qualified Active Directory DNS Domain Name (e.g. 'contoso.com')." + } + }, + "domainJoinUser": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain." + } + }, + "domainJoinPassword": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter." + } + }, + "domainJoinOU": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Used only if domainName is specified. LDAP Path for the Organization Unit (OU) where SMB Server machine accounts will be created (i.e. 'OU=SecondLevel,OU=FirstLevel')." + } + }, + "dnsServers": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed." + } + }, + "smbServerNamePrefix": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes." + } + }, + "capacityPools": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Capacity pools to create." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all resources." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "variables": { + "enableReferencedModulesTelemetry": false, + "activeDirectoryConnectionProperties": [ + { + "username": "[if(not(empty(parameters('domainName'))), parameters('domainJoinUser'), null())]", + "password": "[if(not(empty(parameters('domainName'))), parameters('domainJoinPassword'), null())]", + "domain": "[if(not(empty(parameters('domainName'))), parameters('domainName'), null())]", + "dns": "[if(not(empty(parameters('domainName'))), parameters('dnsServers'), null())]", + "smbServerName": "[if(not(empty(parameters('domainName'))), parameters('smbServerNamePrefix'), null())]", + "organizationalUnit": "[if(not(empty(parameters('domainJoinOU'))), parameters('domainJoinOU'), null())]" + } + ], + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null()), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "netAppAccount": { + "type": "Microsoft.NetApp/netAppAccounts", + "apiVersion": "2022-11-01", + "name": "[parameters('name')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "location": "[parameters('location')]", + "properties": { + "activeDirectories": "[if(not(empty(parameters('domainName'))), variables('activeDirectoryConnectionProperties'), null())]" + } + }, + "netAppAccount_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.NetApp/netAppAccounts/{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": [ + "netAppAccount" + ] + }, + "netAppAccount_roleAssignments": { + "copy": { + "name": "netAppAccount_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.NetApp/netAppAccounts', 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": [ + "netAppAccount" + ] + }, + "netAppAccount_capacityPools": { + "copy": { + "name": "netAppAccount_capacityPools", + "count": "[length(parameters('capacityPools'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-ANFAccount-CapPool-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "netAppAccountName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('capacityPools')[copyIndex()].name]" + }, + "location": { + "value": "[parameters('location')]" + }, + "size": { + "value": "[parameters('capacityPools')[copyIndex()].size]" + }, + "serviceLevel": "[if(contains(parameters('capacityPools')[copyIndex()], 'serviceLevel'), createObject('value', parameters('capacityPools')[copyIndex()].serviceLevel), createObject('value', 'Standard'))]", + "qosType": "[if(contains(parameters('capacityPools')[copyIndex()], 'qosType'), createObject('value', parameters('capacityPools')[copyIndex()].qosType), createObject('value', 'Auto'))]", + "volumes": "[if(contains(parameters('capacityPools')[copyIndex()], 'volumes'), createObject('value', parameters('capacityPools')[copyIndex()].volumes), createObject('value', createArray()))]", + "coolAccess": "[if(contains(parameters('capacityPools')[copyIndex()], 'coolAccess'), createObject('value', parameters('capacityPools')[copyIndex()].coolAccess), createObject('value', false()))]", + "roleAssignments": "[if(contains(parameters('capacityPools')[copyIndex()], 'roleAssignments'), createObject('value', parameters('capacityPools')[copyIndex()].roleAssignments), createObject('value', createArray()))]", + "encryptionType": "[if(contains(parameters('capacityPools')[copyIndex()], 'encryptionType'), createObject('value', parameters('capacityPools')[copyIndex()].encryptionType), createObject('value', 'Single'))]", + "tags": { + "value": "[coalesce(tryGet(parameters('capacityPools')[copyIndex()], 'tags'), parameters('tags'))]" + }, + "enableDefaultTelemetry": { + "value": "[variables('enableReferencedModulesTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "15353329491336313807" + }, + "name": "Azure NetApp Files Capacity Pools", + "description": "This module deploys an Azure NetApp Files Capacity Pool.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "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": { + "netAppAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the capacity pool." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location of the pool volume." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all resources." + } + }, + "serviceLevel": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Premium", + "Standard", + "StandardZRS", + "Ultra" + ], + "metadata": { + "description": "Optional. The pool service level." + } + }, + "size": { + "type": "int", + "metadata": { + "description": "Required. Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104)." + } + }, + "qosType": { + "type": "string", + "defaultValue": "Auto", + "allowedValues": [ + "Auto", + "Manual" + ], + "metadata": { + "description": "Optional. The qos type of the pool." + } + }, + "volumes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of volumnes to create in the capacity pool." + } + }, + "coolAccess": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If enabled (true) the pool can contain cool Access enabled volumes." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "encryptionType": { + "type": "string", + "defaultValue": "Single", + "allowedValues": [ + "Double", + "Single" + ], + "metadata": { + "description": "Optional. Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool." + } + }, + "enableDefaultTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + } + }, + "variables": { + "enableReferencedModulesTelemetry": false, + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "netAppAccount": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts", + "apiVersion": "2022-11-01", + "name": "[parameters('netAppAccountName')]" + }, + "capacityPool": { + "type": "Microsoft.NetApp/netAppAccounts/capacityPools", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "serviceLevel": "[parameters('serviceLevel')]", + "size": "[parameters('size')]", + "qosType": "[parameters('qosType')]", + "coolAccess": "[parameters('coolAccess')]", + "encryptionType": "[parameters('encryptionType')]" + }, + "dependsOn": [ + "netAppAccount" + ] + }, + "capacityPool_roleAssignments": { + "copy": { + "name": "capacityPool_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}/capacityPools/{1}', parameters('netAppAccountName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.NetApp/netAppAccounts/capacityPools', parameters('netAppAccountName'), 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": [ + "capacityPool" + ] + }, + "capacityPool_volumes": { + "copy": { + "name": "capacityPool_volumes", + "count": "[length(parameters('volumes'))]", + "mode": "serial", + "batchSize": 1 + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Vol-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "netAppAccountName": { + "value": "[parameters('netAppAccountName')]" + }, + "capacityPoolName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('volumes')[copyIndex()].name]" + }, + "location": { + "value": "[parameters('location')]" + }, + "serviceLevel": { + "value": "[parameters('serviceLevel')]" + }, + "creationToken": "[if(contains(parameters('volumes')[copyIndex()], 'creationToken'), createObject('value', parameters('volumes')[copyIndex()].creationToken), createObject('value', parameters('volumes')[copyIndex()].name))]", + "usageThreshold": { + "value": "[parameters('volumes')[copyIndex()].usageThreshold]" + }, + "protocolTypes": "[if(contains(parameters('volumes')[copyIndex()], 'protocolTypes'), createObject('value', parameters('volumes')[copyIndex()].protocolTypes), createObject('value', createArray()))]", + "subnetResourceId": { + "value": "[parameters('volumes')[copyIndex()].subnetResourceId]" + }, + "exportPolicyRules": "[if(contains(parameters('volumes')[copyIndex()], 'exportPolicyRules'), createObject('value', parameters('volumes')[copyIndex()].exportPolicyRules), createObject('value', createArray()))]", + "roleAssignments": "[if(contains(parameters('volumes')[copyIndex()], 'roleAssignments'), createObject('value', parameters('volumes')[copyIndex()].roleAssignments), createObject('value', createArray()))]", + "enableDefaultTelemetry": { + "value": "[variables('enableReferencedModulesTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "3662331312918191126" + }, + "name": "Azure NetApp Files Capacity Pool Volumes", + "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "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": { + "netAppAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment." + } + }, + "capacityPoolName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the pool volume." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location of the pool volume." + } + }, + "serviceLevel": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Premium", + "Standard", + "StandardZRS", + "Ultra" + ], + "metadata": { + "description": "Optional. The pool service level. Must match the one of the parent capacity pool." + } + }, + "creationToken": { + "type": "string", + "defaultValue": "[parameters('name')]", + "metadata": { + "description": "Optional. A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription." + } + }, + "usageThreshold": { + "type": "int", + "metadata": { + "description": "Required. Maximum storage quota allowed for a file system in bytes." + } + }, + "protocolTypes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Set of protocol types." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes." + } + }, + "exportPolicyRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Export policy rules." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "enableDefaultTelemetry": { + "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')]", + "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": { + "netAppAccount::capacityPool": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts/capacityPools", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('capacityPoolName'))]", + "dependsOn": [ + "netAppAccount" + ] + }, + "defaultTelemetry": { + "condition": "[parameters('enableDefaultTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2021-04-01", + "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, + "netAppAccount": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts", + "apiVersion": "2022-11-01", + "name": "[parameters('netAppAccountName')]" + }, + "volume": { + "type": "Microsoft.NetApp/netAppAccounts/capacityPools/volumes", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "serviceLevel": "[parameters('serviceLevel')]", + "creationToken": "[parameters('creationToken')]", + "usageThreshold": "[parameters('usageThreshold')]", + "protocolTypes": "[parameters('protocolTypes')]", + "subnetId": "[parameters('subnetResourceId')]", + "exportPolicy": "[if(not(empty(parameters('exportPolicyRules'))), createObject('rules', parameters('exportPolicyRules')), null())]" + }, + "dependsOn": [ + "netAppAccount::capacityPool" + ] + }, + "volume_roleAssignments": { + "copy": { + "name": "volume_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}/capacityPools/{1}/volumes/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.NetApp/netAppAccounts/capacityPools/volumes', parameters('netAppAccountName'), parameters('capacityPoolName'), 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": [ + "volume" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the Volume." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the Volume." + }, + "value": "[resourceId('Microsoft.NetApp/netAppAccounts/capacityPools/volumes', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the Volume was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('volume', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "capacityPool", + "netAppAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the Capacity Pool." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Capacity Pool." + }, + "value": "[resourceId('Microsoft.NetApp/netAppAccounts/capacityPools', parameters('netAppAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the Capacity Pool was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('capacityPool', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "netAppAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the NetApp account." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the NetApp account." + }, + "value": "[resourceId('Microsoft.NetApp/netAppAccounts', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the NetApp account was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('netAppAccount', '2022-11-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/net-app/net-app-account/tests/e2e/defaults/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..5a4111f482 --- /dev/null +++ b/avm/res/net-app/net-app-account/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,48 @@ +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}-netapp.netappaccounts-${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 = 'nanaamin' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + } +} diff --git a/avm/res/net-app/net-app-account/tests/e2e/nfs3/dependencies.bicep b/avm/res/net-app/net-app-account/tests/e2e/nfs3/dependencies.bicep new file mode 100644 index 0000000000..71e1d77e16 --- /dev/null +++ b/avm/res/net-app/net-app-account/tests/e2e/nfs3/dependencies.bicep @@ -0,0 +1,49 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + delegations: [ + { + name: 'netappDel' + properties: { + serviceName: 'Microsoft.Netapp/volumes' + } + } + ] + } + } + ] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep new file mode 100644 index 0000000000..dc2b95f9b3 --- /dev/null +++ b/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep @@ -0,0 +1,146 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-netapp.netappaccounts-${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 = 'nanaanfs3' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + capacityPools: [ + { + name: '${namePrefix}-${serviceShort}-cp-001' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [ + { + exportPolicyRules: [ + { + allowedClients: '0.0.0.0/0' + nfsv3: true + nfsv41: false + ruleIndex: 1 + unixReadOnly: false + unixReadWrite: true + } + ] + name: '${namePrefix}-${serviceShort}-vol-001' + protocolTypes: [ + 'NFSv3' + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + usageThreshold: 107374182400 + } + { + name: '${namePrefix}-${serviceShort}-vol-002' + protocolTypes: [ + 'NFSv3' + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + usageThreshold: 107374182400 + } + ] + } + { + name: '${namePrefix}-${serviceShort}-cp-002' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [] + } + ] + 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' + Contact: 'test.user@testcompany.com' + CostCenter: '7890' + Environment: 'Non-Prod' + PurchaseOrder: '1234' + Role: 'DeploymentValidation' + ServiceName: 'DeploymentValidation' + } + } +} diff --git a/avm/res/net-app/net-app-account/tests/e2e/nfs41/dependencies.bicep b/avm/res/net-app/net-app-account/tests/e2e/nfs41/dependencies.bicep new file mode 100644 index 0000000000..d0c6383547 --- /dev/null +++ b/avm/res/net-app/net-app-account/tests/e2e/nfs41/dependencies.bicep @@ -0,0 +1,52 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + delegations: [ + { + name: 'netappDel' + properties: { + serviceName: 'Microsoft.Netapp/volumes' + } + } + ] + } + } + ] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].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/net-app/net-app-account/tests/e2e/nfs41/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/nfs41/main.test.bicep new file mode 100644 index 0000000000..a751b084cc --- /dev/null +++ b/avm/res/net-app/net-app-account/tests/e2e/nfs41/main.test.bicep @@ -0,0 +1,157 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-netapp.netappaccounts-${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 = 'nanaanfs41' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + capacityPools: [ + { + name: '${namePrefix}-${serviceShort}-cp-001' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [ + { + exportPolicyRules: [ + { + allowedClients: '0.0.0.0/0' + nfsv3: false + nfsv41: true + ruleIndex: 1 + unixReadOnly: false + unixReadWrite: true + } + ] + name: '${namePrefix}-${serviceShort}-vol-001' + protocolTypes: [ + 'NFSv4.1' + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + usageThreshold: 107374182400 + } + { + exportPolicyRules: [ + { + allowedClients: '0.0.0.0/0' + nfsv3: false + nfsv41: true + ruleIndex: 1 + unixReadOnly: false + unixReadWrite: true + } + ] + name: '${namePrefix}-${serviceShort}-vol-002' + protocolTypes: [ + 'NFSv4.1' + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + usageThreshold: 107374182400 + } + ] + } + { + name: '${namePrefix}-${serviceShort}-cp-002' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [] + } + ] + 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' + Contact: 'test.user@testcompany.com' + CostCenter: '7890' + Environment: 'Non-Prod' + PurchaseOrder: '1234' + Role: 'DeploymentValidation' + ServiceName: 'DeploymentValidation' + } + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + } +} diff --git a/avm/res/net-app/net-app-account/version.json b/avm/res/net-app/net-app-account/version.json new file mode 100644 index 0000000000..04a0dd1a80 --- /dev/null +++ b/avm/res/net-app/net-app-account/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.5", + "pathFilters": [ + "./main.json" + ] +} From 67728d83ad23d7a930ab481e16b8fa75a8ba68e9 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 21 Dec 2023 21:38:42 +1000 Subject: [PATCH 03/33] tests --- avm/res/analysis-services/server/main.bicep | 12 ++++-- .../server/tests/e2e/defaults/main.test.bicep | 7 +--- .../server/tests/e2e/max/main.test.bicep | 8 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 5 ++- avm/res/analysis-services/server/version.json | 2 +- avm/res/backup-vault/version.json | 7 ---- avm/res/cache/redis/main.bicep | 40 +++++++++++++------ .../redis/tests/e2e/defaults/main.test.bicep | 4 +- .../cache/redis/tests/e2e/max/main.test.bicep | 8 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 7 +--- avm/res/cache/redis/version.json | 2 +- avm/res/compute/disk/main.bicep | 12 ++++-- .../disk/tests/e2e/defaults/main.test.bicep | 7 +--- .../disk/tests/e2e/image/main.test.bicep | 8 ++-- .../disk/tests/e2e/import/main.test.bicep | 8 ++-- .../disk/tests/e2e/max/main.test.bicep | 8 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 8 ++-- avm/res/compute/disk/version.json | 2 +- avm/res/compute/image/main.bicep | 12 ++++-- .../image/tests/e2e/max/main.test.bicep | 8 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 8 ++-- avm/res/compute/image/version.json | 2 +- .../tests/e2e/waf-aligned/dependencies.bicep | 2 +- avm/res/consumption/budget/main.bicep | 13 ++++-- .../budget/tests/e2e/defaults/main.test.bicep | 7 +--- .../budget/tests/e2e/max/main.test.bicep | 8 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 7 +--- avm/res/consumption/budget/version.json | 2 +- .../backup-vault/README.md | 0 .../backup-vault/backup-policy/README.md | 0 .../backup-vault/backup-policy/main.bicep | 15 ------- .../backup-vault/backup-policy/main.json | 0 .../backup-vault/main.bicep | 15 ++++--- .../backup-vault/main.json | 0 .../tests/e2e/defaults/main.test.bicep | 7 +--- .../tests/e2e/max/dependencies.bicep | 0 .../tests/e2e/max/main.test.bicep | 8 ++-- .../tests/e2e/waf-aligned/dependencies.bicep | 0 .../tests/e2e/waf-aligned/main.test.bicep | 8 ++-- .../backup-vault}/version.json | 0 .../databricks/access-connector/main.bicep | 12 ++++-- .../tests/e2e/defaults/main.test.bicep | 7 +--- .../tests/e2e/max/main.test.bicep | 7 +--- .../tests/e2e/waf-aligned/main.test.bicep | 7 +--- .../databricks/access-connector/version.json | 2 +- avm/res/databricks/workspace/main.bicep | 40 +++++++++++++------ .../tests/e2e/defaults/main.test.bicep | 7 +--- .../workspace/tests/e2e/max/main.test.bicep | 6 +-- .../tests/e2e/waf-aligned/main.test.bicep | 7 +--- avm/res/databricks/workspace/version.json | 2 +- .../flexible-server/README.md | 0 .../flexible-server/administrator/README.md | 0 .../flexible-server/administrator/main.bicep | 18 --------- .../flexible-server/administrator/main.json | 0 .../flexible-server/database/README.md | 0 .../flexible-server/database/main.bicep | 18 --------- .../flexible-server/database/main.json | 0 .../flexible-server/firewall-rule/README.md | 0 .../flexible-server/firewall-rule/main.bicep | 15 ------- .../flexible-server/firewall-rule/main.json | 0 .../flexible-server/main.bicep | 16 ++++---- .../flexible-server/main.json | 0 .../tests/e2e/defaults/main.test.bicep | 7 +--- .../tests/e2e/private/dependencies.bicep | 0 .../tests/e2e/private/main.test.bicep | 7 +--- .../tests/e2e/public/dependencies1.bicep | 0 .../tests/e2e/public/dependencies2.bicep | 0 .../tests/e2e/public/main.test.bicep | 7 +--- .../flexible-server}/version.json | 0 avm/res/flexible-server/database/version.json | 7 ---- .../firewall-rule/version.json | 7 ---- avm/res/flexible-server/version.json | 7 ---- avm/res/health-bot/health-bot/main.bicep | 12 ++++-- .../tests/e2e/defaults/main.test.bicep | 7 +--- .../health-bot/tests/e2e/max/main.test.bicep | 8 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 8 ++-- avm/res/health-bot/health-bot/version.json | 7 ---- .../net-app-account/capacity-pool/main.bicep | 13 ++++-- .../capacity-pool/volume/main.bicep | 15 ------- .../capacity-pool/volume/version.json | 7 ---- avm/res/net-app/net-app-account/main.bicep | 16 ++++---- .../tests/e2e/defaults/main.test.bicep | 7 +--- .../tests/e2e/nfs3/main.test.bicep | 8 ++-- .../tests/e2e/nfs41/main.test.bicep | 8 ++-- avm/res/net-app/net-app-account/version.json | 2 +- 85 files changed, 238 insertions(+), 363 deletions(-) delete mode 100644 avm/res/backup-vault/version.json rename avm/res/{ => data-protection}/backup-vault/README.md (100%) rename avm/res/{ => data-protection}/backup-vault/backup-policy/README.md (100%) rename avm/res/{ => data-protection}/backup-vault/backup-policy/main.bicep (66%) rename avm/res/{ => data-protection}/backup-vault/backup-policy/main.json (100%) rename avm/res/{ => data-protection}/backup-vault/main.bicep (94%) rename avm/res/{ => data-protection}/backup-vault/main.json (100%) rename avm/res/{ => data-protection}/backup-vault/tests/e2e/defaults/main.test.bicep (86%) rename avm/res/{ => data-protection}/backup-vault/tests/e2e/max/dependencies.bicep (100%) rename avm/res/{ => data-protection}/backup-vault/tests/e2e/max/main.test.bicep (95%) rename avm/res/{ => data-protection}/backup-vault/tests/e2e/waf-aligned/dependencies.bicep (100%) rename avm/res/{ => data-protection}/backup-vault/tests/e2e/waf-aligned/main.test.bicep (94%) rename avm/res/{backup-vault/backup-policy => data-protection/backup-vault}/version.json (100%) rename avm/res/{ => db-for-my-sql}/flexible-server/README.md (100%) rename avm/res/{ => db-for-my-sql}/flexible-server/administrator/README.md (100%) rename avm/res/{ => db-for-my-sql}/flexible-server/administrator/main.bicep (70%) rename avm/res/{ => db-for-my-sql}/flexible-server/administrator/main.json (100%) rename avm/res/{ => db-for-my-sql}/flexible-server/database/README.md (100%) rename avm/res/{ => db-for-my-sql}/flexible-server/database/main.bicep (66%) rename avm/res/{ => db-for-my-sql}/flexible-server/database/main.json (100%) rename avm/res/{ => db-for-my-sql}/flexible-server/firewall-rule/README.md (100%) rename avm/res/{ => db-for-my-sql}/flexible-server/firewall-rule/main.bicep (74%) rename avm/res/{ => db-for-my-sql}/flexible-server/firewall-rule/main.json (100%) rename avm/res/{ => db-for-my-sql}/flexible-server/main.bicep (97%) rename avm/res/{ => db-for-my-sql}/flexible-server/main.json (100%) rename avm/res/{ => db-for-my-sql}/flexible-server/tests/e2e/defaults/main.test.bicep (87%) rename avm/res/{ => db-for-my-sql}/flexible-server/tests/e2e/private/dependencies.bicep (100%) rename avm/res/{ => db-for-my-sql}/flexible-server/tests/e2e/private/main.test.bicep (95%) rename avm/res/{ => db-for-my-sql}/flexible-server/tests/e2e/public/dependencies1.bicep (100%) rename avm/res/{ => db-for-my-sql}/flexible-server/tests/e2e/public/dependencies2.bicep (100%) rename avm/res/{ => db-for-my-sql}/flexible-server/tests/e2e/public/main.test.bicep (96%) rename avm/res/{flexible-server/administrator => db-for-my-sql/flexible-server}/version.json (100%) delete mode 100644 avm/res/flexible-server/database/version.json delete mode 100644 avm/res/flexible-server/firewall-rule/version.json delete mode 100644 avm/res/flexible-server/version.json delete mode 100644 avm/res/health-bot/health-bot/version.json delete mode 100644 avm/res/net-app/net-app-account/capacity-pool/volume/version.json diff --git a/avm/res/analysis-services/server/main.bicep b/avm/res/analysis-services/server/main.bicep index 0d4d966a3b..9cef68c740 100644 --- a/avm/res/analysis-services/server/main.bicep +++ b/avm/res/analysis-services/server/main.bicep @@ -39,7 +39,7 @@ param roleAssignments roleAssignmentType param tags object? @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true +param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') @@ -49,14 +49,20 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.analysisservices-server.${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' + } + } } } } diff --git a/avm/res/analysis-services/server/tests/e2e/defaults/main.test.bicep b/avm/res/analysis-services/server/tests/e2e/defaults/main.test.bicep index d068d9795e..3e700be923 100644 --- a/avm/res/analysis-services/server/tests/e2e/defaults/main.test.bicep +++ b/avm/res/analysis-services/server/tests/e2e/defaults/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'assmin' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -43,7 +40,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}' + location: location } }] diff --git a/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep b/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep index 93bfb2efaa..112129c7e9 100644 --- a/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep +++ b/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'assmax' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -39,6 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -65,8 +63,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}' + location: location lock: { kind: 'CanNotDelete' name: 'myCustomLockName' diff --git a/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep b/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep index 705eaf124d..1b23d8f2fa 100644 --- a/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep @@ -21,7 +21,7 @@ param serviceShort string = 'asswaf' param enableDefaultTelemetry bool = true @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -39,6 +39,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -65,8 +66,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}' + location: location lock: { kind: 'CanNotDelete' name: 'myCustomLockName' diff --git a/avm/res/analysis-services/server/version.json b/avm/res/analysis-services/server/version.json index 96236a61ba..7fa401bdf7 100644 --- a/avm/res/analysis-services/server/version.json +++ b/avm/res/analysis-services/server/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", + "version": "0.1", "pathFilters": [ "./main.json" ] diff --git a/avm/res/backup-vault/version.json b/avm/res/backup-vault/version.json deleted file mode 100644 index 96236a61ba..0000000000 --- a/avm/res/backup-vault/version.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", - "pathFilters": [ - "./main.json" - ] -} diff --git a/avm/res/cache/redis/main.bicep b/avm/res/cache/redis/main.bicep index 4a34e577ce..12c05f9e79 100644 --- a/avm/res/cache/redis/main.bicep +++ b/avm/res/cache/redis/main.bicep @@ -103,7 +103,7 @@ param privateEndpoints privateEndpointType param diagnosticSettings diagnosticSettingType @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true +param enableTelemetry bool = true var availabilityZones = skuName == 'Premium' ? zoneRedundant ? !empty(zones) ? zones : pickZones('Microsoft.Cache', 'redis', location, 3) : [] : [] @@ -125,14 +125,20 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.cache-redis.${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' + } + } } } } @@ -212,16 +218,23 @@ resource redis_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04- scope: redis }] -module redis_privateEndpoints '../../network/private-endpoint/main.bicep' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-redis-PrivateEndpoint-${index}' +module redis_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-KeyVault-PrivateEndpoint-${index}' params: { - groupIds: [ - privateEndpoint.?service ?? 'redisCache' + privateLinkServiceConnections: [ + { + name: name + properties: { + privateLinkServiceId: redis.id + groupIds: [ + privateEndpoint.?service ?? 'redisCache' + ] + } + } ] name: privateEndpoint.?name ?? 'pep-${last(split(redis.id, '/'))}-${privateEndpoint.?service ?? 'redisCache'}-${index}' - serviceResourceId: redis.id subnetResourceId: privateEndpoint.subnetResourceId - enableDefaultTelemetry: privateEndpoint.?enableDefaultTelemetry ?? enableReferencedModulesTelemetry + enableTelemetry: enableTelemetry location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location lock: privateEndpoint.?lock ?? lock privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName @@ -304,6 +317,7 @@ type roleAssignmentType = { }[]? type privateEndpointType = { + @description('Optional. The name of the private endpoint.') name: string? @@ -316,7 +330,7 @@ type privateEndpointType = { @description('Required. Resource ID of the subnet where the endpoint needs to be created.') subnetResourceId: string - @description('Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided.') + @description('Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided.') privateDnsZoneGroupName: string? @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') @@ -324,10 +338,10 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint ip address.') + @description('Required. Fqdn that resolves to private endpoint IP address.') fqdn: string? - @description('Required. A list of private ip addresses of the private endpoint.') + @description('Required. A list of private IP addresses of the private endpoint.') ipAddresses: string[] }[]? @@ -344,7 +358,7 @@ type privateEndpointType = { @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') memberName: string - @description('Required. A private ip address obtained from the private endpoint\'s subnet.') + @description('Required. A private IP address obtained from the private endpoint\'s subnet.') privateIPAddress: string } }[]? diff --git a/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep b/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep index 4c8ef85da3..8915fc4d68 100644 --- a/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep @@ -21,7 +21,7 @@ param serviceShort string = 'crmin' param enableDefaultTelemetry bool = true @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -42,7 +42,7 @@ module testDeployment '../../../main.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location } } diff --git a/avm/res/cache/redis/tests/e2e/max/main.test.bicep b/avm/res/cache/redis/tests/e2e/max/main.test.bicep index dd1a06da7d..7d6bc990d2 100644 --- a/avm/res/cache/redis/tests/e2e/max/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/max/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'crmax' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -39,6 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' } } @@ -65,8 +63,8 @@ module testDeployment '../../../main.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location capacity: 2 diagnosticSettings: [ { diff --git a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep index 01f1338b3d..685670e6dc 100644 --- a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'crwaf' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -65,8 +62,8 @@ module testDeployment '../../../main.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location capacity: 2 diagnosticSettings: [ { diff --git a/avm/res/cache/redis/version.json b/avm/res/cache/redis/version.json index 04a0dd1a80..7fa401bdf7 100644 --- a/avm/res/cache/redis/version.json +++ b/avm/res/cache/redis/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.5", + "version": "0.1", "pathFilters": [ "./main.json" ] diff --git a/avm/res/compute/disk/main.bicep b/avm/res/compute/disk/main.bicep index 7989977bb4..d480c2f93b 100644 --- a/avm/res/compute/disk/main.bicep +++ b/avm/res/compute/disk/main.bicep @@ -128,7 +128,7 @@ param roleAssignments roleAssignmentType param tags object? @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true +param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') @@ -143,14 +143,20 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource defaultTelemetry 'Microsoft.Resources/deployments@2022-09-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' +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' + } + } } } } diff --git a/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep b/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep index 95b44f7771..e1426d150c 100644 --- a/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep @@ -17,11 +17,8 @@ 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. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -42,8 +39,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}-${serviceShort}001' + location: location sku: 'Standard_LRS' diskSizeGB: 1 } 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 67fd259073..4171d33a65 100644 --- a/avm/res/compute/disk/tests/e2e/image/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/image/main.test.bicep @@ -14,11 +14,8 @@ 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. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -36,6 +33,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -47,8 +45,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry 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' 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 0622d78455..40e4b460a8 100644 --- a/avm/res/compute/disk/tests/e2e/import/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/import/main.test.bicep @@ -14,11 +14,8 @@ 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. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -36,6 +33,7 @@ module nestedDependencies 'dependencies.bicep' = { 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' @@ -51,8 +49,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}-${serviceShort}001' + location: location sku: 'Standard_LRS' createOption: 'Import' roleAssignments: [ diff --git a/avm/res/compute/disk/tests/e2e/max/main.test.bicep b/avm/res/compute/disk/tests/e2e/max/main.test.bicep index 25ab818edd..abfb1258f5 100644 --- a/avm/res/compute/disk/tests/e2e/max/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/max/main.test.bicep @@ -17,11 +17,8 @@ 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. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -39,6 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -50,8 +48,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}-${serviceShort}001' + location: location sku: 'UltraSSD_LRS' diskIOPSReadWrite: 500 diskMBpsReadWrite: 60 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 index e22035fb5e..61bef3fa1b 100644 --- a/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep @@ -17,11 +17,8 @@ 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. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -39,6 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -50,8 +48,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}-${serviceShort}001' + location: location sku: 'UltraSSD_LRS' diskIOPSReadWrite: 500 diskMBpsReadWrite: 60 diff --git a/avm/res/compute/disk/version.json b/avm/res/compute/disk/version.json index 96236a61ba..7fa401bdf7 100644 --- a/avm/res/compute/disk/version.json +++ b/avm/res/compute/disk/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", + "version": "0.1", "pathFilters": [ "./main.json" ] diff --git a/avm/res/compute/image/main.bicep b/avm/res/compute/image/main.bicep index 20e3e6ea11..58ffde6a47 100644 --- a/avm/res/compute/image/main.bicep +++ b/avm/res/compute/image/main.bicep @@ -61,7 +61,7 @@ param snapshotResourceId string = '' param dataDisks array = [] @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true +param enableTelemetry bool = true var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') @@ -71,14 +71,20 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource defaultTelemetry 'Microsoft.Resources/deployments@2022-09-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.compute-image.${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' + } + } } } } diff --git a/avm/res/compute/image/tests/e2e/max/main.test.bicep b/avm/res/compute/image/tests/e2e/max/main.test.bicep index 4ef529aeea..214df0f600 100644 --- a/avm/res/compute/image/tests/e2e/max/main.test.bicep +++ b/avm/res/compute/image/tests/e2e/max/main.test.bicep @@ -20,11 +20,8 @@ param serviceShort string = 'cimax' @description('Generated. Used as a basis for unique resource names.') param baseTime string = utcNow('u') -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -42,6 +39,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' diskEncryptionSetName: 'dep-${namePrefix}-des-${serviceShort}' @@ -60,8 +58,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location osAccountType: 'Premium_LRS' osDiskBlobUri: nestedDependencies.outputs.vhdUri osDiskCaching: 'ReadWrite' diff --git a/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep index ee4dfe3db0..7e799c3cd6 100644 --- a/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep @@ -20,11 +20,8 @@ param serviceShort string = 'ciwaf' @description('Generated. Used as a basis for unique resource names.') param baseTime string = utcNow('u') -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -42,6 +39,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' diskEncryptionSetName: 'dep-${namePrefix}-des-${serviceShort}' @@ -60,8 +58,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location osAccountType: 'Premium_LRS' osDiskBlobUri: nestedDependencies.outputs.vhdUri osDiskCaching: 'ReadWrite' diff --git a/avm/res/compute/image/version.json b/avm/res/compute/image/version.json index 96236a61ba..7fa401bdf7 100644 --- a/avm/res/compute/image/version.json +++ b/avm/res/compute/image/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", + "version": "0.1", "pathFilters": [ "./main.json" ] diff --git a/avm/res/compute/ssh-public-key/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/ssh-public-key/tests/e2e/waf-aligned/dependencies.bicep index 5bc0b90f5f..3665ddc00e 100644 --- a/avm/res/compute/ssh-public-key/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/compute/ssh-public-key/tests/e2e/waf-aligned/dependencies.bicep @@ -20,7 +20,7 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018- // required for the deployment script to create a new temporary ssh public key object resource msi_ContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, 'ManagedIdentityContributor', '[[namePrefix]]') + name: guid(resourceGroup().id, 'ManagedIdentityContributor', '#_namePrefix_#') properties: { roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor principalId: managedIdentity.properties.principalId diff --git a/avm/res/consumption/budget/main.bicep b/avm/res/consumption/budget/main.bicep index 853e144964..99dacec5c4 100644 --- a/avm/res/consumption/budget/main.bicep +++ b/avm/res/consumption/budget/main.bicep @@ -54,7 +54,7 @@ param contactRoles array = [] param actionGroups array = [] @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true +param enableTelemetry bool = true @sys.description('Optional. Location deployment metadata.') param location string = deployment().location @@ -73,15 +73,20 @@ var notificationsArray = [for threshold in thresholds: { var notifications = json(replace(replace(replace(string(notificationsArray), '[{', '{'), '}]', '}'), '}},{', '},')) -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' - location: location +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.consumption-budget.${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' + } + } } } } diff --git a/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep b/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep index 44789640d2..a2eafa450f 100644 --- a/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep +++ b/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep @@ -10,11 +10,8 @@ metadata description = 'This instance deploys the module with the minimum set of @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 = 'cbmin' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============== // // Test Execution // @@ -24,8 +21,8 @@ param namePrefix string = '[[namePrefix]]' module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location amount: 500 contactEmails: [ 'dummy@contoso.com' diff --git a/avm/res/consumption/budget/tests/e2e/max/main.test.bicep b/avm/res/consumption/budget/tests/e2e/max/main.test.bicep index 15fa49855c..d3f12a005f 100644 --- a/avm/res/consumption/budget/tests/e2e/max/main.test.bicep +++ b/avm/res/consumption/budget/tests/e2e/max/main.test.bicep @@ -10,11 +10,11 @@ metadata description = 'This instance deploys the module with most of its featur @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 = 'cbmax' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true +@description('Optional. The location to deploy resources to.') +param location string = deployment().location @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============== // // Test Execution // @@ -24,8 +24,8 @@ param namePrefix string = '[[namePrefix]]' module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location amount: 500 contactEmails: [ 'dummy@contoso.com' diff --git a/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep b/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep index 0d2260e7d8..df44ccfad7 100644 --- a/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep @@ -10,11 +10,8 @@ metadata description = 'This instance deploys the module in alignment with the b @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 = 'cbwaf' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============== // // Test Execution // @@ -24,8 +21,8 @@ param namePrefix string = '[[namePrefix]]' module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { name: '${uniqueString(deployment().name)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location amount: 500 contactEmails: [ 'dummy@contoso.com' diff --git a/avm/res/consumption/budget/version.json b/avm/res/consumption/budget/version.json index 96236a61ba..7fa401bdf7 100644 --- a/avm/res/consumption/budget/version.json +++ b/avm/res/consumption/budget/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", + "version": "0.1", "pathFilters": [ "./main.json" ] diff --git a/avm/res/backup-vault/README.md b/avm/res/data-protection/backup-vault/README.md similarity index 100% rename from avm/res/backup-vault/README.md rename to avm/res/data-protection/backup-vault/README.md diff --git a/avm/res/backup-vault/backup-policy/README.md b/avm/res/data-protection/backup-vault/backup-policy/README.md similarity index 100% rename from avm/res/backup-vault/backup-policy/README.md rename to avm/res/data-protection/backup-vault/backup-policy/README.md diff --git a/avm/res/backup-vault/backup-policy/main.bicep b/avm/res/data-protection/backup-vault/backup-policy/main.bicep similarity index 66% rename from avm/res/backup-vault/backup-policy/main.bicep rename to avm/res/data-protection/backup-vault/backup-policy/main.bicep index b3b28ca62a..f692e60b50 100644 --- a/avm/res/backup-vault/backup-policy/main.bicep +++ b/avm/res/data-protection/backup-vault/backup-policy/main.bicep @@ -11,21 +11,6 @@ param name string = 'DefaultPolicy' @description('Optional. The properties of the backup policy.') param properties object = {} -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - resource backupVault 'Microsoft.DataProtection/backupVaults@2023-05-01' existing = { name: backupVaultName } diff --git a/avm/res/backup-vault/backup-policy/main.json b/avm/res/data-protection/backup-vault/backup-policy/main.json similarity index 100% rename from avm/res/backup-vault/backup-policy/main.json rename to avm/res/data-protection/backup-vault/backup-policy/main.json diff --git a/avm/res/backup-vault/main.bicep b/avm/res/data-protection/backup-vault/main.bicep similarity index 94% rename from avm/res/backup-vault/main.bicep rename to avm/res/data-protection/backup-vault/main.bicep index f337814938..7f76b54721 100644 --- a/avm/res/backup-vault/main.bicep +++ b/avm/res/data-protection/backup-vault/main.bicep @@ -6,7 +6,7 @@ metadata owner = 'Azure/module-maintainers' param name string @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true +param enableTelemetry bool = true @description('Optional. Location for all resources.') param location string = resourceGroup().location @@ -59,8 +59,6 @@ var identity = !empty(managedIdentities) ? { type: (managedIdentities.?systemAssigned ?? false) ? 'SystemAssigned' : null } : null -var enableReferencedModulesTelemetry = false - var builtInRoleNames = { 'Backup Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b') 'Backup Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324') @@ -72,14 +70,20 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.dataprotection-backupvault.${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' + } + } } } } @@ -112,7 +116,6 @@ module backupVault_backupPolicies 'backup-policy/main.bicep' = [for (backupPolic backupVaultName: backupVault.name name: backupPolicy.name properties: backupPolicy.properties - enableDefaultTelemetry: enableReferencedModulesTelemetry } }] diff --git a/avm/res/backup-vault/main.json b/avm/res/data-protection/backup-vault/main.json similarity index 100% rename from avm/res/backup-vault/main.json rename to avm/res/data-protection/backup-vault/main.json diff --git a/avm/res/backup-vault/tests/e2e/defaults/main.test.bicep b/avm/res/data-protection/backup-vault/tests/e2e/defaults/main.test.bicep similarity index 86% rename from avm/res/backup-vault/tests/e2e/defaults/main.test.bicep rename to avm/res/data-protection/backup-vault/tests/e2e/defaults/main.test.bicep index eb6dd485a2..87d5dbc39d 100644 --- a/avm/res/backup-vault/tests/e2e/defaults/main.test.bicep +++ b/avm/res/data-protection/backup-vault/tests/e2e/defaults/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'dpbvmin' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -43,7 +40,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location } }] diff --git a/avm/res/backup-vault/tests/e2e/max/dependencies.bicep b/avm/res/data-protection/backup-vault/tests/e2e/max/dependencies.bicep similarity index 100% rename from avm/res/backup-vault/tests/e2e/max/dependencies.bicep rename to avm/res/data-protection/backup-vault/tests/e2e/max/dependencies.bicep diff --git a/avm/res/backup-vault/tests/e2e/max/main.test.bicep b/avm/res/data-protection/backup-vault/tests/e2e/max/main.test.bicep similarity index 95% rename from avm/res/backup-vault/tests/e2e/max/main.test.bicep rename to avm/res/data-protection/backup-vault/tests/e2e/max/main.test.bicep index 588b2e0c20..0feddffd60 100644 --- a/avm/res/backup-vault/tests/e2e/max/main.test.bicep +++ b/avm/res/data-protection/backup-vault/tests/e2e/max/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'dpbvmax' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -39,6 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -51,8 +49,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location roleAssignments: [ { roleDefinitionIdOrName: 'Owner' diff --git a/avm/res/backup-vault/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/dependencies.bicep similarity index 100% rename from avm/res/backup-vault/tests/e2e/waf-aligned/dependencies.bicep rename to avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/dependencies.bicep diff --git a/avm/res/backup-vault/tests/e2e/waf-aligned/main.test.bicep b/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/main.test.bicep similarity index 94% rename from avm/res/backup-vault/tests/e2e/waf-aligned/main.test.bicep rename to avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/main.test.bicep index 1bcb119964..6caa849807 100644 --- a/avm/res/backup-vault/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'dpbvwaf' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -39,6 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -51,8 +49,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location azureMonitorAlertSettingsAlertsForAllJobFailures: 'Disabled' managedIdentities: { systemAssigned: true diff --git a/avm/res/backup-vault/backup-policy/version.json b/avm/res/data-protection/backup-vault/version.json similarity index 100% rename from avm/res/backup-vault/backup-policy/version.json rename to avm/res/data-protection/backup-vault/version.json diff --git a/avm/res/databricks/access-connector/main.bicep b/avm/res/databricks/access-connector/main.bicep index 53ba92c2c2..185995fda1 100644 --- a/avm/res/databricks/access-connector/main.bicep +++ b/avm/res/databricks/access-connector/main.bicep @@ -21,7 +21,7 @@ param lock lockType param managedIdentities managedIdentitiesType @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true +param enableTelemetry bool = true var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } @@ -38,14 +38,20 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.databricks-accessconnector.${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' + } + } } } } diff --git a/avm/res/databricks/access-connector/tests/e2e/defaults/main.test.bicep b/avm/res/databricks/access-connector/tests/e2e/defaults/main.test.bicep index 17bf07d2fc..7c2e4e1ad9 100644 --- a/avm/res/databricks/access-connector/tests/e2e/defaults/main.test.bicep +++ b/avm/res/databricks/access-connector/tests/e2e/defaults/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'dacmin' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -43,7 +40,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location } }] diff --git a/avm/res/databricks/access-connector/tests/e2e/max/main.test.bicep b/avm/res/databricks/access-connector/tests/e2e/max/main.test.bicep index 586cd17f0c..444b287771 100644 --- a/avm/res/databricks/access-connector/tests/e2e/max/main.test.bicep +++ b/avm/res/databricks/access-connector/tests/e2e/max/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'dacmax' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -39,6 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -51,7 +49,6 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' lock: { kind: 'CanNotDelete' diff --git a/avm/res/databricks/access-connector/tests/e2e/waf-aligned/main.test.bicep b/avm/res/databricks/access-connector/tests/e2e/waf-aligned/main.test.bicep index 64b4f1b6ab..a5afe4fe52 100644 --- a/avm/res/databricks/access-connector/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/databricks/access-connector/tests/e2e/waf-aligned/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'dacwaf' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -39,6 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -51,7 +49,6 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' lock: { kind: 'CanNotDelete' diff --git a/avm/res/databricks/access-connector/version.json b/avm/res/databricks/access-connector/version.json index 96236a61ba..7fa401bdf7 100644 --- a/avm/res/databricks/access-connector/version.json +++ b/avm/res/databricks/access-connector/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", + "version": "0.1", "pathFilters": [ "./main.json" ] diff --git a/avm/res/databricks/workspace/main.bicep b/avm/res/databricks/workspace/main.bicep index 0d7e6cdb19..70ce6634d2 100644 --- a/avm/res/databricks/workspace/main.bicep +++ b/avm/res/databricks/workspace/main.bicep @@ -32,7 +32,7 @@ param lock lockType param tags object? @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true +param enableTelemetry bool = true @description('Optional. The resource ID of a Virtual Network where this Databricks Cluster should be created.') param customVirtualNetworkResourceId string = '' @@ -109,14 +109,20 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.databricks-workspace.${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' + } + } } } } @@ -284,16 +290,23 @@ resource workspace_roleAssignments 'Microsoft.Authorization/roleAssignments@2022 scope: workspace }] -module workspace_privateEndpoints '../../network/private-endpoint/main.bicep' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-workspace-PrivateEndpoint-${index}' +module workspace_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-KeyVault-PrivateEndpoint-${index}' params: { - groupIds: [ - privateEndpoint.?service ?? 'databricks_ui_api' + privateLinkServiceConnections: [ + { + name: name + properties: { + privateLinkServiceId: workspace.id + groupIds: [ + privateEndpoint.?service ?? 'databricks_ui_api' + ] + } + } ] name: privateEndpoint.?name ?? 'pep-${last(split(workspace.id, '/'))}-${privateEndpoint.?service ?? 'databricks_ui_api'}-${index}' - serviceResourceId: workspace.id subnetResourceId: privateEndpoint.subnetResourceId - enableDefaultTelemetry: privateEndpoint.?enableDefaultTelemetry ?? enableReferencedModulesTelemetry + enableTelemetry: enableTelemetry location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location lock: privateEndpoint.?lock ?? lock privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName @@ -356,6 +369,7 @@ type roleAssignmentType = { }[]? type privateEndpointType = { + @description('Optional. The name of the private endpoint.') name: string? @@ -368,7 +382,7 @@ type privateEndpointType = { @description('Required. Resource ID of the subnet where the endpoint needs to be created.') subnetResourceId: string - @description('Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided.') + @description('Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided.') privateDnsZoneGroupName: string? @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') @@ -376,10 +390,10 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint ip address.') + @description('Required. Fqdn that resolves to private endpoint IP address.') fqdn: string? - @description('Required. A list of private ip addresses of the private endpoint.') + @description('Required. A list of private IP addresses of the private endpoint.') ipAddresses: string[] }[]? @@ -396,7 +410,7 @@ type privateEndpointType = { @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') memberName: string - @description('Required. A private ip address obtained from the private endpoint\'s subnet.') + @description('Required. A private IP address obtained from the private endpoint\'s subnet.') privateIPAddress: string } }[]? diff --git a/avm/res/databricks/workspace/tests/e2e/defaults/main.test.bicep b/avm/res/databricks/workspace/tests/e2e/defaults/main.test.bicep index 8c3002937e..23f5959852 100644 --- a/avm/res/databricks/workspace/tests/e2e/defaults/main.test.bicep +++ b/avm/res/databricks/workspace/tests/e2e/defaults/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'dwmin' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -43,7 +40,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location } }] diff --git a/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep b/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep index 5656e772da..f1362ed131 100644 --- a/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep +++ b/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep @@ -24,7 +24,7 @@ param enableDefaultTelemetry bool = true param baseTime string = utcNow('u') @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -42,6 +42,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location amlWorkspaceName: 'dep-${namePrefix}-aml-${serviceShort}' applicationInsightsName: 'dep-${namePrefix}-appi-${serviceShort}' loadBalancerName: 'dep-${namePrefix}-lb-${serviceShort}' @@ -77,8 +78,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location diagnosticSettings: [ { name: 'customSetting' @@ -162,6 +163,5 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' managedResourceGroupResourceId: '${subscription().id}/resourceGroups/rg-${resourceGroupName}-managed' requireInfrastructureEncryption: true vnetAddressPrefix: '10.100' - location: resourceGroup.location } }] diff --git a/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep index 66928e1121..81e79c45e9 100644 --- a/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep @@ -17,14 +17,11 @@ 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 = 'dwwaf' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Generated. Used as a basis for unique resource names.') param baseTime string = utcNow('u') @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -42,6 +39,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location amlWorkspaceName: 'dep-${namePrefix}-aml-${serviceShort}' applicationInsightsName: 'dep-${namePrefix}-appi-${serviceShort}' loadBalancerName: 'dep-${namePrefix}-lb-${serviceShort}' @@ -77,7 +75,6 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' diagnosticSettings: [ { diff --git a/avm/res/databricks/workspace/version.json b/avm/res/databricks/workspace/version.json index 96236a61ba..7fa401bdf7 100644 --- a/avm/res/databricks/workspace/version.json +++ b/avm/res/databricks/workspace/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", + "version": "0.1", "pathFilters": [ "./main.json" ] diff --git a/avm/res/flexible-server/README.md b/avm/res/db-for-my-sql/flexible-server/README.md similarity index 100% rename from avm/res/flexible-server/README.md rename to avm/res/db-for-my-sql/flexible-server/README.md diff --git a/avm/res/flexible-server/administrator/README.md b/avm/res/db-for-my-sql/flexible-server/administrator/README.md similarity index 100% rename from avm/res/flexible-server/administrator/README.md rename to avm/res/db-for-my-sql/flexible-server/administrator/README.md diff --git a/avm/res/flexible-server/administrator/main.bicep b/avm/res/db-for-my-sql/flexible-server/administrator/main.bicep similarity index 70% rename from avm/res/flexible-server/administrator/main.bicep rename to avm/res/db-for-my-sql/flexible-server/administrator/main.bicep index c5442f24ea..912d7cbdcd 100644 --- a/avm/res/flexible-server/administrator/main.bicep +++ b/avm/res/db-for-my-sql/flexible-server/administrator/main.bicep @@ -17,24 +17,6 @@ param login string @description('Optional. The tenantId of the Active Directory administrator.') param tenantId string = tenant().tenantId -@description('Optional. Location for all resources.') -param location string = resourceGroup().location - -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - resource flexibleServer 'Microsoft.DBforMySQL/flexibleServers@2022-01-01' existing = { name: flexibleServerName } diff --git a/avm/res/flexible-server/administrator/main.json b/avm/res/db-for-my-sql/flexible-server/administrator/main.json similarity index 100% rename from avm/res/flexible-server/administrator/main.json rename to avm/res/db-for-my-sql/flexible-server/administrator/main.json diff --git a/avm/res/flexible-server/database/README.md b/avm/res/db-for-my-sql/flexible-server/database/README.md similarity index 100% rename from avm/res/flexible-server/database/README.md rename to avm/res/db-for-my-sql/flexible-server/database/README.md diff --git a/avm/res/flexible-server/database/main.bicep b/avm/res/db-for-my-sql/flexible-server/database/main.bicep similarity index 66% rename from avm/res/flexible-server/database/main.bicep rename to avm/res/db-for-my-sql/flexible-server/database/main.bicep index 2c4fd62547..51fdfed6ca 100644 --- a/avm/res/flexible-server/database/main.bicep +++ b/avm/res/db-for-my-sql/flexible-server/database/main.bicep @@ -14,24 +14,6 @@ param collation string = 'utf8' @description('Optional. The charset of the database.') param charset string = 'utf8_general_ci' -@description('Optional. Location for all resources.') -param location string = resourceGroup().location - -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - -resource defaultTelemetry 'Microsoft.Resources/deployments@2022-09-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - resource flexibleServer 'Microsoft.DBforMySQL/flexibleServers@2022-09-30-preview' existing = { name: flexibleServerName } diff --git a/avm/res/flexible-server/database/main.json b/avm/res/db-for-my-sql/flexible-server/database/main.json similarity index 100% rename from avm/res/flexible-server/database/main.json rename to avm/res/db-for-my-sql/flexible-server/database/main.json diff --git a/avm/res/flexible-server/firewall-rule/README.md b/avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md similarity index 100% rename from avm/res/flexible-server/firewall-rule/README.md rename to avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md diff --git a/avm/res/flexible-server/firewall-rule/main.bicep b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.bicep similarity index 74% rename from avm/res/flexible-server/firewall-rule/main.bicep rename to avm/res/db-for-my-sql/flexible-server/firewall-rule/main.bicep index cba30a70e3..19c077118e 100644 --- a/avm/res/flexible-server/firewall-rule/main.bicep +++ b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.bicep @@ -14,21 +14,6 @@ param endIpAddress string @description('Conditional. The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment.') param flexibleServerName string -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - -resource defaultTelemetry 'Microsoft.Resources/deployments@2022-09-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - resource flexibleServer 'Microsoft.DBforMySQL/flexibleServers@2022-09-30-preview' existing = { name: flexibleServerName } diff --git a/avm/res/flexible-server/firewall-rule/main.json b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json similarity index 100% rename from avm/res/flexible-server/firewall-rule/main.json rename to avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json diff --git a/avm/res/flexible-server/main.bicep b/avm/res/db-for-my-sql/flexible-server/main.bicep similarity index 97% rename from avm/res/flexible-server/main.bicep rename to avm/res/db-for-my-sql/flexible-server/main.bicep index d89c29094a..6946247e4c 100644 --- a/avm/res/flexible-server/main.bicep +++ b/avm/res/db-for-my-sql/flexible-server/main.bicep @@ -160,7 +160,7 @@ param roleAssignments roleAssignmentType param diagnosticSettings diagnosticSettingType @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true +param enableTelemetry bool = true var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } @@ -169,8 +169,6 @@ var identity = !empty(managedIdentities) ? { userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null -var enableReferencedModulesTelemetry = false - var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') 'MySQL Backup And Export Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd18ad5f3-1baf-4119-b49b-d944edb1f9d0') @@ -180,14 +178,20 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource defaultTelemetry 'Microsoft.Resources/deployments@2022-09-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.dbformysql-flexibleserver.${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' + } + } } } } @@ -302,7 +306,6 @@ module flexibleServer_databases 'database/main.bicep' = [for (database, index) i flexibleServerName: flexibleServer.name collation: contains(database, 'collation') ? database.collation : '' charset: contains(database, 'charset') ? database.charset : '' - enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -313,7 +316,6 @@ module flexibleServer_firewallRules 'firewall-rule/main.bicep' = [for (firewallR flexibleServerName: flexibleServer.name startIpAddress: firewallRule.startIpAddress endIpAddress: firewallRule.endIpAddress - enableDefaultTelemetry: enableReferencedModulesTelemetry } }] diff --git a/avm/res/flexible-server/main.json b/avm/res/db-for-my-sql/flexible-server/main.json similarity index 100% rename from avm/res/flexible-server/main.json rename to avm/res/db-for-my-sql/flexible-server/main.json diff --git a/avm/res/flexible-server/tests/e2e/defaults/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/defaults/main.test.bicep similarity index 87% rename from avm/res/flexible-server/tests/e2e/defaults/main.test.bicep rename to avm/res/db-for-my-sql/flexible-server/tests/e2e/defaults/main.test.bicep index 60b6289226..b4091bfc11 100644 --- a/avm/res/flexible-server/tests/e2e/defaults/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/defaults/main.test.bicep @@ -21,11 +21,8 @@ param serviceShort string = 'dfmsfsmin' @secure() param password string = newGuid() -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -47,8 +44,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location administratorLogin: 'adminUserName' administratorLoginPassword: password skuName: 'Standard_B1ms' diff --git a/avm/res/flexible-server/tests/e2e/private/dependencies.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/dependencies.bicep similarity index 100% rename from avm/res/flexible-server/tests/e2e/private/dependencies.bicep rename to avm/res/db-for-my-sql/flexible-server/tests/e2e/private/dependencies.bicep diff --git a/avm/res/flexible-server/tests/e2e/private/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep similarity index 95% rename from avm/res/flexible-server/tests/e2e/private/main.test.bicep rename to avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep index 46a67b9445..e65e9bc580 100644 --- a/avm/res/flexible-server/tests/e2e/private/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep @@ -18,11 +18,8 @@ param serviceShort string = 'dfmsfspvt' @secure() param password string = newGuid() -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -41,6 +38,7 @@ module nestedDependencies 'dependencies.bicep' = { params: { virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -67,7 +65,6 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' location: resourceGroup.location lock: { diff --git a/avm/res/flexible-server/tests/e2e/public/dependencies1.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/dependencies1.bicep similarity index 100% rename from avm/res/flexible-server/tests/e2e/public/dependencies1.bicep rename to avm/res/db-for-my-sql/flexible-server/tests/e2e/public/dependencies1.bicep diff --git a/avm/res/flexible-server/tests/e2e/public/dependencies2.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/dependencies2.bicep similarity index 100% rename from avm/res/flexible-server/tests/e2e/public/dependencies2.bicep rename to avm/res/db-for-my-sql/flexible-server/tests/e2e/public/dependencies2.bicep diff --git a/avm/res/flexible-server/tests/e2e/public/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/main.test.bicep similarity index 96% rename from avm/res/flexible-server/tests/e2e/public/main.test.bicep rename to avm/res/db-for-my-sql/flexible-server/tests/e2e/public/main.test.bicep index 7f522933c1..986ae6bf7d 100644 --- a/avm/res/flexible-server/tests/e2e/public/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/main.test.bicep @@ -21,11 +21,8 @@ param password string = newGuid() @description('Generated. Used as a basis for unique resource names.') param baseTime string = utcNow('u') -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -56,6 +53,7 @@ module nestedDependencies2 'dependencies2.bicep' = { // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location geoBackupKeyVaultName: 'dep-${namePrefix}-kvp-${serviceShort}-${substring(uniqueString(baseTime), 0, 2)}' geoBackupManagedIdentityName: 'dep-${namePrefix}-msip-${serviceShort}' geoBackupLocation: nestedDependencies1.outputs.pairedRegionName @@ -85,7 +83,6 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' location: resourceGroup.location lock: { diff --git a/avm/res/flexible-server/administrator/version.json b/avm/res/db-for-my-sql/flexible-server/version.json similarity index 100% rename from avm/res/flexible-server/administrator/version.json rename to avm/res/db-for-my-sql/flexible-server/version.json diff --git a/avm/res/flexible-server/database/version.json b/avm/res/flexible-server/database/version.json deleted file mode 100644 index 96236a61ba..0000000000 --- a/avm/res/flexible-server/database/version.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", - "pathFilters": [ - "./main.json" - ] -} diff --git a/avm/res/flexible-server/firewall-rule/version.json b/avm/res/flexible-server/firewall-rule/version.json deleted file mode 100644 index 96236a61ba..0000000000 --- a/avm/res/flexible-server/firewall-rule/version.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", - "pathFilters": [ - "./main.json" - ] -} diff --git a/avm/res/flexible-server/version.json b/avm/res/flexible-server/version.json deleted file mode 100644 index 96236a61ba..0000000000 --- a/avm/res/flexible-server/version.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", - "pathFilters": [ - "./main.json" - ] -} diff --git a/avm/res/health-bot/health-bot/main.bicep b/avm/res/health-bot/health-bot/main.bicep index bf0e08c90d..6d77c9d03a 100644 --- a/avm/res/health-bot/health-bot/main.bicep +++ b/avm/res/health-bot/health-bot/main.bicep @@ -29,7 +29,7 @@ param roleAssignments roleAssignmentType param tags object? @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true +param enableTelemetry bool = true var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } @@ -46,14 +46,20 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.healthbot-healthbot.${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' + } + } } } } diff --git a/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep index f2b46c90a3..27295dc34e 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'hbhbmin' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -43,8 +40,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location sku: 'F0' } }] diff --git a/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep index d5e7889ab8..21051fd516 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'hbhbmax' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -39,6 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -51,8 +49,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location lock: { kind: 'CanNotDelete' name: 'myCustomLockName' diff --git a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep index 4e5cb79986..0b84c6a96c 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'hbhbwaf' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -39,6 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -51,8 +49,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location lock: { kind: 'CanNotDelete' name: 'myCustomLockName' diff --git a/avm/res/health-bot/health-bot/version.json b/avm/res/health-bot/health-bot/version.json deleted file mode 100644 index 96236a61ba..0000000000 --- a/avm/res/health-bot/health-bot/version.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", - "pathFilters": [ - "./main.json" - ] -} diff --git a/avm/res/net-app/net-app-account/capacity-pool/main.bicep b/avm/res/net-app/net-app-account/capacity-pool/main.bicep index 213245ba7e..ba9c73ac8f 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/main.bicep +++ b/avm/res/net-app/net-app-account/capacity-pool/main.bicep @@ -50,7 +50,7 @@ param roleAssignments roleAssignmentType param encryptionType string = 'Single' @description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true +param enableTelemetry bool = true var enableReferencedModulesTelemetry = false @@ -62,14 +62,20 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.netapp-netappaccount.${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' + } + } } } } @@ -107,7 +113,6 @@ module capacityPool_volumes 'volume/main.bicep' = [for (volume, index) in volume subnetResourceId: volume.subnetResourceId exportPolicyRules: contains(volume, 'exportPolicyRules') ? volume.exportPolicyRules : [] roleAssignments: contains(volume, 'roleAssignments') ? volume.roleAssignments : [] - enableDefaultTelemetry: enableReferencedModulesTelemetry } }] diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep b/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep index 5870382621..c34b9485a6 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep @@ -41,9 +41,6 @@ param exportPolicyRules array = [] @description('Optional. Array of role assignments to create.') param roleAssignments roleAssignmentType -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') @@ -52,18 +49,6 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2022-11-01' existing = { name: netAppAccountName diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/version.json b/avm/res/net-app/net-app-account/capacity-pool/volume/version.json deleted file mode 100644 index 96236a61ba..0000000000 --- a/avm/res/net-app/net-app-account/capacity-pool/volume/version.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", - "pathFilters": [ - "./main.json" - ] -} diff --git a/avm/res/net-app/net-app-account/main.bicep b/avm/res/net-app/net-app-account/main.bicep index 2fc4c5833d..3c06547974 100644 --- a/avm/res/net-app/net-app-account/main.bicep +++ b/avm/res/net-app/net-app-account/main.bicep @@ -42,11 +42,6 @@ param lock lockType @description('Optional. Tags for all resources.') param tags object? -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - -var enableReferencedModulesTelemetry = false - var activeDirectoryConnectionProperties = [ { username: !empty(domainName) ? domainJoinUser : null @@ -73,14 +68,20 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.network-networksecuritygroup.${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' + } + } } } } @@ -132,7 +133,6 @@ module netAppAccount_capacityPools 'capacity-pool/main.bicep' = [for (capacityPo roleAssignments: contains(capacityPool, 'roleAssignments') ? capacityPool.roleAssignments : [] encryptionType: contains(capacityPool, 'encryptionType') ? capacityPool.encryptionType : 'Single' tags: capacityPool.?tags ?? tags - enableDefaultTelemetry: enableReferencedModulesTelemetry } }] diff --git a/avm/res/net-app/net-app-account/tests/e2e/defaults/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/defaults/main.test.bicep index 5a4111f482..58aa75474c 100644 --- a/avm/res/net-app/net-app-account/tests/e2e/defaults/main.test.bicep +++ b/avm/res/net-app/net-app-account/tests/e2e/defaults/main.test.bicep @@ -17,11 +17,8 @@ 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 = 'nanaamin' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -42,7 +39,7 @@ module testDeployment '../../../main.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location } } diff --git a/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep index dc2b95f9b3..26b4c9e122 100644 --- a/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep +++ b/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep @@ -14,11 +14,8 @@ 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 = 'nanaanfs3' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -37,6 +34,7 @@ module nestedDependencies 'dependencies.bicep' = { params: { virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -48,8 +46,8 @@ module testDeployment '../../../main.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location capacityPools: [ { name: '${namePrefix}-${serviceShort}-cp-001' diff --git a/avm/res/net-app/net-app-account/tests/e2e/nfs41/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/nfs41/main.test.bicep index a751b084cc..8298ddd89e 100644 --- a/avm/res/net-app/net-app-account/tests/e2e/nfs41/main.test.bicep +++ b/avm/res/net-app/net-app-account/tests/e2e/nfs41/main.test.bicep @@ -14,11 +14,8 @@ 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 = 'nanaanfs41' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // @@ -37,6 +34,7 @@ module nestedDependencies 'dependencies.bicep' = { params: { virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location } } @@ -48,8 +46,8 @@ module testDeployment '../../../main.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' params: { - enableDefaultTelemetry: enableDefaultTelemetry name: '${namePrefix}${serviceShort}001' + location: location capacityPools: [ { name: '${namePrefix}-${serviceShort}-cp-001' diff --git a/avm/res/net-app/net-app-account/version.json b/avm/res/net-app/net-app-account/version.json index 04a0dd1a80..7fa401bdf7 100644 --- a/avm/res/net-app/net-app-account/version.json +++ b/avm/res/net-app/net-app-account/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.5", + "version": "0.1", "pathFilters": [ "./main.json" ] From 9ce10c625f4da59f029aab53b97a80b2813a7126 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 21 Dec 2023 21:44:10 +1000 Subject: [PATCH 04/33] diagnosticdependencies --- .../server/tests/e2e/max/main.test.bicep | 2 +- .../tests/e2e/waf-aligned/dependencies.bicep | 13 ------------- .../server/tests/e2e/waf-aligned/main.test.bicep | 14 +------------- avm/res/cache/redis/tests/e2e/max/main.test.bicep | 2 +- .../redis/tests/e2e/waf-aligned/main.test.bicep | 3 ++- .../workspace/tests/e2e/max/main.test.bicep | 2 +- .../tests/e2e/waf-aligned/main.test.bicep | 2 +- .../tests/e2e/private/main.test.bicep | 2 +- .../tests/e2e/public/main.test.bicep | 2 +- 9 files changed, 9 insertions(+), 33 deletions(-) delete mode 100644 avm/res/analysis-services/server/tests/e2e/waf-aligned/dependencies.bicep diff --git a/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep b/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep index 112129c7e9..671e861ae2 100644 --- a/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep +++ b/avm/res/analysis-services/server/tests/e2e/max/main.test.bicep @@ -42,7 +42,7 @@ module nestedDependencies 'dependencies.bicep' = { // Diagnostics // =========== -module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' params: { diff --git a/avm/res/analysis-services/server/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/analysis-services/server/tests/e2e/waf-aligned/dependencies.bicep deleted file mode 100644 index 29b9641692..0000000000 --- a/avm/res/analysis-services/server/tests/e2e/waf-aligned/dependencies.bicep +++ /dev/null @@ -1,13 +0,0 @@ -@description('Required. The name of the managed identity to create.') -param managedIdentityName string - -@description('Optional. The location to deploy resources to.') -param location string = resourceGroup().location - -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/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep b/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep index 1b23d8f2fa..a088a94b8f 100644 --- a/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/analysis-services/server/tests/e2e/waf-aligned/main.test.bicep @@ -17,9 +17,6 @@ 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 = 'asswaf' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' @@ -34,18 +31,9 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { location: location } -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - location: location - } -} - // Diagnostics // =========== -module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' params: { diff --git a/avm/res/cache/redis/tests/e2e/max/main.test.bicep b/avm/res/cache/redis/tests/e2e/max/main.test.bicep index 7d6bc990d2..0a8d75a182 100644 --- a/avm/res/cache/redis/tests/e2e/max/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/max/main.test.bicep @@ -43,7 +43,7 @@ module nestedDependencies 'dependencies.bicep' = { // Diagnostics // =========== -module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' params: { diff --git a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep index 685670e6dc..c55ed0f5df 100644 --- a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep @@ -36,13 +36,14 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' } } // Diagnostics // =========== -module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' params: { diff --git a/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep b/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep index f1362ed131..32738144a8 100644 --- a/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep +++ b/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep @@ -57,7 +57,7 @@ module nestedDependencies 'dependencies.bicep' = { // Diagnostics // =========== -module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' params: { diff --git a/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep b/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep index 81e79c45e9..8060b63d58 100644 --- a/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/databricks/workspace/tests/e2e/waf-aligned/main.test.bicep @@ -54,7 +54,7 @@ module nestedDependencies 'dependencies.bicep' = { // Diagnostics // =========== -module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' params: { diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep index e65e9bc580..15ae96eed1 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep @@ -44,7 +44,7 @@ module nestedDependencies 'dependencies.bicep' = { // Diagnostics // =========== -module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' params: { diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/main.test.bicep index 986ae6bf7d..99cce59bb3 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/main.test.bicep @@ -62,7 +62,7 @@ module nestedDependencies2 'dependencies2.bicep' = { // Diagnostics // =========== -module diagnosticDependencies '../../../../../.shared/.templates/diagnostic.dependencies.bicep' = { +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' params: { From 71e7a5c138fe364ad43c1a422f873d19b82a9589 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 21 Dec 2023 22:02:06 +1000 Subject: [PATCH 05/33] finishing touches --- avm/res/analysis-services/server/README.md | 34 +-- avm/res/analysis-services/server/main.json | 20 +- avm/res/cache/redis/README.md | 50 ++-- avm/res/cache/redis/main.bicep | 2 - avm/res/cache/redis/main.json | 223 +++++++++++------- avm/res/compute/disk/README.md | 48 ++-- avm/res/compute/disk/main.json | 20 +- avm/res/compute/image/README.md | 74 ++++-- avm/res/compute/image/main.json | 20 +- .../image/tests/e2e/defaults/main.test.bicep | 45 ++++ avm/res/consumption/budget/README.md | 44 ++-- avm/res/consumption/budget/main.json | 19 +- .../data-protection/backup-vault/README.md | 30 +-- .../data-protection/backup-vault/main.json | 47 ++-- avm/res/databricks/access-connector/README.md | 26 +- avm/res/databricks/access-connector/main.json | 20 +- avm/res/databricks/workspace/README.md | 32 +-- avm/res/databricks/workspace/main.bicep | 2 - avm/res/databricks/workspace/main.json | 223 +++++++++++------- .../db-for-my-sql/flexible-server/README.md | 64 +++-- .../db-for-my-sql/flexible-server/main.json | 112 ++------- .../tests/e2e/waf-aligned/main.test.bicep | 45 ++++ avm/res/health-bot/health-bot/README.md | 30 +-- avm/res/health-bot/health-bot/main.json | 20 +- avm/res/health-bot/health-bot/version.json | 7 + avm/res/net-app/net-app-account/README.md | 68 ++++-- .../net-app-account/capacity-pool/main.bicep | 23 -- .../capacity-pool/version.json | 7 - avm/res/net-app/net-app-account/main.bicep | 5 +- avm/res/net-app/net-app-account/main.json | 76 ++---- .../tests/e2e/waf-aligned/main.test.bicep | 45 ++++ 31 files changed, 839 insertions(+), 642 deletions(-) create mode 100644 avm/res/compute/image/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/health-bot/health-bot/version.json delete mode 100644 avm/res/net-app/net-app-account/capacity-pool/version.json create mode 100644 avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep diff --git a/avm/res/analysis-services/server/README.md b/avm/res/analysis-services/server/README.md index e98e2db197..5869c1db46 100644 --- a/avm/res/analysis-services/server/README.md +++ b/avm/res/analysis-services/server/README.md @@ -25,7 +25,7 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/analysis-services.server:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/analysis-services/server:`. - [Using only defaults](#example-1-using-only-defaults) - [Using large parameter set](#example-2-using-large-parameter-set) @@ -41,13 +41,13 @@ This instance deploys the module with the minimum set of required parameters.

via Bicep module ```bicep -module server 'br:bicep/modules/analysis-services.server:1.0.0' = { +module server 'br/public:avm/res/analysis-services/server:' = { name: '${uniqueString(deployment().name, location)}-test-assmin' params: { // Required parameters name: 'assmin' // Non-required parameters - enableDefaultTelemetry: '' + location: '' } } ``` @@ -69,8 +69,8 @@ module server 'br:bicep/modules/analysis-services.server:1.0.0' = { "value": "assmin" }, // Non-required parameters - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" } } } @@ -89,7 +89,7 @@ This instance deploys the module with most of its features enabled. via Bicep module ```bicep -module server 'br:bicep/modules/analysis-services.server:1.0.0' = { +module server 'br/public:avm/res/analysis-services/server:' = { name: '${uniqueString(deployment().name, location)}-test-assmax' params: { // Required parameters @@ -117,7 +117,6 @@ module server 'br:bicep/modules/analysis-services.server:1.0.0' = { workspaceResourceId: '' } ] - enableDefaultTelemetry: '' firewallSettings: { enablePowerBIService: true firewallRules: [ @@ -128,6 +127,7 @@ module server 'br:bicep/modules/analysis-services.server:1.0.0' = { } ] } + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -201,9 +201,6 @@ module server 'br:bicep/modules/analysis-services.server:1.0.0' = { } ] }, - "enableDefaultTelemetry": { - "value": "" - }, "firewallSettings": { "value": { "enablePowerBIService": true, @@ -216,6 +213,9 @@ module server 'br:bicep/modules/analysis-services.server:1.0.0' = { ] } }, + "location": { + "value": "" + }, "lock": { "value": { "kind": "CanNotDelete", @@ -271,7 +271,7 @@ This instance deploys the module in alignment with the best-practices of the Azu via Bicep module ```bicep -module server 'br:bicep/modules/analysis-services.server:1.0.0' = { +module server 'br/public:avm/res/analysis-services/server:' = { name: '${uniqueString(deployment().name, location)}-test-asswaf' params: { // Required parameters @@ -299,7 +299,6 @@ module server 'br:bicep/modules/analysis-services.server:1.0.0' = { workspaceResourceId: '' } ] - enableDefaultTelemetry: '' firewallSettings: { enablePowerBIService: true firewallRules: [ @@ -310,6 +309,7 @@ module server 'br:bicep/modules/analysis-services.server:1.0.0' = { } ] } + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -366,9 +366,6 @@ module server 'br:bicep/modules/analysis-services.server:1.0.0' = { } ] }, - "enableDefaultTelemetry": { - "value": "" - }, "firewallSettings": { "value": { "enablePowerBIService": true, @@ -381,6 +378,9 @@ module server 'br:bicep/modules/analysis-services.server:1.0.0' = { ] } }, + "location": { + "value": "" + }, "lock": { "value": { "kind": "CanNotDelete", @@ -421,7 +421,7 @@ module server 'br:bicep/modules/analysis-services.server:1.0.0' = { | Parameter | Type | Description | | :-- | :-- | :-- | | [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`firewallSettings`](#parameter-firewallsettings) | object | The inbound firewall rules to define on the server. If not specified, firewall is disabled. | | [`location`](#parameter-location) | string | Location for all Resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | @@ -528,7 +528,7 @@ Resource ID of the diagnostic log analytics workspace. For security reasons, it - Required: No - Type: string -### Parameter: `enableDefaultTelemetry` +### Parameter: `enableTelemetry` Enable telemetry via a Globally Unique Identifier (GUID). diff --git a/avm/res/analysis-services/server/main.json b/avm/res/analysis-services/server/main.json index b3e4158662..e050279221 100644 --- a/avm/res/analysis-services/server/main.json +++ b/avm/res/analysis-services/server/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "1605417065240868452" + "templateHash": "15153643486811668197" }, "name": "Analysis Services Servers", "description": "This module deploys an Analysis Services Server.", @@ -280,7 +280,7 @@ "description": "Optional. Tags of the resource." } }, - "enableDefaultTelemetry": { + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -298,17 +298,23 @@ } }, "resources": { - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.analysisservices-server.{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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, diff --git a/avm/res/cache/redis/README.md b/avm/res/cache/redis/README.md index 5f026c7c76..e28143dc71 100644 --- a/avm/res/cache/redis/README.md +++ b/avm/res/cache/redis/README.md @@ -28,7 +28,7 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/cache.redis:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/cache/redis:`. - [Using only defaults](#example-1-using-only-defaults) - [Using large parameter set](#example-2-using-large-parameter-set) @@ -44,13 +44,13 @@ This instance deploys the module with the minimum set of required parameters. via Bicep module ```bicep -module redis 'br:bicep/modules/cache.redis:1.0.0' = { +module redis 'br/public:avm/res/cache/redis:' = { name: '${uniqueString(deployment().name, location)}-test-crmin' params: { // Required parameters name: 'crmin001' // Non-required parameters - enableDefaultTelemetry: '' + location: '' } } ``` @@ -72,8 +72,8 @@ module redis 'br:bicep/modules/cache.redis:1.0.0' = { "value": "crmin001" }, // Non-required parameters - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" } } } @@ -92,7 +92,7 @@ This instance deploys the module with most of its features enabled. via Bicep module ```bicep -module redis 'br:bicep/modules/cache.redis:1.0.0' = { +module redis 'br/public:avm/res/cache/redis:' = { name: '${uniqueString(deployment().name, location)}-test-crmax' params: { // Required parameters @@ -113,8 +113,8 @@ module redis 'br:bicep/modules/cache.redis:1.0.0' = { workspaceResourceId: '' } ] - enableDefaultTelemetry: '' enableNonSslPort: true + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -192,12 +192,12 @@ module redis 'br:bicep/modules/cache.redis:1.0.0' = { } ] }, - "enableDefaultTelemetry": { - "value": "" - }, "enableNonSslPort": { "value": true }, + "location": { + "value": "" + }, "lock": { "value": { "kind": "CanNotDelete", @@ -274,7 +274,7 @@ This instance deploys the module in alignment with the best-practices of the Azu via Bicep module ```bicep -module redis 'br:bicep/modules/cache.redis:1.0.0' = { +module redis 'br/public:avm/res/cache/redis:' = { name: '${uniqueString(deployment().name, location)}-test-crwaf' params: { // Required parameters @@ -295,8 +295,8 @@ module redis 'br:bicep/modules/cache.redis:1.0.0' = { workspaceResourceId: '' } ] - enableDefaultTelemetry: '' enableNonSslPort: true + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -374,12 +374,12 @@ module redis 'br:bicep/modules/cache.redis:1.0.0' = { } ] }, - "enableDefaultTelemetry": { - "value": "" - }, "enableNonSslPort": { "value": true }, + "location": { + "value": "" + }, "lock": { "value": { "kind": "CanNotDelete", @@ -461,8 +461,8 @@ module redis 'br:bicep/modules/cache.redis:1.0.0' = { | :-- | :-- | :-- | | [`capacity`](#parameter-capacity) | int | The size of the Redis cache to deploy. Valid values: for C (Basic/Standard) family (0, 1, 2, 3, 4, 5, 6), for P (Premium) family (1, 2, 3, 4). | | [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`enableNonSslPort`](#parameter-enablenonsslport) | bool | Specifies whether the non-ssl Redis server port (6379) is enabled. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`location`](#parameter-location) | string | The location to deploy the Redis cache service. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | @@ -601,21 +601,21 @@ Resource ID of the diagnostic log analytics workspace. For security reasons, it - Required: No - Type: string -### Parameter: `enableDefaultTelemetry` +### Parameter: `enableNonSslPort` -Enable telemetry via a Globally Unique Identifier (GUID). +Specifies whether the non-ssl Redis server port (6379) is enabled. - Required: No - Type: bool -- Default: `True` +- Default: `False` -### Parameter: `enableNonSslPort` +### Parameter: `enableTelemetry` -Specifies whether the non-ssl Redis server port (6379) is enabled. +Enable telemetry via a Globally Unique Identifier (GUID). - Required: No - Type: bool -- Default: `False` +- Default: `True` ### Parameter: `location` @@ -731,7 +731,7 @@ Configuration details for private endpoints. For security reasons, it is recomme | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | | [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | | [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | -| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. | +| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. | | [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | array | The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | | [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | @@ -838,7 +838,7 @@ The name of the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroupName` -The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. +The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. - Required: No - Type: string @@ -1188,7 +1188,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `modules/network/private-endpoint` | Local reference | +| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | ## Notes diff --git a/avm/res/cache/redis/main.bicep b/avm/res/cache/redis/main.bicep index 12c05f9e79..2e5a8ea4cb 100644 --- a/avm/res/cache/redis/main.bicep +++ b/avm/res/cache/redis/main.bicep @@ -114,8 +114,6 @@ var identity = !empty(managedIdentities) ? { userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null } : null -var enableReferencedModulesTelemetry = false - var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') diff --git a/avm/res/cache/redis/main.json b/avm/res/cache/redis/main.json index 90b5617b8a..9b1b223441 100644 --- a/avm/res/cache/redis/main.json +++ b/avm/res/cache/redis/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "10455754336377427456" + "templateHash": "12006824777124262825" }, "name": "Redis Cache", "description": "This module deploys a Redis Cache.", @@ -163,7 +163,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided." + "description": "Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided." } }, "privateDnsZoneResourceIds": { @@ -185,7 +185,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." + "description": "Required. Fqdn that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -194,7 +194,7 @@ "type": "string" }, "metadata": { - "description": "Required. A list of private ip addresses of the private endpoint." + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -233,7 +233,7 @@ "privateIPAddress": { "type": "string", "metadata": { - "description": "Required. A private ip address obtained from the private endpoint's subnet." + "description": "Required. A private IP address obtained from the private endpoint's subnet." } } }, @@ -596,7 +596,7 @@ "description": "Optional. The diagnostic settings of the service." } }, - "enableDefaultTelemetry": { + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -608,7 +608,6 @@ "availabilityZones": "[if(equals(parameters('skuName'), 'Premium'), if(parameters('zoneRedundant'), if(not(empty(parameters('zones'))), parameters('zones'), pickZones('Microsoft.Cache', 'redis', parameters('location'), 3)), createArray()), createArray())]", "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null())), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", - "enableReferencedModulesTelemetry": false, "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", @@ -619,17 +618,23 @@ } }, "resources": { - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.cache-redis.{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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, @@ -726,29 +731,34 @@ }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-redis-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "name": "[format('{0}-KeyVault-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", "properties": { "expressionEvaluationOptions": { "scope": "inner" }, "mode": "Incremental", "parameters": { - "groupIds": { + "privateLinkServiceConnections": { "value": [ - "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'redisCache')]" + { + "name": "[parameters('name')]", + "properties": { + "privateLinkServiceId": "[resourceId('Microsoft.Cache/redis', parameters('name'))]", + "groupIds": [ + "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'redisCache')]" + ] + } + } ] }, "name": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Cache/redis', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'redisCache'), copyIndex()))]" }, - "serviceResourceId": { - "value": "[resourceId('Microsoft.Cache/redis', parameters('name'))]" - }, "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, - "enableDefaultTelemetry": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableDefaultTelemetry'), variables('enableReferencedModulesTelemetry'))]" + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" }, "location": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" @@ -792,7 +802,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "6873008238043407177" + "templateHash": "2821141217598568122" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -807,7 +817,7 @@ "roleDefinitionIdOrName": { "type": "string", "metadata": { - "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + "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": { @@ -931,6 +941,89 @@ }, "nullable": true }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, "customDnsConfigType": { "type": "array", "items": { @@ -969,12 +1062,6 @@ "description": "Required. Resource ID of the subnet where the endpoint needs to be created." } }, - "serviceResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the resource that needs to be connected to the network." - } - }, "applicationSecurityGroupResourceIds": { "type": "array", "nullable": true, @@ -991,17 +1078,10 @@ }, "ipConfigurations": { "$ref": "#/definitions/ipConfigurationsType", - "nullable": true, "metadata": { "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." } }, - "groupIds": { - "type": "array", - "metadata": { - "description": "Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to." - } - }, "privateDnsZoneGroupName": { "type": "string", "nullable": true, @@ -1032,7 +1112,7 @@ "roleAssignments": { "$ref": "#/definitions/roleAssignmentType", "metadata": { - "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + "description": "Optional. Array of role assignments to create." } }, "tags": { @@ -1044,19 +1124,23 @@ }, "customDnsConfigs": { "$ref": "#/definitions/customDnsConfigType", - "nullable": true, "metadata": { "description": "Optional. Custom DNS configurations." } }, "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." } }, - "enableDefaultTelemetry": { + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -1065,7 +1149,6 @@ } }, "variables": { - "enableReferencedModulesTelemetry": false, "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", @@ -1080,17 +1163,23 @@ } }, "resources": { - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), 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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, @@ -1110,19 +1199,11 @@ } } ], - "customDnsConfigs": "[parameters('customDnsConfigs')]", + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", - "privateLinkServiceConnections": [ - { - "name": "[parameters('name')]", - "properties": { - "privateLinkServiceId": "[parameters('serviceResourceId')]", - "groupIds": "[parameters('groupIds')]" - } - } - ], + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", "subnet": { "id": "[parameters('subnetResourceId')]" } @@ -1152,7 +1233,7 @@ "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', 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], coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "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')]", @@ -1183,9 +1264,6 @@ }, "privateEndpointName": { "value": "[parameters('name')]" - }, - "enableDefaultTelemetry": { - "value": "[variables('enableReferencedModulesTelemetry')]" } }, "template": { @@ -1195,7 +1273,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "17578977753131828304" + "templateHash": "18168683629401652671" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", @@ -1222,13 +1300,6 @@ "metadata": { "description": "Optional. The name of the private DNS zone group." } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } } }, "variables": { @@ -1246,20 +1317,6 @@ ] }, "resources": [ - { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, { "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", "apiVersion": "2023-04-01", diff --git a/avm/res/compute/disk/README.md b/avm/res/compute/disk/README.md index 3bc00fac1b..6aa74cfad5 100644 --- a/avm/res/compute/disk/README.md +++ b/avm/res/compute/disk/README.md @@ -24,7 +24,7 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/compute.disk:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/compute/disk:`. - [Using only defaults](#example-1-using-only-defaults) - [Image](#example-2-image) @@ -42,7 +42,7 @@ This instance deploys the module with the minimum set of required parameters. via Bicep module ```bicep -module disk 'br:bicep/modules/compute.disk:1.0.0' = { +module disk 'br/public:avm/res/compute/disk:' = { name: '${uniqueString(deployment().name, location)}-test-cdmin' params: { // Required parameters @@ -50,7 +50,7 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { sku: 'Standard_LRS' // Non-required parameters diskSizeGB: 1 - enableDefaultTelemetry: '' + location: '' } } ``` @@ -78,8 +78,8 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { "diskSizeGB": { "value": 1 }, - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" } } } @@ -95,7 +95,7 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { via Bicep module ```bicep -module disk 'br:bicep/modules/compute.disk:1.0.0' = { +module disk 'br/public:avm/res/compute/disk:' = { name: '${uniqueString(deployment().name, location)}-test-cdimg' params: { // Required parameters @@ -103,8 +103,8 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { sku: 'Standard_LRS' // Non-required parameters createOption: 'FromImage' - enableDefaultTelemetry: '' imageReferenceId: '' + location: '' roleAssignments: [ { principalId: '' @@ -154,12 +154,12 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { "createOption": { "value": "FromImage" }, - "enableDefaultTelemetry": { - "value": "" - }, "imageReferenceId": { "value": "" }, + "location": { + "value": "" + }, "roleAssignments": { "value": [ { @@ -200,7 +200,7 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { via Bicep module ```bicep -module disk 'br:bicep/modules/compute.disk:1.0.0' = { +module disk 'br/public:avm/res/compute/disk:' = { name: '${uniqueString(deployment().name, location)}-test-cdimp' params: { // Required parameters @@ -208,7 +208,7 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { sku: 'Standard_LRS' // Non-required parameters createOption: 'Import' - enableDefaultTelemetry: '' + location: '' roleAssignments: [ { principalId: '' @@ -260,8 +260,8 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { "createOption": { "value": "Import" }, - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" }, "roleAssignments": { "value": [ @@ -312,7 +312,7 @@ This instance deploys the module with most of its features enabled. via Bicep module ```bicep -module disk 'br:bicep/modules/compute.disk:1.0.0' = { +module disk 'br/public:avm/res/compute/disk:' = { name: '${uniqueString(deployment().name, location)}-test-cdmax' params: { // Required parameters @@ -322,7 +322,7 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { diskIOPSReadWrite: 500 diskMBpsReadWrite: 60 diskSizeGB: 128 - enableDefaultTelemetry: '' + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -385,8 +385,8 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { "diskSizeGB": { "value": 128 }, - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" }, "lock": { "value": { @@ -446,7 +446,7 @@ This instance deploys the module in alignment with the best-practices of the Azu via Bicep module ```bicep -module disk 'br:bicep/modules/compute.disk:1.0.0' = { +module disk 'br/public:avm/res/compute/disk:' = { name: '${uniqueString(deployment().name, location)}-test-cdwaf' params: { // Required parameters @@ -456,7 +456,7 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { diskIOPSReadWrite: 500 diskMBpsReadWrite: 60 diskSizeGB: 128 - enableDefaultTelemetry: '' + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -502,8 +502,8 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { "diskSizeGB": { "value": 128 }, - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" }, "lock": { "value": { @@ -562,7 +562,7 @@ module disk 'br:bicep/modules/compute.disk:1.0.0' = { | [`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. | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`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. | @@ -701,7 +701,7 @@ The bandwidth allowed for this disk; only settable for UltraSSD disks. - Type: int - Default: `0` -### Parameter: `enableDefaultTelemetry` +### Parameter: `enableTelemetry` Enable telemetry via a Globally Unique Identifier (GUID). diff --git a/avm/res/compute/disk/main.json b/avm/res/compute/disk/main.json index 37e7361de7..741308dfc3 100644 --- a/avm/res/compute/disk/main.json +++ b/avm/res/compute/disk/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "8419179965275134660" + "templateHash": "8431673418740300927" }, "name": "Compute Disks", "description": "This module deploys a Compute Disk", @@ -335,7 +335,7 @@ "description": "Optional. Tags of the availability set resource." } }, - "enableDefaultTelemetry": { + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -358,17 +358,23 @@ } }, "resources": { - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, diff --git a/avm/res/compute/image/README.md b/avm/res/compute/image/README.md index dbfd145add..33c5fc43dc 100644 --- a/avm/res/compute/image/README.md +++ b/avm/res/compute/image/README.md @@ -23,22 +23,57 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/compute.image:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/compute/image:`. -- [Using large parameter set](#example-1-using-large-parameter-set) -- [WAF-aligned](#example-2-waf-aligned) +- [Defaults](#example-1-defaults) +- [Max](#example-2-max) +- [Waf-Aligned](#example-3-waf-aligned) -### Example 1: _Using large parameter set_ +### Example 1: _Defaults_ -This instance deploys the module with most of its features enabled. +
+ +via Bicep module + +```bicep +module image 'br/public:avm/res/compute/image:' = { + name: '${uniqueString(deployment().name, location)}-test-cidef' + params: { + name: 'cidef001' + } +} +``` + +
+

+ +

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

+ +### Example 2: _Max_

via Bicep module ```bicep -module image 'br:bicep/modules/compute.image:1.0.0' = { +module image 'br/public:avm/res/compute/image:' = { name: '${uniqueString(deployment().name, location)}-test-cimax' params: { // Required parameters @@ -50,8 +85,8 @@ module image 'br:bicep/modules/compute.image:1.0.0' = { // Non-required parameters diskEncryptionSetResourceId: '' diskSizeGB: 128 - enableDefaultTelemetry: '' hyperVGeneration: 'V1' + location: '' osState: 'Generalized' roleAssignments: [ { @@ -115,12 +150,12 @@ module image 'br:bicep/modules/compute.image:1.0.0' = { "diskSizeGB": { "value": 128 }, - "enableDefaultTelemetry": { - "value": "" - }, "hyperVGeneration": { "value": "V1" }, + "location": { + "value": "" + }, "osState": { "value": "Generalized" }, @@ -160,17 +195,14 @@ module image 'br:bicep/modules/compute.image:1.0.0' = {

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

via Bicep module ```bicep -module image 'br:bicep/modules/compute.image:1.0.0' = { +module image 'br/public:avm/res/compute/image:' = { name: '${uniqueString(deployment().name, location)}-test-ciwaf' params: { // Required parameters @@ -182,8 +214,8 @@ module image 'br:bicep/modules/compute.image:1.0.0' = { // Non-required parameters diskEncryptionSetResourceId: '' diskSizeGB: 128 - enableDefaultTelemetry: '' hyperVGeneration: 'V1' + location: '' osState: 'Generalized' tags: { 'hidden-title': 'This is visible in the resource name' @@ -230,12 +262,12 @@ module image 'br:bicep/modules/compute.image:1.0.0' = { "diskSizeGB": { "value": 128 }, - "enableDefaultTelemetry": { - "value": "" - }, "hyperVGeneration": { "value": "V1" }, + "location": { + "value": "" + }, "osState": { "value": "Generalized" }, @@ -274,7 +306,7 @@ module image 'br:bicep/modules/compute.image:1.0.0' = { | [`dataDisks`](#parameter-datadisks) | array | Specifies the parameters that are used to add a data disk to a virtual machine. | | [`diskEncryptionSetResourceId`](#parameter-diskencryptionsetresourceid) | string | Specifies the customer managed disk encryption set resource ID for the managed image disk. | | [`diskSizeGB`](#parameter-disksizegb) | int | Specifies the size of empty data disks in gigabytes. This element can be used to overwrite the name of the disk in a virtual machine image. This value cannot be larger than 1023 GB. | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`extendedLocation`](#parameter-extendedlocation) | object | The extended location of the Image. | | [`hyperVGeneration`](#parameter-hypervgeneration) | string | Gets the HyperVGenerationType of the VirtualMachine created from the image. - V1 or V2. | | [`location`](#parameter-location) | string | Location for all resources. | @@ -333,7 +365,7 @@ Specifies the size of empty data disks in gigabytes. This element can be used to - Type: int - Default: `128` -### Parameter: `enableDefaultTelemetry` +### Parameter: `enableTelemetry` Enable telemetry via a Globally Unique Identifier (GUID). diff --git a/avm/res/compute/image/main.json b/avm/res/compute/image/main.json index b3099a9dec..3bc9aec995 100644 --- a/avm/res/compute/image/main.json +++ b/avm/res/compute/image/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "6473488393825855372" + "templateHash": "9039111988355192698" }, "name": "Images", "description": "This module deploys a Compute Image.", @@ -205,7 +205,7 @@ "description": "Optional. Specifies the parameters that are used to add a data disk to a virtual machine." } }, - "enableDefaultTelemetry": { + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -223,17 +223,23 @@ } }, "resources": { - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.compute-image.{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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, diff --git a/avm/res/compute/image/tests/e2e/defaults/main.test.bicep b/avm/res/compute/image/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..655aa61422 --- /dev/null +++ b/avm/res/compute/image/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,45 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +// e.g., for a module 'network/private-endpoint' you could use 'dep-dev-network.privateendpoints-${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}---${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.') +// e.g., for a module 'network/private-endpoint' you could use 'npe' as a prefix and then 'waf' as a suffix for the waf-aligned test +param serviceShort string = 'cidef' + +@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: 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: { + // You parameters go here + name: '${namePrefix}${serviceShort}001' + } +}] diff --git a/avm/res/consumption/budget/README.md b/avm/res/consumption/budget/README.md index 27a7dbedeb..6e955e668b 100644 --- a/avm/res/consumption/budget/README.md +++ b/avm/res/consumption/budget/README.md @@ -22,23 +22,20 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/consumption.budget:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/consumption/budget:`. -- [Using only defaults](#example-1-using-only-defaults) +- [Defaults](#example-1-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. +- [Waf-Aligned](#example-3-waf-aligned) +### Example 1: _Defaults_
via Bicep module ```bicep -module budget 'br:bicep/modules/consumption.budget:1.0.0' = { +module budget 'br/public:avm/res/consumption/budget:' = { name: '${uniqueString(deployment().name)}-test-cbmin' params: { // Required parameters @@ -48,7 +45,7 @@ module budget 'br:bicep/modules/consumption.budget:1.0.0' = { contactEmails: [ 'dummy@contoso.com' ] - enableDefaultTelemetry: '' + location: '' } } ``` @@ -78,8 +75,8 @@ module budget 'br:bicep/modules/consumption.budget:1.0.0' = { "dummy@contoso.com" ] }, - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" } } } @@ -98,7 +95,7 @@ This instance deploys the module with most of its features enabled. via Bicep module ```bicep -module budget 'br:bicep/modules/consumption.budget:1.0.0' = { +module budget 'br/public:avm/res/consumption/budget:' = { name: '${uniqueString(deployment().name)}-test-cbmax' params: { // Required parameters @@ -108,7 +105,7 @@ module budget 'br:bicep/modules/consumption.budget:1.0.0' = { contactEmails: [ 'dummy@contoso.com' ] - enableDefaultTelemetry: '' + location: '' thresholds: [ 50 75 @@ -145,8 +142,8 @@ module budget 'br:bicep/modules/consumption.budget:1.0.0' = { "dummy@contoso.com" ] }, - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" }, "thresholds": { "value": [ @@ -164,17 +161,14 @@ module budget 'br:bicep/modules/consumption.budget:1.0.0' = {

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

via Bicep module ```bicep -module budget 'br:bicep/modules/consumption.budget:1.0.0' = { +module budget 'br/public:avm/res/consumption/budget:' = { name: '${uniqueString(deployment().name)}-test-cbwaf' params: { // Required parameters @@ -184,7 +178,7 @@ module budget 'br:bicep/modules/consumption.budget:1.0.0' = { contactEmails: [ 'dummy@contoso.com' ] - enableDefaultTelemetry: '' + location: '' thresholds: [ 50 75 @@ -221,8 +215,8 @@ module budget 'br:bicep/modules/consumption.budget:1.0.0' = { "dummy@contoso.com" ] }, - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" }, "thresholds": { "value": [ @@ -263,7 +257,7 @@ module budget 'br:bicep/modules/consumption.budget:1.0.0' = { | Parameter | Type | Description | | :-- | :-- | :-- | | [`category`](#parameter-category) | string | The category of the budget, whether the budget tracks cost or usage. | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`endDate`](#parameter-enddate) | string | The end date for the budget. If not provided, it will default to 10 years from the start date. | | [`location`](#parameter-location) | string | Location deployment metadata. | | [`resetPeriod`](#parameter-resetperiod) | string | The time covered by a budget. Tracking of the amount will be reset based on the time grain. BillingMonth, BillingQuarter, and BillingAnnual are only supported by WD customers. | @@ -323,7 +317,7 @@ The category of the budget, whether the budget tracks cost or usage. ] ``` -### Parameter: `enableDefaultTelemetry` +### Parameter: `enableTelemetry` Enable telemetry via a Globally Unique Identifier (GUID). diff --git a/avm/res/consumption/budget/main.json b/avm/res/consumption/budget/main.json index 31a5523934..8d5f9ea8f9 100644 --- a/avm/res/consumption/budget/main.json +++ b/avm/res/consumption/budget/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "10861664842554589267" + "templateHash": "6182258303963233923" }, "name": "Consumption Budgets", "description": "This module deploys a Consumption Budget for Subscriptions.", @@ -99,7 +99,7 @@ "description": "Conditional. List of action group resource IDs that will receive the alert. Required if neither `contactEmails` nor `contactEmails` was provided." } }, - "enableDefaultTelemetry": { + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -136,17 +136,22 @@ }, "resources": [ { - "condition": "[parameters('enableDefaultTelemetry')]", + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", - "location": "[parameters('location')]", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.consumption-budget.{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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, diff --git a/avm/res/data-protection/backup-vault/README.md b/avm/res/data-protection/backup-vault/README.md index 3744f13387..a463e0cbe5 100644 --- a/avm/res/data-protection/backup-vault/README.md +++ b/avm/res/data-protection/backup-vault/README.md @@ -26,7 +26,7 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/data-protection.backup-vault:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/data-protection/backup-vault:`. - [Using only defaults](#example-1-using-only-defaults) - [Using large parameter set](#example-2-using-large-parameter-set) @@ -42,13 +42,13 @@ This instance deploys the module with the minimum set of required parameters. via Bicep module ```bicep -module backupVault 'br:bicep/modules/data-protection.backup-vault:1.0.0' = { +module backupVault 'br/public:avm/res/data-protection/backup-vault:' = { name: '${uniqueString(deployment().name, location)}-test-dpbvmin' params: { // Required parameters name: 'dpbvmin001' // Non-required parameters - enableDefaultTelemetry: '' + location: '' } } ``` @@ -70,8 +70,8 @@ module backupVault 'br:bicep/modules/data-protection.backup-vault:1.0.0' = { "value": "dpbvmin001" }, // Non-required parameters - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" } } } @@ -90,7 +90,7 @@ This instance deploys the module with most of its features enabled. via Bicep module ```bicep -module backupVault 'br:bicep/modules/data-protection.backup-vault:1.0.0' = { +module backupVault 'br/public:avm/res/data-protection/backup-vault:' = { name: '${uniqueString(deployment().name, location)}-test-dpbvmax' params: { // Required parameters @@ -159,7 +159,7 @@ module backupVault 'br:bicep/modules/data-protection.backup-vault:1.0.0' = { } } ] - enableDefaultTelemetry: '' + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -277,8 +277,8 @@ module backupVault 'br:bicep/modules/data-protection.backup-vault:1.0.0' = { } ] }, - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" }, "lock": { "value": { @@ -334,7 +334,7 @@ This instance deploys the module in alignment with the best-practices of the Azu via Bicep module ```bicep -module backupVault 'br:bicep/modules/data-protection.backup-vault:1.0.0' = { +module backupVault 'br/public:avm/res/data-protection/backup-vault:' = { name: '${uniqueString(deployment().name, location)}-test-dpbvwaf' params: { // Required parameters @@ -403,7 +403,7 @@ module backupVault 'br:bicep/modules/data-protection.backup-vault:1.0.0' = { } } ] - enableDefaultTelemetry: '' + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -504,8 +504,8 @@ module backupVault 'br:bicep/modules/data-protection.backup-vault:1.0.0' = { } ] }, - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" }, "lock": { "value": { @@ -548,7 +548,7 @@ module backupVault 'br:bicep/modules/data-protection.backup-vault:1.0.0' = { | [`azureMonitorAlertSettingsAlertsForAllJobFailures`](#parameter-azuremonitoralertsettingsalertsforalljobfailures) | string | Settings for Azure Monitor based alerts for job failures. | | [`backupPolicies`](#parameter-backuppolicies) | array | List of all backup policies. | | [`dataStoreType`](#parameter-datastoretype) | string | The datastore type to use. ArchiveStore does not support ZoneRedundancy. | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`featureSettings`](#parameter-featuresettings) | object | Feature settings for the backup vault. | | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | @@ -604,7 +604,7 @@ The datastore type to use. ArchiveStore does not support ZoneRedundancy. ] ``` -### Parameter: `enableDefaultTelemetry` +### Parameter: `enableTelemetry` Enable telemetry via a Globally Unique Identifier (GUID). diff --git a/avm/res/data-protection/backup-vault/main.json b/avm/res/data-protection/backup-vault/main.json index 487583bb38..c5e0f0f727 100644 --- a/avm/res/data-protection/backup-vault/main.json +++ b/avm/res/data-protection/backup-vault/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "11737453267233569722" + "templateHash": "6830132536079831372" }, "name": "Data Protection Backup Vaults", "description": "This module deploys a Data Protection Backup Vault.", @@ -125,7 +125,7 @@ "description": "Required. Name of the Backup Vault." } }, - "enableDefaultTelemetry": { + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -223,7 +223,6 @@ }, "variables": { "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), 'SystemAssigned', null())), null())]", - "enableReferencedModulesTelemetry": false, "builtInRoleNames": { "Backup Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e467623-bb1f-42f4-a55d-6e525e11384b')]", "Backup Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00c29273-979b-4161-815c-10b084fb9324')]", @@ -236,17 +235,23 @@ } }, "resources": { - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.dataprotection-backupvault.{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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, @@ -331,9 +336,6 @@ }, "properties": { "value": "[parameters('backupPolicies')[copyIndex()].properties]" - }, - "enableDefaultTelemetry": { - "value": "[variables('enableReferencedModulesTelemetry')]" } }, "template": { @@ -343,7 +345,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "3378438498887899064" + "templateHash": "9679092928668541836" }, "name": "Data Protection Backup Vault Backup Policies", "description": "This module deploys a Data Protection Backup Vault Backup Policy.", @@ -369,30 +371,9 @@ "metadata": { "description": "Optional. The properties of the backup policy." } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "resources": [ - { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, { "type": "Microsoft.DataProtection/backupVaults/backupPolicies", "apiVersion": "2023-05-01", diff --git a/avm/res/databricks/access-connector/README.md b/avm/res/databricks/access-connector/README.md index ba68a44a37..bc1f487b71 100644 --- a/avm/res/databricks/access-connector/README.md +++ b/avm/res/databricks/access-connector/README.md @@ -24,7 +24,7 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/databricks.access-connector:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/databricks/access-connector:`. - [Using only defaults](#example-1-using-only-defaults) - [Using large parameter set](#example-2-using-large-parameter-set) @@ -40,13 +40,13 @@ This instance deploys the module with the minimum set of required parameters. via Bicep module ```bicep -module accessConnector 'br:bicep/modules/databricks.access-connector:1.0.0' = { +module accessConnector 'br/public:avm/res/databricks/access-connector:' = { name: '${uniqueString(deployment().name, location)}-test-dacmin' params: { // Required parameters name: 'dacmin001' // Non-required parameters - enableDefaultTelemetry: '' + location: '' } } ``` @@ -68,8 +68,8 @@ module accessConnector 'br:bicep/modules/databricks.access-connector:1.0.0' = { "value": "dacmin001" }, // Non-required parameters - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" } } } @@ -88,13 +88,12 @@ This instance deploys the module with most of its features enabled. via Bicep module ```bicep -module accessConnector 'br:bicep/modules/databricks.access-connector:1.0.0' = { +module accessConnector 'br/public:avm/res/databricks/access-connector:' = { name: '${uniqueString(deployment().name, location)}-test-dacmax' params: { // Required parameters name: 'dacmax001' // Non-required parameters - enableDefaultTelemetry: '' location: '' lock: { kind: 'CanNotDelete' @@ -149,9 +148,6 @@ module accessConnector 'br:bicep/modules/databricks.access-connector:1.0.0' = { "value": "dacmax001" }, // Non-required parameters - "enableDefaultTelemetry": { - "value": "" - }, "location": { "value": "" }, @@ -212,13 +208,12 @@ This instance deploys the module in alignment with the best-practices of the Azu via Bicep module ```bicep -module accessConnector 'br:bicep/modules/databricks.access-connector:1.0.0' = { +module accessConnector 'br/public:avm/res/databricks/access-connector:' = { name: '${uniqueString(deployment().name, location)}-test-dacwaf' params: { // Required parameters name: 'dacwaf001' // Non-required parameters - enableDefaultTelemetry: '' location: '' lock: { kind: 'CanNotDelete' @@ -256,9 +251,6 @@ module accessConnector 'br:bicep/modules/databricks.access-connector:1.0.0' = { "value": "dacwaf001" }, // Non-required parameters - "enableDefaultTelemetry": { - "value": "" - }, "location": { "value": "" }, @@ -303,7 +295,7 @@ module accessConnector 'br:bicep/modules/databricks.access-connector:1.0.0' = { | Parameter | Type | Description | | :-- | :-- | :-- | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`location`](#parameter-location) | string | Location for all Resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | @@ -317,7 +309,7 @@ The name of the Azure Databricks access connector to create. - Required: Yes - Type: string -### Parameter: `enableDefaultTelemetry` +### Parameter: `enableTelemetry` Enable telemetry via a Globally Unique Identifier (GUID). diff --git a/avm/res/databricks/access-connector/main.json b/avm/res/databricks/access-connector/main.json index dce724ef4b..b55b4ceff1 100644 --- a/avm/res/databricks/access-connector/main.json +++ b/avm/res/databricks/access-connector/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "3245638906962144809" + "templateHash": "394207615675999827" }, "name": "Azure Databricks Access Connectors", "description": "This module deploys an Azure Databricks Access Connector.", @@ -167,7 +167,7 @@ "description": "Optional. The managed identity definition for this resource." } }, - "enableDefaultTelemetry": { + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -187,17 +187,23 @@ } }, "resources": { - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.databricks-accessconnector.{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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, diff --git a/avm/res/databricks/workspace/README.md b/avm/res/databricks/workspace/README.md index a6502ad9f6..0b9a5f72f1 100644 --- a/avm/res/databricks/workspace/README.md +++ b/avm/res/databricks/workspace/README.md @@ -28,7 +28,7 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/databricks.workspace:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/databricks/workspace:`. - [Using only defaults](#example-1-using-only-defaults) - [Using large parameter set](#example-2-using-large-parameter-set) @@ -44,13 +44,13 @@ This instance deploys the module with the minimum set of required parameters. via Bicep module ```bicep -module workspace 'br:bicep/modules/databricks.workspace:1.0.0' = { +module workspace 'br/public:avm/res/databricks/workspace:' = { name: '${uniqueString(deployment().name, location)}-test-dwmin' params: { // Required parameters name: 'dwmin001' // Non-required parameters - enableDefaultTelemetry: '' + location: '' } } ``` @@ -72,8 +72,8 @@ module workspace 'br:bicep/modules/databricks.workspace:1.0.0' = { "value": "dwmin001" }, // Non-required parameters - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" } } } @@ -92,7 +92,7 @@ This instance deploys the module with most of its features enabled. via Bicep module ```bicep -module workspace 'br:bicep/modules/databricks.workspace:1.0.0' = { +module workspace 'br/public:avm/res/databricks/workspace:' = { name: '${uniqueString(deployment().name, location)}-test-dwmax' params: { // Required parameters @@ -129,7 +129,6 @@ module workspace 'br:bicep/modules/databricks.workspace:1.0.0' = { } ] disablePublicIp: true - enableDefaultTelemetry: '' loadBalancerBackendPoolName: '' loadBalancerResourceId: '' location: '' @@ -250,9 +249,6 @@ module workspace 'br:bicep/modules/databricks.workspace:1.0.0' = { "disablePublicIp": { "value": true }, - "enableDefaultTelemetry": { - "value": "" - }, "loadBalancerBackendPoolName": { "value": "" }, @@ -358,7 +354,7 @@ This instance deploys the module in alignment with the best-practices of the Azu via Bicep module ```bicep -module workspace 'br:bicep/modules/databricks.workspace:1.0.0' = { +module workspace 'br/public:avm/res/databricks/workspace:' = { name: '${uniqueString(deployment().name, location)}-test-dwwaf' params: { // Required parameters @@ -395,7 +391,6 @@ module workspace 'br:bicep/modules/databricks.workspace:1.0.0' = { } ] disablePublicIp: true - enableDefaultTelemetry: '' loadBalancerBackendPoolName: '' loadBalancerResourceId: '' location: '' @@ -499,9 +494,6 @@ module workspace 'br:bicep/modules/databricks.workspace:1.0.0' = { "disablePublicIp": { "value": true }, - "enableDefaultTelemetry": { - "value": "" - }, "loadBalancerBackendPoolName": { "value": "" }, @@ -599,7 +591,7 @@ module workspace 'br:bicep/modules/databricks.workspace:1.0.0' = { | [`customVirtualNetworkResourceId`](#parameter-customvirtualnetworkresourceid) | string | The resource ID of a Virtual Network where this Databricks Cluster should be created. | | [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | | [`disablePublicIp`](#parameter-disablepublicip) | bool | Disable Public IP. | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`loadBalancerBackendPoolName`](#parameter-loadbalancerbackendpoolname) | string | Name of the outbound Load Balancer Backend Pool for Secure Cluster Connectivity (No Public IP). | | [`loadBalancerResourceId`](#parameter-loadbalancerresourceid) | string | Resource URI of Outbound Load balancer for Secure Cluster Connectivity (No Public IP) workspace. | | [`location`](#parameter-location) | string | Location for all Resources. | @@ -855,7 +847,7 @@ Disable Public IP. - Type: bool - Default: `False` -### Parameter: `enableDefaultTelemetry` +### Parameter: `enableTelemetry` Enable telemetry via a Globally Unique Identifier (GUID). @@ -973,7 +965,7 @@ Configuration details for private endpoints. For security reasons, it is recomme | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | | [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | | [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | -| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. | +| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. | | [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | array | The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | | [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | @@ -1080,7 +1072,7 @@ The name of the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroupName` -The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. +The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. - Required: No - Type: string @@ -1393,7 +1385,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `modules/network/private-endpoint` | Local reference | +| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | ## Notes diff --git a/avm/res/databricks/workspace/main.bicep b/avm/res/databricks/workspace/main.bicep index 70ce6634d2..81d6f4fa46 100644 --- a/avm/res/databricks/workspace/main.bicep +++ b/avm/res/databricks/workspace/main.bicep @@ -99,8 +99,6 @@ param requiredNsgRules string = 'AllRules' @description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') param privateEndpoints privateEndpointType -var enableReferencedModulesTelemetry = false - var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') diff --git a/avm/res/databricks/workspace/main.json b/avm/res/databricks/workspace/main.json index 47a19aa465..4444ba4674 100644 --- a/avm/res/databricks/workspace/main.json +++ b/avm/res/databricks/workspace/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "17678709403904494263" + "templateHash": "14087130830480205215" }, "name": "Azure Databricks Workspaces", "description": "This module deploys an Azure Databricks Workspace.", @@ -140,7 +140,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided." + "description": "Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided." } }, "privateDnsZoneResourceIds": { @@ -162,7 +162,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." + "description": "Required. Fqdn that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -171,7 +171,7 @@ "type": "string" }, "metadata": { - "description": "Required. A list of private ip addresses of the private endpoint." + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -210,7 +210,7 @@ "privateIPAddress": { "type": "string", "metadata": { - "description": "Required. A private ip address obtained from the private endpoint's subnet." + "description": "Required. A private IP address obtained from the private endpoint's subnet." } } }, @@ -497,7 +497,7 @@ "description": "Optional. Tags of the resource." } }, - "enableDefaultTelemetry": { + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -644,7 +644,6 @@ } }, "variables": { - "enableReferencedModulesTelemetry": false, "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", @@ -678,17 +677,23 @@ "cMKManagedDiskKeyVault" ] }, - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.databricks-workspace.{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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, @@ -796,29 +801,34 @@ }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-workspace-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "name": "[format('{0}-KeyVault-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", "properties": { "expressionEvaluationOptions": { "scope": "inner" }, "mode": "Incremental", "parameters": { - "groupIds": { + "privateLinkServiceConnections": { "value": [ - "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'databricks_ui_api')]" + { + "name": "[parameters('name')]", + "properties": { + "privateLinkServiceId": "[resourceId('Microsoft.Databricks/workspaces', parameters('name'))]", + "groupIds": [ + "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'databricks_ui_api')]" + ] + } + } ] }, "name": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Databricks/workspaces', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'databricks_ui_api'), copyIndex()))]" }, - "serviceResourceId": { - "value": "[resourceId('Microsoft.Databricks/workspaces', parameters('name'))]" - }, "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, - "enableDefaultTelemetry": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableDefaultTelemetry'), variables('enableReferencedModulesTelemetry'))]" + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" }, "location": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" @@ -862,7 +872,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "6873008238043407177" + "templateHash": "2821141217598568122" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -877,7 +887,7 @@ "roleDefinitionIdOrName": { "type": "string", "metadata": { - "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + "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": { @@ -1001,6 +1011,89 @@ }, "nullable": true }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, "customDnsConfigType": { "type": "array", "items": { @@ -1039,12 +1132,6 @@ "description": "Required. Resource ID of the subnet where the endpoint needs to be created." } }, - "serviceResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the resource that needs to be connected to the network." - } - }, "applicationSecurityGroupResourceIds": { "type": "array", "nullable": true, @@ -1061,17 +1148,10 @@ }, "ipConfigurations": { "$ref": "#/definitions/ipConfigurationsType", - "nullable": true, "metadata": { "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." } }, - "groupIds": { - "type": "array", - "metadata": { - "description": "Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to." - } - }, "privateDnsZoneGroupName": { "type": "string", "nullable": true, @@ -1102,7 +1182,7 @@ "roleAssignments": { "$ref": "#/definitions/roleAssignmentType", "metadata": { - "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + "description": "Optional. Array of role assignments to create." } }, "tags": { @@ -1114,19 +1194,23 @@ }, "customDnsConfigs": { "$ref": "#/definitions/customDnsConfigType", - "nullable": true, "metadata": { "description": "Optional. Custom DNS configurations." } }, "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." } }, - "enableDefaultTelemetry": { + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -1135,7 +1219,6 @@ } }, "variables": { - "enableReferencedModulesTelemetry": false, "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", @@ -1150,17 +1233,23 @@ } }, "resources": { - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), 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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, @@ -1180,19 +1269,11 @@ } } ], - "customDnsConfigs": "[parameters('customDnsConfigs')]", + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", - "privateLinkServiceConnections": [ - { - "name": "[parameters('name')]", - "properties": { - "privateLinkServiceId": "[parameters('serviceResourceId')]", - "groupIds": "[parameters('groupIds')]" - } - } - ], + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", "subnet": { "id": "[parameters('subnetResourceId')]" } @@ -1222,7 +1303,7 @@ "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', 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], coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "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')]", @@ -1253,9 +1334,6 @@ }, "privateEndpointName": { "value": "[parameters('name')]" - }, - "enableDefaultTelemetry": { - "value": "[variables('enableReferencedModulesTelemetry')]" } }, "template": { @@ -1265,7 +1343,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "17578977753131828304" + "templateHash": "18168683629401652671" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", @@ -1292,13 +1370,6 @@ "metadata": { "description": "Optional. The name of the private DNS zone group." } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } } }, "variables": { @@ -1316,20 +1387,6 @@ ] }, "resources": [ - { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, { "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", "apiVersion": "2023-04-01", diff --git a/avm/res/db-for-my-sql/flexible-server/README.md b/avm/res/db-for-my-sql/flexible-server/README.md index bdbfbf4aa1..b62c12a34c 100644 --- a/avm/res/db-for-my-sql/flexible-server/README.md +++ b/avm/res/db-for-my-sql/flexible-server/README.md @@ -28,11 +28,12 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/db-for-my-sql.flexible-server:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/db-for-my-sql/flexible-server:`. - [Using only defaults](#example-1-using-only-defaults) - [Private](#example-2-private) - [Public](#example-3-public) +- [Waf-Aligned](#example-4-waf-aligned) ### Example 1: _Using only defaults_ @@ -44,7 +45,7 @@ This instance deploys the module with the minimum set of required parameters. via Bicep module ```bicep -module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { +module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { name: '${uniqueString(deployment().name, location)}-test-dfmsfsmin' params: { // Required parameters @@ -54,7 +55,7 @@ module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { // Non-required parameters administratorLogin: 'adminUserName' administratorLoginPassword: '' - enableDefaultTelemetry: '' + location: '' } } ``` @@ -88,8 +89,8 @@ module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { "administratorLoginPassword": { "value": "" }, - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" } } } @@ -105,7 +106,7 @@ module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { via Bicep module ```bicep -module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { +module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { name: '${uniqueString(deployment().name, location)}-test-dfmsfspvt' params: { // Required parameters @@ -143,7 +144,6 @@ module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { workspaceResourceId: '' } ] - enableDefaultTelemetry: '' highAvailability: 'SameZone' location: '' lock: { @@ -253,9 +253,6 @@ module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { } ] }, - "enableDefaultTelemetry": { - "value": "" - }, "highAvailability": { "value": "SameZone" }, @@ -330,7 +327,7 @@ module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { via Bicep module ```bicep -module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { +module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { name: '${uniqueString(deployment().name, location)}-test-dfmsfsp' params: { // Required parameters @@ -376,7 +373,6 @@ module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { workspaceResourceId: '' } ] - enableDefaultTelemetry: '' firewallRules: [ { endIpAddress: '0.0.0.0' @@ -505,9 +501,6 @@ module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { } ] }, - "enableDefaultTelemetry": { - "value": "" - }, "firewallRules": { "value": [ { @@ -588,6 +581,43 @@ module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = {

+### Example 4: _Waf-Aligned_ + +

+ +via Bicep module + +```bicep +module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { + name: '${uniqueString(deployment().name, location)}-test-dfmsfswaf' + params: { + name: 'dfmsfswaf001' + } +} +``` + +
+

+ +

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

+ ## Parameters @@ -624,7 +654,7 @@ module flexibleServer 'br:bicep/modules/db-for-my-sql.flexible-server:1.0.0' = { | [`databases`](#parameter-databases) | array | The databases to create in the server. | | [`delegatedSubnetResourceId`](#parameter-delegatedsubnetresourceid) | string | Delegated subnet arm resource ID. Used when the desired connectivity mode is "Private Access" - virtual network integration. Delegation must be enabled on the subnet for MySQL Flexible Servers and subnet CIDR size is /29. | | [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`firewallRules`](#parameter-firewallrules) | array | The firewall rules to create in the MySQL flexible server. | | [`geoRedundantBackup`](#parameter-georedundantbackup) | string | A value indicating whether Geo-Redundant backup is enabled on the server. If "Enabled" and "cMKKeyName" is not empty, then "geoBackupCMKKeyVaultResourceId" and "cMKUserAssignedIdentityResourceId" are also required. | | [`highAvailability`](#parameter-highavailability) | string | The mode for High Availability (HA). It is not supported for the Burstable pricing tier and Zone redundant HA can only be set during server provisioning. | @@ -998,7 +1028,7 @@ Resource ID of the diagnostic log analytics workspace. For security reasons, it - Required: No - Type: string -### Parameter: `enableDefaultTelemetry` +### Parameter: `enableTelemetry` Enable telemetry via a Globally Unique Identifier (GUID). diff --git a/avm/res/db-for-my-sql/flexible-server/main.json b/avm/res/db-for-my-sql/flexible-server/main.json index 5d63ee48ca..40d415eff2 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.json +++ b/avm/res/db-for-my-sql/flexible-server/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "13509958318011769977" + "templateHash": "9454239676460003107" }, "name": "DBforMySQL Flexible Servers", "description": "This module deploys a DBforMySQL Flexible Server.", @@ -533,7 +533,7 @@ "description": "Optional. The diagnostic settings of the service." } }, - "enableDefaultTelemetry": { + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -544,7 +544,6 @@ "variables": { "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null()), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", - "enableReferencedModulesTelemetry": false, "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "MySQL Backup And Export Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd18ad5f3-1baf-4119-b49b-d944edb1f9d0')]", @@ -579,17 +578,23 @@ "cMKGeoKeyVault" ] }, - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.dbformysql-flexibleserver.{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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, @@ -754,10 +759,7 @@ "value": "[parameters('name')]" }, "collation": "[if(contains(parameters('databases')[copyIndex()], 'collation'), createObject('value', parameters('databases')[copyIndex()].collation), createObject('value', ''))]", - "charset": "[if(contains(parameters('databases')[copyIndex()], 'charset'), createObject('value', parameters('databases')[copyIndex()].charset), createObject('value', ''))]", - "enableDefaultTelemetry": { - "value": "[variables('enableReferencedModulesTelemetry')]" - } + "charset": "[if(contains(parameters('databases')[copyIndex()], 'charset'), createObject('value', parameters('databases')[copyIndex()].charset), createObject('value', ''))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -766,7 +768,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "7585808247826533259" + "templateHash": "4885810309374527606" }, "name": "DBforMySQL Flexible Server Databases", "description": "This module deploys a DBforMySQL Flexible Server Database.", @@ -798,37 +800,9 @@ "metadata": { "description": "Optional. The charset of the database." } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. Location for all resources." - } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "resources": [ - { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, { "type": "Microsoft.DBforMySQL/flexibleServers/databases", "apiVersion": "2022-01-01", @@ -893,9 +867,6 @@ }, "endIpAddress": { "value": "[parameters('firewallRules')[copyIndex()].endIpAddress]" - }, - "enableDefaultTelemetry": { - "value": "[variables('enableReferencedModulesTelemetry')]" } }, "template": { @@ -905,7 +876,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "9889972221731602451" + "templateHash": "5525339023784252205" }, "name": "DBforMySQL Flexible Server Firewall Rules", "description": "This module deploys a DBforMySQL Flexible Server Firewall Rule.", @@ -935,30 +906,9 @@ "metadata": { "description": "Conditional. The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment." } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "resources": [ - { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, { "type": "Microsoft.DBforMySQL/flexibleServers/firewallRules", "apiVersion": "2022-01-01", @@ -1033,7 +983,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "8863151548145849170" + "templateHash": "12048235018035722270" }, "name": "DBforMySQL Flexible Server Administrators", "description": "This module deploys a DBforMySQL Flexible Server Administrator.", @@ -1070,37 +1020,9 @@ "metadata": { "description": "Optional. The tenantId of the Active Directory administrator." } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. Location for all resources." - } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "resources": [ - { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, { "type": "Microsoft.DBforMySQL/flexibleServers/administrators", "apiVersion": "2022-01-01", diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..1c3183493c --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,45 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +// e.g., for a module 'network/private-endpoint' you could use 'dep-dev-network.privateendpoints-${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}---${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.') +// e.g., for a module 'network/private-endpoint' you could use 'npe' as a prefix and then 'waf' as a suffix for the waf-aligned test +param serviceShort string = 'dfmsfswaf' + +@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: 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: { + // You parameters go here + name: '${namePrefix}${serviceShort}001' + } +}] diff --git a/avm/res/health-bot/health-bot/README.md b/avm/res/health-bot/health-bot/README.md index 3b796cfb65..77e0fddafa 100644 --- a/avm/res/health-bot/health-bot/README.md +++ b/avm/res/health-bot/health-bot/README.md @@ -24,7 +24,7 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/health-bot.health-bot:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/health-bot/health-bot:`. - [Using only defaults](#example-1-using-only-defaults) - [Using large parameter set](#example-2-using-large-parameter-set) @@ -40,14 +40,14 @@ This instance deploys the module with the minimum set of required parameters.

via Bicep module ```bicep -module healthBot 'br:bicep/modules/health-bot.health-bot:1.0.0' = { +module healthBot 'br/public:avm/res/health-bot/health-bot:' = { name: '${uniqueString(deployment().name, location)}-test-hbhbmin' params: { // Required parameters name: 'hbhbmin001' sku: 'F0' // Non-required parameters - enableDefaultTelemetry: '' + location: '' } } ``` @@ -72,8 +72,8 @@ module healthBot 'br:bicep/modules/health-bot.health-bot:1.0.0' = { "value": "F0" }, // Non-required parameters - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" } } } @@ -92,14 +92,14 @@ This instance deploys the module with most of its features enabled. via Bicep module ```bicep -module healthBot 'br:bicep/modules/health-bot.health-bot:1.0.0' = { +module healthBot 'br/public:avm/res/health-bot/health-bot:' = { name: '${uniqueString(deployment().name, location)}-test-hbhbmax' params: { // Required parameters name: 'hbhbmax001' sku: 'F0' // Non-required parameters - enableDefaultTelemetry: '' + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -155,8 +155,8 @@ module healthBot 'br:bicep/modules/health-bot.health-bot:1.0.0' = { "value": "F0" }, // Non-required parameters - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" }, "lock": { "value": { @@ -214,14 +214,14 @@ This instance deploys the module in alignment with the best-practices of the Azu via Bicep module ```bicep -module healthBot 'br:bicep/modules/health-bot.health-bot:1.0.0' = { +module healthBot 'br/public:avm/res/health-bot/health-bot:' = { name: '${uniqueString(deployment().name, location)}-test-hbhbwaf' params: { // Required parameters name: 'hbhbwaf001' sku: 'F0' // Non-required parameters - enableDefaultTelemetry: '' + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -260,8 +260,8 @@ module healthBot 'br:bicep/modules/health-bot.health-bot:1.0.0' = { "value": "F0" }, // Non-required parameters - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" }, "lock": { "value": { @@ -304,7 +304,7 @@ module healthBot 'br:bicep/modules/health-bot.health-bot:1.0.0' = { | Parameter | Type | Description | | :-- | :-- | :-- | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | @@ -333,7 +333,7 @@ The name of the Azure Health Bot SKU. ] ``` -### Parameter: `enableDefaultTelemetry` +### Parameter: `enableTelemetry` Enable telemetry via a Globally Unique Identifier (GUID). diff --git a/avm/res/health-bot/health-bot/main.json b/avm/res/health-bot/health-bot/main.json index 538d2d760a..f2fa5f7eb1 100644 --- a/avm/res/health-bot/health-bot/main.json +++ b/avm/res/health-bot/health-bot/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "582765600236650029" + "templateHash": "15987244695395932464" }, "name": "Azure Health Bots", "description": "This module deploys an Azure Health Bot.", @@ -170,7 +170,7 @@ "description": "Optional. Tags of the resource." } }, - "enableDefaultTelemetry": { + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -190,17 +190,23 @@ } }, "resources": { - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.healthbot-healthbot.{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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, diff --git a/avm/res/health-bot/health-bot/version.json b/avm/res/health-bot/health-bot/version.json new file mode 100644 index 0000000000..8def869ede --- /dev/null +++ b/avm/res/health-bot/health-bot/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} diff --git a/avm/res/net-app/net-app-account/README.md b/avm/res/net-app/net-app-account/README.md index c0fdd19a6e..3e4cae9c70 100644 --- a/avm/res/net-app/net-app-account/README.md +++ b/avm/res/net-app/net-app-account/README.md @@ -26,11 +26,12 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/net-app.net-app-account:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/net-app/net-app-account:`. - [Using only defaults](#example-1-using-only-defaults) - [Nfs3](#example-2-nfs3) - [Nfs41](#example-3-nfs41) +- [Waf-Aligned](#example-4-waf-aligned) ### Example 1: _Using only defaults_ @@ -42,13 +43,13 @@ This instance deploys the module with the minimum set of required parameters. via Bicep module ```bicep -module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { +module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { name: '${uniqueString(deployment().name, location)}-test-nanaamin' params: { // Required parameters name: 'nanaamin001' // Non-required parameters - enableDefaultTelemetry: '' + location: '' } } ``` @@ -70,8 +71,8 @@ module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { "value": "nanaamin001" }, // Non-required parameters - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" } } } @@ -87,7 +88,7 @@ module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { via Bicep module ```bicep -module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { +module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { name: '${uniqueString(deployment().name, location)}-test-nanaanfs3' params: { // Required parameters @@ -155,7 +156,7 @@ module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { volumes: [] } ] - enableDefaultTelemetry: '' + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -271,8 +272,8 @@ module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { } ] }, - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" }, "lock": { "value": { @@ -324,7 +325,7 @@ module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { via Bicep module ```bicep -module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { +module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { name: '${uniqueString(deployment().name, location)}-test-nanaanfs41' params: { // Required parameters @@ -402,7 +403,7 @@ module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { volumes: [] } ] - enableDefaultTelemetry: '' + location: '' managedIdentities: { userAssignedResourceIds: [ '' @@ -529,8 +530,8 @@ module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { } ] }, - "enableDefaultTelemetry": { - "value": "" + "location": { + "value": "" }, "managedIdentities": { "value": { @@ -576,6 +577,43 @@ module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = {

+### Example 4: _Waf-Aligned_ + +

+ +via Bicep module + +```bicep +module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { + name: '${uniqueString(deployment().name, location)}-test-nanaawaf' + params: { + name: 'nanaawaf001' + } +} +``` + +
+

+ +

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

+ ## Parameters @@ -595,7 +633,7 @@ module netAppAccount 'br:bicep/modules/net-app.net-app-account:1.0.0' = { | [`domainJoinPassword`](#parameter-domainjoinpassword) | securestring | Required if domainName is specified. Password of the user specified in domainJoinUser parameter. | | [`domainJoinUser`](#parameter-domainjoinuser) | string | Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain. | | [`domainName`](#parameter-domainname) | string | Fully Qualified Active Directory DNS Domain Name (e.g. 'contoso.com'). | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | @@ -658,7 +696,7 @@ Fully Qualified Active Directory DNS Domain Name (e.g. 'contoso.com'). - Type: string - Default: `''` -### Parameter: `enableDefaultTelemetry` +### Parameter: `enableTelemetry` Enable telemetry via a Globally Unique Identifier (GUID). diff --git a/avm/res/net-app/net-app-account/capacity-pool/main.bicep b/avm/res/net-app/net-app-account/capacity-pool/main.bicep index ba9c73ac8f..51dd53b329 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/main.bicep +++ b/avm/res/net-app/net-app-account/capacity-pool/main.bicep @@ -49,11 +49,6 @@ param roleAssignments roleAssignmentType ]) param encryptionType string = 'Single' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableTelemetry bool = true - -var enableReferencedModulesTelemetry = false - var builtInRoleNames = { Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') @@ -62,24 +57,6 @@ var builtInRoleNames = { '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.netapp-netappaccount.${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 netAppAccount 'Microsoft.NetApp/netAppAccounts@2022-11-01' existing = { name: netAppAccountName } diff --git a/avm/res/net-app/net-app-account/capacity-pool/version.json b/avm/res/net-app/net-app-account/capacity-pool/version.json deleted file mode 100644 index 96236a61ba..0000000000 --- a/avm/res/net-app/net-app-account/capacity-pool/version.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.4", - "pathFilters": [ - "./main.json" - ] -} diff --git a/avm/res/net-app/net-app-account/main.bicep b/avm/res/net-app/net-app-account/main.bicep index 3c06547974..76b7ff8caa 100644 --- a/avm/res/net-app/net-app-account/main.bicep +++ b/avm/res/net-app/net-app-account/main.bicep @@ -42,6 +42,9 @@ param lock lockType @description('Optional. Tags for all resources.') param tags object? +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableTelemetry bool = true + var activeDirectoryConnectionProperties = [ { username: !empty(domainName) ? domainJoinUser : null @@ -69,7 +72,7 @@ var builtInRoleNames = { } resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.network-networksecuritygroup.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + name: '46d3xbcp.res.netapp-netappaccount.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' properties: { mode: 'Incremental' template: { diff --git a/avm/res/net-app/net-app-account/main.json b/avm/res/net-app/net-app-account/main.json index 862b3c67db..ef054cec6e 100644 --- a/avm/res/net-app/net-app-account/main.json +++ b/avm/res/net-app/net-app-account/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "8081072067801758787" + "templateHash": "16523658267969007487" }, "name": "Azure NetApp Files", "description": "This module deploys an Azure NetApp File.", @@ -208,7 +208,7 @@ "description": "Optional. Tags for all resources." } }, - "enableDefaultTelemetry": { + "enableTelemetry": { "type": "bool", "defaultValue": true, "metadata": { @@ -217,7 +217,6 @@ } }, "variables": { - "enableReferencedModulesTelemetry": false, "activeDirectoryConnectionProperties": [ { "username": "[if(not(empty(parameters('domainName'))), parameters('domainJoinUser'), null())]", @@ -239,17 +238,23 @@ } }, "resources": { - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.netapp-netappaccount.{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": [] + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } } } }, @@ -334,9 +339,6 @@ "encryptionType": "[if(contains(parameters('capacityPools')[copyIndex()], 'encryptionType'), createObject('value', parameters('capacityPools')[copyIndex()].encryptionType), createObject('value', 'Single'))]", "tags": { "value": "[coalesce(tryGet(parameters('capacityPools')[copyIndex()], 'tags'), parameters('tags'))]" - }, - "enableDefaultTelemetry": { - "value": "[variables('enableReferencedModulesTelemetry')]" } }, "template": { @@ -347,7 +349,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "15353329491336313807" + "templateHash": "13567874697839927577" }, "name": "Azure NetApp Files Capacity Pools", "description": "This module deploys an Azure NetApp Files Capacity Pool.", @@ -508,17 +510,9 @@ "metadata": { "description": "Optional. Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool." } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "variables": { - "enableReferencedModulesTelemetry": false, "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", @@ -528,20 +522,6 @@ } }, "resources": { - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, "netAppAccount": { "existing": true, "type": "Microsoft.NetApp/netAppAccounts", @@ -627,10 +607,7 @@ "value": "[parameters('volumes')[copyIndex()].subnetResourceId]" }, "exportPolicyRules": "[if(contains(parameters('volumes')[copyIndex()], 'exportPolicyRules'), createObject('value', parameters('volumes')[copyIndex()].exportPolicyRules), createObject('value', createArray()))]", - "roleAssignments": "[if(contains(parameters('volumes')[copyIndex()], 'roleAssignments'), createObject('value', parameters('volumes')[copyIndex()].roleAssignments), createObject('value', createArray()))]", - "enableDefaultTelemetry": { - "value": "[variables('enableReferencedModulesTelemetry')]" - } + "roleAssignments": "[if(contains(parameters('volumes')[copyIndex()], 'roleAssignments'), createObject('value', parameters('volumes')[copyIndex()].roleAssignments), createObject('value', createArray()))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -640,7 +617,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "3662331312918191126" + "templateHash": "13281702213100562603" }, "name": "Azure NetApp Files Capacity Pool Volumes", "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", @@ -791,13 +768,6 @@ "metadata": { "description": "Optional. Array of role assignments to create." } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "variables": { @@ -819,20 +789,6 @@ "netAppAccount" ] }, - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, "netAppAccount": { "existing": true, "type": "Microsoft.NetApp/netAppAccounts", diff --git a/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..6b4ddb0e4e --- /dev/null +++ b/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,45 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +// e.g., for a module 'network/private-endpoint' you could use 'dep-dev-network.privateendpoints-${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}---${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.') +// e.g., for a module 'network/private-endpoint' you could use 'npe' as a prefix and then 'waf' as a suffix for the waf-aligned test +param serviceShort string = 'nanaawaf' + +@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: 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: { + // You parameters go here + name: '${namePrefix}${serviceShort}001' + } +}] From 9b8286c1840bb7575cef047248e28386d96f0c91 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 21 Dec 2023 22:09:56 +1000 Subject: [PATCH 06/33] . --- .github/workflows/avm.res.databricks.workspace.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/avm.res.databricks.workspace.yml b/.github/workflows/avm.res.databricks.workspace.yml index 58e0e93390..d9d477def4 100644 --- a/.github/workflows/avm.res.databricks.workspace.yml +++ b/.github/workflows/avm.res.databricks.workspace.yml @@ -27,14 +27,14 @@ on: paths: - ".github/actions/templates/avm-**" - ".github/workflows/avm.template.module.yml" - - ".github/workflows/avm.res.databricks/workspace.yml" + - ".github/workflows/avm.res.databricks.workspace.yml" - "avm/res/databricks/workspace/**" - "avm/utilities/pipelines/**" - "!*/**/README.md" env: modulePath: "avm/res/databricks/workspace" - workflowPath: ".github/workflows/avm.res.databricks/workspace.yml" + workflowPath: ".github/workflows/avm.res.databricks.workspace.yml" concurrency: group: ${{ github.workflow }} From 720d0c94cf099c80839dfb96b11b686385bd74c7 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 10:19:01 +1000 Subject: [PATCH 07/33] orphaned --- avm/res/analysis-services/server/ORPHANED.md | 4 ++++ avm/res/analysis-services/server/README.md | 5 +++++ avm/res/analysis-services/server/main.json | 2 +- avm/res/cache/redis/ORPHANED.md | 4 ++++ avm/res/compute/image/ORPHANED.md | 4 ++++ avm/res/data-protection/backup-vault/ORPHANED.md | 4 ++++ avm/res/databricks/access-connector/ORPHANED.md | 4 ++++ avm/res/databricks/workspace/ORPHANED.md | 4 ++++ avm/res/db-for-my-sql/flexible-server/ORPHANED.md | 4 ++++ avm/res/health-bot/health-bot/ORPHANED.md | 4 ++++ avm/res/net-app/net-app-account/ORPHANED.md | 4 ++++ 11 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 avm/res/analysis-services/server/ORPHANED.md create mode 100644 avm/res/cache/redis/ORPHANED.md create mode 100644 avm/res/compute/image/ORPHANED.md create mode 100644 avm/res/data-protection/backup-vault/ORPHANED.md create mode 100644 avm/res/databricks/access-connector/ORPHANED.md create mode 100644 avm/res/databricks/workspace/ORPHANED.md create mode 100644 avm/res/db-for-my-sql/flexible-server/ORPHANED.md create mode 100644 avm/res/health-bot/health-bot/ORPHANED.md create mode 100644 avm/res/net-app/net-app-account/ORPHANED.md diff --git a/avm/res/analysis-services/server/ORPHANED.md b/avm/res/analysis-services/server/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/analysis-services/server/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/analysis-services/server/README.md b/avm/res/analysis-services/server/README.md index 5869c1db46..f967256c4e 100644 --- a/avm/res/analysis-services/server/README.md +++ b/avm/res/analysis-services/server/README.md @@ -1,5 +1,10 @@ # Analysis Services Servers `[Microsoft.AnalysisServices/servers]` +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + This module deploys an Analysis Services Server. ## Navigation diff --git a/avm/res/analysis-services/server/main.json b/avm/res/analysis-services/server/main.json index e050279221..fc3e70d8a2 100644 --- a/avm/res/analysis-services/server/main.json +++ b/avm/res/analysis-services/server/main.json @@ -422,4 +422,4 @@ "value": "[reference('server', '2017-08-01', 'full').location]" } } -} \ No newline at end of file +} diff --git a/avm/res/cache/redis/ORPHANED.md b/avm/res/cache/redis/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/cache/redis/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/compute/image/ORPHANED.md b/avm/res/compute/image/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/compute/image/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/data-protection/backup-vault/ORPHANED.md b/avm/res/data-protection/backup-vault/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/data-protection/backup-vault/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/databricks/access-connector/ORPHANED.md b/avm/res/databricks/access-connector/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/databricks/access-connector/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/databricks/workspace/ORPHANED.md b/avm/res/databricks/workspace/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/databricks/workspace/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/db-for-my-sql/flexible-server/ORPHANED.md b/avm/res/db-for-my-sql/flexible-server/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/health-bot/health-bot/ORPHANED.md b/avm/res/health-bot/health-bot/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/health-bot/health-bot/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/net-app/net-app-account/ORPHANED.md b/avm/res/net-app/net-app-account/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/net-app/net-app-account/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file From 427fddb0ab4e9432567a2ec9edc0b8022098f8e4 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 15:06:55 +1000 Subject: [PATCH 08/33] interfaces --- avm/res/analysis-services/server/main.bicep | 8 +- avm/res/cache/redis/main.bicep | 52 ++++---- avm/res/cache/redis/main.json | 2 +- .../redis/tests/e2e/defaults/main.test.bicep | 3 - .../tests/e2e/waf-aligned/dependencies.bicep | 11 -- .../tests/e2e/waf-aligned/main.test.bicep | 4 - avm/res/compute/disk/main.bicep | 2 +- avm/res/compute/disk/main.json | 6 +- .../disk/tests/e2e/import/dependencies.bicep | 4 +- .../tests/e2e/waf-aligned/dependencies.bicep | 13 -- .../tests/e2e/waf-aligned/main.test.bicep | 9 -- avm/res/compute/image/main.bicep | 2 +- .../image/tests/e2e/defaults/main.test.bicep | 2 +- .../image/tests/e2e/max/dependencies.bicep | 4 +- .../tests/e2e/waf-aligned/dependencies.bicep | 2 +- .../budget/tests/e2e/defaults/main.test.bicep | 3 + .../tests/e2e/waf-aligned/main.test.bicep | 3 + .../databricks/access-connector/main.bicep | 2 +- avm/res/databricks/workspace/main.bicep | 116 +++++++++--------- .../db-for-my-sql/flexible-server/main.bicep | 8 +- avm/res/health-bot/health-bot/main.bicep | 2 +- avm/res/net-app/net-app-account/main.bicep | 2 +- 22 files changed, 116 insertions(+), 144 deletions(-) delete mode 100644 avm/res/compute/disk/tests/e2e/waf-aligned/dependencies.bicep diff --git a/avm/res/analysis-services/server/main.bicep b/avm/res/analysis-services/server/main.bicep index 9cef68c740..578f8e7f2e 100644 --- a/avm/res/analysis-services/server/main.bicep +++ b/avm/res/analysis-services/server/main.bicep @@ -166,7 +166,7 @@ type roleAssignmentType = { @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"') + @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.') @@ -185,13 +185,13 @@ type diagnosticSettingType = { @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? - @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.') + @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? }[]? - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + @description('Optional. The name of logs that will be streamed. "allMetrics" includes all possible logs for the resource. Set to \'\' to disable log collection.') metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to \'AllMetrics\' to collect all metrics.') + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') category: string }[]? diff --git a/avm/res/cache/redis/main.bicep b/avm/res/cache/redis/main.bicep index 2e5a8ea4cb..a7e1c00ab8 100644 --- a/avm/res/cache/redis/main.bicep +++ b/avm/res/cache/redis/main.bicep @@ -291,29 +291,6 @@ type lockType = { 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? -}[]? - type privateEndpointType = { @description('Optional. The name of the private endpoint.') @@ -383,6 +360,29 @@ type privateEndpointType = { enableTelemetry: bool? }[]? +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? +}[]? + type diagnosticSettingType = { @description('Optional. The name of diagnostic setting.') name: string? @@ -392,13 +392,13 @@ type diagnosticSettingType = { @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? - @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.') + @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? }[]? - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + @description('Optional. The name of logs that will be streamed. "allMetrics" includes all possible logs for the resource. Set to \'\' to disable log collection.') metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to \'AllMetrics\' to collect all metrics.') + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') category: string }[]? diff --git a/avm/res/cache/redis/main.json b/avm/res/cache/redis/main.json index 9b1b223441..1fedbb9604 100644 --- a/avm/res/cache/redis/main.json +++ b/avm/res/cache/redis/main.json @@ -1451,4 +1451,4 @@ "value": "[reference('redis', '2022-06-01', 'full').location]" } } -} \ No newline at end of file +} diff --git a/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep b/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep index 8915fc4d68..8339873e82 100644 --- a/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep @@ -17,9 +17,6 @@ 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 = 'crmin' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' diff --git a/avm/res/cache/redis/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/cache/redis/tests/e2e/waf-aligned/dependencies.bicep index 8218e0c1ad..bbf0956900 100644 --- a/avm/res/cache/redis/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/cache/redis/tests/e2e/waf-aligned/dependencies.bicep @@ -1,9 +1,6 @@ @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 - @description('Required. The name of the Virtual Network to create.') param virtualNetworkName string @@ -45,14 +42,6 @@ resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { } } -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location -} - -@description('The resource ID of the created Managed Identity.') -output managedIdentityResourceId string = managedIdentity.id - @description('The resource ID of the created Virtual Network Subnet.') output subnetResourceId string = virtualNetwork.properties.subnets[0].id diff --git a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep index c55ed0f5df..679c070d35 100644 --- a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep @@ -35,7 +35,6 @@ module nestedDependencies 'dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' location: location virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' } @@ -107,9 +106,6 @@ module testDeployment '../../../main.bicep' = { skuName: 'Premium' managedIdentities: { systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] } tags: { 'hidden-title': 'This is visible in the resource name' diff --git a/avm/res/compute/disk/main.bicep b/avm/res/compute/disk/main.bicep index d480c2f93b..16630825ae 100644 --- a/avm/res/compute/disk/main.bicep +++ b/avm/res/compute/disk/main.bicep @@ -259,7 +259,7 @@ type roleAssignmentType = { @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"') + @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.') diff --git a/avm/res/compute/disk/main.json b/avm/res/compute/disk/main.json index 741308dfc3..4d9e767876 100644 --- a/avm/res/compute/disk/main.json +++ b/avm/res/compute/disk/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "8431673418740300927" + "templateHash": "13942315411071014925" }, "name": "Compute Disks", "description": "This module deploys a Compute Disk", @@ -80,7 +80,7 @@ "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\"" + "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": { @@ -479,4 +479,4 @@ "value": "[reference('disk', '2022-07-02', 'full').location]" } } -} \ No newline at end of file +} diff --git a/avm/res/compute/disk/tests/e2e/import/dependencies.bicep b/avm/res/compute/disk/tests/e2e/import/dependencies.bicep index aa2912f2ec..adaf509a2d 100644 --- a/avm/res/compute/disk/tests/e2e/import/dependencies.bicep +++ b/avm/res/compute/disk/tests/e2e/import/dependencies.bicep @@ -108,7 +108,7 @@ resource triggerImageDeploymentScript 'Microsoft.Resources/deploymentScripts@202 azPowerShellVersion: '8.0' retentionInterval: 'P1D' arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\"' - scriptContent: loadTextContent('../../../../../.shared/.scripts/Start-ImageTemplate.ps1') + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/.scripts/Start-ImageTemplate.ps1') cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } @@ -132,7 +132,7 @@ resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10- azPowerShellVersion: '8.0' retentionInterval: 'P1D' arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\" -DestinationStorageAccountName \\"${storageAccount.name}\\" -VhdName \\"${imageTemplateNamePrefix}\\" -WaitForComplete' - scriptContent: loadTextContent('../../../../../.shared/.scripts/Copy-VhdToStorageAccount.ps1') + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/.scripts/Copy-VhdToStorageAccount.ps1') cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } diff --git a/avm/res/compute/disk/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/disk/tests/e2e/waf-aligned/dependencies.bicep deleted file mode 100644 index 616cf219fe..0000000000 --- a/avm/res/compute/disk/tests/e2e/waf-aligned/dependencies.bicep +++ /dev/null @@ -1,13 +0,0 @@ -@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/waf-aligned/main.test.bicep b/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep index 61bef3fa1b..d901c7a4d3 100644 --- a/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep @@ -31,15 +31,6 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { location: location } -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - location: location - } -} - // ============== // // Test Execution // // ============== // diff --git a/avm/res/compute/image/main.bicep b/avm/res/compute/image/main.bicep index 58ffde6a47..15bbfe092f 100644 --- a/avm/res/compute/image/main.bicep +++ b/avm/res/compute/image/main.bicep @@ -165,7 +165,7 @@ type roleAssignmentType = { @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"') + @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.') diff --git a/avm/res/compute/image/tests/e2e/defaults/main.test.bicep b/avm/res/compute/image/tests/e2e/defaults/main.test.bicep index 655aa61422..a761d8c10b 100644 --- a/avm/res/compute/image/tests/e2e/defaults/main.test.bicep +++ b/avm/res/compute/image/tests/e2e/defaults/main.test.bicep @@ -39,7 +39,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - // You parameters go here name: '${namePrefix}${serviceShort}001' + location: location } }] diff --git a/avm/res/compute/image/tests/e2e/max/dependencies.bicep b/avm/res/compute/image/tests/e2e/max/dependencies.bicep index 2a31d8730b..f659176d0a 100644 --- a/avm/res/compute/image/tests/e2e/max/dependencies.bicep +++ b/avm/res/compute/image/tests/e2e/max/dependencies.bicep @@ -115,7 +115,7 @@ resource triggerImageDeploymentScript 'Microsoft.Resources/deploymentScripts@202 azPowerShellVersion: '8.0' retentionInterval: 'P1D' arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\"' - scriptContent: loadTextContent('../../../../../.shared/.scripts/Start-ImageTemplate.ps1') + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/.scripts/Start-ImageTemplate.ps1') cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } @@ -139,7 +139,7 @@ resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10- azPowerShellVersion: '8.0' retentionInterval: 'P1D' arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\" -DestinationStorageAccountName \\"${storageAccount.name}\\" -VhdName \\"${imageTemplateNamePrefix}\\" -WaitForComplete' - scriptContent: loadTextContent('../../../../../.shared/.scripts/Copy-VhdToStorageAccount.ps1') + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/.scripts/Copy-VhdToStorageAccount.ps1') cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } diff --git a/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep index 2a31d8730b..ee1e6cbfe3 100644 --- a/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep @@ -115,7 +115,7 @@ resource triggerImageDeploymentScript 'Microsoft.Resources/deploymentScripts@202 azPowerShellVersion: '8.0' retentionInterval: 'P1D' arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\"' - scriptContent: loadTextContent('../../../../../.shared/.scripts/Start-ImageTemplate.ps1') + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/.scripts/Start-ImageTemplate.ps1') cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } diff --git a/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep b/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep index a2eafa450f..a4f181b32c 100644 --- a/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep +++ b/avm/res/consumption/budget/tests/e2e/defaults/main.test.bicep @@ -7,6 +7,9 @@ metadata description = 'This instance deploys the module with the minimum set of // Parameters // // ========== // +@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 = 'cbmin' diff --git a/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep b/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep index df44ccfad7..dd498bce67 100644 --- a/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/consumption/budget/tests/e2e/waf-aligned/main.test.bicep @@ -7,6 +7,9 @@ metadata description = 'This instance deploys the module in alignment with the b // Parameters // // ========== // +@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 = 'cbwaf' diff --git a/avm/res/databricks/access-connector/main.bicep b/avm/res/databricks/access-connector/main.bicep index 185995fda1..3d6acd2c6e 100644 --- a/avm/res/databricks/access-connector/main.bicep +++ b/avm/res/databricks/access-connector/main.bicep @@ -135,7 +135,7 @@ type roleAssignmentType = { @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"') + @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.') diff --git a/avm/res/databricks/workspace/main.bicep b/avm/res/databricks/workspace/main.bicep index 81d6f4fa46..433b5a950f 100644 --- a/avm/res/databricks/workspace/main.bicep +++ b/avm/res/databricks/workspace/main.bicep @@ -343,29 +343,6 @@ type lockType = { 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? -}[]? - type privateEndpointType = { @description('Optional. The name of the private endpoint.') @@ -435,38 +412,6 @@ type privateEndpointType = { enableTelemetry: bool? }[]? -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @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: { - @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? - - @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? - }[]? - - @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')? - - @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? - - @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? - - @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? - - @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? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? - type customerManagedKeyType = { @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') keyVaultResourceId: string @@ -497,3 +442,64 @@ type customerManagedKeyManagedDiskType = { @description('Optional. Indicate whether the latest key version should be automatically used for Managed Disk Encryption. Enabled by default.') rotationToLatestKeyVersionEnabled: bool? }? + +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? +}[]? + +type diagnosticSettingType = { + @description('Optional. The name of diagnostic setting.') + name: string? + + @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: { + @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? + + @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? + }[]? + + @description('Optional. The name of logs that will be streamed. "allMetrics" includes all possible logs for the resource. Set to \'\' to disable log collection.') + metricCategories: { + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') + category: string + }[]? + + @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')? + + @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? + + @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? + + @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? + + @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? + + @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/db-for-my-sql/flexible-server/main.bicep b/avm/res/db-for-my-sql/flexible-server/main.bicep index 6946247e4c..595affa177 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.bicep +++ b/avm/res/db-for-my-sql/flexible-server/main.bicep @@ -398,7 +398,7 @@ type roleAssignmentType = { @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"') + @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.') @@ -417,13 +417,13 @@ type diagnosticSettingType = { @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? - @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.') + @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? }[]? - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + @description('Optional. The name of logs that will be streamed. "allMetrics" includes all possible logs for the resource. Set to \'\' to disable log collection.') metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to \'AllMetrics\' to collect all metrics.') + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics.') category: string }[]? diff --git a/avm/res/health-bot/health-bot/main.bicep b/avm/res/health-bot/health-bot/main.bicep index 6d77c9d03a..0a09bde642 100644 --- a/avm/res/health-bot/health-bot/main.bicep +++ b/avm/res/health-bot/health-bot/main.bicep @@ -140,7 +140,7 @@ type roleAssignmentType = { @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"') + @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.') diff --git a/avm/res/net-app/net-app-account/main.bicep b/avm/res/net-app/net-app-account/main.bicep index 76b7ff8caa..69926a38de 100644 --- a/avm/res/net-app/net-app-account/main.bicep +++ b/avm/res/net-app/net-app-account/main.bicep @@ -181,7 +181,7 @@ type roleAssignmentType = { @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"') + @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.') From 501b99d373796601dfc8c906c8a3c0952730aaa7 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 15:52:28 +1000 Subject: [PATCH 09/33] . --- avm/res/compute/disk/README.md | 18 ++- .../disk/tests/e2e/image/main.test.bicep | 3 + .../disk/tests/e2e/import/main.test.bicep | 3 + avm/res/compute/image/README.md | 69 ++++++-- avm/res/compute/image/main.json | 4 +- .../tests/e2e/defaults/dependencies.bicep | 150 ++++++++++++++++++ .../e2e/defaults/dependencies_rbac.bicep | 16 ++ .../image/tests/e2e/defaults/main.test.bicep | 19 ++- .../image/tests/e2e/max/main.test.bicep | 4 +- .../tests/e2e/waf-aligned/dependencies.bicep | 2 +- .../tests/e2e/waf-aligned/main.test.bicep | 4 +- 11 files changed, 261 insertions(+), 31 deletions(-) create mode 100644 avm/res/compute/image/tests/e2e/defaults/dependencies.bicep create mode 100644 avm/res/compute/image/tests/e2e/defaults/dependencies_rbac.bicep diff --git a/avm/res/compute/disk/README.md b/avm/res/compute/disk/README.md index 6aa74cfad5..a11d91b225 100644 --- a/avm/res/compute/disk/README.md +++ b/avm/res/compute/disk/README.md @@ -27,8 +27,8 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br/public:avm/res/compute/disk:`. - [Using only defaults](#example-1-using-only-defaults) -- [Image](#example-2-image) -- [Import](#example-3-import) +- [Using an image](#example-2-using-an-image) +- [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) @@ -88,7 +88,10 @@ module disk 'br/public:avm/res/compute/disk:' = {

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

@@ -193,7 +196,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. +

@@ -865,7 +871,7 @@ Array of role assignments to create. | 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" | +| [`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. | @@ -887,7 +893,7 @@ The role to assign. You can provide either the display name of the role definiti ### 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" +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 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 4171d33a65..d1a82e8596 100644 --- a/avm/res/compute/disk/tests/e2e/image/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/image/main.test.bicep @@ -1,5 +1,8 @@ targetScope = 'subscription' +metadata name = 'Using an image' +metadata description = 'This instance deploys the module with an image reference.' + // ========== // // Parameters // // ========== // 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 40e4b460a8..56fe012475 100644 --- a/avm/res/compute/disk/tests/e2e/import/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/import/main.test.bicep @@ -1,5 +1,8 @@ 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 // // ========== // diff --git a/avm/res/compute/image/README.md b/avm/res/compute/image/README.md index 33c5fc43dc..b24a5e53ea 100644 --- a/avm/res/compute/image/README.md +++ b/avm/res/compute/image/README.md @@ -1,5 +1,10 @@ # Images `[Microsoft.Compute/images]` +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + This module deploys a Compute Image. ## Navigation @@ -26,8 +31,8 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br/public:avm/res/compute/image:`. - [Defaults](#example-1-defaults) -- [Max](#example-2-max) -- [Waf-Aligned](#example-3-waf-aligned) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [WAF-aligned](#example-3-waf-aligned) ### Example 1: _Defaults_ @@ -37,9 +42,16 @@ The following section provides usage examples for the module, which were used to ```bicep module image 'br/public:avm/res/compute/image:' = { - name: '${uniqueString(deployment().name, location)}-test-cidef' + name: '${uniqueString(deployment().name, location)}-test-cimin' params: { - name: 'cidef001' + // Required parameters + name: 'cimin001' + osAccountType: 'Standard_LRS' + osDiskBlobUri: '' + osDiskCaching: 'ReadWrite' + osType: 'Windows' + // Non-required parameters + location: '' } } ``` @@ -56,8 +68,25 @@ module image 'br/public:avm/res/compute/image:' = { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { + // Required parameters "name": { - "value": "cidef001" + "value": "cimin001" + }, + "osAccountType": { + "value": "Standard_LRS" + }, + "osDiskBlobUri": { + "value": "" + }, + "osDiskCaching": { + "value": "ReadWrite" + }, + "osType": { + "value": "Windows" + }, + // Non-required parameters + "location": { + "value": "" } } } @@ -66,7 +95,10 @@ module image 'br/public:avm/res/compute/image:' = {

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

@@ -106,9 +138,9 @@ module image 'br/public:avm/res/compute/image:' = { } ] tags: { + Environment: 'Non-Prod' 'hidden-title': 'This is visible in the resource name' - tagA: 'You\'re it' - tagB: 'Player' + Role: 'DeploymentValidation' } zoneResilient: true } @@ -180,9 +212,9 @@ module image 'br/public:avm/res/compute/image:' = { }, "tags": { "value": { + "Environment": "Non-Prod", "hidden-title": "This is visible in the resource name", - "tagA": "You\"re it", - "tagB": "Player" + "Role": "DeploymentValidation" } }, "zoneResilient": { @@ -195,7 +227,10 @@ module image 'br/public:avm/res/compute/image:' = {

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

@@ -218,9 +253,9 @@ module image 'br/public:avm/res/compute/image:' = { location: '' osState: 'Generalized' tags: { + Environment: 'Non-Prod' 'hidden-title': 'This is visible in the resource name' - tagA: 'You\'re it' - tagB: 'Player' + Role: 'DeploymentValidation' } zoneResilient: true } @@ -273,9 +308,9 @@ module image 'br/public:avm/res/compute/image:' = { }, "tags": { "value": { + "Environment": "Non-Prod", "hidden-title": "This is visible in the resource name", - "tagA": "You\"re it", - "tagB": "Player" + "Role": "DeploymentValidation" } }, "zoneResilient": { @@ -452,7 +487,7 @@ Array of role assignments to create. | 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" | +| [`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. | @@ -474,7 +509,7 @@ The role to assign. You can provide either the display name of the role definiti ### 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" +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 diff --git a/avm/res/compute/image/main.json b/avm/res/compute/image/main.json index 3bc9aec995..e0303f37b5 100644 --- a/avm/res/compute/image/main.json +++ b/avm/res/compute/image/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "9039111988355192698" + "templateHash": "3262439157508833759" }, "name": "Images", "description": "This module deploys a Compute Image.", @@ -55,7 +55,7 @@ "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\"" + "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": { diff --git a/avm/res/compute/image/tests/e2e/defaults/dependencies.bicep b/avm/res/compute/image/tests/e2e/defaults/dependencies.bicep new file mode 100644 index 0000000000..b0c24f72ae --- /dev/null +++ b/avm/res/compute/image/tests/e2e/defaults/dependencies.bicep @@ -0,0 +1,150 @@ +@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' = { + #disable-next-line use-stable-resource-identifiers + 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 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/image/tests/e2e/defaults/dependencies_rbac.bicep b/avm/res/compute/image/tests/e2e/defaults/dependencies_rbac.bicep new file mode 100644 index 0000000000..cdca1b63bd --- /dev/null +++ b/avm/res/compute/image/tests/e2e/defaults/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/image/tests/e2e/defaults/main.test.bicep b/avm/res/compute/image/tests/e2e/defaults/main.test.bicep index a761d8c10b..6f86caa441 100644 --- a/avm/res/compute/image/tests/e2e/defaults/main.test.bicep +++ b/avm/res/compute/image/tests/e2e/defaults/main.test.bicep @@ -14,7 +14,7 @@ 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.') // e.g., for a module 'network/private-endpoint' you could use 'npe' as a prefix and then 'waf' as a suffix for the waf-aligned test -param serviceShort string = 'cidef' +param serviceShort string = 'cimin' @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_#' @@ -30,6 +30,19 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { 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 // // ============== // @@ -41,5 +54,9 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' params: { name: '${namePrefix}${serviceShort}001' location: location + osAccountType: 'Standard_LRS' + osDiskBlobUri: nestedDependencies.outputs.vhdUri + osDiskCaching: 'ReadWrite' + osType: 'Windows' } }] diff --git a/avm/res/compute/image/tests/e2e/max/main.test.bicep b/avm/res/compute/image/tests/e2e/max/main.test.bicep index 214df0f600..c9b868bac9 100644 --- a/avm/res/compute/image/tests/e2e/max/main.test.bicep +++ b/avm/res/compute/image/tests/e2e/max/main.test.bicep @@ -88,8 +88,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' diskSizeGB: 128 tags: { 'hidden-title': 'This is visible in the resource name' - tagA: 'You\'re it' - tagB: 'Player' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } } }] diff --git a/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep index ee1e6cbfe3..f659176d0a 100644 --- a/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep @@ -139,7 +139,7 @@ resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10- azPowerShellVersion: '8.0' retentionInterval: 'P1D' arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\" -DestinationStorageAccountName \\"${storageAccount.name}\\" -VhdName \\"${imageTemplateNamePrefix}\\" -WaitForComplete' - scriptContent: loadTextContent('../../../../../.shared/.scripts/Copy-VhdToStorageAccount.ps1') + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/.scripts/Copy-VhdToStorageAccount.ps1') cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } diff --git a/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep index 7e799c3cd6..965dd3ca4c 100644 --- a/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/compute/image/tests/e2e/waf-aligned/main.test.bicep @@ -71,8 +71,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' diskSizeGB: 128 tags: { 'hidden-title': 'This is visible in the resource name' - tagA: 'You\'re it' - tagB: 'Player' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' } } }] From 59d638031a8435ea581cd2522b085459defef75c Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 16:57:14 +1000 Subject: [PATCH 10/33] . --- .../redis/tests/e2e/defaults/main.test.bicep | 7 +++--- .../cache/redis/tests/e2e/max/main.test.bicep | 7 +++--- .../tests/e2e/waf-aligned/main.test.bicep | 7 +++--- .../disk/tests/e2e/defaults/main.test.bicep | 2 +- .../disk/tests/e2e/image/main.test.bicep | 2 +- .../disk/tests/e2e/import/main.test.bicep | 2 +- .../disk/tests/e2e/max/main.test.bicep | 2 +- .../tests/e2e/waf-aligned/main.test.bicep | 2 +- avm/res/compute/image/README.md | 7 ++++-- avm/res/compute/image/main.json | 2 +- .../image/tests/e2e/defaults/main.test.bicep | 7 ++++-- .../tests/e2e/waf-aligned/dependencies.bicep | 16 ------------- .../tests/e2e/waf-aligned/main.test.bicep | 9 ------- .../tests/e2e/waf-aligned/dependencies.bicep | 16 ------------- .../tests/e2e/waf-aligned/main.test.bicep | 12 ---------- .../workspace/tests/e2e/max/main.test.bicep | 3 --- .../e2e/{public => max}/dependencies1.bicep | 2 +- .../e2e/{public => max}/dependencies2.bicep | 0 .../tests/e2e/{public => max}/main.test.bicep | 2 +- .../tests/e2e/private/main.test.bicep | 3 +++ .../tests/e2e/waf-aligned/main.test.bicep | 24 +++++++++++++++++-- .../tests/e2e/waf-aligned/dependencies.bicep | 16 ------------- .../tests/e2e/waf-aligned/main.test.bicep | 14 ----------- .../e2e/{nfs41 => max}/dependencies.bicep | 0 .../tests/e2e/{nfs41 => max}/main.test.bicep | 5 +++- .../tests/e2e/nfs3/main.test.bicep | 3 +++ .../tests/e2e/waf-aligned/main.test.bicep | 4 ++-- 27 files changed, 64 insertions(+), 112 deletions(-) delete mode 100644 avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/dependencies.bicep delete mode 100644 avm/res/databricks/access-connector/tests/e2e/waf-aligned/dependencies.bicep rename avm/res/db-for-my-sql/flexible-server/tests/e2e/{public => max}/dependencies1.bicep (92%) rename avm/res/db-for-my-sql/flexible-server/tests/e2e/{public => max}/dependencies2.bicep (100%) rename avm/res/db-for-my-sql/flexible-server/tests/e2e/{public => max}/main.test.bicep (99%) delete mode 100644 avm/res/health-bot/health-bot/tests/e2e/waf-aligned/dependencies.bicep rename avm/res/net-app/net-app-account/tests/e2e/{nfs41 => max}/dependencies.bicep (100%) rename avm/res/net-app/net-app-account/tests/e2e/{nfs41 => max}/main.test.bicep (96%) diff --git a/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep b/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep index 8339873e82..434bfd9737 100644 --- a/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/defaults/main.test.bicep @@ -35,11 +35,12 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // Test Execution // // ============== // -module testDeployment '../../../main.bicep' = { +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' location: location } -} +}] diff --git a/avm/res/cache/redis/tests/e2e/max/main.test.bicep b/avm/res/cache/redis/tests/e2e/max/main.test.bicep index 0a8d75a182..3c5dd8b0ab 100644 --- a/avm/res/cache/redis/tests/e2e/max/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/max/main.test.bicep @@ -59,9 +59,10 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // Test Execution // // ============== // -module testDeployment '../../../main.bicep' = { +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' location: location @@ -116,4 +117,4 @@ module testDeployment '../../../main.bicep' = { resourceType: 'Redis Cache' } } -} +}] diff --git a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep index 679c070d35..80c60cbe0e 100644 --- a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep @@ -58,9 +58,10 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t // Test Execution // // ============== // -module testDeployment '../../../main.bicep' = { +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' location: location @@ -112,4 +113,4 @@ module testDeployment '../../../main.bicep' = { resourceType: 'Redis Cache' } } -} +}] diff --git a/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep b/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep index e1426d150c..cb89afcd7a 100644 --- a/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/defaults/main.test.bicep @@ -9,7 +9,7 @@ metadata description = 'This instance deploys the module with the minimum set of @description('Optional. The name of the resource group to deploy for testing purposes.') @maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-compute.images-${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}-compute.disk-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') param location string = deployment().location 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 d1a82e8596..096d8eed74 100644 --- a/avm/res/compute/disk/tests/e2e/image/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/image/main.test.bicep @@ -9,7 +9,7 @@ metadata description = 'This instance deploys the module with an image reference @description('Optional. The name of the resource group to deploy for testing purposes.') @maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-compute.images-${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}-compute.disks-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') param location string = deployment().location 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 56fe012475..e677ae61dc 100644 --- a/avm/res/compute/disk/tests/e2e/import/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/import/main.test.bicep @@ -9,7 +9,7 @@ metadata description = 'This instance deploys the module with a custom image tha @description('Optional. The name of the resource group to deploy for testing purposes.') @maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-compute.images-${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}-compute.disks-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') param location string = deployment().location diff --git a/avm/res/compute/disk/tests/e2e/max/main.test.bicep b/avm/res/compute/disk/tests/e2e/max/main.test.bicep index abfb1258f5..523619915c 100644 --- a/avm/res/compute/disk/tests/e2e/max/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/max/main.test.bicep @@ -9,7 +9,7 @@ metadata description = 'This instance deploys the module with most of its featur @description('Optional. The name of the resource group to deploy for testing purposes.') @maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-compute.images-${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}-compute.disks-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') param location string = deployment().location 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 index d901c7a4d3..df88b86a47 100644 --- a/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/compute/disk/tests/e2e/waf-aligned/main.test.bicep @@ -9,7 +9,7 @@ metadata description = 'This instance deploys the module in alignment with the b @description('Optional. The name of the resource group to deploy for testing purposes.') @maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-compute.images-${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}-compute.disks-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') param location string = deployment().location diff --git a/avm/res/compute/image/README.md b/avm/res/compute/image/README.md index b24a5e53ea..02113cc373 100644 --- a/avm/res/compute/image/README.md +++ b/avm/res/compute/image/README.md @@ -30,11 +30,14 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br/public:avm/res/compute/image:`. -- [Defaults](#example-1-defaults) +- [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: _Defaults_ +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. +
diff --git a/avm/res/compute/image/main.json b/avm/res/compute/image/main.json index e0303f37b5..9e92285770 100644 --- a/avm/res/compute/image/main.json +++ b/avm/res/compute/image/main.json @@ -323,4 +323,4 @@ "value": "[reference('image', '2022-11-01', 'full').location]" } } -} \ No newline at end of file +} diff --git a/avm/res/compute/image/tests/e2e/defaults/main.test.bicep b/avm/res/compute/image/tests/e2e/defaults/main.test.bicep index 6f86caa441..959db89c66 100644 --- a/avm/res/compute/image/tests/e2e/defaults/main.test.bicep +++ b/avm/res/compute/image/tests/e2e/defaults/main.test.bicep @@ -1,5 +1,8 @@ targetScope = 'subscription' +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + // ========== // // Parameters // // ========== // @@ -7,7 +10,7 @@ targetScope = 'subscription' @description('Optional. The name of the resource group to deploy for testing purposes.') @maxLength(90) // e.g., for a module 'network/private-endpoint' you could use 'dep-dev-network.privateendpoints-${serviceShort}-rg' -param resourceGroupName string = 'dep-${namePrefix}---${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}-compute.images-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') param location string = deployment().location @@ -17,7 +20,7 @@ param location string = deployment().location param serviceShort string = 'cimin' @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_#' +param namePrefix string = 'wsdfv' // ============ // // Dependencies // diff --git a/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/dependencies.bicep deleted file mode 100644 index 0f0755a6f4..0000000000 --- a/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/dependencies.bicep +++ /dev/null @@ -1,16 +0,0 @@ -@description('Optional. The location to deploy to.') -param location string = resourceGroup().location - -@description('Required. The name of the Managed Identity to create.') -param managedIdentityName string - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location -} - -@description('The principal ID of the created Managed Identity.') -output managedIdentityPrincipalId string = managedIdentity.properties.principalId - -@description('The resource ID of the created Managed Identity.') -output managedIdentityResourceId string = managedIdentity.id diff --git a/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/main.test.bicep b/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/main.test.bicep index 6caa849807..ed5f4485a4 100644 --- a/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/data-protection/backup-vault/tests/e2e/waf-aligned/main.test.bicep @@ -31,15 +31,6 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { location: location } -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - location: location - } -} - // ============== // // Test Execution // // ============== // diff --git a/avm/res/databricks/access-connector/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/databricks/access-connector/tests/e2e/waf-aligned/dependencies.bicep deleted file mode 100644 index b20bc53e8f..0000000000 --- a/avm/res/databricks/access-connector/tests/e2e/waf-aligned/dependencies.bicep +++ /dev/null @@ -1,16 +0,0 @@ -@description('Optional. The location to deploy to.') -param location string = resourceGroup().location - -@description('Required. The name of the Managed Identity to create.') -param managedIdentityName string - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: managedIdentityName - location: location -} - -@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/databricks/access-connector/tests/e2e/waf-aligned/main.test.bicep b/avm/res/databricks/access-connector/tests/e2e/waf-aligned/main.test.bicep index a5afe4fe52..2d140359fb 100644 --- a/avm/res/databricks/access-connector/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/databricks/access-connector/tests/e2e/waf-aligned/main.test.bicep @@ -31,15 +31,6 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { location: location } -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - location: location - } -} - // ============== // // Test Execution // // ============== // @@ -56,9 +47,6 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' } managedIdentities: { systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] } tags: { 'hidden-title': 'This is visible in the resource name' diff --git a/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep b/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep index 32738144a8..471d2b9f00 100644 --- a/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep +++ b/avm/res/databricks/workspace/tests/e2e/max/main.test.bicep @@ -17,9 +17,6 @@ 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 = 'dwmax' -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableDefaultTelemetry bool = true - @description('Generated. Used as a basis for unique resource names.') param baseTime string = utcNow('u') diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/dependencies1.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies1.bicep similarity index 92% rename from avm/res/db-for-my-sql/flexible-server/tests/e2e/public/dependencies1.bicep rename to avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies1.bicep index 82fbab799d..13e2a08e42 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/dependencies1.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies1.bicep @@ -35,7 +35,7 @@ resource getPairedRegionScript 'Microsoft.Resources/deploymentScripts@2020-10-01 azPowerShellVersion: '8.0' retentionInterval: 'P1D' arguments: '-Location \\"${location}\\"' - scriptContent: loadTextContent('../../../../../.shared/.scripts/Get-PairedRegion.ps1') + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/.scripts/Get-PairedRegion.ps1') } dependsOn: [ roleAssignment diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/dependencies2.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies2.bicep similarity index 100% rename from avm/res/db-for-my-sql/flexible-server/tests/e2e/public/dependencies2.bicep rename to avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies2.bicep diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep similarity index 99% rename from avm/res/db-for-my-sql/flexible-server/tests/e2e/public/main.test.bicep rename to avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep index 99cce59bb3..6b8ac78e1b 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/public/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep @@ -12,7 +12,7 @@ param resourceGroupName string = 'dep-${namePrefix}-dbformysql.flexibleservers-$ 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 = 'dfmsfsp' +param serviceShort string = 'dfmsfsmax' @description('Optional. The password to leverage for the login.') @secure() diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep index 15ae96eed1..5e28aa17b3 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep @@ -1,5 +1,8 @@ targetScope = 'subscription' +metadata name = 'Deploys in connectivity mode "Private Access"' +metadata description = 'This instance deploys the module with connectivity mode "Private Access".' + // ========== // // Parameters // // ========== // diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep index 1c3183493c..ae4483dba2 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep @@ -1,5 +1,8 @@ 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 // // ========== // @@ -7,7 +10,7 @@ targetScope = 'subscription' @description('Optional. The name of the resource group to deploy for testing purposes.') @maxLength(90) // e.g., for a module 'network/private-endpoint' you could use 'dep-dev-network.privateendpoints-${serviceShort}-rg' -param resourceGroupName string = 'dep-${namePrefix}---${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}-dbformysql.flexibleservers-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') param location string = deployment().location @@ -16,6 +19,10 @@ param location string = deployment().location // e.g., for a module 'network/private-endpoint' you could use 'npe' as a prefix and then 'waf' as a suffix for the waf-aligned test param serviceShort string = 'dfmsfswaf' +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + @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_#' @@ -39,7 +46,20 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - // You parameters go here name: '${namePrefix}${serviceShort}001' + location: location + administratorLogin: 'adminUserName' + administratorLoginPassword: password + skuName: 'Standard_B1ms' + tier: 'Burstable' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } } }] diff --git a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/dependencies.bicep deleted file mode 100644 index 539240be2b..0000000000 --- a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/dependencies.bicep +++ /dev/null @@ -1,16 +0,0 @@ -@description('Optional. The location to deploy to.') -param location string = resourceGroup().location - -@description('Required. The name of the Managed Identity to create.') -param managedIdentityName string - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location -} - -@description('The resource ID of the created Managed Identity.') -output managedIdentityResourceId string = managedIdentity.id - -@description('The principal ID of the created Managed Identity.') -output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep index 0b84c6a96c..0e2649a748 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep @@ -31,15 +31,6 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { location: location } -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - location: location - } -} - // ============== // // Test Execution // // ============== // @@ -61,10 +52,5 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Role: 'DeploymentValidation' } sku: 'F0' - managedIdentities: { - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } } }] diff --git a/avm/res/net-app/net-app-account/tests/e2e/nfs41/dependencies.bicep b/avm/res/net-app/net-app-account/tests/e2e/max/dependencies.bicep similarity index 100% rename from avm/res/net-app/net-app-account/tests/e2e/nfs41/dependencies.bicep rename to avm/res/net-app/net-app-account/tests/e2e/max/dependencies.bicep diff --git a/avm/res/net-app/net-app-account/tests/e2e/nfs41/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/max/main.test.bicep similarity index 96% rename from avm/res/net-app/net-app-account/tests/e2e/nfs41/main.test.bicep rename to avm/res/net-app/net-app-account/tests/e2e/max/main.test.bicep index 8298ddd89e..cf0c4fba73 100644 --- a/avm/res/net-app/net-app-account/tests/e2e/nfs41/main.test.bicep +++ b/avm/res/net-app/net-app-account/tests/e2e/max/main.test.bicep @@ -1,5 +1,8 @@ targetScope = 'subscription' +metadata name = 'Using large parameter set' +metadata description = 'This instance deploys the module with most of its features enabled.' + // ========== // // Parameters // // ========== // @@ -12,7 +15,7 @@ param resourceGroupName string = 'dep-${namePrefix}-netapp.netappaccounts-${serv 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 = 'nanaanfs41' +param serviceShort string = 'nanaamax' @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' diff --git a/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep index 26b4c9e122..b9adce0c96 100644 --- a/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep +++ b/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep @@ -1,5 +1,8 @@ targetScope = 'subscription' +metadata name = 'Using nfs31 parameter set' +metadata description = 'This instance deploys the module with nfs31.' + // ========== // // Parameters // // ========== // diff --git a/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep index 6b4ddb0e4e..de405f6652 100644 --- a/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep @@ -7,7 +7,7 @@ targetScope = 'subscription' @description('Optional. The name of the resource group to deploy for testing purposes.') @maxLength(90) // e.g., for a module 'network/private-endpoint' you could use 'dep-dev-network.privateendpoints-${serviceShort}-rg' -param resourceGroupName string = 'dep-${namePrefix}---${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}-netapp.netappaccounts-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') param location string = deployment().location @@ -39,7 +39,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { - // You parameters go here name: '${namePrefix}${serviceShort}001' + location: location } }] From c52a3860b3bb1ac1682626c680df24e0b1c87510 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 17:16:23 +1000 Subject: [PATCH 11/33] . --- avm/res/analysis-services/server/README.md | 8 +- avm/res/analysis-services/server/main.json | 12 +- avm/res/cache/redis/README.md | 25 +- avm/res/cache/redis/main.json | 142 +++---- avm/res/compute/disk/main.json | 2 +- .../image/tests/e2e/defaults/main.test.bicep | 2 +- avm/res/consumption/budget/README.md | 14 +- .../data-protection/backup-vault/README.md | 5 + avm/res/databricks/access-connector/README.md | 17 +- avm/res/databricks/access-connector/main.json | 4 +- avm/res/databricks/workspace/README.md | 21 +- avm/res/databricks/workspace/main.json | 296 +++++++------- .../db-for-my-sql/flexible-server/README.md | 373 ++++++++++-------- .../db-for-my-sql/flexible-server/main.json | 10 +- avm/res/health-bot/health-bot/README.md | 21 +- avm/res/health-bot/health-bot/main.json | 4 +- avm/res/net-app/net-app-account/README.md | 175 ++++---- avm/res/net-app/net-app-account/main.json | 4 +- 18 files changed, 622 insertions(+), 513 deletions(-) diff --git a/avm/res/analysis-services/server/README.md b/avm/res/analysis-services/server/README.md index f967256c4e..d00c8ba280 100644 --- a/avm/res/analysis-services/server/README.md +++ b/avm/res/analysis-services/server/README.md @@ -458,7 +458,7 @@ The diagnostic settings of the service. | [`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. | -| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allMetrics" includes all possible logs for the resource. Set to '' to disable log collection. | | [`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. | @@ -507,7 +507,7 @@ The full ARM resource ID of the Marketplace resource to which you would like to ### Parameter: `diagnosticSettings.metricCategories` -The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. +The name of logs that will be streamed. "allMetrics" includes all possible logs for the resource. Set to '' to disable log collection. - Required: No - Type: array @@ -623,7 +623,7 @@ Array of role assignments to create. | 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" | +| [`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. | @@ -645,7 +645,7 @@ The role to assign. You can provide either the display name of the role definiti ### 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" +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 diff --git a/avm/res/analysis-services/server/main.json b/avm/res/analysis-services/server/main.json index fc3e70d8a2..0202c2c6c8 100644 --- a/avm/res/analysis-services/server/main.json +++ b/avm/res/analysis-services/server/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "15153643486811668197" + "templateHash": "17318307385986864132" }, "name": "Analysis Services Servers", "description": "This module deploys an Analysis Services Server.", @@ -80,7 +80,7 @@ "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\"" + "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": { @@ -132,7 +132,7 @@ "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." + "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." } } } @@ -150,14 +150,14 @@ "category": { "type": "string", "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to 'AllMetrics' to collect all metrics." + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." } } } }, "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." + "description": "Optional. The name of logs that will be streamed. \"allMetrics\" includes all possible logs for the resource. Set to '' to disable log collection." } }, "logAnalyticsDestinationType": { @@ -422,4 +422,4 @@ "value": "[reference('server', '2017-08-01', 'full').location]" } } -} +} \ No newline at end of file diff --git a/avm/res/cache/redis/README.md b/avm/res/cache/redis/README.md index e28143dc71..c1b71173dd 100644 --- a/avm/res/cache/redis/README.md +++ b/avm/res/cache/redis/README.md @@ -1,5 +1,10 @@ # Redis Cache `[Microsoft.Cache/redis]` +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + This module deploys a Redis Cache. ## Navigation @@ -303,9 +308,6 @@ module redis 'br/public:avm/res/cache/redis:' = { } managedIdentities: { systemAssigned: true - userAssignedResourceIds: [ - '' - ] } minimumTlsVersion: '1.2' privateEndpoints: [ @@ -388,10 +390,7 @@ module redis 'br/public:avm/res/cache/redis:' = { }, "managedIdentities": { "value": { - "systemAssigned": true, - "userAssignedResourceIds": [ - "" - ] + "systemAssigned": true } }, "minimumTlsVersion": { @@ -526,7 +525,7 @@ The diagnostic settings of the service. | [`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. | -| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allMetrics" includes all possible logs for the resource. Set to '' to disable log collection. | | [`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. | @@ -575,7 +574,7 @@ The full ARM resource ID of the Marketplace resource to which you would like to ### Parameter: `diagnosticSettings.metricCategories` -The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. +The name of logs that will be streamed. "allMetrics" includes all possible logs for the resource. Set to '' to disable log collection. - Required: No - Type: array @@ -868,7 +867,7 @@ Array of role assignments to create. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`condition`](#parameter-privateendpointsroleassignmentscondition) | 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" | +| [`condition`](#parameter-privateendpointsroleassignmentscondition) | 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-privateendpointsroleassignmentsconditionversion) | string | Version of the condition. | | [`delegatedManagedIdentityResourceId`](#parameter-privateendpointsroleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | | [`description`](#parameter-privateendpointsroleassignmentsdescription) | string | The description of the role assignment. | @@ -890,7 +889,7 @@ The role to assign. You can provide either the display name of the role definiti ### Parameter: `privateEndpoints.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" +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 @@ -1026,7 +1025,7 @@ Array of role assignments to create. | 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" | +| [`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. | @@ -1048,7 +1047,7 @@ The role to assign. You can provide either the display name of the role definiti ### 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" +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 diff --git a/avm/res/cache/redis/main.json b/avm/res/cache/redis/main.json index 1fedbb9604..f40cbccc41 100644 --- a/avm/res/cache/redis/main.json +++ b/avm/res/cache/redis/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "12006824777124262825" + "templateHash": "4044387362593822012" }, "name": "Redis Cache", "description": "This module deploys a Redis Cache.", @@ -61,72 +61,6 @@ }, "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 - }, "privateEndpointType": { "type": "array", "items": { @@ -302,6 +236,72 @@ }, "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": { @@ -330,7 +330,7 @@ "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." + "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." } } } @@ -348,14 +348,14 @@ "category": { "type": "string", "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to 'AllMetrics' to collect all metrics." + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." } } } }, "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." + "description": "Optional. The name of logs that will be streamed. \"allMetrics\" includes all possible logs for the resource. Set to '' to disable log collection." } }, "logAnalyticsDestinationType": { @@ -1451,4 +1451,4 @@ "value": "[reference('redis', '2022-06-01', 'full').location]" } } -} +} \ No newline at end of file diff --git a/avm/res/compute/disk/main.json b/avm/res/compute/disk/main.json index 4d9e767876..bc84f59e04 100644 --- a/avm/res/compute/disk/main.json +++ b/avm/res/compute/disk/main.json @@ -479,4 +479,4 @@ "value": "[reference('disk', '2022-07-02', 'full').location]" } } -} +} \ No newline at end of file diff --git a/avm/res/compute/image/tests/e2e/defaults/main.test.bicep b/avm/res/compute/image/tests/e2e/defaults/main.test.bicep index 959db89c66..e0b36cf3db 100644 --- a/avm/res/compute/image/tests/e2e/defaults/main.test.bicep +++ b/avm/res/compute/image/tests/e2e/defaults/main.test.bicep @@ -20,7 +20,7 @@ param location string = deployment().location param serviceShort string = 'cimin' @description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') -param namePrefix string = 'wsdfv' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // diff --git a/avm/res/consumption/budget/README.md b/avm/res/consumption/budget/README.md index 6e955e668b..46a09e3687 100644 --- a/avm/res/consumption/budget/README.md +++ b/avm/res/consumption/budget/README.md @@ -24,11 +24,14 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br/public:avm/res/consumption/budget:`. -- [Defaults](#example-1-defaults) +- [Using only defaults](#example-1-using-only-defaults) - [Using large parameter set](#example-2-using-large-parameter-set) -- [Waf-Aligned](#example-3-waf-aligned) +- [WAF-aligned](#example-3-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. -### Example 1: _Defaults_
@@ -161,7 +164,10 @@ module budget 'br/public:avm/res/consumption/budget:' = {

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

diff --git a/avm/res/data-protection/backup-vault/README.md b/avm/res/data-protection/backup-vault/README.md index a463e0cbe5..4a25216945 100644 --- a/avm/res/data-protection/backup-vault/README.md +++ b/avm/res/data-protection/backup-vault/README.md @@ -1,5 +1,10 @@ # Data Protection Backup Vaults `[Microsoft.DataProtection/backupVaults]` +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + This module deploys a Data Protection Backup Vault. ## Navigation diff --git a/avm/res/databricks/access-connector/README.md b/avm/res/databricks/access-connector/README.md index bc1f487b71..1db170c0a6 100644 --- a/avm/res/databricks/access-connector/README.md +++ b/avm/res/databricks/access-connector/README.md @@ -1,5 +1,10 @@ # Azure Databricks Access Connectors `[Microsoft.Databricks/accessConnectors]` +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + This module deploys an Azure Databricks Access Connector. ## Navigation @@ -221,9 +226,6 @@ module accessConnector 'br/public:avm/res/databricks/access-connector:' } managedIdentities: { systemAssigned: true - userAssignedResourceIds: [ - '' - ] } tags: { Environment: 'Non-Prod' @@ -262,10 +264,7 @@ module accessConnector 'br/public:avm/res/databricks/access-connector:' }, "managedIdentities": { "value": { - "systemAssigned": true, - "userAssignedResourceIds": [ - "" - ] + "systemAssigned": true } }, "tags": { @@ -407,7 +406,7 @@ Array of role assignments to create. | 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" | +| [`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. | @@ -429,7 +428,7 @@ The role to assign. You can provide either the display name of the role definiti ### 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" +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 diff --git a/avm/res/databricks/access-connector/main.json b/avm/res/databricks/access-connector/main.json index b55b4ceff1..b7808bde2b 100644 --- a/avm/res/databricks/access-connector/main.json +++ b/avm/res/databricks/access-connector/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "394207615675999827" + "templateHash": "16111229850064788886" }, "name": "Azure Databricks Access Connectors", "description": "This module deploys an Azure Databricks Access Connector.", @@ -103,7 +103,7 @@ "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\"" + "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": { diff --git a/avm/res/databricks/workspace/README.md b/avm/res/databricks/workspace/README.md index 0b9a5f72f1..976df39ed4 100644 --- a/avm/res/databricks/workspace/README.md +++ b/avm/res/databricks/workspace/README.md @@ -1,5 +1,10 @@ # Azure Databricks Workspaces `[Microsoft.Databricks/workspaces]` +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + This module deploys an Azure Databricks Workspace. ## Navigation @@ -772,6 +777,7 @@ The diagnostic settings of the service. | [`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. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allMetrics" includes all possible logs for the resource. Set to '' to disable log collection. | | [`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. | @@ -818,6 +824,13 @@ The full ARM resource ID of the Marketplace resource to which you would like to - Required: No - Type: string +### Parameter: `diagnosticSettings.metricCategories` + +The name of logs that will be streamed. "allMetrics" includes all possible logs for the resource. Set to '' to disable log collection. + +- Required: No +- Type: array + ### Parameter: `diagnosticSettings.name` The name of diagnostic setting. @@ -1102,7 +1115,7 @@ Array of role assignments to create. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`condition`](#parameter-privateendpointsroleassignmentscondition) | 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" | +| [`condition`](#parameter-privateendpointsroleassignmentscondition) | 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-privateendpointsroleassignmentsconditionversion) | string | Version of the condition. | | [`delegatedManagedIdentityResourceId`](#parameter-privateendpointsroleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | | [`description`](#parameter-privateendpointsroleassignmentsdescription) | string | The description of the role assignment. | @@ -1124,7 +1137,7 @@ The role to assign. You can provide either the display name of the role definiti ### Parameter: `privateEndpoints.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" +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 @@ -1251,7 +1264,7 @@ Array of role assignments to create. | 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" | +| [`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. | @@ -1273,7 +1286,7 @@ The role to assign. You can provide either the display name of the role definiti ### 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" +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 diff --git a/avm/res/databricks/workspace/main.json b/avm/res/databricks/workspace/main.json index 4444ba4674..0c4fc446e6 100644 --- a/avm/res/databricks/workspace/main.json +++ b/avm/res/databricks/workspace/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "14087130830480205215" + "templateHash": "10487472164108897566" }, "name": "Azure Databricks Workspaces", "description": "This module deploys an Azure Databricks Workspace.", @@ -38,72 +38,6 @@ }, "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 - }, "privateEndpointType": { "type": "array", "items": { @@ -279,6 +213,143 @@ }, "nullable": true }, + "customerManagedKeyType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + } + }, + "nullable": true + }, + "customerManagedKeyManagedDiskType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + }, + "rotationToLatestKeyVersionEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Indicate whether the latest key version should be automatically used for Managed Disk Encryption. Enabled by default." + } + } + }, + "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": { @@ -307,7 +378,7 @@ "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." + "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." } } } @@ -317,6 +388,24 @@ "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." } }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allMetrics\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, "logAnalyticsDestinationType": { "type": "string", "allowedValues": [ @@ -366,77 +455,6 @@ } }, "nullable": true - }, - "customerManagedKeyType": { - "type": "object", - "properties": { - "keyVaultResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." - } - }, - "keyName": { - "type": "string", - "metadata": { - "description": "Required. The name of the customer managed key to use for encryption." - } - }, - "keyVersion": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." - } - }, - "userAssignedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." - } - } - }, - "nullable": true - }, - "customerManagedKeyManagedDiskType": { - "type": "object", - "properties": { - "keyVaultResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." - } - }, - "keyName": { - "type": "string", - "metadata": { - "description": "Required. The name of the customer managed key to use for encryption." - } - }, - "keyVersion": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." - } - }, - "userAssignedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." - } - }, - "rotationToLatestKeyVersionEnabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Indicate whether the latest key version should be automatically used for Managed Disk Encryption. Enabled by default." - } - } - }, - "nullable": true } }, "parameters": { diff --git a/avm/res/db-for-my-sql/flexible-server/README.md b/avm/res/db-for-my-sql/flexible-server/README.md index b62c12a34c..75748b13df 100644 --- a/avm/res/db-for-my-sql/flexible-server/README.md +++ b/avm/res/db-for-my-sql/flexible-server/README.md @@ -1,5 +1,10 @@ # DBforMySQL Flexible Servers `[Microsoft.DBforMySQL/flexibleServers]` +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + This module deploys a DBforMySQL Flexible Server. ## Navigation @@ -31,9 +36,9 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br/public:avm/res/db-for-my-sql/flexible-server:`. - [Using only defaults](#example-1-using-only-defaults) -- [Private](#example-2-private) -- [Public](#example-3-public) -- [Waf-Aligned](#example-4-waf-aligned) +- [Max](#example-2-max) +- [Deploys in connectivity mode "Private Access"](#example-3-deploys-in-connectivity-mode-private-access) +- [WAF-aligned](#example-4-waf-aligned) ### Example 1: _Using only defaults_ @@ -99,7 +104,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:

-### Example 2: _Private_ +### Example 2: _Max_

@@ -107,29 +112,37 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: ```bicep module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, location)}-test-dfmsfspvt' + name: '${uniqueString(deployment().name, location)}-test-dfmsfsmax' params: { // Required parameters - name: 'dfmsfspvt001' + name: 'dfmsfsmax001' skuName: 'Standard_D2ds_v4' tier: 'GeneralPurpose' // Non-required parameters administratorLogin: 'adminUserName' administratorLoginPassword: '' - administrators: [ - { - identityResourceId: '' - login: '' - sid: '' - } - ] - backupRetentionDays: 10 + availabilityZone: '1' + backupRetentionDays: 20 + customerManagedKey: { + keyName: '' + keyVaultResourceId: '' + userAssignedIdentityResourceId: '' + } + customerManagedKeyGeo: { + keyName: '' + keyVaultResourceId: '' + userAssignedIdentityResourceId: '' + } databases: [ { name: 'testdb1' } + { + charset: 'ascii' + collation: 'ascii_general_ci' + name: 'testdb2' + } ] - delegatedSubnetResourceId: '' diagnosticSettings: [ { eventHubAuthorizationRuleResourceId: '' @@ -144,6 +157,24 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: workspaceResourceId: '' } ] + firewallRules: [ + { + endIpAddress: '0.0.0.0' + name: 'AllowAllWindowsAzureIps' + startIpAddress: '0.0.0.0' + } + { + endIpAddress: '10.10.10.10' + name: 'test-rule1' + startIpAddress: '10.10.10.1' + } + { + endIpAddress: '100.100.100.10' + name: 'test-rule2' + startIpAddress: '100.100.100.1' + } + ] + geoRedundantBackup: 'Enabled' highAvailability: 'SameZone' location: '' lock: { @@ -152,36 +183,27 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: } managedIdentities: { userAssignedResourceIds: [ + '' '' ] } - privateDnsZoneResourceId: '' roleAssignments: [ { principalId: '' principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Owner' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: '' + roleDefinitionIdOrName: 'Reader' } ] storageAutoGrow: 'Enabled' storageAutoIoScaling: 'Enabled' storageIOPS: 400 - storageSizeGB: 64 + storageSizeGB: 32 tags: { 'hidden-title': 'This is visible in the resource name' resourceType: 'MySQL Flexible Server' - serverName: 'dfmsfspvt001' + serverName: 'dfmsfsmax001' } + version: '8.0.21' } } ``` @@ -200,7 +222,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "parameters": { // Required parameters "name": { - "value": "dfmsfspvt001" + "value": "dfmsfsmax001" }, "skuName": { "value": "Standard_D2ds_v4" @@ -215,28 +237,38 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "administratorLoginPassword": { "value": "" }, - "administrators": { - "value": [ - { - "identityResourceId": "", - "login": "", - "sid": "" - } - ] + "availabilityZone": { + "value": "1" }, "backupRetentionDays": { - "value": 10 + "value": 20 + }, + "customerManagedKey": { + "value": { + "keyName": "", + "keyVaultResourceId": "", + "userAssignedIdentityResourceId": "" + } + }, + "customerManagedKeyGeo": { + "value": { + "keyName": "", + "keyVaultResourceId": "", + "userAssignedIdentityResourceId": "" + } }, "databases": { "value": [ { "name": "testdb1" + }, + { + "charset": "ascii", + "collation": "ascii_general_ci", + "name": "testdb2" } ] }, - "delegatedSubnetResourceId": { - "value": "" - }, "diagnosticSettings": { "value": [ { @@ -253,6 +285,28 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: } ] }, + "firewallRules": { + "value": [ + { + "endIpAddress": "0.0.0.0", + "name": "AllowAllWindowsAzureIps", + "startIpAddress": "0.0.0.0" + }, + { + "endIpAddress": "10.10.10.10", + "name": "test-rule1", + "startIpAddress": "10.10.10.1" + }, + { + "endIpAddress": "100.100.100.10", + "name": "test-rule2", + "startIpAddress": "100.100.100.1" + } + ] + }, + "geoRedundantBackup": { + "value": "Enabled" + }, "highAvailability": { "value": "SameZone" }, @@ -268,29 +322,17 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "managedIdentities": { "value": { "userAssignedResourceIds": [ + "", "" ] } }, - "privateDnsZoneResourceId": { - "value": "" - }, "roleAssignments": { "value": [ { "principalId": "", "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Owner" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "" + "roleDefinitionIdOrName": "Reader" } ] }, @@ -304,14 +346,17 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "value": 400 }, "storageSizeGB": { - "value": 64 + "value": 32 }, "tags": { "value": { "hidden-title": "This is visible in the resource name", "resourceType": "MySQL Flexible Server", - "serverName": "dfmsfspvt001" + "serverName": "dfmsfsmax001" } + }, + "version": { + "value": "8.0.21" } } } @@ -320,7 +365,10 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:

-### Example 3: _Public_ +### Example 3: _Deploys in connectivity mode "Private Access"_ + +This instance deploys the module with connectivity mode "Private Access". +

@@ -328,37 +376,29 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: ```bicep module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, location)}-test-dfmsfsp' + name: '${uniqueString(deployment().name, location)}-test-dfmsfspvt' params: { // Required parameters - name: 'dfmsfsp001' + name: 'dfmsfspvt001' skuName: 'Standard_D2ds_v4' tier: 'GeneralPurpose' // Non-required parameters administratorLogin: 'adminUserName' administratorLoginPassword: '' - availabilityZone: '1' - backupRetentionDays: 20 - customerManagedKey: { - keyName: '' - keyVaultResourceId: '' - userAssignedIdentityResourceId: '' - } - customerManagedKeyGeo: { - keyName: '' - keyVaultResourceId: '' - userAssignedIdentityResourceId: '' - } - databases: [ + administrators: [ { - name: 'testdb1' + identityResourceId: '' + login: '' + sid: '' } + ] + backupRetentionDays: 10 + databases: [ { - charset: 'ascii' - collation: 'ascii_general_ci' - name: 'testdb2' + name: 'testdb1' } ] + delegatedSubnetResourceId: '' diagnosticSettings: [ { eventHubAuthorizationRuleResourceId: '' @@ -373,24 +413,6 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: workspaceResourceId: '' } ] - firewallRules: [ - { - endIpAddress: '0.0.0.0' - name: 'AllowAllWindowsAzureIps' - startIpAddress: '0.0.0.0' - } - { - endIpAddress: '10.10.10.10' - name: 'test-rule1' - startIpAddress: '10.10.10.1' - } - { - endIpAddress: '100.100.100.10' - name: 'test-rule2' - startIpAddress: '100.100.100.1' - } - ] - geoRedundantBackup: 'Enabled' highAvailability: 'SameZone' location: '' lock: { @@ -399,27 +421,36 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: } managedIdentities: { userAssignedResourceIds: [ - '' '' ] } + privateDnsZoneResourceId: '' roleAssignments: [ { principalId: '' principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Reader' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' } ] storageAutoGrow: 'Enabled' storageAutoIoScaling: 'Enabled' storageIOPS: 400 - storageSizeGB: 32 + storageSizeGB: 64 tags: { 'hidden-title': 'This is visible in the resource name' resourceType: 'MySQL Flexible Server' - serverName: 'dfmsfsp001' + serverName: 'dfmsfspvt001' } - version: '8.0.21' } } ``` @@ -438,7 +469,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "parameters": { // Required parameters "name": { - "value": "dfmsfsp001" + "value": "dfmsfspvt001" }, "skuName": { "value": "Standard_D2ds_v4" @@ -453,38 +484,28 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "administratorLoginPassword": { "value": "" }, - "availabilityZone": { - "value": "1" + "administrators": { + "value": [ + { + "identityResourceId": "", + "login": "", + "sid": "" + } + ] }, "backupRetentionDays": { - "value": 20 - }, - "customerManagedKey": { - "value": { - "keyName": "", - "keyVaultResourceId": "", - "userAssignedIdentityResourceId": "" - } - }, - "customerManagedKeyGeo": { - "value": { - "keyName": "", - "keyVaultResourceId": "", - "userAssignedIdentityResourceId": "" - } + "value": 10 }, "databases": { "value": [ { "name": "testdb1" - }, - { - "charset": "ascii", - "collation": "ascii_general_ci", - "name": "testdb2" } ] }, + "delegatedSubnetResourceId": { + "value": "" + }, "diagnosticSettings": { "value": [ { @@ -501,28 +522,6 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: } ] }, - "firewallRules": { - "value": [ - { - "endIpAddress": "0.0.0.0", - "name": "AllowAllWindowsAzureIps", - "startIpAddress": "0.0.0.0" - }, - { - "endIpAddress": "10.10.10.10", - "name": "test-rule1", - "startIpAddress": "10.10.10.1" - }, - { - "endIpAddress": "100.100.100.10", - "name": "test-rule2", - "startIpAddress": "100.100.100.1" - } - ] - }, - "geoRedundantBackup": { - "value": "Enabled" - }, "highAvailability": { "value": "SameZone" }, @@ -538,17 +537,29 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "managedIdentities": { "value": { "userAssignedResourceIds": [ - "", "" ] } }, + "privateDnsZoneResourceId": { + "value": "" + }, "roleAssignments": { "value": [ { "principalId": "", "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Reader" + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" } ] }, @@ -562,17 +573,14 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "value": 400 }, "storageSizeGB": { - "value": 32 + "value": 64 }, "tags": { "value": { "hidden-title": "This is visible in the resource name", "resourceType": "MySQL Flexible Server", - "serverName": "dfmsfsp001" + "serverName": "dfmsfspvt001" } - }, - "version": { - "value": "8.0.21" } } } @@ -581,7 +589,10 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:

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

@@ -591,7 +602,23 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { name: '${uniqueString(deployment().name, location)}-test-dfmsfswaf' params: { + // Required parameters name: 'dfmsfswaf001' + skuName: 'Standard_B1ms' + tier: 'Burstable' + // Non-required parameters + administratorLogin: 'adminUserName' + administratorLoginPassword: '' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } } } ``` @@ -608,8 +635,38 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { + // Required parameters "name": { "value": "dfmsfswaf001" + }, + "skuName": { + "value": "Standard_B1ms" + }, + "tier": { + "value": "Burstable" + }, + // Non-required parameters + "administratorLogin": { + "value": "adminUserName" + }, + "administratorLoginPassword": { + "value": "" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } } } } @@ -953,7 +1010,7 @@ The diagnostic settings of the service. | [`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. | -| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of logs that will be streamed. "allMetrics" includes all possible logs for the resource. Set to '' to disable log collection. | | [`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. | @@ -1002,7 +1059,7 @@ The full ARM resource ID of the Marketplace resource to which you would like to ### Parameter: `diagnosticSettings.metricCategories` -The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. +The name of logs that will be streamed. "allMetrics" includes all possible logs for the resource. Set to '' to disable log collection. - Required: No - Type: array @@ -1161,7 +1218,7 @@ Array of role assignment objects that contain the "roleDefinitionIdOrName" and " | 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" | +| [`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. | @@ -1183,7 +1240,7 @@ The role to assign. You can provide either the display name of the role definiti ### 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" +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 diff --git a/avm/res/db-for-my-sql/flexible-server/main.json b/avm/res/db-for-my-sql/flexible-server/main.json index 40d415eff2..e56b8aa8e7 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.json +++ b/avm/res/db-for-my-sql/flexible-server/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "9454239676460003107" + "templateHash": "10366576748540516282" }, "name": "DBforMySQL Flexible Servers", "description": "This module deploys a DBforMySQL Flexible Server.", @@ -95,7 +95,7 @@ "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\"" + "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": { @@ -147,7 +147,7 @@ "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." + "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." } } } @@ -165,14 +165,14 @@ "category": { "type": "string", "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to 'AllMetrics' to collect all metrics." + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." } } } }, "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." + "description": "Optional. The name of logs that will be streamed. \"allMetrics\" includes all possible logs for the resource. Set to '' to disable log collection." } }, "logAnalyticsDestinationType": { diff --git a/avm/res/health-bot/health-bot/README.md b/avm/res/health-bot/health-bot/README.md index 77e0fddafa..d29eb1585b 100644 --- a/avm/res/health-bot/health-bot/README.md +++ b/avm/res/health-bot/health-bot/README.md @@ -1,5 +1,10 @@ # Azure Health Bots `[Microsoft.HealthBot/healthBots]` +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + This module deploys an Azure Health Bot. ## Navigation @@ -226,11 +231,6 @@ module healthBot 'br/public:avm/res/health-bot/health-bot:' = { kind: 'CanNotDelete' name: 'myCustomLockName' } - managedIdentities: { - userAssignedResourceIds: [ - '' - ] - } tags: { Environment: 'Non-Prod' 'hidden-title': 'This is visible in the resource name' @@ -269,13 +269,6 @@ module healthBot 'br/public:avm/res/health-bot/health-bot:' = { "name": "myCustomLockName" } }, - "managedIdentities": { - "value": { - "userAssignedResourceIds": [ - "" - ] - } - }, "tags": { "value": { "Environment": "Non-Prod", @@ -423,7 +416,7 @@ Array of role assignments to create. | 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" | +| [`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. | @@ -445,7 +438,7 @@ The role to assign. You can provide either the display name of the role definiti ### 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" +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 diff --git a/avm/res/health-bot/health-bot/main.json b/avm/res/health-bot/health-bot/main.json index f2fa5f7eb1..c074878ca8 100644 --- a/avm/res/health-bot/health-bot/main.json +++ b/avm/res/health-bot/health-bot/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "15987244695395932464" + "templateHash": "1383571101384884749" }, "name": "Azure Health Bots", "description": "This module deploys an Azure Health Bot.", @@ -95,7 +95,7 @@ "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\"" + "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": { diff --git a/avm/res/net-app/net-app-account/README.md b/avm/res/net-app/net-app-account/README.md index 3e4cae9c70..765d638873 100644 --- a/avm/res/net-app/net-app-account/README.md +++ b/avm/res/net-app/net-app-account/README.md @@ -1,5 +1,10 @@ # Azure NetApp Files `[Microsoft.NetApp/netAppAccounts]` +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + This module deploys an Azure NetApp File. ## Navigation @@ -29,8 +34,8 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br/public:avm/res/net-app/net-app-account:`. - [Using only defaults](#example-1-using-only-defaults) -- [Nfs3](#example-2-nfs3) -- [Nfs41](#example-3-nfs41) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [Using nfs31 parameter set](#example-3-using-nfs31-parameter-set) - [Waf-Aligned](#example-4-waf-aligned) ### Example 1: _Using only defaults_ @@ -81,7 +86,10 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = {

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

@@ -89,14 +97,14 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { ```bicep module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { - name: '${uniqueString(deployment().name, location)}-test-nanaanfs3' + name: '${uniqueString(deployment().name, location)}-test-nanaamax' params: { // Required parameters - name: 'nanaanfs3001' + name: 'nanaamax001' // Non-required parameters capacityPools: [ { - name: 'nanaanfs3-cp-001' + name: 'nanaamax-cp-001' roleAssignments: [ { principalId: '' @@ -111,16 +119,16 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { exportPolicyRules: [ { allowedClients: '0.0.0.0/0' - nfsv3: true - nfsv41: false + nfsv3: false + nfsv41: true ruleIndex: 1 unixReadOnly: false unixReadWrite: true } ] - name: 'nanaanfs3-vol-001' + name: 'nanaamax-vol-001' protocolTypes: [ - 'NFSv3' + 'NFSv4.1' ] roleAssignments: [ { @@ -133,9 +141,19 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { usageThreshold: 107374182400 } { - name: 'nanaanfs3-vol-002' + exportPolicyRules: [ + { + allowedClients: '0.0.0.0/0' + nfsv3: false + nfsv41: true + ruleIndex: 1 + unixReadOnly: false + unixReadWrite: true + } + ] + name: 'nanaamax-vol-002' protocolTypes: [ - 'NFSv3' + 'NFSv4.1' ] subnetResourceId: '' usageThreshold: 107374182400 @@ -143,7 +161,7 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { ] } { - name: 'nanaanfs3-cp-002' + name: 'nanaamax-cp-002' roleAssignments: [ { principalId: '' @@ -157,9 +175,10 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { } ] location: '' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' + managedIdentities: { + userAssignedResourceIds: [ + '' + ] } roleAssignments: [ { @@ -205,13 +224,13 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { "parameters": { // Required parameters "name": { - "value": "nanaanfs3001" + "value": "nanaamax001" }, // Non-required parameters "capacityPools": { "value": [ { - "name": "nanaanfs3-cp-001", + "name": "nanaamax-cp-001", "roleAssignments": [ { "principalId": "", @@ -226,16 +245,16 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { "exportPolicyRules": [ { "allowedClients": "0.0.0.0/0", - "nfsv3": true, - "nfsv41": false, + "nfsv3": false, + "nfsv41": true, "ruleIndex": 1, "unixReadOnly": false, "unixReadWrite": true } ], - "name": "nanaanfs3-vol-001", + "name": "nanaamax-vol-001", "protocolTypes": [ - "NFSv3" + "NFSv4.1" ], "roleAssignments": [ { @@ -248,9 +267,19 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { "usageThreshold": 107374182400 }, { - "name": "nanaanfs3-vol-002", + "exportPolicyRules": [ + { + "allowedClients": "0.0.0.0/0", + "nfsv3": false, + "nfsv41": true, + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true + } + ], + "name": "nanaamax-vol-002", "protocolTypes": [ - "NFSv3" + "NFSv4.1" ], "subnetResourceId": "", "usageThreshold": 107374182400 @@ -258,7 +287,7 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { ] }, { - "name": "nanaanfs3-cp-002", + "name": "nanaamax-cp-002", "roleAssignments": [ { "principalId": "", @@ -275,10 +304,11 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { "location": { "value": "" }, - "lock": { + "managedIdentities": { "value": { - "kind": "CanNotDelete", - "name": "myCustomLockName" + "userAssignedResourceIds": [ + "" + ] } }, "roleAssignments": { @@ -318,7 +348,10 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = {

-### Example 3: _Nfs41_ +### Example 3: _Using nfs31 parameter set_ + +This instance deploys the module with nfs31. +

@@ -326,14 +359,14 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { ```bicep module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { - name: '${uniqueString(deployment().name, location)}-test-nanaanfs41' + name: '${uniqueString(deployment().name, location)}-test-nanaanfs3' params: { // Required parameters - name: 'nanaanfs41001' + name: 'nanaanfs3001' // Non-required parameters capacityPools: [ { - name: 'nanaanfs41-cp-001' + name: 'nanaanfs3-cp-001' roleAssignments: [ { principalId: '' @@ -348,16 +381,16 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { exportPolicyRules: [ { allowedClients: '0.0.0.0/0' - nfsv3: false - nfsv41: true + nfsv3: true + nfsv41: false ruleIndex: 1 unixReadOnly: false unixReadWrite: true } ] - name: 'nanaanfs41-vol-001' + name: 'nanaanfs3-vol-001' protocolTypes: [ - 'NFSv4.1' + 'NFSv3' ] roleAssignments: [ { @@ -370,19 +403,9 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { usageThreshold: 107374182400 } { - exportPolicyRules: [ - { - allowedClients: '0.0.0.0/0' - nfsv3: false - nfsv41: true - ruleIndex: 1 - unixReadOnly: false - unixReadWrite: true - } - ] - name: 'nanaanfs41-vol-002' + name: 'nanaanfs3-vol-002' protocolTypes: [ - 'NFSv4.1' + 'NFSv3' ] subnetResourceId: '' usageThreshold: 107374182400 @@ -390,7 +413,7 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { ] } { - name: 'nanaanfs41-cp-002' + name: 'nanaanfs3-cp-002' roleAssignments: [ { principalId: '' @@ -404,10 +427,9 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { } ] location: '' - managedIdentities: { - userAssignedResourceIds: [ - '' - ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' } roleAssignments: [ { @@ -453,13 +475,13 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { "parameters": { // Required parameters "name": { - "value": "nanaanfs41001" + "value": "nanaanfs3001" }, // Non-required parameters "capacityPools": { "value": [ { - "name": "nanaanfs41-cp-001", + "name": "nanaanfs3-cp-001", "roleAssignments": [ { "principalId": "", @@ -474,16 +496,16 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { "exportPolicyRules": [ { "allowedClients": "0.0.0.0/0", - "nfsv3": false, - "nfsv41": true, + "nfsv3": true, + "nfsv41": false, "ruleIndex": 1, "unixReadOnly": false, "unixReadWrite": true } ], - "name": "nanaanfs41-vol-001", + "name": "nanaanfs3-vol-001", "protocolTypes": [ - "NFSv4.1" + "NFSv3" ], "roleAssignments": [ { @@ -496,19 +518,9 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { "usageThreshold": 107374182400 }, { - "exportPolicyRules": [ - { - "allowedClients": "0.0.0.0/0", - "nfsv3": false, - "nfsv41": true, - "ruleIndex": 1, - "unixReadOnly": false, - "unixReadWrite": true - } - ], - "name": "nanaanfs41-vol-002", + "name": "nanaanfs3-vol-002", "protocolTypes": [ - "NFSv4.1" + "NFSv3" ], "subnetResourceId": "", "usageThreshold": 107374182400 @@ -516,7 +528,7 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { ] }, { - "name": "nanaanfs41-cp-002", + "name": "nanaanfs3-cp-002", "roleAssignments": [ { "principalId": "", @@ -533,11 +545,10 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { "location": { "value": "" }, - "managedIdentities": { + "lock": { "value": { - "userAssignedResourceIds": [ - "" - ] + "kind": "CanNotDelete", + "name": "myCustomLockName" } }, "roleAssignments": { @@ -587,7 +598,10 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { name: '${uniqueString(deployment().name, location)}-test-nanaawaf' params: { + // Required parameters name: 'nanaawaf001' + // Non-required parameters + location: '' } } ``` @@ -604,8 +618,13 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { + // Required parameters "name": { "value": "nanaawaf001" + }, + // Non-required parameters + "location": { + "value": "" } } } @@ -786,7 +805,7 @@ Array of role assignments to create. | 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" | +| [`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. | @@ -808,7 +827,7 @@ The role to assign. You can provide either the display name of the role definiti ### 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" +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 diff --git a/avm/res/net-app/net-app-account/main.json b/avm/res/net-app/net-app-account/main.json index ef054cec6e..26c5aff406 100644 --- a/avm/res/net-app/net-app-account/main.json +++ b/avm/res/net-app/net-app-account/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "16523658267969007487" + "templateHash": "14715331993420856618" }, "name": "Azure NetApp Files", "description": "This module deploys an Azure NetApp File.", @@ -95,7 +95,7 @@ "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\"" + "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": { From e569215e9c983d7058792bf0c7d738a64bee5dde Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 20:45:11 +1000 Subject: [PATCH 12/33] added child readme's --- avm/res/compute/image/main.json | 2 +- .../backup-vault/backup-policy/README.md | 9 ---- .../backup-vault/backup-policy/main.json | 23 +------- .../flexible-server/administrator/README.md | 18 ------- .../flexible-server/administrator/main.json | 30 +---------- .../flexible-server/database/README.md | 18 ------- .../flexible-server/database/main.json | 30 +---------- .../flexible-server/firewall-rule/README.md | 14 ----- .../flexible-server/firewall-rule/main.json | 23 +------- .../net-app-account/capacity-pool/README.md | 9 ---- .../net-app-account/capacity-pool/main.json | 52 ++----------------- .../capacity-pool/volume/README.md | 9 ---- .../capacity-pool/volume/main.json | 23 +------- 13 files changed, 9 insertions(+), 251 deletions(-) diff --git a/avm/res/compute/image/main.json b/avm/res/compute/image/main.json index 9e92285770..e0303f37b5 100644 --- a/avm/res/compute/image/main.json +++ b/avm/res/compute/image/main.json @@ -323,4 +323,4 @@ "value": "[reference('image', '2022-11-01', 'full').location]" } } -} +} \ No newline at end of file diff --git a/avm/res/data-protection/backup-vault/backup-policy/README.md b/avm/res/data-protection/backup-vault/backup-policy/README.md index 990af9e3de..4c9ac0dd8d 100644 --- a/avm/res/data-protection/backup-vault/backup-policy/README.md +++ b/avm/res/data-protection/backup-vault/backup-policy/README.md @@ -28,7 +28,6 @@ This module deploys a Data Protection Backup Vault Backup Policy. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`name`](#parameter-name) | string | The name of the backup policy. | | [`properties`](#parameter-properties) | object | The properties of the backup policy. | @@ -39,14 +38,6 @@ The name of the backup vault. - Required: Yes - Type: string -### Parameter: `enableDefaultTelemetry` - -Enable telemetry via a Globally Unique Identifier (GUID). - -- Required: No -- Type: bool -- Default: `True` - ### Parameter: `name` The name of the backup policy. diff --git a/avm/res/data-protection/backup-vault/backup-policy/main.json b/avm/res/data-protection/backup-vault/backup-policy/main.json index f3a79705fc..4b94f1bf44 100644 --- a/avm/res/data-protection/backup-vault/backup-policy/main.json +++ b/avm/res/data-protection/backup-vault/backup-policy/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "3378438498887899064" + "templateHash": "9679092928668541836" }, "name": "Data Protection Backup Vault Backup Policies", "description": "This module deploys a Data Protection Backup Vault Backup Policy.", @@ -31,30 +31,9 @@ "metadata": { "description": "Optional. The properties of the backup policy." } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "resources": [ - { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, { "type": "Microsoft.DataProtection/backupVaults/backupPolicies", "apiVersion": "2023-05-01", diff --git a/avm/res/db-for-my-sql/flexible-server/administrator/README.md b/avm/res/db-for-my-sql/flexible-server/administrator/README.md index 827b434ef7..c4e7f91360 100644 --- a/avm/res/db-for-my-sql/flexible-server/administrator/README.md +++ b/avm/res/db-for-my-sql/flexible-server/administrator/README.md @@ -35,8 +35,6 @@ This module deploys a DBforMySQL Flexible Server Administrator. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | -| [`location`](#parameter-location) | string | Location for all resources. | | [`tenantId`](#parameter-tenantid) | string | The tenantId of the Active Directory administrator. | ### Parameter: `identityResourceId` @@ -67,22 +65,6 @@ The name of the parent DBforMySQL flexible server. Required if the template is u - Required: Yes - Type: string -### Parameter: `enableDefaultTelemetry` - -Enable telemetry via a Globally Unique Identifier (GUID). - -- Required: No -- Type: bool -- Default: `True` - -### Parameter: `location` - -Location for all resources. - -- Required: No -- Type: string -- Default: `[resourceGroup().location]` - ### Parameter: `tenantId` The tenantId of the Active Directory administrator. diff --git a/avm/res/db-for-my-sql/flexible-server/administrator/main.json b/avm/res/db-for-my-sql/flexible-server/administrator/main.json index 347c0a171f..edb3bf0a2c 100644 --- a/avm/res/db-for-my-sql/flexible-server/administrator/main.json +++ b/avm/res/db-for-my-sql/flexible-server/administrator/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "8863151548145849170" + "templateHash": "12048235018035722270" }, "name": "DBforMySQL Flexible Server Administrators", "description": "This module deploys a DBforMySQL Flexible Server Administrator.", @@ -42,37 +42,9 @@ "metadata": { "description": "Optional. The tenantId of the Active Directory administrator." } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. Location for all resources." - } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "resources": [ - { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, { "type": "Microsoft.DBforMySQL/flexibleServers/administrators", "apiVersion": "2022-01-01", diff --git a/avm/res/db-for-my-sql/flexible-server/database/README.md b/avm/res/db-for-my-sql/flexible-server/database/README.md index 4bcb034a0b..5c36c3db04 100644 --- a/avm/res/db-for-my-sql/flexible-server/database/README.md +++ b/avm/res/db-for-my-sql/flexible-server/database/README.md @@ -35,8 +35,6 @@ This module deploys a DBforMySQL Flexible Server Database. | :-- | :-- | :-- | | [`charset`](#parameter-charset) | string | The charset of the database. | | [`collation`](#parameter-collation) | string | The collation of the database. | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | -| [`location`](#parameter-location) | string | Location for all resources. | ### Parameter: `name` @@ -68,22 +66,6 @@ The collation of the database. - Type: string - Default: `'utf8'` -### Parameter: `enableDefaultTelemetry` - -Enable telemetry via a Globally Unique Identifier (GUID). - -- Required: No -- Type: bool -- Default: `True` - -### Parameter: `location` - -Location for all resources. - -- Required: No -- Type: string -- Default: `[resourceGroup().location]` - ## Outputs diff --git a/avm/res/db-for-my-sql/flexible-server/database/main.json b/avm/res/db-for-my-sql/flexible-server/database/main.json index c7747c6684..97d40ca618 100644 --- a/avm/res/db-for-my-sql/flexible-server/database/main.json +++ b/avm/res/db-for-my-sql/flexible-server/database/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "7585808247826533259" + "templateHash": "4885810309374527606" }, "name": "DBforMySQL Flexible Server Databases", "description": "This module deploys a DBforMySQL Flexible Server Database.", @@ -37,37 +37,9 @@ "metadata": { "description": "Optional. The charset of the database." } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. Location for all resources." - } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "resources": [ - { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, { "type": "Microsoft.DBforMySQL/flexibleServers/databases", "apiVersion": "2022-01-01", diff --git a/avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md b/avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md index 593969aa25..238ded49b0 100644 --- a/avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md +++ b/avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md @@ -31,12 +31,6 @@ This module deploys a DBforMySQL Flexible Server Firewall Rule. | :-- | :-- | :-- | | [`flexibleServerName`](#parameter-flexibleservername) | string | The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment. | -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | - ### Parameter: `endIpAddress` The end IP address of the firewall rule. Must be IPv4 format. Must be greater than or equal to startIpAddress. Use value '0.0.0.0' for all Azure-internal IP addresses. @@ -65,14 +59,6 @@ The name of the parent MySQL flexible server. Required if the template is used i - Required: Yes - Type: string -### Parameter: `enableDefaultTelemetry` - -Enable telemetry via a Globally Unique Identifier (GUID). - -- Required: No -- Type: bool -- Default: `True` - ## Outputs diff --git a/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json index c86c3c1a46..1031be3d1b 100644 --- a/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json +++ b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "9889972221731602451" + "templateHash": "5525339023784252205" }, "name": "DBforMySQL Flexible Server Firewall Rules", "description": "This module deploys a DBforMySQL Flexible Server Firewall Rule.", @@ -35,30 +35,9 @@ "metadata": { "description": "Conditional. The name of the parent MySQL flexible server. Required if the template is used in a standalone deployment." } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "resources": [ - { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, { "type": "Microsoft.DBforMySQL/flexibleServers/firewallRules", "apiVersion": "2022-01-01", diff --git a/avm/res/net-app/net-app-account/capacity-pool/README.md b/avm/res/net-app/net-app-account/capacity-pool/README.md index 381674df79..0f7933597e 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/README.md +++ b/avm/res/net-app/net-app-account/capacity-pool/README.md @@ -37,7 +37,6 @@ This module deploys an Azure NetApp Files Capacity Pool. | Parameter | Type | Description | | :-- | :-- | :-- | | [`coolAccess`](#parameter-coolaccess) | bool | If enabled (true) the pool can contain cool Access enabled volumes. | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`encryptionType`](#parameter-encryptiontype) | string | Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool. | | [`location`](#parameter-location) | string | Location of the pool volume. | | [`qosType`](#parameter-qostype) | string | The qos type of the pool. | @@ -75,14 +74,6 @@ If enabled (true) the pool can contain cool Access enabled volumes. - Type: bool - Default: `False` -### Parameter: `enableDefaultTelemetry` - -Enable telemetry via a Globally Unique Identifier (GUID). - -- Required: No -- Type: bool -- Default: `True` - ### Parameter: `encryptionType` Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool. diff --git a/avm/res/net-app/net-app-account/capacity-pool/main.json b/avm/res/net-app/net-app-account/capacity-pool/main.json index 464a90fcd8..6fe8c85730 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/main.json +++ b/avm/res/net-app/net-app-account/capacity-pool/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "15353329491336313807" + "templateHash": "13567874697839927577" }, "name": "Azure NetApp Files Capacity Pools", "description": "This module deploys an Azure NetApp Files Capacity Pool.", @@ -167,17 +167,9 @@ "metadata": { "description": "Optional. Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool." } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "variables": { - "enableReferencedModulesTelemetry": false, "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", @@ -187,20 +179,6 @@ } }, "resources": { - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, "netAppAccount": { "existing": true, "type": "Microsoft.NetApp/netAppAccounts", @@ -286,10 +264,7 @@ "value": "[parameters('volumes')[copyIndex()].subnetResourceId]" }, "exportPolicyRules": "[if(contains(parameters('volumes')[copyIndex()], 'exportPolicyRules'), createObject('value', parameters('volumes')[copyIndex()].exportPolicyRules), createObject('value', createArray()))]", - "roleAssignments": "[if(contains(parameters('volumes')[copyIndex()], 'roleAssignments'), createObject('value', parameters('volumes')[copyIndex()].roleAssignments), createObject('value', createArray()))]", - "enableDefaultTelemetry": { - "value": "[variables('enableReferencedModulesTelemetry')]" - } + "roleAssignments": "[if(contains(parameters('volumes')[copyIndex()], 'roleAssignments'), createObject('value', parameters('volumes')[copyIndex()].roleAssignments), createObject('value', createArray()))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -299,7 +274,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "3662331312918191126" + "templateHash": "13281702213100562603" }, "name": "Azure NetApp Files Capacity Pool Volumes", "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", @@ -450,13 +425,6 @@ "metadata": { "description": "Optional. Array of role assignments to create." } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "variables": { @@ -478,20 +446,6 @@ "netAppAccount" ] }, - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, "netAppAccount": { "existing": true, "type": "Microsoft.NetApp/netAppAccounts", diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/README.md b/avm/res/net-app/net-app-account/capacity-pool/volume/README.md index bf17feb0a2..14945106ec 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/volume/README.md +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/README.md @@ -38,7 +38,6 @@ This module deploys an Azure NetApp Files Capacity Pool Volume. | Parameter | Type | Description | | :-- | :-- | :-- | | [`creationToken`](#parameter-creationtoken) | string | A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription. | -| [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`exportPolicyRules`](#parameter-exportpolicyrules) | array | Export policy rules. | | [`location`](#parameter-location) | string | Location of the pool volume. | | [`protocolTypes`](#parameter-protocoltypes) | array | Set of protocol types. | @@ -88,14 +87,6 @@ A unique file path for the volume. This is the name of the volume export. A volu - Type: string - Default: `[parameters('name')]` -### Parameter: `enableDefaultTelemetry` - -Enable telemetry via a Globally Unique Identifier (GUID). - -- Required: No -- Type: bool -- Default: `True` - ### Parameter: `exportPolicyRules` Export policy rules. diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/main.json b/avm/res/net-app/net-app-account/capacity-pool/volume/main.json index 5e0f1b20ef..2a66a51403 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/volume/main.json +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "3662331312918191126" + "templateHash": "13281702213100562603" }, "name": "Azure NetApp Files Capacity Pool Volumes", "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", @@ -157,13 +157,6 @@ "metadata": { "description": "Optional. Array of role assignments to create." } - }, - "enableDefaultTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } } }, "variables": { @@ -185,20 +178,6 @@ "netAppAccount" ] }, - "defaultTelemetry": { - "condition": "[parameters('enableDefaultTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2021-04-01", - "name": "[format('pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-{0}', uniqueString(deployment().name))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [] - } - } - }, "netAppAccount": { "existing": true, "type": "Microsoft.NetApp/netAppAccounts", From 253a54eb9d3706837962c69d5322bab1a19ae04d Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 20:49:33 +1000 Subject: [PATCH 13/33] . --- .github/workflows/avm.res.health-bot.health-bot.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/avm.res.health-bot.health-bot.yml b/.github/workflows/avm.res.health-bot.health-bot.yml index a4d65b00bd..c98a870a49 100644 --- a/.github/workflows/avm.res.health-bot.health-bot.yml +++ b/.github/workflows/avm.res.health-bot.health-bot.yml @@ -27,14 +27,14 @@ on: paths: - ".github/actions/templates/avm-**" - ".github/workflows/avm.template.module.yml" - - ".github/workflows/avm.res.health-bot/health-bot.yml" + - ".github/workflows/avm.res.health-bot.health-bot.yml" - "avm/res/health-bot/health-bot/**" - "avm/utilities/pipelines/**" - "!*/**/README.md" env: modulePath: "avm/res/health-bot/health-bot" - workflowPath: ".github/workflows/avm.res.health-bot/health-bot.yml" + workflowPath: ".github/workflows/avm.res.health-bot.health-bot.yml" concurrency: group: ${{ github.workflow }} From 7c74b2147f75a796eb8602268e0bf8aaa5ac3ab7 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 20:53:01 +1000 Subject: [PATCH 14/33] . --- .github/workflows/avm.res.data-protection.backup-vault.yml | 4 ++-- .github/workflows/avm.res.databricks.access-connector.yml | 4 ++-- .github/workflows/avm.res.db-for-my-sql.flexible-server.yml | 4 ++-- .github/workflows/avm.res.net-app.net-app-account.yml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/avm.res.data-protection.backup-vault.yml b/.github/workflows/avm.res.data-protection.backup-vault.yml index c96c595cc2..f9d48f0b66 100644 --- a/.github/workflows/avm.res.data-protection.backup-vault.yml +++ b/.github/workflows/avm.res.data-protection.backup-vault.yml @@ -27,14 +27,14 @@ on: paths: - ".github/actions/templates/avm-**" - ".github/workflows/avm.template.module.yml" - - ".github/workflows/avm.res.data-protection/backup-vault.yml" + - ".github/workflows/avm.res.data-protection.backup-vault.yml" - "avm/res/data-protection/backup-vault/**" - "avm/utilities/pipelines/**" - "!*/**/README.md" env: modulePath: "avm/res/data-protection/backup-vault" - workflowPath: ".github/workflows/avm.res.data-protection/backup-vault.yml" + workflowPath: ".github/workflows/avm.res.data-protection.backup-vault.yml" concurrency: group: ${{ github.workflow }} diff --git a/.github/workflows/avm.res.databricks.access-connector.yml b/.github/workflows/avm.res.databricks.access-connector.yml index 1621066c20..6839086d8e 100644 --- a/.github/workflows/avm.res.databricks.access-connector.yml +++ b/.github/workflows/avm.res.databricks.access-connector.yml @@ -27,14 +27,14 @@ on: paths: - ".github/actions/templates/avm-**" - ".github/workflows/avm.template.module.yml" - - ".github/workflows/avm.res.databricks/access-connector.yml" + - ".github/workflows/avm.res.databricks.access-connector.yml" - "avm/res/databricks/access-connector/**" - "avm/utilities/pipelines/**" - "!*/**/README.md" env: modulePath: "avm/res/databricks/access-connector" - workflowPath: ".github/workflows/avm.res.databricks/access-connector.yml" + workflowPath: ".github/workflows/avm.res.databricks.access-connector.yml" concurrency: group: ${{ github.workflow }} diff --git a/.github/workflows/avm.res.db-for-my-sql.flexible-server.yml b/.github/workflows/avm.res.db-for-my-sql.flexible-server.yml index eb1a40e796..27980e4dea 100644 --- a/.github/workflows/avm.res.db-for-my-sql.flexible-server.yml +++ b/.github/workflows/avm.res.db-for-my-sql.flexible-server.yml @@ -27,14 +27,14 @@ on: paths: - ".github/actions/templates/avm-**" - ".github/workflows/avm.template.module.yml" - - ".github/workflows/avm.res.db-for-my-sql/flexible-server.yml" + - ".github/workflows/avm.res.db-for-my-sql.flexible-server.yml" - "avm/res/db-for-my-sql/flexible-server/**" - "avm/utilities/pipelines/**" - "!*/**/README.md" env: modulePath: "avm/res/db-for-my-sql/flexible-server" - workflowPath: ".github/workflows/avm.res.db-for-my-sql/flexible-server.yml" + workflowPath: ".github/workflows/avm.res.db-for-my-sql.flexible-server.yml" concurrency: group: ${{ github.workflow }} diff --git a/.github/workflows/avm.res.net-app.net-app-account.yml b/.github/workflows/avm.res.net-app.net-app-account.yml index 8bc8f3b70b..fb55b8dd86 100644 --- a/.github/workflows/avm.res.net-app.net-app-account.yml +++ b/.github/workflows/avm.res.net-app.net-app-account.yml @@ -27,14 +27,14 @@ on: paths: - ".github/actions/templates/avm-**" - ".github/workflows/avm.template.module.yml" - - ".github/workflows/avm.res.net-app/net-app-account.yml" + - ".github/workflows/avm.res.net-app.net-app-account.yml" - "avm/res/net-app/net-app-account/**" - "avm/utilities/pipelines/**" - "!*/**/README.md" env: modulePath: "avm/res/net-app/net-app-account" - workflowPath: ".github/workflows/avm.res.net-app/net-app-account.yml" + workflowPath: ".github/workflows/avm.res.net-app.net-app-account.yml" concurrency: group: ${{ github.workflow }} From 90d573061f9a050086d7929a78beb4b322179c0e Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 21:14:22 +1000 Subject: [PATCH 15/33] . --- avm/res/analysis-services/server/main.bicep | 1 + avm/res/cache/redis/main.bicep | 1 + avm/res/compute/disk/main.bicep | 1 + avm/res/compute/image/main.bicep | 1 + avm/res/consumption/budget/README.md | 2 +- avm/res/consumption/budget/main.bicep | 3 ++- avm/res/consumption/budget/main.json | 5 +++-- avm/res/data-protection/backup-vault/main.bicep | 1 + avm/res/databricks/access-connector/main.bicep | 1 + avm/res/databricks/workspace/main.bicep | 1 + avm/res/db-for-my-sql/flexible-server/main.bicep | 1 + avm/res/health-bot/health-bot/main.bicep | 1 + avm/res/net-app/net-app-account/main.bicep | 1 + .../net-app-account/tests/e2e/waf-aligned/main.test.bicep | 3 +++ 14 files changed, 19 insertions(+), 4 deletions(-) diff --git a/avm/res/analysis-services/server/main.bicep b/avm/res/analysis-services/server/main.bicep index 578f8e7f2e..eb2ab6f92d 100644 --- a/avm/res/analysis-services/server/main.bicep +++ b/avm/res/analysis-services/server/main.bicep @@ -51,6 +51,7 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.analysisservices-server.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/cache/redis/main.bicep b/avm/res/cache/redis/main.bicep index a7e1c00ab8..d6b5a51192 100644 --- a/avm/res/cache/redis/main.bicep +++ b/avm/res/cache/redis/main.bicep @@ -125,6 +125,7 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.cache-redis.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/compute/disk/main.bicep b/avm/res/compute/disk/main.bicep index 16630825ae..9b84da7b84 100644 --- a/avm/res/compute/disk/main.bicep +++ b/avm/res/compute/disk/main.bicep @@ -145,6 +145,7 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.compute-disk.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/compute/image/main.bicep b/avm/res/compute/image/main.bicep index 15bbfe092f..be52d4dabf 100644 --- a/avm/res/compute/image/main.bicep +++ b/avm/res/compute/image/main.bicep @@ -73,6 +73,7 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.compute-image.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/consumption/budget/README.md b/avm/res/consumption/budget/README.md index 46a09e3687..794163a2c8 100644 --- a/avm/res/consumption/budget/README.md +++ b/avm/res/consumption/budget/README.md @@ -14,7 +14,7 @@ This module deploys a Consumption Budget for Subscriptions. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.Consumption/budgets` | [2021-10-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Consumption/2021-10-01/budgets) | +| `Microsoft.Consumption/budgets` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Consumption/budgets) | ## Usage examples diff --git a/avm/res/consumption/budget/main.bicep b/avm/res/consumption/budget/main.bicep index 99dacec5c4..64a5d7d769 100644 --- a/avm/res/consumption/budget/main.bicep +++ b/avm/res/consumption/budget/main.bicep @@ -75,6 +75,7 @@ var notifications = json(replace(replace(replace(string(notificationsArray), '[{ resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.consumption-budget.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location properties: { mode: 'Incremental' template: { @@ -91,7 +92,7 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableT } } -resource budget 'Microsoft.Consumption/budgets@2021-10-01' = { +resource budget 'Microsoft.Consumption/budgets@2023-11-01' = { name: name properties: { category: category diff --git a/avm/res/consumption/budget/main.json b/avm/res/consumption/budget/main.json index 8d5f9ea8f9..22c9acf7d5 100644 --- a/avm/res/consumption/budget/main.json +++ b/avm/res/consumption/budget/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "6182258303963233923" + "templateHash": "5946331948544882274" }, "name": "Consumption Budgets", "description": "This module deploys a Consumption Budget for Subscriptions.", @@ -140,6 +140,7 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.consumption-budget.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": { @@ -157,7 +158,7 @@ }, { "type": "Microsoft.Consumption/budgets", - "apiVersion": "2021-10-01", + "apiVersion": "2023-11-01", "name": "[parameters('name')]", "properties": { "category": "[parameters('category')]", diff --git a/avm/res/data-protection/backup-vault/main.bicep b/avm/res/data-protection/backup-vault/main.bicep index 7f76b54721..6f558e8285 100644 --- a/avm/res/data-protection/backup-vault/main.bicep +++ b/avm/res/data-protection/backup-vault/main.bicep @@ -72,6 +72,7 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.dataprotection-backupvault.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/databricks/access-connector/main.bicep b/avm/res/databricks/access-connector/main.bicep index 3d6acd2c6e..4803b25907 100644 --- a/avm/res/databricks/access-connector/main.bicep +++ b/avm/res/databricks/access-connector/main.bicep @@ -40,6 +40,7 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.databricks-accessconnector.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/databricks/workspace/main.bicep b/avm/res/databricks/workspace/main.bicep index 433b5a950f..ebb8a74827 100644 --- a/avm/res/databricks/workspace/main.bicep +++ b/avm/res/databricks/workspace/main.bicep @@ -109,6 +109,7 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.databricks-workspace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/db-for-my-sql/flexible-server/main.bicep b/avm/res/db-for-my-sql/flexible-server/main.bicep index 595affa177..569851c234 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.bicep +++ b/avm/res/db-for-my-sql/flexible-server/main.bicep @@ -180,6 +180,7 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.dbformysql-flexibleserver.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/health-bot/health-bot/main.bicep b/avm/res/health-bot/health-bot/main.bicep index 0a09bde642..59712a42cd 100644 --- a/avm/res/health-bot/health-bot/main.bicep +++ b/avm/res/health-bot/health-bot/main.bicep @@ -48,6 +48,7 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.healthbot-healthbot.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/net-app/net-app-account/main.bicep b/avm/res/net-app/net-app-account/main.bicep index 69926a38de..8977d54e8c 100644 --- a/avm/res/net-app/net-app-account/main.bicep +++ b/avm/res/net-app/net-app-account/main.bicep @@ -73,6 +73,7 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.netapp-netappaccount.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep index de405f6652..ec156242f4 100644 --- a/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep @@ -1,5 +1,8 @@ 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 // // ========== // From 4b0320a9d96d447b888a30cf0ae35ed53fcb7221 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 21:24:31 +1000 Subject: [PATCH 16/33] . --- avm/res/net-app/net-app-account/capacity-pool/main.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/net-app/net-app-account/capacity-pool/main.bicep b/avm/res/net-app/net-app-account/capacity-pool/main.bicep index 51dd53b329..de6ac7a47c 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/main.bicep +++ b/avm/res/net-app/net-app-account/capacity-pool/main.bicep @@ -135,7 +135,7 @@ type roleAssignmentType = { @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"') + @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.') From 6c331293c85c1ac7d0aa351a35a26ecd21fb85cf Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 21:46:59 +1000 Subject: [PATCH 17/33] . --- avm/res/analysis-services/server/main.json | 3 ++- avm/res/cache/redis/main.bicep | 1 - avm/res/cache/redis/main.json | 3 ++- avm/res/compute/disk/main.bicep | 1 - avm/res/compute/image/main.json | 3 ++- avm/res/data-protection/backup-vault/main.bicep | 1 - avm/res/databricks/access-connector/main.bicep | 1 - avm/res/databricks/workspace/main.bicep | 1 - avm/res/db-for-my-sql/flexible-server/main.bicep | 1 - avm/res/db-for-my-sql/flexible-server/main.json | 3 ++- avm/res/health-bot/health-bot/main.bicep | 1 - avm/res/health-bot/health-bot/main.json | 3 ++- avm/res/net-app/net-app-account/README.md | 7 +++++-- avm/res/net-app/net-app-account/capacity-pool/README.md | 4 ++-- avm/res/net-app/net-app-account/capacity-pool/main.json | 4 ++-- avm/res/net-app/net-app-account/main.json | 7 ++++--- 16 files changed, 23 insertions(+), 21 deletions(-) diff --git a/avm/res/analysis-services/server/main.json b/avm/res/analysis-services/server/main.json index 0202c2c6c8..61bef93bad 100644 --- a/avm/res/analysis-services/server/main.json +++ b/avm/res/analysis-services/server/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "17318307385986864132" + "templateHash": "8177409501670000951" }, "name": "Analysis Services Servers", "description": "This module deploys an Analysis Services Server.", @@ -303,6 +303,7 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.analysisservices-server.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": { diff --git a/avm/res/cache/redis/main.bicep b/avm/res/cache/redis/main.bicep index d6b5a51192..a7e1c00ab8 100644 --- a/avm/res/cache/redis/main.bicep +++ b/avm/res/cache/redis/main.bicep @@ -125,7 +125,6 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.cache-redis.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/cache/redis/main.json b/avm/res/cache/redis/main.json index f40cbccc41..409809fb4a 100644 --- a/avm/res/cache/redis/main.json +++ b/avm/res/cache/redis/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "4044387362593822012" + "templateHash": "13174455984034292849" }, "name": "Redis Cache", "description": "This module deploys a Redis Cache.", @@ -623,6 +623,7 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.cache-redis.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": { diff --git a/avm/res/compute/disk/main.bicep b/avm/res/compute/disk/main.bicep index 9b84da7b84..16630825ae 100644 --- a/avm/res/compute/disk/main.bicep +++ b/avm/res/compute/disk/main.bicep @@ -145,7 +145,6 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.compute-disk.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/compute/image/main.json b/avm/res/compute/image/main.json index e0303f37b5..c76c1ef55f 100644 --- a/avm/res/compute/image/main.json +++ b/avm/res/compute/image/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "3262439157508833759" + "templateHash": "2794327147421392454" }, "name": "Images", "description": "This module deploys a Compute Image.", @@ -228,6 +228,7 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.compute-image.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": { diff --git a/avm/res/data-protection/backup-vault/main.bicep b/avm/res/data-protection/backup-vault/main.bicep index 6f558e8285..7f76b54721 100644 --- a/avm/res/data-protection/backup-vault/main.bicep +++ b/avm/res/data-protection/backup-vault/main.bicep @@ -72,7 +72,6 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.dataprotection-backupvault.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/databricks/access-connector/main.bicep b/avm/res/databricks/access-connector/main.bicep index 4803b25907..3d6acd2c6e 100644 --- a/avm/res/databricks/access-connector/main.bicep +++ b/avm/res/databricks/access-connector/main.bicep @@ -40,7 +40,6 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.databricks-accessconnector.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/databricks/workspace/main.bicep b/avm/res/databricks/workspace/main.bicep index ebb8a74827..433b5a950f 100644 --- a/avm/res/databricks/workspace/main.bicep +++ b/avm/res/databricks/workspace/main.bicep @@ -109,7 +109,6 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.databricks-workspace.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/db-for-my-sql/flexible-server/main.bicep b/avm/res/db-for-my-sql/flexible-server/main.bicep index 569851c234..595affa177 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.bicep +++ b/avm/res/db-for-my-sql/flexible-server/main.bicep @@ -180,7 +180,6 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.dbformysql-flexibleserver.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/db-for-my-sql/flexible-server/main.json b/avm/res/db-for-my-sql/flexible-server/main.json index e56b8aa8e7..8e049417f9 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.json +++ b/avm/res/db-for-my-sql/flexible-server/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "10366576748540516282" + "templateHash": "8210001038895550912" }, "name": "DBforMySQL Flexible Servers", "description": "This module deploys a DBforMySQL Flexible Server.", @@ -583,6 +583,7 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.dbformysql-flexibleserver.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": { diff --git a/avm/res/health-bot/health-bot/main.bicep b/avm/res/health-bot/health-bot/main.bicep index 59712a42cd..0a09bde642 100644 --- a/avm/res/health-bot/health-bot/main.bicep +++ b/avm/res/health-bot/health-bot/main.bicep @@ -48,7 +48,6 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.healthbot-healthbot.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location properties: { mode: 'Incremental' template: { diff --git a/avm/res/health-bot/health-bot/main.json b/avm/res/health-bot/health-bot/main.json index c074878ca8..e7e09be6b5 100644 --- a/avm/res/health-bot/health-bot/main.json +++ b/avm/res/health-bot/health-bot/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "1383571101384884749" + "templateHash": "12487039479368500675" }, "name": "Azure Health Bots", "description": "This module deploys an Azure Health Bot.", @@ -195,6 +195,7 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.healthbot-healthbot.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": { diff --git a/avm/res/net-app/net-app-account/README.md b/avm/res/net-app/net-app-account/README.md index 765d638873..ec9bb2ab83 100644 --- a/avm/res/net-app/net-app-account/README.md +++ b/avm/res/net-app/net-app-account/README.md @@ -36,7 +36,7 @@ The following section provides usage examples for the module, which were used to - [Using only defaults](#example-1-using-only-defaults) - [Using large parameter set](#example-2-using-large-parameter-set) - [Using nfs31 parameter set](#example-3-using-nfs31-parameter-set) -- [Waf-Aligned](#example-4-waf-aligned) +- [WAF-aligned](#example-4-waf-aligned) ### Example 1: _Using only defaults_ @@ -588,7 +588,10 @@ module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = {

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

diff --git a/avm/res/net-app/net-app-account/capacity-pool/README.md b/avm/res/net-app/net-app-account/capacity-pool/README.md index 0f7933597e..89616e3664 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/README.md +++ b/avm/res/net-app/net-app-account/capacity-pool/README.md @@ -130,7 +130,7 @@ Array of role assignments to create. | 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" | +| [`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. | @@ -152,7 +152,7 @@ The role to assign. You can provide either the display name of the role definiti ### 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" +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 diff --git a/avm/res/net-app/net-app-account/capacity-pool/main.json b/avm/res/net-app/net-app-account/capacity-pool/main.json index 6fe8c85730..e0755bc503 100644 --- a/avm/res/net-app/net-app-account/capacity-pool/main.json +++ b/avm/res/net-app/net-app-account/capacity-pool/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "13567874697839927577" + "templateHash": "6236557182741049347" }, "name": "Azure NetApp Files Capacity Pools", "description": "This module deploys an Azure NetApp Files Capacity Pool.", @@ -55,7 +55,7 @@ "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\"" + "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": { diff --git a/avm/res/net-app/net-app-account/main.json b/avm/res/net-app/net-app-account/main.json index 26c5aff406..dcb5edc1ff 100644 --- a/avm/res/net-app/net-app-account/main.json +++ b/avm/res/net-app/net-app-account/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "14715331993420856618" + "templateHash": "6600668718433779489" }, "name": "Azure NetApp Files", "description": "This module deploys an Azure NetApp File.", @@ -243,6 +243,7 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.netapp-netappaccount.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": { @@ -349,7 +350,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "13567874697839927577" + "templateHash": "6236557182741049347" }, "name": "Azure NetApp Files Capacity Pools", "description": "This module deploys an Azure NetApp Files Capacity Pool.", @@ -398,7 +399,7 @@ "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\"" + "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": { From 5e672c253e5fbe3f1ef94377038411477f0f56c2 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 21:49:33 +1000 Subject: [PATCH 18/33] . --- avm/res/cache/redis/main.json | 3 +-- avm/res/db-for-my-sql/flexible-server/main.json | 3 +-- avm/res/health-bot/health-bot/main.json | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/avm/res/cache/redis/main.json b/avm/res/cache/redis/main.json index 409809fb4a..f40cbccc41 100644 --- a/avm/res/cache/redis/main.json +++ b/avm/res/cache/redis/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "13174455984034292849" + "templateHash": "4044387362593822012" }, "name": "Redis Cache", "description": "This module deploys a Redis Cache.", @@ -623,7 +623,6 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.cache-redis.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", - "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": { diff --git a/avm/res/db-for-my-sql/flexible-server/main.json b/avm/res/db-for-my-sql/flexible-server/main.json index 8e049417f9..e56b8aa8e7 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.json +++ b/avm/res/db-for-my-sql/flexible-server/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "8210001038895550912" + "templateHash": "10366576748540516282" }, "name": "DBforMySQL Flexible Servers", "description": "This module deploys a DBforMySQL Flexible Server.", @@ -583,7 +583,6 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.dbformysql-flexibleserver.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", - "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": { diff --git a/avm/res/health-bot/health-bot/main.json b/avm/res/health-bot/health-bot/main.json index e7e09be6b5..c074878ca8 100644 --- a/avm/res/health-bot/health-bot/main.json +++ b/avm/res/health-bot/health-bot/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "12487039479368500675" + "templateHash": "1383571101384884749" }, "name": "Azure Health Bots", "description": "This module deploys an Azure Health Bot.", @@ -195,7 +195,6 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.healthbot-healthbot.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", - "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": { From 1a9343cd11885e48a32158314f67e103e2a96ca3 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 21:54:54 +1000 Subject: [PATCH 19/33] location --- avm/res/net-app/net-app-account/main.bicep | 1 - 1 file changed, 1 deletion(-) diff --git a/avm/res/net-app/net-app-account/main.bicep b/avm/res/net-app/net-app-account/main.bicep index 8977d54e8c..69926a38de 100644 --- a/avm/res/net-app/net-app-account/main.bicep +++ b/avm/res/net-app/net-app-account/main.bicep @@ -73,7 +73,6 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.netapp-netappaccount.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location properties: { mode: 'Incremental' template: { From e35a73e830b73eac045fd78cfa5edcd795f7df1b Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 21:57:08 +1000 Subject: [PATCH 20/33] . --- avm/res/net-app/net-app-account/main.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/avm/res/net-app/net-app-account/main.json b/avm/res/net-app/net-app-account/main.json index dcb5edc1ff..a33a83cb7a 100644 --- a/avm/res/net-app/net-app-account/main.json +++ b/avm/res/net-app/net-app-account/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "6600668718433779489" + "templateHash": "14170411293699618494" }, "name": "Azure NetApp Files", "description": "This module deploys an Azure NetApp File.", @@ -243,7 +243,6 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.netapp-netappaccount.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", - "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": { From f650b2ec0225d4d41f9a7d3ed37c73a3024ce757 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 21:59:13 +1000 Subject: [PATCH 21/33] . --- .../flexible-server/tests/e2e/max/main.test.bicep | 3 +++ 1 file changed, 3 insertions(+) diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep index 6b8ac78e1b..9e1eee679b 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep @@ -1,5 +1,8 @@ targetScope = 'subscription' +metadata name = 'Using large parameter set' +metadata description = 'This instance deploys the module with most of its features enabled.' + // ========== // // Parameters // // ========== // From 27440bb6d6f999e35559491070385cfe74ed6570 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 22 Dec 2023 22:01:29 +1000 Subject: [PATCH 22/33] . --- avm/res/db-for-my-sql/flexible-server/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/avm/res/db-for-my-sql/flexible-server/README.md b/avm/res/db-for-my-sql/flexible-server/README.md index 75748b13df..3205cc4998 100644 --- a/avm/res/db-for-my-sql/flexible-server/README.md +++ b/avm/res/db-for-my-sql/flexible-server/README.md @@ -36,7 +36,7 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br/public:avm/res/db-for-my-sql/flexible-server:`. - [Using only defaults](#example-1-using-only-defaults) -- [Max](#example-2-max) +- [Using large parameter set](#example-2-using-large-parameter-set) - [Deploys in connectivity mode "Private Access"](#example-3-deploys-in-connectivity-mode-private-access) - [WAF-aligned](#example-4-waf-aligned) @@ -104,7 +104,10 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:

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

From 241245eaf058a88019f4dad2c4e845c5c93a2a77 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Sat, 23 Dec 2023 11:12:42 +1000 Subject: [PATCH 23/33] . --- .../db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep | 2 +- .../flexible-server/tests/e2e/private/main.test.bicep | 2 +- .../flexible-server/tests/e2e/waf-aligned/main.test.bicep | 2 +- avm/res/health-bot/health-bot/main.json | 2 +- .../health-bot/health-bot/tests/e2e/defaults/main.test.bicep | 2 +- avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep | 2 +- .../health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep index 9e1eee679b..62d76ff573 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep @@ -15,7 +15,7 @@ param resourceGroupName string = 'dep-${namePrefix}-dbformysql.flexibleservers-$ 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 = 'dfmsfsmax' +param serviceShort string = 'dfmsmax' @description('Optional. The password to leverage for the login.') @secure() diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep index 5e28aa17b3..d364d95460 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep @@ -15,7 +15,7 @@ param resourceGroupName string = 'dep-${namePrefix}-dbformysql.flexibleservers-$ 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 = 'dfmsfspvt' +param serviceShort string = 'dfmspvt' @description('Optional. The password to leverage for the login.') @secure() diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep index ae4483dba2..65b0aa08c2 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep @@ -17,7 +17,7 @@ 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.') // e.g., for a module 'network/private-endpoint' you could use 'npe' as a prefix and then 'waf' as a suffix for the waf-aligned test -param serviceShort string = 'dfmsfswaf' +param serviceShort string = 'dfmswaf' @description('Optional. The password to leverage for the login.') @secure() diff --git a/avm/res/health-bot/health-bot/main.json b/avm/res/health-bot/health-bot/main.json index c074878ca8..685ec1895b 100644 --- a/avm/res/health-bot/health-bot/main.json +++ b/avm/res/health-bot/health-bot/main.json @@ -289,4 +289,4 @@ "value": "[reference('healthBot', '2022-08-08', 'full').location]" } } -} \ No newline at end of file +} diff --git a/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep index 27295dc34e..b99d025c4b 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep @@ -12,7 +12,7 @@ metadata description = 'This instance deploys the module with the minimum set of param resourceGroupName string = 'dep-${namePrefix}-healthbot.healthbots-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') -param location string = deployment().location +param location string = 'westeurope' @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 = 'hbhbmin' diff --git a/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep index 21051fd516..e827ecee3a 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep @@ -12,7 +12,7 @@ metadata description = 'This instance deploys the module with most of its featur param resourceGroupName string = 'dep-${namePrefix}-healthbot.healthbots-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') -param location string = deployment().location +param location string = 'westeurope' @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 = 'hbhbmax' diff --git a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep index 0e2649a748..cbea40de33 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep @@ -12,7 +12,7 @@ metadata description = 'This instance deploys the module in alignment with the b param resourceGroupName string = 'dep-${namePrefix}-healthbot.healthbots-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') -param location string = deployment().location +param location string = 'westeurope' @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 = 'hbhbwaf' From b7fe375b3880f4fd3c319feb01905c7ca473aeb9 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Sat, 23 Dec 2023 14:36:14 +1000 Subject: [PATCH 24/33] . --- .../db-for-my-sql/flexible-server/README.md | 26 +++++++++---------- .../tests/e2e/defaults/main.test.bicep | 4 +-- .../health-bot/tests/e2e/max/main.test.bicep | 4 +-- .../tests/e2e/waf-aligned/main.test.bicep | 4 +-- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/avm/res/db-for-my-sql/flexible-server/README.md b/avm/res/db-for-my-sql/flexible-server/README.md index 3205cc4998..49596a3c56 100644 --- a/avm/res/db-for-my-sql/flexible-server/README.md +++ b/avm/res/db-for-my-sql/flexible-server/README.md @@ -115,10 +115,10 @@ This instance deploys the module with most of its features enabled. ```bicep module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, location)}-test-dfmsfsmax' + name: '${uniqueString(deployment().name, location)}-test-dfmsmax' params: { // Required parameters - name: 'dfmsfsmax001' + name: 'dfmsmax001' skuName: 'Standard_D2ds_v4' tier: 'GeneralPurpose' // Non-required parameters @@ -204,7 +204,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: tags: { 'hidden-title': 'This is visible in the resource name' resourceType: 'MySQL Flexible Server' - serverName: 'dfmsfsmax001' + serverName: 'dfmsmax001' } version: '8.0.21' } @@ -225,7 +225,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "parameters": { // Required parameters "name": { - "value": "dfmsfsmax001" + "value": "dfmsmax001" }, "skuName": { "value": "Standard_D2ds_v4" @@ -355,7 +355,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "value": { "hidden-title": "This is visible in the resource name", "resourceType": "MySQL Flexible Server", - "serverName": "dfmsfsmax001" + "serverName": "dfmsmax001" } }, "version": { @@ -379,10 +379,10 @@ This instance deploys the module with connectivity mode "Private Access". ```bicep module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, location)}-test-dfmsfspvt' + name: '${uniqueString(deployment().name, location)}-test-dfmspvt' params: { // Required parameters - name: 'dfmsfspvt001' + name: 'dfmspvt001' skuName: 'Standard_D2ds_v4' tier: 'GeneralPurpose' // Non-required parameters @@ -452,7 +452,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: tags: { 'hidden-title': 'This is visible in the resource name' resourceType: 'MySQL Flexible Server' - serverName: 'dfmsfspvt001' + serverName: 'dfmspvt001' } } } @@ -472,7 +472,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "parameters": { // Required parameters "name": { - "value": "dfmsfspvt001" + "value": "dfmspvt001" }, "skuName": { "value": "Standard_D2ds_v4" @@ -582,7 +582,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "value": { "hidden-title": "This is visible in the resource name", "resourceType": "MySQL Flexible Server", - "serverName": "dfmsfspvt001" + "serverName": "dfmspvt001" } } } @@ -603,10 +603,10 @@ This instance deploys the module in alignment with the best-practices of the Azu ```bicep module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { - name: '${uniqueString(deployment().name, location)}-test-dfmsfswaf' + name: '${uniqueString(deployment().name, location)}-test-dfmswaf' params: { // Required parameters - name: 'dfmsfswaf001' + name: 'dfmswaf001' skuName: 'Standard_B1ms' tier: 'Burstable' // Non-required parameters @@ -640,7 +640,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "parameters": { // Required parameters "name": { - "value": "dfmsfswaf001" + "value": "dfmswaf001" }, "skuName": { "value": "Standard_B1ms" diff --git a/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep index b99d025c4b..df6d90ef04 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/defaults/main.test.bicep @@ -12,7 +12,7 @@ metadata description = 'This instance deploys the module with the minimum set of param resourceGroupName string = 'dep-${namePrefix}-healthbot.healthbots-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') -param location string = 'westeurope' +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 = 'hbhbmin' @@ -41,7 +41,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' - location: location + location: resourceGroup.location sku: 'F0' } }] diff --git a/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep index e827ecee3a..0ad9d9b673 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/max/main.test.bicep @@ -12,7 +12,7 @@ metadata description = 'This instance deploys the module with most of its featur param resourceGroupName string = 'dep-${namePrefix}-healthbot.healthbots-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') -param location string = 'westeurope' +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 = 'hbhbmax' @@ -50,7 +50,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' - location: location + location: resourceGroup.location lock: { kind: 'CanNotDelete' name: 'myCustomLockName' diff --git a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep index cbea40de33..a6f93c3546 100644 --- a/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/health-bot/health-bot/tests/e2e/waf-aligned/main.test.bicep @@ -12,7 +12,7 @@ metadata description = 'This instance deploys the module in alignment with the b param resourceGroupName string = 'dep-${namePrefix}-healthbot.healthbots-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') -param location string = 'westeurope' +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 = 'hbhbwaf' @@ -41,7 +41,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' - location: location + location: resourceGroup.location lock: { kind: 'CanNotDelete' name: 'myCustomLockName' From 62f259c18edd92cb45aef37e14c5755d7781066e Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Sat, 23 Dec 2023 15:21:56 +1000 Subject: [PATCH 25/33] redis --- avm/res/cache/redis/README.md | 8 -------- avm/res/cache/redis/tests/e2e/max/main.test.bicep | 1 - avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep | 1 - 3 files changed, 10 deletions(-) diff --git a/avm/res/cache/redis/README.md b/avm/res/cache/redis/README.md index c1b71173dd..4b8073c9d8 100644 --- a/avm/res/cache/redis/README.md +++ b/avm/res/cache/redis/README.md @@ -144,7 +144,6 @@ module redis 'br/public:avm/res/cache/redis:' = { } } ] - publicNetworkAccess: 'Enabled' redisVersion: '6' shardCount: 1 skuName: 'Premium' @@ -235,9 +234,6 @@ module redis 'br/public:avm/res/cache/redis:' = { } ] }, - "publicNetworkAccess": { - "value": "Enabled" - }, "redisVersion": { "value": "6" }, @@ -323,7 +319,6 @@ module redis 'br/public:avm/res/cache/redis:' = { } } ] - publicNetworkAccess: 'Enabled' redisVersion: '6' shardCount: 1 skuName: 'Premium' @@ -411,9 +406,6 @@ module redis 'br/public:avm/res/cache/redis:' = { } ] }, - "publicNetworkAccess": { - "value": "Enabled" - }, "redisVersion": { "value": "6" }, diff --git a/avm/res/cache/redis/tests/e2e/max/main.test.bicep b/avm/res/cache/redis/tests/e2e/max/main.test.bicep index 3c5dd8b0ab..d3e93fac1e 100644 --- a/avm/res/cache/redis/tests/e2e/max/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/max/main.test.bicep @@ -102,7 +102,6 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' } } ] - publicNetworkAccess: 'Enabled' redisVersion: '6' shardCount: 1 skuName: 'Premium' diff --git a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep index 80c60cbe0e..c6a97b6f0a 100644 --- a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep @@ -101,7 +101,6 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' } } ] - publicNetworkAccess: 'Enabled' redisVersion: '6' shardCount: 1 skuName: 'Premium' From 0ff8a3dca61a34ecb183bf729471011c991594c6 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 11 Jan 2024 11:58:00 +1000 Subject: [PATCH 26/33] location --- avm/res/compute/image/main.bicep | 1 - 1 file changed, 1 deletion(-) diff --git a/avm/res/compute/image/main.bicep b/avm/res/compute/image/main.bicep index be52d4dabf..15bbfe092f 100644 --- a/avm/res/compute/image/main.bicep +++ b/avm/res/compute/image/main.bicep @@ -73,7 +73,6 @@ var builtInRoleNames = { resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { name: '46d3xbcp.res.compute-image.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - location: location properties: { mode: 'Incremental' template: { From bc15b1182237d5f154495739cab9eb38ba7ddcaf Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 11 Jan 2024 12:18:21 +1000 Subject: [PATCH 27/33] . --- .../flexible-server/tests/e2e/max/main.test.bicep | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep index 62d76ff573..a51e640f10 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep @@ -106,10 +106,10 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' } administratorLogin: 'adminUserName' administratorLoginPassword: password - skuName: 'Standard_D2ds_v4' + skuName: 'Standard_D2ads_v5' tier: 'GeneralPurpose' storageAutoIoScaling: 'Enabled' - storageSizeGB: 32 + storageSizeGB: 64 storageIOPS: 400 backupRetentionDays: 20 availabilityZone: '1' From c7b508e9087fcda173b3cedc007cc131e0eda6a8 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 11 Jan 2024 13:32:44 +1000 Subject: [PATCH 28/33] location --- .../db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep index a51e640f10..1211aa6a2d 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep @@ -12,7 +12,7 @@ metadata description = 'This instance deploys the module with most of its featur param resourceGroupName string = 'dep-${namePrefix}-dbformysql.flexibleservers-${serviceShort}-rg' @description('Optional. The location to deploy resources to.') -param location string = deployment().location +param location string = 'eastus' @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 = 'dfmsmax' From 3cb02644833a510782df0c360fda6f2e5d6507ee Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 11 Jan 2024 13:39:57 +1000 Subject: [PATCH 29/33] . --- .../flexible-server/tests/e2e/max/dependencies1.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies1.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies1.bicep index 13e2a08e42..96b9ae71af 100644 --- a/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies1.bicep +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies1.bicep @@ -35,7 +35,7 @@ resource getPairedRegionScript 'Microsoft.Resources/deploymentScripts@2020-10-01 azPowerShellVersion: '8.0' retentionInterval: 'P1D' arguments: '-Location \\"${location}\\"' - scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/.scripts/Get-PairedRegion.ps1') + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Get-PairedRegion.ps1') } dependsOn: [ roleAssignment From cd40b9eeda8082c425eb031c4cbe2b5da053bbe4 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 11 Jan 2024 13:42:39 +1000 Subject: [PATCH 30/33] e2e-template-assets/scripts/ --- avm/res/compute/image/tests/e2e/defaults/dependencies.bicep | 4 ++-- avm/res/compute/image/tests/e2e/max/dependencies.bicep | 4 ++-- .../compute/image/tests/e2e/waf-aligned/dependencies.bicep | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/avm/res/compute/image/tests/e2e/defaults/dependencies.bicep b/avm/res/compute/image/tests/e2e/defaults/dependencies.bicep index b0c24f72ae..7614a52892 100644 --- a/avm/res/compute/image/tests/e2e/defaults/dependencies.bicep +++ b/avm/res/compute/image/tests/e2e/defaults/dependencies.bicep @@ -109,7 +109,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 } @@ -133,7 +133,7 @@ resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10- 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') + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Copy-VhdToStorageAccount.ps1') cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } diff --git a/avm/res/compute/image/tests/e2e/max/dependencies.bicep b/avm/res/compute/image/tests/e2e/max/dependencies.bicep index f659176d0a..b37c3cf39f 100644 --- a/avm/res/compute/image/tests/e2e/max/dependencies.bicep +++ b/avm/res/compute/image/tests/e2e/max/dependencies.bicep @@ -115,7 +115,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 } @@ -139,7 +139,7 @@ resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10- 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') + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Copy-VhdToStorageAccount.ps1') cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } diff --git a/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep index f659176d0a..b37c3cf39f 100644 --- a/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/compute/image/tests/e2e/waf-aligned/dependencies.bicep @@ -115,7 +115,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 } @@ -139,7 +139,7 @@ resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10- 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') + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Copy-VhdToStorageAccount.ps1') cleanupPreference: 'OnSuccess' forceUpdateTag: baseTime } From 5d2c883d377d220cbab83e4967ae7db6341c99f0 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 11 Jan 2024 13:46:57 +1000 Subject: [PATCH 31/33] data collection --- avm/res/cache/redis/README.md | 5 +++++ avm/res/cache/redis/main.json | 4 ++-- avm/res/compute/image/README.md | 5 +++++ avm/res/compute/image/main.json | 5 ++--- avm/res/databricks/workspace/README.md | 5 +++++ avm/res/databricks/workspace/main.json | 4 ++-- avm/res/db-for-my-sql/flexible-server/README.md | 13 +++++++++---- .../flexible-server/administrator/README.md | 5 +++++ .../flexible-server/administrator/main.json | 4 ++-- .../flexible-server/database/README.md | 5 +++++ .../flexible-server/database/main.json | 4 ++-- .../flexible-server/firewall-rule/README.md | 5 +++++ .../flexible-server/firewall-rule/main.json | 4 ++-- avm/res/db-for-my-sql/flexible-server/main.json | 16 ++++++++-------- 14 files changed, 59 insertions(+), 25 deletions(-) diff --git a/avm/res/cache/redis/README.md b/avm/res/cache/redis/README.md index 4b8073c9d8..6bcaf4efdd 100644 --- a/avm/res/cache/redis/README.md +++ b/avm/res/cache/redis/README.md @@ -15,6 +15,7 @@ This module deploys a Redis Cache. - [Outputs](#Outputs) - [Cross-referenced modules](#Cross-referenced-modules) - [Notes](#Notes) +- [Data Collection](#Data-Collection) ## Resource Types @@ -1215,3 +1216,7 @@ userAssignedIdentities: {

+ +## 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/cache/redis/main.json b/avm/res/cache/redis/main.json index f40cbccc41..f01226bc06 100644 --- a/avm/res/cache/redis/main.json +++ b/avm/res/cache/redis/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "4044387362593822012" + "version": "0.24.24.22086", + "templateHash": "12989369361653663747" }, "name": "Redis Cache", "description": "This module deploys a Redis Cache.", diff --git a/avm/res/compute/image/README.md b/avm/res/compute/image/README.md index 02113cc373..58ac247297 100644 --- a/avm/res/compute/image/README.md +++ b/avm/res/compute/image/README.md @@ -14,6 +14,7 @@ This module deploys a Compute Image. - [Parameters](#Parameters) - [Outputs](#Outputs) - [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) ## Resource Types @@ -605,3 +606,7 @@ Default is false. Specifies whether an image is zone resilient or not. Zone resi ## 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/image/main.json b/avm/res/compute/image/main.json index c76c1ef55f..f71aca9437 100644 --- a/avm/res/compute/image/main.json +++ b/avm/res/compute/image/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "2794327147421392454" + "version": "0.24.24.22086", + "templateHash": "8195862099053535046" }, "name": "Images", "description": "This module deploys a Compute Image.", @@ -228,7 +228,6 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", "name": "[format('46d3xbcp.res.compute-image.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", - "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": { diff --git a/avm/res/databricks/workspace/README.md b/avm/res/databricks/workspace/README.md index 976df39ed4..a64a729c2c 100644 --- a/avm/res/databricks/workspace/README.md +++ b/avm/res/databricks/workspace/README.md @@ -15,6 +15,7 @@ This module deploys an Azure Databricks Workspace. - [Outputs](#Outputs) - [Cross-referenced modules](#Cross-referenced-modules) - [Notes](#Notes) +- [Data Collection](#Data-Collection) ## Resource Types @@ -1466,3 +1467,7 @@ parameters: {

+ +## 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/databricks/workspace/main.json b/avm/res/databricks/workspace/main.json index 0c4fc446e6..932eb4c80a 100644 --- a/avm/res/databricks/workspace/main.json +++ b/avm/res/databricks/workspace/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "10487472164108897566" + "version": "0.24.24.22086", + "templateHash": "8058701732527405193" }, "name": "Azure Databricks Workspaces", "description": "This module deploys an Azure Databricks Workspace.", diff --git a/avm/res/db-for-my-sql/flexible-server/README.md b/avm/res/db-for-my-sql/flexible-server/README.md index 49596a3c56..cee11fd784 100644 --- a/avm/res/db-for-my-sql/flexible-server/README.md +++ b/avm/res/db-for-my-sql/flexible-server/README.md @@ -14,6 +14,7 @@ This module deploys a DBforMySQL Flexible Server. - [Parameters](#Parameters) - [Outputs](#Outputs) - [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) ## Resource Types @@ -119,7 +120,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: params: { // Required parameters name: 'dfmsmax001' - skuName: 'Standard_D2ds_v4' + skuName: 'Standard_D2ads_v5' tier: 'GeneralPurpose' // Non-required parameters administratorLogin: 'adminUserName' @@ -200,7 +201,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: storageAutoGrow: 'Enabled' storageAutoIoScaling: 'Enabled' storageIOPS: 400 - storageSizeGB: 32 + storageSizeGB: 64 tags: { 'hidden-title': 'This is visible in the resource name' resourceType: 'MySQL Flexible Server' @@ -228,7 +229,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "value": "dfmsmax001" }, "skuName": { - "value": "Standard_D2ds_v4" + "value": "Standard_D2ads_v5" }, "tier": { "value": "GeneralPurpose" @@ -349,7 +350,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "value": 400 }, "storageSizeGB": { - "value": 32 + "value": 64 }, "tags": { "value": { @@ -1374,3 +1375,7 @@ MySQL Server version. ## 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/db-for-my-sql/flexible-server/administrator/README.md b/avm/res/db-for-my-sql/flexible-server/administrator/README.md index c4e7f91360..ffe1d5f9cd 100644 --- a/avm/res/db-for-my-sql/flexible-server/administrator/README.md +++ b/avm/res/db-for-my-sql/flexible-server/administrator/README.md @@ -8,6 +8,7 @@ This module deploys a DBforMySQL Flexible Server Administrator. - [Parameters](#Parameters) - [Outputs](#Outputs) - [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) ## Resource Types @@ -85,3 +86,7 @@ The tenantId of the Active Directory administrator. ## 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/db-for-my-sql/flexible-server/administrator/main.json b/avm/res/db-for-my-sql/flexible-server/administrator/main.json index edb3bf0a2c..56d0bff8b4 100644 --- a/avm/res/db-for-my-sql/flexible-server/administrator/main.json +++ b/avm/res/db-for-my-sql/flexible-server/administrator/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "12048235018035722270" + "version": "0.24.24.22086", + "templateHash": "5949458902590917375" }, "name": "DBforMySQL Flexible Server Administrators", "description": "This module deploys a DBforMySQL Flexible Server Administrator.", diff --git a/avm/res/db-for-my-sql/flexible-server/database/README.md b/avm/res/db-for-my-sql/flexible-server/database/README.md index 5c36c3db04..d4fe4f68fb 100644 --- a/avm/res/db-for-my-sql/flexible-server/database/README.md +++ b/avm/res/db-for-my-sql/flexible-server/database/README.md @@ -8,6 +8,7 @@ This module deploys a DBforMySQL Flexible Server Database. - [Parameters](#Parameters) - [Outputs](#Outputs) - [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) ## Resource Types @@ -78,3 +79,7 @@ The collation of the database. ## 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/db-for-my-sql/flexible-server/database/main.json b/avm/res/db-for-my-sql/flexible-server/database/main.json index 97d40ca618..9a7d2f7aac 100644 --- a/avm/res/db-for-my-sql/flexible-server/database/main.json +++ b/avm/res/db-for-my-sql/flexible-server/database/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "4885810309374527606" + "version": "0.24.24.22086", + "templateHash": "3740413409622743148" }, "name": "DBforMySQL Flexible Server Databases", "description": "This module deploys a DBforMySQL Flexible Server Database.", diff --git a/avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md b/avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md index 238ded49b0..082750e131 100644 --- a/avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md +++ b/avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md @@ -8,6 +8,7 @@ This module deploys a DBforMySQL Flexible Server Firewall Rule. - [Parameters](#Parameters) - [Outputs](#Outputs) - [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) ## Resource Types @@ -71,3 +72,7 @@ The name of the parent MySQL flexible server. Required if the template is used i ## 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/db-for-my-sql/flexible-server/firewall-rule/main.json b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json index 1031be3d1b..1e78abe670 100644 --- a/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json +++ b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "5525339023784252205" + "version": "0.24.24.22086", + "templateHash": "13884040071380358802" }, "name": "DBforMySQL Flexible Server Firewall Rules", "description": "This module deploys a DBforMySQL Flexible Server Firewall Rule.", diff --git a/avm/res/db-for-my-sql/flexible-server/main.json b/avm/res/db-for-my-sql/flexible-server/main.json index e56b8aa8e7..cc902ab439 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.json +++ b/avm/res/db-for-my-sql/flexible-server/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "10366576748540516282" + "version": "0.24.24.22086", + "templateHash": "12608549284965955698" }, "name": "DBforMySQL Flexible Servers", "description": "This module deploys a DBforMySQL Flexible Server.", @@ -767,8 +767,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "4885810309374527606" + "version": "0.24.24.22086", + "templateHash": "3740413409622743148" }, "name": "DBforMySQL Flexible Server Databases", "description": "This module deploys a DBforMySQL Flexible Server Database.", @@ -875,8 +875,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "5525339023784252205" + "version": "0.24.24.22086", + "templateHash": "13884040071380358802" }, "name": "DBforMySQL Flexible Server Firewall Rules", "description": "This module deploys a DBforMySQL Flexible Server Firewall Rule.", @@ -982,8 +982,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "12048235018035722270" + "version": "0.24.24.22086", + "templateHash": "5949458902590917375" }, "name": "DBforMySQL Flexible Server Administrators", "description": "This module deploys a DBforMySQL Flexible Server Administrator.", From 90699f4e8034d6be0128ab4fd3c8265ba431d277 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 11 Jan 2024 14:02:41 +1000 Subject: [PATCH 32/33] 09ef9f59-e7b6-422e-84e4-508cfc8d64e7 --- .../workspace/tests/e2e/waf-aligned/dependencies.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/databricks/workspace/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/databricks/workspace/tests/e2e/waf-aligned/dependencies.bicep index 4c074d6ae8..a45e4247ea 100644 --- a/avm/res/databricks/workspace/tests/e2e/waf-aligned/dependencies.bicep +++ b/avm/res/databricks/workspace/tests/e2e/waf-aligned/dependencies.bicep @@ -91,7 +91,7 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Key-Vault-Crypto-User-RoleAssignment') scope: keyVault::key properties: { - principalId: '5167ea7a-355a-466f-ae8b-8ea60f718b35' // AzureDatabricks Enterprise Application Object Id + principalId: '09ef9f59-e7b6-422e-84e4-508cfc8d64e7' // AzureDatabricks Enterprise Application Object Id roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User principalType: 'ServicePrincipal' } From 46e5deaf58d6db54eff1df030fa87140c5c14d7c Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Thu, 11 Jan 2024 14:27:13 +1000 Subject: [PATCH 33/33] AzureDatabricks Enterprise Application Object Id --- avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep b/avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep index 4c074d6ae8..a45e4247ea 100644 --- a/avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep +++ b/avm/res/databricks/workspace/tests/e2e/max/dependencies.bicep @@ -91,7 +91,7 @@ resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Key-Vault-Crypto-User-RoleAssignment') scope: keyVault::key properties: { - principalId: '5167ea7a-355a-466f-ae8b-8ea60f718b35' // AzureDatabricks Enterprise Application Object Id + principalId: '09ef9f59-e7b6-422e-84e4-508cfc8d64e7' // AzureDatabricks Enterprise Application Object Id roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User principalType: 'ServicePrincipal' }