From 260ced14fdd13a26f09ff8e11ac845f81ae1f760 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 12 Jan 2024 15:49:33 +1000 Subject: [PATCH 01/13] feat: `avm/res/db-for-my-sql/flexible-server` --- .../avm.res.db-for-my-sql.flexible-server.yml | 83 + .../db-for-my-sql/flexible-server/ORPHANED.md | 4 + .../db-for-my-sql/flexible-server/README.md | 1381 +++++++++++++++++ .../flexible-server/administrator/README.md | 92 ++ .../flexible-server/administrator/main.bicep | 43 + .../flexible-server/administrator/main.json | 84 + .../flexible-server/database/README.md | 85 + .../flexible-server/database/main.bicep | 37 + .../flexible-server/database/main.json | 76 + .../flexible-server/firewall-rule/README.md | 78 + .../flexible-server/firewall-rule/main.bicep | 37 + .../flexible-server/firewall-rule/main.json | 74 + .../db-for-my-sql/flexible-server/main.bicep | 461 ++++++ .../db-for-my-sql/flexible-server/main.json | 1099 +++++++++++++ .../tests/e2e/defaults/main.test.bicep | 54 + .../tests/e2e/max/dependencies1.bicep | 46 + .../tests/e2e/max/dependencies2.bicep | 120 ++ .../tests/e2e/max/main.test.bicep | 179 +++ .../tests/e2e/private/dependencies.bicep | 74 + .../tests/e2e/private/main.test.bicep | 144 ++ .../tests/e2e/waf-aligned/main.test.bicep | 65 + .../flexible-server/version.json | 7 + 22 files changed, 4323 insertions(+) create mode 100644 .github/workflows/avm.res.db-for-my-sql.flexible-server.yml create mode 100644 avm/res/db-for-my-sql/flexible-server/ORPHANED.md create mode 100644 avm/res/db-for-my-sql/flexible-server/README.md create mode 100644 avm/res/db-for-my-sql/flexible-server/administrator/README.md create mode 100644 avm/res/db-for-my-sql/flexible-server/administrator/main.bicep create mode 100644 avm/res/db-for-my-sql/flexible-server/administrator/main.json create mode 100644 avm/res/db-for-my-sql/flexible-server/database/README.md create mode 100644 avm/res/db-for-my-sql/flexible-server/database/main.bicep create mode 100644 avm/res/db-for-my-sql/flexible-server/database/main.json create mode 100644 avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md create mode 100644 avm/res/db-for-my-sql/flexible-server/firewall-rule/main.bicep create mode 100644 avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json create mode 100644 avm/res/db-for-my-sql/flexible-server/main.bicep create mode 100644 avm/res/db-for-my-sql/flexible-server/main.json create mode 100644 avm/res/db-for-my-sql/flexible-server/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies1.bicep create mode 100644 avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies2.bicep create mode 100644 avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep create mode 100644 avm/res/db-for-my-sql/flexible-server/tests/e2e/private/dependencies.bicep create mode 100644 avm/res/db-for-my-sql/flexible-server/tests/e2e/private/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/db-for-my-sql/flexible-server/version.json 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..27980e4dea --- /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/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/db-for-my-sql/flexible-server/README.md b/avm/res/db-for-my-sql/flexible-server/README.md new file mode 100644 index 0000000000..cee11fd784 --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/README.md @@ -0,0 +1,1381 @@ +# 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 + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.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/public:avm/res/db-for-my-sql/flexible-server:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [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) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep +module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { + name: '${uniqueString(deployment().name, location)}-test-dfmsfsmin' + params: { + // Required parameters + name: 'dfmsfsmin001' + skuName: 'Standard_B1ms' + tier: 'Burstable' + // Non-required parameters + administratorLogin: 'adminUserName' + administratorLoginPassword: '' + location: '' + } +} +``` + +
+

+ +

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

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

