diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 82a963800c..9c4620938b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -74,7 +74,7 @@ /avm/res/managed-identity/user-assigned-identity/ @Azure/avm-res-managedidentity-userassignedidentity-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/managed-services/registration-definition/ @Azure/avm-res-managedservices-registrationdefinition-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/management/management-group/ @Azure/avm-res-management-managementgroup-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/net-app/net-app-account/ @Azure/avm-res-netapp-netappaccount-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/net-app/net-app-account/ @Azure/avm-res-netapp-netappaccount-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/network/application-gateway/ @Azure/avm-res-network-applicationgateway-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/network/application-gateway-web-application-firewall-policy/ @Azure/avm-res-network-applicationgatewaywebapplicationfirewallpolicy-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/network/application-security-group/ @Azure/avm-res-network-applicationsecuritygroup-module-owners-bicep @Azure/avm-core-team-technical-bicep diff --git a/.github/workflows/avm.res.net-app.net-app-account.yml b/.github/workflows/avm.res.net-app.net-app-account.yml new file mode 100644 index 0000000000..8eabd526d2 --- /dev/null +++ b/.github/workflows/avm.res.net-app.net-app-account.yml @@ -0,0 +1,83 @@ +name: "avm.res.net-app.net-app-account" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + workflow_dispatch: + inputs: + staticValidation: + type: boolean + description: "Execute static validation" + required: false + default: true + deploymentValidation: + type: boolean + description: "Execute deployment validation" + required: false + default: true + removeDeployment: + type: boolean + description: "Remove deployed module" + required: false + default: true + + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.net-app.net-app-account.yml" + - "avm/res/net-app/net-app-account/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/net-app/net-app-account" + workflowPath: ".github/workflows/avm.res.net-app.net-app-account.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/net-app/net-app-account/ORPHANED.md b/avm/res/net-app/net-app-account/ORPHANED.md new file mode 100644 index 0000000000..ef8fa911d2 --- /dev/null +++ b/avm/res/net-app/net-app-account/ORPHANED.md @@ -0,0 +1,4 @@ +⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ + +- Only security and bug fixes are being handled by the AVM core team at present. +- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/net-app/net-app-account/README.md b/avm/res/net-app/net-app-account/README.md new file mode 100644 index 0000000000..22acd8f044 --- /dev/null +++ b/avm/res/net-app/net-app-account/README.md @@ -0,0 +1,914 @@ +# Azure NetApp Files `[Microsoft.NetApp/netAppAccounts]` + +> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ +> +> - Only security and bug fixes are being handled by the AVM core team at present. +> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! + +This module deploys an Azure NetApp File. + +## Navigation + +- [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.NetApp/netAppAccounts` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts) | +| `Microsoft.NetApp/netAppAccounts/capacityPools` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools) | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools/volumes) | + +## Usage examples + +The following section provides usage examples for the module, which were used to validate and deploy the module successfully. For a full reference, please review the module's test folder in its repository. + +>**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/net-app/net-app-account:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [Using nfs31 parameter set](#example-3-using-nfs31-parameter-set) +- [WAF-aligned](#example-4-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep +module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { + name: '${uniqueString(deployment().name, location)}-test-nanaamin' + params: { + // Required parameters + name: 'nanaamin001' + // Non-required parameters + 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": "nanaamin001" + }, + // Non-required parameters + "location": { + "value": "" + } + } +} +``` + +
+

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

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

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "nanaamax001" + }, + // Non-required parameters + "capacityPools": { + "value": [ + { + "name": "nanaamax-cp-001", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [ + { + "exportPolicyRules": [ + { + "allowedClients": "0.0.0.0/0", + "nfsv3": false, + "nfsv41": true, + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true + } + ], + "name": "nanaamax-vol-001", + "protocolTypes": [ + "NFSv4.1" + ], + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "subnetResourceId": "", + "usageThreshold": 107374182400 + }, + { + "exportPolicyRules": [ + { + "allowedClients": "0.0.0.0/0", + "nfsv3": false, + "nfsv41": true, + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true + } + ], + "name": "nanaamax-vol-002", + "protocolTypes": [ + "NFSv4.1" + ], + "subnetResourceId": "", + "usageThreshold": 107374182400 + } + ] + }, + { + "name": "nanaamax-cp-002", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [] + } + ] + }, + "location": { + "value": "" + }, + "managedIdentities": { + "value": { + "userAssignedResourceIds": [ + "" + ] + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Contact": "test.user@testcompany.com", + "CostCenter": "7890", + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "PurchaseOrder": "1234", + "Role": "DeploymentValidation", + "ServiceName": "DeploymentValidation" + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { + name: '${uniqueString(deployment().name, location)}-test-nanaanfs3' + params: { + // Required parameters + name: 'nanaanfs3001' + // Non-required parameters + capacityPools: [ + { + name: 'nanaanfs3-cp-001' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [ + { + exportPolicyRules: [ + { + allowedClients: '0.0.0.0/0' + nfsv3: true + nfsv41: false + ruleIndex: 1 + unixReadOnly: false + unixReadWrite: true + } + ] + name: 'nanaanfs3-vol-001' + protocolTypes: [ + 'NFSv3' + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + subnetResourceId: '' + usageThreshold: 107374182400 + } + { + name: 'nanaanfs3-vol-002' + protocolTypes: [ + 'NFSv3' + ] + subnetResourceId: '' + usageThreshold: 107374182400 + } + ] + } + { + name: 'nanaanfs3-cp-002' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [] + } + ] + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Contact: 'test.user@testcompany.com' + CostCenter: '7890' + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + PurchaseOrder: '1234' + Role: 'DeploymentValidation' + ServiceName: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "nanaanfs3001" + }, + // Non-required parameters + "capacityPools": { + "value": [ + { + "name": "nanaanfs3-cp-001", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [ + { + "exportPolicyRules": [ + { + "allowedClients": "0.0.0.0/0", + "nfsv3": true, + "nfsv41": false, + "ruleIndex": 1, + "unixReadOnly": false, + "unixReadWrite": true + } + ], + "name": "nanaanfs3-vol-001", + "protocolTypes": [ + "NFSv3" + ], + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "subnetResourceId": "", + "usageThreshold": 107374182400 + }, + { + "name": "nanaanfs3-vol-002", + "protocolTypes": [ + "NFSv3" + ], + "subnetResourceId": "", + "usageThreshold": 107374182400 + } + ] + }, + { + "name": "nanaanfs3-cp-002", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "serviceLevel": "Premium", + "size": 4398046511104, + "volumes": [] + } + ] + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Contact": "test.user@testcompany.com", + "CostCenter": "7890", + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "PurchaseOrder": "1234", + "Role": "DeploymentValidation", + "ServiceName": "DeploymentValidation" + } + } + } +} +``` + +
+