+ +via Bicep module + +```bicep +module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { + name: '${uniqueString(deployment().name, location)}-test-dfmsmax' + params: { + // Required parameters + name: 'dfmsmax001' + skuName: 'Standard_D2ads_v5' + 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: '' + } + ] + 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: 64 + tags: { + 'hidden-title': 'This is visible in the resource name' + resourceType: 'MySQL Flexible Server' + serverName: 'dfmsmax001' + } + 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": "dfmsmax001" + }, + "skuName": { + "value": "Standard_D2ads_v5" + }, + "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": "" + } + ] + }, + "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": 64 + }, + "tags": { + "value": { + "hidden-title": "This is visible in the resource name", + "resourceType": "MySQL Flexible Server", + "serverName": "dfmsmax001" + } + }, + "version": { + "value": "8.0.21" + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { + name: '${uniqueString(deployment().name, location)}-test-dfmspvt' + params: { + // Required parameters + name: 'dfmspvt001' + 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: '' + } + ] + 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: 'dfmspvt001' + } + } +} +``` + +
+

+ +

+ +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": "dfmspvt001" + }, + "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": "" + } + ] + }, + "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": "dfmspvt001" + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server:' = { + name: '${uniqueString(deployment().name, location)}-test-dfmswaf' + params: { + // Required parameters + name: 'dfmswaf001' + 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' + } + } +} +``` + +
+

+ +

+ +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": "dfmswaf001" + }, + "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" + } + } + } +} +``` + +
+

+ + +## 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. | +| [`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. | +| [`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. "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. | + +### 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. "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. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.storageAccountResourceId` + +Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.workspaceResourceId` + +Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `enableTelemetry` + +Enable 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_ + +## 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 new file mode 100644 index 0000000000..ffe1d5f9cd --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/administrator/README.md @@ -0,0 +1,92 @@ +# 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) +- [Data Collection](#Data-Collection) + +## 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 | +| :-- | :-- | :-- | +| [`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: `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_ + +## 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.bicep b/avm/res/db-for-my-sql/flexible-server/administrator/main.bicep new file mode 100644 index 0000000000..912d7cbdcd --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/administrator/main.bicep @@ -0,0 +1,43 @@ +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 + +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/db-for-my-sql/flexible-server/administrator/main.json b/avm/res/db-for-my-sql/flexible-server/administrator/main.json new file mode 100644 index 0000000000..56d0bff8b4 --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/administrator/main.json @@ -0,0 +1,84 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "5949458902590917375" + }, + "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." + } + } + }, + "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/db-for-my-sql/flexible-server/database/README.md b/avm/res/db-for-my-sql/flexible-server/database/README.md new file mode 100644 index 0000000000..d4fe4f68fb --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/database/README.md @@ -0,0 +1,85 @@ +# 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) +- [Data Collection](#Data-Collection) + +## 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. | + +### 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'` + + +## 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_ + +## 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.bicep b/avm/res/db-for-my-sql/flexible-server/database/main.bicep new file mode 100644 index 0000000000..51fdfed6ca --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/database/main.bicep @@ -0,0 +1,37 @@ +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' + +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/db-for-my-sql/flexible-server/database/main.json b/avm/res/db-for-my-sql/flexible-server/database/main.json new file mode 100644 index 0000000000..9a7d2f7aac --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/database/main.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "3740413409622743148" + }, + "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." + } + } + }, + "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/db-for-my-sql/flexible-server/firewall-rule/README.md b/avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md new file mode 100644 index 0000000000..082750e131 --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/firewall-rule/README.md @@ -0,0 +1,78 @@ +# 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) +- [Data Collection](#Data-Collection) + +## 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. | + +### 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 + + +## 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_ + +## 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.bicep b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.bicep new file mode 100644 index 0000000000..19c077118e --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.bicep @@ -0,0 +1,37 @@ +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 + +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/db-for-my-sql/flexible-server/firewall-rule/main.json b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json new file mode 100644 index 0000000000..1e78abe670 --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/firewall-rule/main.json @@ -0,0 +1,74 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13884040071380358802" + }, + "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." + } + } + }, + "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/db-for-my-sql/flexible-server/main.bicep b/avm/res/db-for-my-sql/flexible-server/main.bicep new file mode 100644 index 0000000000..595affa177 --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/main.bicep @@ -0,0 +1,461 @@ +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 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}': {} } + +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') + '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 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' + } + } + } + } +} + +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 : '' + } +}] + +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 + } +}] + +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. "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? +}[]? + +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/db-for-my-sql/flexible-server/main.json b/avm/res/db-for-my-sql/flexible-server/main.json new file mode 100644 index 0000000000..cc902ab439 --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/main.json @@ -0,0 +1,1099 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "12608549284965955698" + }, + "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. \"allMetrics\" 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." + } + }, + "enableTelemetry": { + "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')]", + "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" + ] + }, + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "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))]", + "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" + } + } + } + } + }, + "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', ''))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "3740413409622743148" + }, + "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." + } + } + }, + "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]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13884040071380358802" + }, + "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." + } + } + }, + "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.24.24.22086", + "templateHash": "5949458902590917375" + }, + "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." + } + } + }, + "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/db-for-my-sql/flexible-server/tests/e2e/defaults/main.test.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..b4091bfc11 --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,54 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// 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. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: location + administratorLogin: 'adminUserName' + administratorLoginPassword: password + skuName: 'Standard_B1ms' + tier: 'Burstable' + } +}] 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 new file mode 100644 index 0000000000..96b9ae71af --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/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('../../../../../../utilities/e2e-template-assets/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/db-for-my-sql/flexible-server/tests/e2e/max/dependencies2.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/dependencies2.bicep new file mode 100644 index 0000000000..258d087ade --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/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/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 new file mode 100644 index 0000000000..1211aa6a2d --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep @@ -0,0 +1,179 @@ +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}-dbformysql.flexibleservers-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +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' + +@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. 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}' + location: location + geoBackupKeyVaultName: 'dep-${namePrefix}-kvp-${serviceShort}-${substring(uniqueString(baseTime), 0, 2)}' + geoBackupManagedIdentityName: 'dep-${namePrefix}-msip-${serviceShort}' + geoBackupLocation: nestedDependencies1.outputs.pairedRegionName + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/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: { + 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_D2ads_v5' + tier: 'GeneralPurpose' + storageAutoIoScaling: 'Enabled' + storageSizeGB: 64 + 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/db-for-my-sql/flexible-server/tests/e2e/private/dependencies.bicep b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/dependencies.bicep new file mode 100644 index 0000000000..ca3c6ceec6 --- /dev/null +++ b/avm/res/db-for-my-sql/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/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 new file mode 100644 index 0000000000..d364d95460 --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep @@ -0,0 +1,144 @@ +targetScope = 'subscription' + +metadata name = 'Deploys in connectivity mode "Private Access"' +metadata description = 'This instance deploys the module with connectivity mode "Private Access".' + +// ========== // +// 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 = 'dfmspvt' + +@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.') +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}' + location: location + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/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: { + 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/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..65b0aa08c2 --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,65 @@ +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) +// e.g., for a module 'network/private-endpoint' you could use 'dep-dev-network.privateendpoints-${serviceShort}-rg' +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.') +// 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 = 'dfmswaf' + +@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_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: location + 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/db-for-my-sql/flexible-server/version.json b/avm/res/db-for-my-sql/flexible-server/version.json new file mode 100644 index 0000000000..7fa401bdf7 --- /dev/null +++ b/avm/res/db-for-my-sql/flexible-server/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} From 2791bceaa3435aa6650bba35557126a90a39ff29 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 12 Jan 2024 20:41:44 +1000 Subject: [PATCH 02/13] codeowners --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index baf9bd2b2c..571c235b96 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -38,7 +38,7 @@ #/avm/res/databricks/workspace/ @Azure/avm-res-databricks-workspace-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/data-factory/factory/ @Azure/avm-res-datafactory-factory-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/data-protection/backup-vault/ @Azure/avm-res-dataprotection-backupvault-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/db-for-my-sql/flexible-server/ @Azure/avm-res-dbformysql-flexibleserver-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/db-for-my-sql/flexible-server/ @Azure/avm-res-dbformysql-flexibleserver-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/db-for-postgre-sql/flexible-server/ @Azure/avm-res-dbforpostgresql-flexibleserver-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/desktop-virtualization/application-group/ @Azure/avm-res-desktopvirtualization-applicationgroup-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/desktop-virtualization/host-pool/ @Azure/avm-res-desktopvirtualization-hostpool-module-owners-bicep @Azure/avm-core-team-technical-bicep From dd400d8bae8286cf396494fe4d6b660f4837322b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:13:52 +1000 Subject: [PATCH 03/13] Update avm/res/db-for-my-sql/flexible-server/main.bicep Co-authored-by: Alexander Sehr --- avm/res/db-for-my-sql/flexible-server/main.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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..e498fff266 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.bicep +++ b/avm/res/db-for-my-sql/flexible-server/main.bicep @@ -159,7 +159,7 @@ param roleAssignments roleAssignmentType @description('Optional. The diagnostic settings of the service.') param diagnosticSettings diagnosticSettingType -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +@description('Optional. Enable/Disable usage telemetry for module.') 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}': {} } From 33909fc6c4e30e734822bc07808155888cd3f1e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:14:05 +1000 Subject: [PATCH 04/13] Update avm/res/db-for-my-sql/flexible-server/main.bicep Co-authored-by: Alexander Sehr --- avm/res/db-for-my-sql/flexible-server/main.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e498fff266..f3ad5f5062 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.bicep +++ b/avm/res/db-for-my-sql/flexible-server/main.bicep @@ -153,7 +153,7 @@ 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".') +@description('Optional. Array of role assignments to create.') param roleAssignments roleAssignmentType @description('Optional. The diagnostic settings of the service.') From 47f8f4566cd09b6e2d6617af5f4c2b79b3db07e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:14:14 +1000 Subject: [PATCH 05/13] Update avm/res/db-for-my-sql/flexible-server/main.bicep Co-authored-by: Alexander Sehr --- avm/res/db-for-my-sql/flexible-server/main.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f3ad5f5062..d03e3869af 100644 --- a/avm/res/db-for-my-sql/flexible-server/main.bicep +++ b/avm/res/db-for-my-sql/flexible-server/main.bicep @@ -421,7 +421,7 @@ type diagnosticSettingType = { 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.') + @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to \'\' to disable metric 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 From 9ceb1315a5357cc1d1424669f0980d3fa4ddfff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Sun, 14 Jan 2024 10:14:29 +1000 Subject: [PATCH 06/13] Update .github/workflows/avm.res.db-for-my-sql.flexible-server.yml Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- .github/workflows/avm.res.db-for-my-sql.flexible-server.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 27980e4dea..de2784a190 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 @@ -44,7 +44,7 @@ jobs: # Initialize pipeline # ########################### job_initialize_pipeline: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest name: "Initialize pipeline" steps: - name: "Checkout" From bed72c60e468b5beadcab07eeb633b8571453db7 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Mon, 15 Jan 2024 15:10:02 +1000 Subject: [PATCH 07/13] readme updated --- avm/res/db-for-my-sql/flexible-server/README.md | 12 ++++++------ avm/res/db-for-my-sql/flexible-server/main.json | 8 ++++---- 2 files changed, 10 insertions(+), 10 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 cee11fd784..b6a4234b9d 100644 --- a/avm/res/db-for-my-sql/flexible-server/README.md +++ b/avm/res/db-for-my-sql/flexible-server/README.md @@ -715,7 +715,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: | [`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. | -| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`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. | @@ -723,7 +723,7 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: | [`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". | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | | [`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. | @@ -1014,7 +1014,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. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to '' to disable metric 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. | @@ -1063,7 +1063,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. "allMetrics" includes all possible logs for the resource. Set to '' to disable log collection. +The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to '' to disable metric collection. - Required: No - Type: array @@ -1091,7 +1091,7 @@ Resource ID of the diagnostic log analytics workspace. For security reasons, it ### Parameter: `enableTelemetry` -Enable telemetry via a Globally Unique Identifier (GUID). +Enable/Disable usage telemetry for module. - Required: No - Type: bool @@ -1206,7 +1206,7 @@ The replication role. ### 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". +Array of role assignments to create. - Required: No - Type: array 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 cc902ab439..6364413b5d 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.24.24.22086", - "templateHash": "12608549284965955698" + "templateHash": "16303493572113818798" }, "name": "DBforMySQL Flexible Servers", "description": "This module deploys a DBforMySQL Flexible Server.", @@ -172,7 +172,7 @@ }, "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." + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to '' to disable metric collection." } }, "logAnalyticsDestinationType": { @@ -524,7 +524,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." } }, "diagnosticSettings": { @@ -537,7 +537,7 @@ "type": "bool", "defaultValue": true, "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + "description": "Optional. Enable/Disable usage telemetry for module." } } }, From 8895d758ba168370a46694bf232d45ef165482e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Thu, 18 Jan 2024 11:08:59 +1000 Subject: [PATCH 08/13] Update avm/res/db-for-my-sql/flexible-server/tests/e2e/max/main.test.bicep Co-authored-by: Alexander Sehr --- .../flexible-server/tests/e2e/max/main.test.bicep | 14 ++++++++++++-- 1 file changed, 12 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 1211aa6a2d..cb31965020 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 @@ -94,8 +94,18 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' } roleAssignments: [ { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies2.outputs.managedIdentityPrincipalId + 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' } ] From 0d93ac02a4d01b04c08405f86a949dc7f0674756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Thu, 18 Jan 2024 11:09:53 +1000 Subject: [PATCH 09/13] Update avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep Co-authored-by: Alexander Sehr --- .../tests/e2e/private/main.test.bicep | 14 -------------- 1 file changed, 14 deletions(-) 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 d364d95460..3622f05820 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 @@ -45,20 +45,6 @@ module nestedDependencies 'dependencies.bicep' = { } } -// Diagnostics -// =========== -module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/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 // // ============== // From 87355c3ebb00faabd44e5047cbf706d29597dbdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Thu, 18 Jan 2024 11:10:06 +1000 Subject: [PATCH 10/13] Update avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep Co-authored-by: Alexander Sehr --- .../tests/e2e/private/main.test.bicep | 14 -------------- 1 file changed, 14 deletions(-) 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 3622f05820..c17e8a7cb2 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 @@ -105,20 +105,6 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' 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 From 3e54e44ba0d9f4433ab31e1f527ffc6bcd9f667b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gr=C3=A4f?= Date: Thu, 18 Jan 2024 11:10:23 +1000 Subject: [PATCH 11/13] Update avm/res/db-for-my-sql/flexible-server/tests/e2e/private/main.test.bicep Co-authored-by: Alexander Sehr --- .../tests/e2e/private/main.test.bicep | 26 ------------------- 1 file changed, 26 deletions(-) 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 c17e8a7cb2..a2457060a4 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 @@ -56,32 +56,6 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' params: { 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' From b407ad2d87fd6bd0a1ebdf2bb6d762358be05846 Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 19 Jan 2024 15:50:13 +1000 Subject: [PATCH 12/13] adjusted dependencies --- .../db-for-my-sql/flexible-server/README.md | 112 ++++-------------- .../tests/e2e/max/dependencies1.bicep | 6 + .../tests/e2e/max/main.test.bicep | 6 +- 3 files changed, 31 insertions(+), 93 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 b6a4234b9d..5dc64657fb 100644 --- a/avm/res/db-for-my-sql/flexible-server/README.md +++ b/avm/res/db-for-my-sql/flexible-server/README.md @@ -195,7 +195,17 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: { principalId: '' principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Reader' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' } ] storageAutoGrow: 'Enabled' @@ -336,7 +346,17 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: { "principalId": "", "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Reader" + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" } ] }, @@ -403,58 +423,18 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: } ] delegatedSubnetResourceId: '' - diagnosticSettings: [ - { - eventHubAuthorizationRuleResourceId: '' - eventHubName: '' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - name: 'customSetting' - storageAccountResourceId: '' - workspaceResourceId: '' - } - ] 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: 'dfmspvt001' - } } } ``` @@ -510,34 +490,12 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "delegatedSubnetResourceId": { "value": "" }, - "diagnosticSettings": { - "value": [ - { - "eventHubAuthorizationRuleResourceId": "", - "eventHubName": "", - "metricCategories": [ - { - "category": "AllMetrics" - } - ], - "name": "customSetting", - "storageAccountResourceId": "", - "workspaceResourceId": "" - } - ] - }, "highAvailability": { "value": "SameZone" }, "location": { "value": "" }, - "lock": { - "value": { - "kind": "CanNotDelete", - "name": "myCustomLockName" - } - }, "managedIdentities": { "value": { "userAssignedResourceIds": [ @@ -548,25 +506,6 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: "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" }, @@ -578,13 +517,6 @@ module flexibleServer 'br/public:avm/res/db-for-my-sql/flexible-server: }, "storageSizeGB": { "value": 64 - }, - "tags": { - "value": { - "hidden-title": "This is visible in the resource name", - "resourceType": "MySQL Flexible Server", - "serverName": "dfmspvt001" - } } } } 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 96b9ae71af..c1ed5dfa4c 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 @@ -44,3 +44,9 @@ resource getPairedRegionScript 'Microsoft.Resources/deploymentScripts@2020-10-01 @description('The name of the paired region.') output pairedRegionName string = getPairedRegionScript.properties.outputs.pairedRegionName + +@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/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 cb31965020..e2db544906 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 @@ -95,17 +95,17 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' roleAssignments: [ { roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalId: nestedDependencies1.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } { roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalId: nestedDependencies1.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } { roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalId: nestedDependencies1.outputs.managedIdentityPrincipalId principalType: 'ServicePrincipal' } ] From ce1bc177b43bf28b612429b65db9c7bd31947daf Mon Sep 17 00:00:00 2001 From: Sebastian Graef Date: Fri, 19 Jan 2024 15:53:59 +1000 Subject: [PATCH 13/13] tempLocation --- .../flexible-server/tests/e2e/max/main.test.bicep | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 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 e2db544906..79ee63174f 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 = 'eastus' +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 = 'dfmsmax' @@ -27,6 +27,9 @@ param baseTime string = utcNow('u') @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' +#disable-next-line no-hardcoded-location // services used for this module are only available in major regions +var tempLocation = 'eastus' + // ============ // // Dependencies // // ============ // @@ -35,7 +38,7 @@ param namePrefix string = '#_namePrefix_#' // ================= resource resourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { name: resourceGroupName - location: location + location: tempLocation } module nestedDependencies1 'dependencies1.bicep' = { @@ -43,7 +46,7 @@ module nestedDependencies1 'dependencies1.bicep' = { 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 + location: tempLocation managedIdentityName: 'dep-${namePrefix}-msi-ds-${serviceShort}' pairedRegionScriptName: 'dep-${namePrefix}-ds-${serviceShort}' } @@ -56,7 +59,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 + location: tempLocation geoBackupKeyVaultName: 'dep-${namePrefix}-kvp-${serviceShort}-${substring(uniqueString(baseTime), 0, 2)}' geoBackupManagedIdentityName: 'dep-${namePrefix}-msip-${serviceShort}' geoBackupLocation: nestedDependencies1.outputs.pairedRegionName @@ -73,7 +76,7 @@ module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/t logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' - location: location + location: tempLocation } } @@ -87,7 +90,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' - location: resourceGroup.location + location: tempLocation lock: { kind: 'CanNotDelete' name: 'myCustomLockName'