+ +### Example 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 netAppAccount 'br/public:avm/res/net-app/net-app-account:' = { + name: '${uniqueString(deployment().name, location)}-test-nanaawaf' + params: { + // Required parameters + name: 'nanaawaf001' + // Non-required parameters + location: '' + } +} +``` + +
+

+ +

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

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the NetApp account. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`capacityPools`](#parameter-capacitypools) | array | Capacity pools to create. | +| [`dnsServers`](#parameter-dnsservers) | string | Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed. | +| [`domainJoinOU`](#parameter-domainjoinou) | string | Used only if domainName is specified. LDAP Path for the Organization Unit (OU) where SMB Server machine accounts will be created (i.e. 'OU=SecondLevel,OU=FirstLevel'). | +| [`domainJoinPassword`](#parameter-domainjoinpassword) | securestring | Required if domainName is specified. Password of the user specified in domainJoinUser parameter. | +| [`domainJoinUser`](#parameter-domainjoinuser) | string | Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain. | +| [`domainName`](#parameter-domainname) | string | Fully Qualified Active Directory DNS Domain Name (e.g. 'contoso.com'). | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`smbServerNamePrefix`](#parameter-smbservernameprefix) | string | Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes. | +| [`tags`](#parameter-tags) | object | Tags for all resources. | + +### Parameter: `name` + +The name of the NetApp account. + +- Required: Yes +- Type: string + +### Parameter: `capacityPools` + +Capacity pools to create. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `dnsServers` + +Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `domainJoinOU` + +Used only if domainName is specified. LDAP Path for the Organization Unit (OU) where SMB Server machine accounts will be created (i.e. 'OU=SecondLevel,OU=FirstLevel'). + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `domainJoinPassword` + +Required if domainName is specified. Password of the user specified in domainJoinUser parameter. + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `domainJoinUser` + +Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `domainName` + +Fully Qualified Active Directory DNS Domain Name (e.g. 'contoso.com'). + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `lock` + +The lock settings of the service. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | +| [`name`](#parameter-lockname) | string | Specify the name of lock. | + +### Parameter: `lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `managedIdentities` + +The managed identity definition for this resource. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | + +### Parameter: `managedIdentities.userAssignedResourceIds` + +The resource ID(s) to assign to the resource. + +- Required: Yes +- Type: array + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". | +| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `smbServerNamePrefix` + +Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `tags` + +Tags for all resources. + +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the NetApp account. | +| `resourceGroupName` | string | The name of the Resource Group the NetApp account was created in. | +| `resourceId` | string | The Resource ID of the NetApp account. | + +## Cross-referenced modules + +_None_ + +## 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/net-app/net-app-account/capacity-pool/README.md b/avm/res/net-app/net-app-account/capacity-pool/README.md new file mode 100644 index 0000000000..d53bccd3e7 --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/README.md @@ -0,0 +1,253 @@ +# Azure NetApp Files Capacity Pools `[Microsoft.NetApp/netAppAccounts/capacityPools]` + +This module deploys an Azure NetApp Files Capacity Pool. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.NetApp/netAppAccounts/capacityPools` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools) | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools/volumes) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the capacity pool. | +| [`size`](#parameter-size) | int | Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104). | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`netAppAccountName`](#parameter-netappaccountname) | string | The name of the parent NetApp account. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`coolAccess`](#parameter-coolaccess) | bool | If enabled (true) the pool can contain cool Access enabled volumes. | +| [`encryptionType`](#parameter-encryptiontype) | string | Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool. | +| [`location`](#parameter-location) | string | Location of the pool volume. | +| [`qosType`](#parameter-qostype) | string | The qos type of the pool. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`serviceLevel`](#parameter-servicelevel) | string | The pool service level. | +| [`tags`](#parameter-tags) | object | Tags for all resources. | +| [`volumes`](#parameter-volumes) | array | List of volumnes to create in the capacity pool. | + +### Parameter: `name` + +The name of the capacity pool. + +- Required: Yes +- Type: string + +### Parameter: `size` + +Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104). + +- Required: Yes +- Type: int + +### Parameter: `netAppAccountName` + +The name of the parent NetApp account. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `coolAccess` + +If enabled (true) the pool can contain cool Access enabled volumes. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `encryptionType` + +Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool. + +- Required: No +- Type: string +- Default: `'Single'` +- Allowed: + ```Bicep + [ + 'Double' + 'Single' + ] + ``` + +### Parameter: `location` + +Location of the pool volume. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `qosType` + +The qos type of the pool. + +- Required: No +- Type: string +- Default: `'Auto'` +- Allowed: + ```Bicep + [ + 'Auto' + 'Manual' + ] + ``` + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". | +| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `serviceLevel` + +The pool service level. + +- Required: No +- Type: string +- Default: `'Standard'` +- Allowed: + ```Bicep + [ + 'Premium' + 'Standard' + 'StandardZRS' + 'Ultra' + ] + ``` + +### Parameter: `tags` + +Tags for all resources. + +- Required: No +- Type: object + +### Parameter: `volumes` + +List of volumnes to create in the capacity pool. + +- Required: No +- Type: array +- Default: `[]` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the Capacity Pool. | +| `resourceGroupName` | string | The name of the Resource Group the Capacity Pool was created in. | +| `resourceId` | string | The resource ID of the Capacity Pool. | + +## Cross-referenced modules + +_None_ + +## 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/net-app/net-app-account/capacity-pool/main.bicep b/avm/res/net-app/net-app-account/capacity-pool/main.bicep new file mode 100644 index 0000000000..93154ca2f6 --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/main.bicep @@ -0,0 +1,147 @@ +metadata name = 'Azure NetApp Files Capacity Pools' +metadata description = 'This module deploys an Azure NetApp Files Capacity Pool.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment.') +param netAppAccountName string + +@description('Required. The name of the capacity pool.') +param name string + +@description('Optional. Location of the pool volume.') +param location string = resourceGroup().location + +@description('Optional. Tags for all resources.') +param tags object? + +@description('Optional. The pool service level.') +@allowed([ + 'Premium' + 'Standard' + 'StandardZRS' + 'Ultra' +]) +param serviceLevel string = 'Standard' + +@description('Required. Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104).') +param size int + +@description('Optional. The qos type of the pool.') +@allowed([ + 'Auto' + 'Manual' +]) +param qosType string = 'Auto' + +@description('Optional. List of volumnes to create in the capacity pool.') +param volumes array = [] + +@description('Optional. If enabled (true) the pool can contain cool Access enabled volumes.') +param coolAccess bool = false + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool.') +@allowed([ + 'Double' + 'Single' +]) +param encryptionType string = 'Single' + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2022-11-01' existing = { + name: netAppAccountName +} + +resource capacityPool 'Microsoft.NetApp/netAppAccounts/capacityPools@2022-11-01' = { + name: name + parent: netAppAccount + location: location + tags: tags + properties: { + serviceLevel: serviceLevel + size: size + qosType: qosType + coolAccess: coolAccess + encryptionType: encryptionType + } +} + +@batchSize(1) +module capacityPool_volumes 'volume/main.bicep' = [for (volume, index) in volumes: { + name: '${deployment().name}-Vol-${index}' + params: { + netAppAccountName: netAppAccount.name + capacityPoolName: capacityPool.name + name: volume.name + location: location + serviceLevel: serviceLevel + creationToken: contains(volume, 'creationToken') ? volume.creationToken : volume.name + usageThreshold: volume.usageThreshold + protocolTypes: contains(volume, 'protocolTypes') ? volume.protocolTypes : [] + subnetResourceId: volume.subnetResourceId + exportPolicyRules: contains(volume, 'exportPolicyRules') ? volume.exportPolicyRules : [] + roleAssignments: contains(volume, 'roleAssignments') ? volume.roleAssignments : [] + } +}] + +resource capacityPool_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(capacityPool.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: capacityPool +}] + +@description('The name of the Capacity Pool.') +output name string = capacityPool.name + +@description('The resource ID of the Capacity Pool.') +output resourceId string = capacityPool.id + +@description('The name of the Resource Group the Capacity Pool was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = capacityPool.location + +// =============== // +// Definitions // +// =============== // + +type roleAssignmentType = { + @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') + roleDefinitionIdOrName: string + + @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @description('Optional. The description of the role assignment.') + description: string? + + @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') + condition: string? + + @description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? diff --git a/avm/res/net-app/net-app-account/capacity-pool/main.json b/avm/res/net-app/net-app-account/capacity-pool/main.json new file mode 100644 index 0000000000..e4bd310cfb --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/main.json @@ -0,0 +1,563 @@ +{ + "$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": "126791606947586118" + }, + "name": "Azure NetApp Files Capacity Pools", + "description": "This module deploys an Azure NetApp Files Capacity Pool.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "netAppAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the capacity pool." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location of the pool volume." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all resources." + } + }, + "serviceLevel": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Premium", + "Standard", + "StandardZRS", + "Ultra" + ], + "metadata": { + "description": "Optional. The pool service level." + } + }, + "size": { + "type": "int", + "metadata": { + "description": "Required. Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104)." + } + }, + "qosType": { + "type": "string", + "defaultValue": "Auto", + "allowedValues": [ + "Auto", + "Manual" + ], + "metadata": { + "description": "Optional. The qos type of the pool." + } + }, + "volumes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of volumnes to create in the capacity pool." + } + }, + "coolAccess": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If enabled (true) the pool can contain cool Access enabled volumes." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "encryptionType": { + "type": "string", + "defaultValue": "Single", + "allowedValues": [ + "Double", + "Single" + ], + "metadata": { + "description": "Optional. Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool." + } + } + }, + "variables": { + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "netAppAccount": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts", + "apiVersion": "2022-11-01", + "name": "[parameters('netAppAccountName')]" + }, + "capacityPool": { + "type": "Microsoft.NetApp/netAppAccounts/capacityPools", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "serviceLevel": "[parameters('serviceLevel')]", + "size": "[parameters('size')]", + "qosType": "[parameters('qosType')]", + "coolAccess": "[parameters('coolAccess')]", + "encryptionType": "[parameters('encryptionType')]" + }, + "dependsOn": [ + "netAppAccount" + ] + }, + "capacityPool_roleAssignments": { + "copy": { + "name": "capacityPool_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}/capacityPools/{1}', parameters('netAppAccountName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.NetApp/netAppAccounts/capacityPools', parameters('netAppAccountName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "capacityPool" + ] + }, + "capacityPool_volumes": { + "copy": { + "name": "capacityPool_volumes", + "count": "[length(parameters('volumes'))]", + "mode": "serial", + "batchSize": 1 + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Vol-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "netAppAccountName": { + "value": "[parameters('netAppAccountName')]" + }, + "capacityPoolName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('volumes')[copyIndex()].name]" + }, + "location": { + "value": "[parameters('location')]" + }, + "serviceLevel": { + "value": "[parameters('serviceLevel')]" + }, + "creationToken": "[if(contains(parameters('volumes')[copyIndex()], 'creationToken'), createObject('value', parameters('volumes')[copyIndex()].creationToken), createObject('value', parameters('volumes')[copyIndex()].name))]", + "usageThreshold": { + "value": "[parameters('volumes')[copyIndex()].usageThreshold]" + }, + "protocolTypes": "[if(contains(parameters('volumes')[copyIndex()], 'protocolTypes'), createObject('value', parameters('volumes')[copyIndex()].protocolTypes), createObject('value', createArray()))]", + "subnetResourceId": { + "value": "[parameters('volumes')[copyIndex()].subnetResourceId]" + }, + "exportPolicyRules": "[if(contains(parameters('volumes')[copyIndex()], 'exportPolicyRules'), createObject('value', parameters('volumes')[copyIndex()].exportPolicyRules), createObject('value', createArray()))]", + "roleAssignments": "[if(contains(parameters('volumes')[copyIndex()], 'roleAssignments'), createObject('value', parameters('volumes')[copyIndex()].roleAssignments), createObject('value', createArray()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "587216728391543886" + }, + "name": "Azure NetApp Files Capacity Pool Volumes", + "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "netAppAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment." + } + }, + "capacityPoolName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the pool volume." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location of the pool volume." + } + }, + "serviceLevel": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Premium", + "Standard", + "StandardZRS", + "Ultra" + ], + "metadata": { + "description": "Optional. The pool service level. Must match the one of the parent capacity pool." + } + }, + "creationToken": { + "type": "string", + "defaultValue": "[parameters('name')]", + "metadata": { + "description": "Optional. A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription." + } + }, + "usageThreshold": { + "type": "int", + "metadata": { + "description": "Required. Maximum storage quota allowed for a file system in bytes." + } + }, + "protocolTypes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Set of protocol types." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes." + } + }, + "exportPolicyRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Export policy rules." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "netAppAccount::capacityPool": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts/capacityPools", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('capacityPoolName'))]", + "dependsOn": [ + "netAppAccount" + ] + }, + "netAppAccount": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts", + "apiVersion": "2022-11-01", + "name": "[parameters('netAppAccountName')]" + }, + "volume": { + "type": "Microsoft.NetApp/netAppAccounts/capacityPools/volumes", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "serviceLevel": "[parameters('serviceLevel')]", + "creationToken": "[parameters('creationToken')]", + "usageThreshold": "[parameters('usageThreshold')]", + "protocolTypes": "[parameters('protocolTypes')]", + "subnetId": "[parameters('subnetResourceId')]", + "exportPolicy": "[if(not(empty(parameters('exportPolicyRules'))), createObject('rules', parameters('exportPolicyRules')), null())]" + }, + "dependsOn": [ + "netAppAccount::capacityPool" + ] + }, + "volume_roleAssignments": { + "copy": { + "name": "volume_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}/capacityPools/{1}/volumes/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.NetApp/netAppAccounts/capacityPools/volumes', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "volume" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the Volume." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the Volume." + }, + "value": "[resourceId('Microsoft.NetApp/netAppAccounts/capacityPools/volumes', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the Volume was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('volume', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "capacityPool", + "netAppAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the Capacity Pool." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Capacity Pool." + }, + "value": "[resourceId('Microsoft.NetApp/netAppAccounts/capacityPools', parameters('netAppAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the Capacity Pool was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('capacityPool', '2022-11-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/README.md b/avm/res/net-app/net-app-account/capacity-pool/volume/README.md new file mode 100644 index 0000000000..4b934d6584 --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/README.md @@ -0,0 +1,237 @@ +# Azure NetApp Files Capacity Pool Volumes `[Microsoft.NetApp/netAppAccounts/capacityPools/volumes]` + +This module deploys an Azure NetApp Files Capacity Pool Volume. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.NetApp/netAppAccounts/capacityPools/volumes` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.NetApp/netAppAccounts/capacityPools/volumes) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the pool volume. | +| [`subnetResourceId`](#parameter-subnetresourceid) | string | The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes. | +| [`usageThreshold`](#parameter-usagethreshold) | int | Maximum storage quota allowed for a file system in bytes. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`capacityPoolName`](#parameter-capacitypoolname) | string | The name of the parent capacity pool. Required if the template is used in a standalone deployment. | +| [`netAppAccountName`](#parameter-netappaccountname) | string | The name of the parent NetApp account. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`creationToken`](#parameter-creationtoken) | string | A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription. | +| [`exportPolicyRules`](#parameter-exportpolicyrules) | array | Export policy rules. | +| [`location`](#parameter-location) | string | Location of the pool volume. | +| [`protocolTypes`](#parameter-protocoltypes) | array | Set of protocol types. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`serviceLevel`](#parameter-servicelevel) | string | The pool service level. Must match the one of the parent capacity pool. | + +### Parameter: `name` + +The name of the pool volume. + +- Required: Yes +- Type: string + +### Parameter: `subnetResourceId` + +The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes. + +- Required: Yes +- Type: string + +### Parameter: `usageThreshold` + +Maximum storage quota allowed for a file system in bytes. + +- Required: Yes +- Type: int + +### Parameter: `capacityPoolName` + +The name of the parent capacity pool. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `netAppAccountName` + +The name of the parent NetApp account. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `creationToken` + +A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription. + +- Required: No +- Type: string +- Default: `[parameters('name')]` + +### Parameter: `exportPolicyRules` + +Export policy rules. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `location` + +Location of the pool volume. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `protocolTypes` + +Set of protocol types. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". | +| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `serviceLevel` + +The pool service level. Must match the one of the parent capacity pool. + +- Required: No +- Type: string +- Default: `'Standard'` +- Allowed: + ```Bicep + [ + 'Premium' + 'Standard' + 'StandardZRS' + 'Ultra' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the Volume. | +| `resourceGroupName` | string | The name of the Resource Group the Volume was created in. | +| `resourceId` | string | The Resource ID of the Volume. | + +## Cross-referenced modules + +_None_ + +## 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/net-app/net-app-account/capacity-pool/volume/main.bicep b/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep new file mode 100644 index 0000000000..4f9ce83488 --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/main.bicep @@ -0,0 +1,127 @@ +metadata name = 'Azure NetApp Files Capacity Pool Volumes' +metadata description = 'This module deploys an Azure NetApp Files Capacity Pool Volume.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment.') +param netAppAccountName string + +@description('Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment.') +param capacityPoolName string + +@description('Required. The name of the pool volume.') +param name string + +@description('Optional. Location of the pool volume.') +param location string = resourceGroup().location + +@description('Optional. The pool service level. Must match the one of the parent capacity pool.') +@allowed([ + 'Premium' + 'Standard' + 'StandardZRS' + 'Ultra' +]) +param serviceLevel string = 'Standard' + +@description('Optional. A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription.') +param creationToken string = name + +@description('Required. Maximum storage quota allowed for a file system in bytes.') +param usageThreshold int + +@description('Optional. Set of protocol types.') +param protocolTypes array = [] + +@description('Required. The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes.') +param subnetResourceId string + +@description('Optional. Export policy rules.') +param exportPolicyRules array = [] + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2022-11-01' existing = { + name: netAppAccountName + + resource capacityPool 'capacityPools@2022-11-01' existing = { + name: capacityPoolName + } +} + +resource volume 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes@2022-11-01' = { + name: name + parent: netAppAccount::capacityPool + location: location + properties: { + serviceLevel: serviceLevel + creationToken: creationToken + usageThreshold: usageThreshold + protocolTypes: protocolTypes + subnetId: subnetResourceId + exportPolicy: !empty(exportPolicyRules) ? { + rules: exportPolicyRules + } : null + } +} + +resource volume_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(volume.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: volume +}] + +@description('The name of the Volume.') +output name string = volume.name + +@description('The Resource ID of the Volume.') +output resourceId string = volume.id + +@description('The name of the Resource Group the Volume was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = volume.location + +// =============== // +// Definitions // +// =============== // + +type roleAssignmentType = { + @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') + roleDefinitionIdOrName: string + + @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @description('Optional. The description of the role assignment.') + description: string? + + @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') + condition: string? + + @description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? diff --git a/avm/res/net-app/net-app-account/capacity-pool/volume/main.json b/avm/res/net-app/net-app-account/capacity-pool/volume/main.json new file mode 100644 index 0000000000..1a8275a515 --- /dev/null +++ b/avm/res/net-app/net-app-account/capacity-pool/volume/main.json @@ -0,0 +1,257 @@ +{ + "$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": "587216728391543886" + }, + "name": "Azure NetApp Files Capacity Pool Volumes", + "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "netAppAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment." + } + }, + "capacityPoolName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the pool volume." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location of the pool volume." + } + }, + "serviceLevel": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Premium", + "Standard", + "StandardZRS", + "Ultra" + ], + "metadata": { + "description": "Optional. The pool service level. Must match the one of the parent capacity pool." + } + }, + "creationToken": { + "type": "string", + "defaultValue": "[parameters('name')]", + "metadata": { + "description": "Optional. A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription." + } + }, + "usageThreshold": { + "type": "int", + "metadata": { + "description": "Required. Maximum storage quota allowed for a file system in bytes." + } + }, + "protocolTypes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Set of protocol types." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes." + } + }, + "exportPolicyRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Export policy rules." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "netAppAccount::capacityPool": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts/capacityPools", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('capacityPoolName'))]", + "dependsOn": [ + "netAppAccount" + ] + }, + "netAppAccount": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts", + "apiVersion": "2022-11-01", + "name": "[parameters('netAppAccountName')]" + }, + "volume": { + "type": "Microsoft.NetApp/netAppAccounts/capacityPools/volumes", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "serviceLevel": "[parameters('serviceLevel')]", + "creationToken": "[parameters('creationToken')]", + "usageThreshold": "[parameters('usageThreshold')]", + "protocolTypes": "[parameters('protocolTypes')]", + "subnetId": "[parameters('subnetResourceId')]", + "exportPolicy": "[if(not(empty(parameters('exportPolicyRules'))), createObject('rules', parameters('exportPolicyRules')), null())]" + }, + "dependsOn": [ + "netAppAccount::capacityPool" + ] + }, + "volume_roleAssignments": { + "copy": { + "name": "volume_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}/capacityPools/{1}/volumes/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.NetApp/netAppAccounts/capacityPools/volumes', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "volume" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the Volume." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the Volume." + }, + "value": "[resourceId('Microsoft.NetApp/netAppAccounts/capacityPools/volumes', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the Volume was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('volume', '2022-11-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/net-app/net-app-account/main.bicep b/avm/res/net-app/net-app-account/main.bicep new file mode 100644 index 0000000000..35913dd2f2 --- /dev/null +++ b/avm/res/net-app/net-app-account/main.bicep @@ -0,0 +1,192 @@ +metadata name = 'Azure NetApp Files' +metadata description = 'This module deploys an Azure NetApp File.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the NetApp account.') +param name string + +@description('Optional. Fully Qualified Active Directory DNS Domain Name (e.g. \'contoso.com\').') +param domainName string = '' + +@description('Optional. Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain.') +param domainJoinUser string = '' + +@description('Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter.') +@secure() +param domainJoinPassword string = '' + +@description('Optional. Used only if domainName is specified. LDAP Path for the Organization Unit (OU) where SMB Server machine accounts will be created (i.e. \'OU=SecondLevel,OU=FirstLevel\').') +param domainJoinOU string = '' + +@description('Optional. Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed.') +param dnsServers string = '' + +@description('Optional. Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes.') +param smbServerNamePrefix string = '' + +@description('Optional. Capacity pools to create.') +param capacityPools array = [] + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Tags for all resources.') +param tags object? + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +var activeDirectoryConnectionProperties = [ + { + username: !empty(domainName) ? domainJoinUser : null + password: !empty(domainName) ? domainJoinPassword : null + domain: !empty(domainName) ? domainName : null + dns: !empty(domainName) ? dnsServers : null + smbServerName: !empty(domainName) ? smbServerNamePrefix : null + organizationalUnit: !empty(domainJoinOU) ? domainJoinOU : null + } +] + +var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } + +var identity = !empty(managedIdentities) ? { + type: !empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.netapp-netappaccount.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +resource netAppAccount 'Microsoft.NetApp/netAppAccounts@2022-11-01' = { + name: name + tags: tags + identity: identity + location: location + properties: { + activeDirectories: !empty(domainName) ? activeDirectoryConnectionProperties : null + } +} + +resource netAppAccount_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { + name: lock.?name ?? 'lock-${name}' + properties: { + level: lock.?kind ?? '' + notes: lock.?kind == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot delete or modify the resource or child resources.' + } + scope: netAppAccount +} + +resource netAppAccount_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(netAppAccount.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: netAppAccount +}] + +module netAppAccount_capacityPools 'capacity-pool/main.bicep' = [for (capacityPool, index) in capacityPools: { + name: '${uniqueString(deployment().name, location)}-ANFAccount-CapPool-${index}' + params: { + netAppAccountName: netAppAccount.name + name: capacityPool.name + location: location + size: capacityPool.size + serviceLevel: contains(capacityPool, 'serviceLevel') ? capacityPool.serviceLevel : 'Standard' + qosType: contains(capacityPool, 'qosType') ? capacityPool.qosType : 'Auto' + volumes: contains(capacityPool, 'volumes') ? capacityPool.volumes : [] + coolAccess: contains(capacityPool, 'coolAccess') ? capacityPool.coolAccess : false + roleAssignments: contains(capacityPool, 'roleAssignments') ? capacityPool.roleAssignments : [] + encryptionType: contains(capacityPool, 'encryptionType') ? capacityPool.encryptionType : 'Single' + tags: capacityPool.?tags ?? tags + } +}] + +@description('The name of the NetApp account.') +output name string = netAppAccount.name + +@description('The Resource ID of the NetApp account.') +output resourceId string = netAppAccount.id + +@description('The name of the Resource Group the NetApp account was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = netAppAccount.location + +// =============== // +// Definitions // +// =============== // + +type managedIdentitiesType = { + @description('Optional. The resource ID(s) to assign to the resource.') + userAssignedResourceIds: string[] +}? + +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. Specify the type of lock.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None')? +}? + +type roleAssignmentType = { + @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') + roleDefinitionIdOrName: string + + @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @description('Optional. The description of the role assignment.') + description: string? + + @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') + condition: string? + + @description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? diff --git a/avm/res/net-app/net-app-account/main.json b/avm/res/net-app/net-app-account/main.json new file mode 100644 index 0000000000..9cff3848e2 --- /dev/null +++ b/avm/res/net-app/net-app-account/main.json @@ -0,0 +1,943 @@ +{ + "$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": "7695895341008630388" + }, + "name": "Azure NetApp Files", + "description": "This module deploys an Azure NetApp File.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the NetApp account." + } + }, + "domainName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Fully Qualified Active Directory DNS Domain Name (e.g. 'contoso.com')." + } + }, + "domainJoinUser": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if domainName is specified. Username of Active Directory domain administrator, with permissions to create SMB server machine account in the AD domain." + } + }, + "domainJoinPassword": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter." + } + }, + "domainJoinOU": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Used only if domainName is specified. LDAP Path for the Organization Unit (OU) where SMB Server machine accounts will be created (i.e. 'OU=SecondLevel,OU=FirstLevel')." + } + }, + "dnsServers": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if domainName is specified. Comma separated list of DNS server IP addresses (IPv4 only) required for the Active Directory (AD) domain join and SMB authentication operations to succeed." + } + }, + "smbServerNamePrefix": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if domainName is specified. NetBIOS name of the SMB server. A computer account with this prefix will be registered in the AD and used to mount volumes." + } + }, + "capacityPools": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Capacity pools to create." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all resources." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "activeDirectoryConnectionProperties": [ + { + "username": "[if(not(empty(parameters('domainName'))), parameters('domainJoinUser'), null())]", + "password": "[if(not(empty(parameters('domainName'))), parameters('domainJoinPassword'), null())]", + "domain": "[if(not(empty(parameters('domainName'))), parameters('domainName'), null())]", + "dns": "[if(not(empty(parameters('domainName'))), parameters('dnsServers'), null())]", + "smbServerName": "[if(not(empty(parameters('domainName'))), parameters('smbServerNamePrefix'), null())]", + "organizationalUnit": "[if(not(empty(parameters('domainJoinOU'))), parameters('domainJoinOU'), null())]" + } + ], + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null()), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.netapp-netappaccount.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "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" + } + } + } + } + }, + "netAppAccount": { + "type": "Microsoft.NetApp/netAppAccounts", + "apiVersion": "2022-11-01", + "name": "[parameters('name')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "location": "[parameters('location')]", + "properties": { + "activeDirectories": "[if(not(empty(parameters('domainName'))), variables('activeDirectoryConnectionProperties'), null())]" + } + }, + "netAppAccount_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "netAppAccount" + ] + }, + "netAppAccount_roleAssignments": { + "copy": { + "name": "netAppAccount_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.NetApp/netAppAccounts', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "netAppAccount" + ] + }, + "netAppAccount_capacityPools": { + "copy": { + "name": "netAppAccount_capacityPools", + "count": "[length(parameters('capacityPools'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-ANFAccount-CapPool-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "netAppAccountName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('capacityPools')[copyIndex()].name]" + }, + "location": { + "value": "[parameters('location')]" + }, + "size": { + "value": "[parameters('capacityPools')[copyIndex()].size]" + }, + "serviceLevel": "[if(contains(parameters('capacityPools')[copyIndex()], 'serviceLevel'), createObject('value', parameters('capacityPools')[copyIndex()].serviceLevel), createObject('value', 'Standard'))]", + "qosType": "[if(contains(parameters('capacityPools')[copyIndex()], 'qosType'), createObject('value', parameters('capacityPools')[copyIndex()].qosType), createObject('value', 'Auto'))]", + "volumes": "[if(contains(parameters('capacityPools')[copyIndex()], 'volumes'), createObject('value', parameters('capacityPools')[copyIndex()].volumes), createObject('value', createArray()))]", + "coolAccess": "[if(contains(parameters('capacityPools')[copyIndex()], 'coolAccess'), createObject('value', parameters('capacityPools')[copyIndex()].coolAccess), createObject('value', false()))]", + "roleAssignments": "[if(contains(parameters('capacityPools')[copyIndex()], 'roleAssignments'), createObject('value', parameters('capacityPools')[copyIndex()].roleAssignments), createObject('value', createArray()))]", + "encryptionType": "[if(contains(parameters('capacityPools')[copyIndex()], 'encryptionType'), createObject('value', parameters('capacityPools')[copyIndex()].encryptionType), createObject('value', 'Single'))]", + "tags": { + "value": "[coalesce(tryGet(parameters('capacityPools')[copyIndex()], 'tags'), parameters('tags'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "126791606947586118" + }, + "name": "Azure NetApp Files Capacity Pools", + "description": "This module deploys an Azure NetApp Files Capacity Pool.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "netAppAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the capacity pool." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location of the pool volume." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all resources." + } + }, + "serviceLevel": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Premium", + "Standard", + "StandardZRS", + "Ultra" + ], + "metadata": { + "description": "Optional. The pool service level." + } + }, + "size": { + "type": "int", + "metadata": { + "description": "Required. Provisioned size of the pool (in bytes). Allowed values are in 4TiB chunks (value must be multiply of 4398046511104)." + } + }, + "qosType": { + "type": "string", + "defaultValue": "Auto", + "allowedValues": [ + "Auto", + "Manual" + ], + "metadata": { + "description": "Optional. The qos type of the pool." + } + }, + "volumes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of volumnes to create in the capacity pool." + } + }, + "coolAccess": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If enabled (true) the pool can contain cool Access enabled volumes." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "encryptionType": { + "type": "string", + "defaultValue": "Single", + "allowedValues": [ + "Double", + "Single" + ], + "metadata": { + "description": "Optional. Encryption type of the capacity pool, set encryption type for data at rest for this pool and all volumes in it. This value can only be set when creating new pool." + } + } + }, + "variables": { + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "netAppAccount": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts", + "apiVersion": "2022-11-01", + "name": "[parameters('netAppAccountName')]" + }, + "capacityPool": { + "type": "Microsoft.NetApp/netAppAccounts/capacityPools", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "serviceLevel": "[parameters('serviceLevel')]", + "size": "[parameters('size')]", + "qosType": "[parameters('qosType')]", + "coolAccess": "[parameters('coolAccess')]", + "encryptionType": "[parameters('encryptionType')]" + }, + "dependsOn": [ + "netAppAccount" + ] + }, + "capacityPool_roleAssignments": { + "copy": { + "name": "capacityPool_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}/capacityPools/{1}', parameters('netAppAccountName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.NetApp/netAppAccounts/capacityPools', parameters('netAppAccountName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "capacityPool" + ] + }, + "capacityPool_volumes": { + "copy": { + "name": "capacityPool_volumes", + "count": "[length(parameters('volumes'))]", + "mode": "serial", + "batchSize": 1 + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Vol-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "netAppAccountName": { + "value": "[parameters('netAppAccountName')]" + }, + "capacityPoolName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('volumes')[copyIndex()].name]" + }, + "location": { + "value": "[parameters('location')]" + }, + "serviceLevel": { + "value": "[parameters('serviceLevel')]" + }, + "creationToken": "[if(contains(parameters('volumes')[copyIndex()], 'creationToken'), createObject('value', parameters('volumes')[copyIndex()].creationToken), createObject('value', parameters('volumes')[copyIndex()].name))]", + "usageThreshold": { + "value": "[parameters('volumes')[copyIndex()].usageThreshold]" + }, + "protocolTypes": "[if(contains(parameters('volumes')[copyIndex()], 'protocolTypes'), createObject('value', parameters('volumes')[copyIndex()].protocolTypes), createObject('value', createArray()))]", + "subnetResourceId": { + "value": "[parameters('volumes')[copyIndex()].subnetResourceId]" + }, + "exportPolicyRules": "[if(contains(parameters('volumes')[copyIndex()], 'exportPolicyRules'), createObject('value', parameters('volumes')[copyIndex()].exportPolicyRules), createObject('value', createArray()))]", + "roleAssignments": "[if(contains(parameters('volumes')[copyIndex()], 'roleAssignments'), createObject('value', parameters('volumes')[copyIndex()].roleAssignments), createObject('value', createArray()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "587216728391543886" + }, + "name": "Azure NetApp Files Capacity Pool Volumes", + "description": "This module deploys an Azure NetApp Files Capacity Pool Volume.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "netAppAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent NetApp account. Required if the template is used in a standalone deployment." + } + }, + "capacityPoolName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent capacity pool. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the pool volume." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location of the pool volume." + } + }, + "serviceLevel": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Premium", + "Standard", + "StandardZRS", + "Ultra" + ], + "metadata": { + "description": "Optional. The pool service level. Must match the one of the parent capacity pool." + } + }, + "creationToken": { + "type": "string", + "defaultValue": "[parameters('name')]", + "metadata": { + "description": "Optional. A unique file path for the volume. This is the name of the volume export. A volume is mounted using the export path. File path must start with an alphabetical character and be unique within the subscription." + } + }, + "usageThreshold": { + "type": "int", + "metadata": { + "description": "Required. Maximum storage quota allowed for a file system in bytes." + } + }, + "protocolTypes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Set of protocol types." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. The Azure Resource URI for a delegated subnet. Must have the delegation Microsoft.NetApp/volumes." + } + }, + "exportPolicyRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Export policy rules." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "netAppAccount::capacityPool": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts/capacityPools", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('netAppAccountName'), parameters('capacityPoolName'))]", + "dependsOn": [ + "netAppAccount" + ] + }, + "netAppAccount": { + "existing": true, + "type": "Microsoft.NetApp/netAppAccounts", + "apiVersion": "2022-11-01", + "name": "[parameters('netAppAccountName')]" + }, + "volume": { + "type": "Microsoft.NetApp/netAppAccounts/capacityPools/volumes", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "serviceLevel": "[parameters('serviceLevel')]", + "creationToken": "[parameters('creationToken')]", + "usageThreshold": "[parameters('usageThreshold')]", + "protocolTypes": "[parameters('protocolTypes')]", + "subnetId": "[parameters('subnetResourceId')]", + "exportPolicy": "[if(not(empty(parameters('exportPolicyRules'))), createObject('rules', parameters('exportPolicyRules')), null())]" + }, + "dependsOn": [ + "netAppAccount::capacityPool" + ] + }, + "volume_roleAssignments": { + "copy": { + "name": "volume_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.NetApp/netAppAccounts/{0}/capacityPools/{1}/volumes/{2}', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]", + "name": "[guid(resourceId('Microsoft.NetApp/netAppAccounts/capacityPools/volumes', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "volume" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the Volume." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the Volume." + }, + "value": "[resourceId('Microsoft.NetApp/netAppAccounts/capacityPools/volumes', parameters('netAppAccountName'), parameters('capacityPoolName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the Volume was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('volume', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "capacityPool", + "netAppAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the Capacity Pool." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Capacity Pool." + }, + "value": "[resourceId('Microsoft.NetApp/netAppAccounts/capacityPools', parameters('netAppAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the Capacity Pool was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('capacityPool', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "netAppAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the NetApp account." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The Resource ID of the NetApp account." + }, + "value": "[resourceId('Microsoft.NetApp/netAppAccounts', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the NetApp account was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('netAppAccount', '2022-11-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/net-app/net-app-account/tests/e2e/defaults/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..3c7446c1ef --- /dev/null +++ b/avm/res/net-app/net-app-account/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,48 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-netapp.netappaccounts-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nanaamin' + +@description('Optional. 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 = 'westus3' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: tempLocation +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + name: '${namePrefix}${serviceShort}001' + location: tempLocation + } +} diff --git a/avm/res/net-app/net-app-account/tests/e2e/max/dependencies.bicep b/avm/res/net-app/net-app-account/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..d0c6383547 --- /dev/null +++ b/avm/res/net-app/net-app-account/tests/e2e/max/dependencies.bicep @@ -0,0 +1,52 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + delegations: [ + { + name: 'netappDel' + properties: { + serviceName: 'Microsoft.Netapp/volumes' + } + } + ] + } + } + ] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id diff --git a/avm/res/net-app/net-app-account/tests/e2e/max/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..14603d2194 --- /dev/null +++ b/avm/res/net-app/net-app-account/tests/e2e/max/main.test.bicep @@ -0,0 +1,161 @@ +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}-netapp.netappaccounts-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nanaamax' + +@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 = 'westus3' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: tempLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: tempLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + name: '${namePrefix}${serviceShort}001' + location: tempLocation + capacityPools: [ + { + name: '${namePrefix}-${serviceShort}-cp-001' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [ + { + exportPolicyRules: [ + { + allowedClients: '0.0.0.0/0' + nfsv3: false + nfsv41: true + ruleIndex: 1 + unixReadOnly: false + unixReadWrite: true + } + ] + name: '${namePrefix}-${serviceShort}-vol-001' + protocolTypes: [ + 'NFSv4.1' + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + usageThreshold: 107374182400 + } + { + exportPolicyRules: [ + { + allowedClients: '0.0.0.0/0' + nfsv3: false + nfsv41: true + ruleIndex: 1 + unixReadOnly: false + unixReadWrite: true + } + ] + name: '${namePrefix}-${serviceShort}-vol-002' + protocolTypes: [ + 'NFSv4.1' + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + usageThreshold: 107374182400 + } + ] + } + { + name: '${namePrefix}-${serviceShort}-cp-002' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [] + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Contact: 'test.user@testcompany.com' + CostCenter: '7890' + Environment: 'Non-Prod' + PurchaseOrder: '1234' + Role: 'DeploymentValidation' + ServiceName: 'DeploymentValidation' + } + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + } +} diff --git a/avm/res/net-app/net-app-account/tests/e2e/nfs3/dependencies.bicep b/avm/res/net-app/net-app-account/tests/e2e/nfs3/dependencies.bicep new file mode 100644 index 0000000000..71e1d77e16 --- /dev/null +++ b/avm/res/net-app/net-app-account/tests/e2e/nfs3/dependencies.bicep @@ -0,0 +1,49 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + delegations: [ + { + name: 'netappDel' + properties: { + serviceName: 'Microsoft.Netapp/volumes' + } + } + ] + } + } + ] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep new file mode 100644 index 0000000000..f389b83a78 --- /dev/null +++ b/avm/res/net-app/net-app-account/tests/e2e/nfs3/main.test.bicep @@ -0,0 +1,150 @@ +targetScope = 'subscription' + +metadata name = 'Using nfs31 parameter set' +metadata description = 'This instance deploys the module with nfs31.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-netapp.netappaccounts-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nanaanfs3' + +@description('Optional. 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 = 'westus3' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: tempLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: tempLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + name: '${namePrefix}${serviceShort}001' + location: tempLocation + capacityPools: [ + { + name: '${namePrefix}-${serviceShort}-cp-001' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [ + { + exportPolicyRules: [ + { + allowedClients: '0.0.0.0/0' + nfsv3: true + nfsv41: false + ruleIndex: 1 + unixReadOnly: false + unixReadWrite: true + } + ] + name: '${namePrefix}-${serviceShort}-vol-001' + protocolTypes: [ + 'NFSv3' + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + usageThreshold: 107374182400 + } + { + name: '${namePrefix}-${serviceShort}-vol-002' + protocolTypes: [ + 'NFSv3' + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + usageThreshold: 107374182400 + } + ] + } + { + name: '${namePrefix}-${serviceShort}-cp-002' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + serviceLevel: 'Premium' + size: 4398046511104 + volumes: [] + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Contact: 'test.user@testcompany.com' + CostCenter: '7890' + Environment: 'Non-Prod' + PurchaseOrder: '1234' + Role: 'DeploymentValidation' + ServiceName: 'DeploymentValidation' + } + } +} diff --git a/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..83f7da408c --- /dev/null +++ b/avm/res/net-app/net-app-account/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,51 @@ +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}-netapp.netappaccounts-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +// e.g., for a module 'network/private-endpoint' you could use 'npe' as a prefix and then 'waf' as a suffix for the waf-aligned test +param serviceShort string = 'nanaawaf' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +#disable-next-line no-hardcoded-location // services used for this module are only available in major regions +var tempLocation = 'westus3' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: tempLocation +} + +// ============== // +// 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: tempLocation + } +}] diff --git a/avm/res/net-app/net-app-account/version.json b/avm/res/net-app/net-app-account/version.json new file mode 100644 index 0000000000..7fa401bdf7 --- /dev/null +++ b/avm/res/net-app/net-app-account/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +}