diff --git a/avm/ptn/lz/sub-vending/README.md b/avm/ptn/lz/sub-vending/README.md index de4ec1a5d2..c5abe03e9f 100644 --- a/avm/ptn/lz/sub-vending/README.md +++ b/avm/ptn/lz/sub-vending/README.md @@ -623,6 +623,7 @@ param virtualNetworkResourceGroupName = '' | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`existingSubscriptionId`](#parameter-existingsubscriptionid) | string | An existing subscription ID. Use this when you do not want the module to create a new subscription. But do want to manage the management group membership. A subscription ID should be provided in the example format `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`. | | [`hubNetworkResourceId`](#parameter-hubnetworkresourceid) | string | The resource ID of the Virtual Network or Virtual WAN Hub in the hub to which the created Virtual Network, by this module, will be peered/connected to via Virtual Network Peering or a Virtual WAN Virtual Hub Connection.

| +| [`managementGroupAssociationDelayCount`](#parameter-managementgroupassociationdelaycount) | int | The number of blank ARM deployments to create sequentially to introduce a delay to the Subscription being moved to the target Management Group being, if set, to allow for background platform RBAC inheritance to occur. | | [`resourceProviders`](#parameter-resourceproviders) | object | An object of resource providers and resource providers features to register. If left blank/empty, no resource providers will be registered.

| | [`roleAssignmentEnabled`](#parameter-roleassignmentenabled) | bool | Whether to create role assignments or not. If true, supply the array of role assignment objects in the parameter called `roleAssignments`.

| | [`roleAssignments`](#parameter-roleassignments) | array | Supply an array of objects containing the details of the role assignments to create.

Each object must contain the following `keys`:

  • `principalId` = The Object ID of the User, Group, SPN, Managed Identity to assign the RBAC role too.
  • `definition` = The Name of one of the pre-defined built-In RBAC Roles or a Resource ID of a Built-in or custom RBAC Role Definition as follows:

    - You can only provide the RBAC role name of the pre-defined roles (Contributor, Owner, Reader, Role Based Access Control Administrator (Preview), and User Access Administrator). We only provide those roles as they are the most common ones to assign to a new subscription, also to reduce the template size and complexity in case we define each and every Built-in RBAC role.

    - You can provide the Resource ID of a Built-in or custom RBAC Role Definition

    - e.g. `/providers/Microsoft.Authorization/roleDefinitions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`

  • `relativeScope` = 2 options can be provided for input value:

    1. `''` *(empty string)* = Make RBAC Role Assignment to Subscription scope

    2. `'/resourceGroups/'` = Make RBAC Role Assignment to specified Resource Group.

    | @@ -735,6 +736,14 @@ The resource ID of the Virtual Network or Virtual WAN Hub in the hub to which th - Type: string - Default: `''` +### Parameter: `managementGroupAssociationDelayCount` + +The number of blank ARM deployments to create sequentially to introduce a delay to the Subscription being moved to the target Management Group being, if set, to allow for background platform RBAC inheritance to occur. + +- Required: No +- Type: int +- Default: `15` + ### Parameter: `resourceProviders` An object of resource providers and resource providers features to register. If left blank/empty, no resource providers will be registered.

    diff --git a/avm/ptn/lz/sub-vending/main.bicep b/avm/ptn/lz/sub-vending/main.bicep index dd26bc28a1..62f27ca2c3 100644 --- a/avm/ptn/lz/sub-vending/main.bicep +++ b/avm/ptn/lz/sub-vending/main.bicep @@ -297,6 +297,9 @@ param resourceProviders object = { 'Microsoft.Web': [] } +@sys.description('Optional. The number of blank ARM deployments to create sequentially to introduce a delay to the Subscription being moved to the target Management Group being, if set, to allow for background platform RBAC inheritance to occur.') +param managementGroupAssociationDelayCount int = 15 + // VARIABLES var existingSubscriptionIDEmptyCheck = empty(existingSubscriptionId) @@ -355,6 +358,7 @@ module createSubscriptionResources './modules/subResourceWrapper.bicep' = if (su subscriptionId: (subscriptionAliasEnabled && empty(existingSubscriptionId)) ? createSubscription.outputs.subscriptionId : existingSubscriptionId + managementGroupAssociationDelayCount: managementGroupAssociationDelayCount subscriptionManagementGroupAssociationEnabled: subscriptionManagementGroupAssociationEnabled subscriptionManagementGroupId: subscriptionManagementGroupId subscriptionTags: subscriptionTags diff --git a/avm/ptn/lz/sub-vending/main.json b/avm/ptn/lz/sub-vending/main.json index e42574e3c1..ee24f61ead 100644 --- a/avm/ptn/lz/sub-vending/main.json +++ b/avm/ptn/lz/sub-vending/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "2343164809013150587" + "templateHash": "2644636658214532574" }, "name": "Sub-vending", "description": "This module deploys a subscription to accelerate deployment of landing zones. For more information on how to use it, please visit this [Wiki](https://github.com/Azure/bicep-lz-vending/wiki).", @@ -377,6 +377,13 @@ "metadata": { "description": "Optional. An object of resource providers and resource providers features to register. If left blank/empty, no resource providers will be registered.\n" } + }, + "managementGroupAssociationDelayCount": { + "type": "int", + "defaultValue": 15, + "metadata": { + "description": "Optional. The number of blank ARM deployments to create sequentially to introduce a delay to the Subscription being moved to the target Management Group being, if set, to allow for background platform RBAC inheritance to occur." + } } }, "variables": { @@ -546,6 +553,9 @@ "mode": "Incremental", "parameters": { "subscriptionId": "[if(and(parameters('subscriptionAliasEnabled'), empty(parameters('existingSubscriptionId'))), createObject('value', reference(extensionResourceId(managementGroup().id, 'Microsoft.Resources/deployments', variables('deploymentNames').createSubscription), '2022-09-01').outputs.subscriptionId.value), createObject('value', parameters('existingSubscriptionId')))]", + "managementGroupAssociationDelayCount": { + "value": "[parameters('managementGroupAssociationDelayCount')]" + }, "subscriptionManagementGroupAssociationEnabled": { "value": "[parameters('subscriptionManagementGroupAssociationEnabled')]" }, @@ -653,7 +663,7 @@ "_generator": { "name": "bicep", "version": "0.30.23.60470", - "templateHash": "12288692280280036332" + "templateHash": "2549730186599602050" }, "name": "`/subResourcesWrapper/deploy.bicep` Parameters", "description": "This module is used by the [`bicep-lz-vending`](https://aka.ms/sub-vending/bicep) module to help orchestrate the deployment", @@ -960,11 +970,19 @@ "metadata": { "description": "The name of the storage account for the deployment script." } + }, + "managementGroupAssociationDelayCount": { + "type": "int", + "defaultValue": 15, + "metadata": { + "description": "Optional. The number of blank ARM deployments to create sequentially to introduce a delay to the Subscription being moved to the target Management Group being, if set, to allow for background platform RBAC inheritance to occur." + } } }, "variables": { - "$fxv#0": "Param(\n[string]$subscriptionId,\n[string]$resourceProviders\n)\n\n$ErrorActionPreference = 'SilentlyContinue'\n# Selecting the right subscription\nSelect-AzSubscription -SubscriptionId $subscriptionId\n\n# Defining variables\n$providers = $resourceProviders | ConvertFrom-Json -AsHashtable\n$failedProviders = ''\n$failedFeatures = ''\n$DeploymentScriptOutputs = @{}\n\n##############################################\n## Registering resource providers and features\n##############################################\n\nif ($providers.Count -gt 0) {\n foreach ($provider in $providers.keys) {\n try {\n # Registering resource providers\n $providerStatus = (Get-AzResourceProvider -ListAvailable | Where-Object ProviderNamespace -EQ $provider).registrationState\n # Check if the providered is registered\n if ($providerStatus -eq 'NotRegistered') {\n Write-Output \"`n Registering the '$provider' provider\"\n if (Register-AzResourceProvider -ProviderNamespace $provider) {\n Write-Output \"`n The registration for provider'$provider' has started successfully\"\n } else {\n Write-Output \"`n The '$provider' provider has not been registered successfully\"\n $failedProviders += \",$provider\"\n }\n } elseif ($providerStatus -eq 'Registering') {\n Write-Output \"`n The '$provider' provider is in registering state\"\n $failedProviders += \",$provider\"\n } elseif ( $null -eq $providerStatus) {\n Write-Output \"`n There was a problem registering the '$provider' provider. Please make sure this provider namespace is valid\"\n $failedProviders += \",$provider\"\n }\n\n if ($failedProviders.length -gt 0) {\n $output = $failedProviders.substring(1)\n } else {\n $output = 'No failures'\n }\n $DeploymentScriptOutputs['failedProvidersRegistrations'] = $output\n } catch {\n Write-Output \"`n There was a problem registering the '$provider' provider. Please make sure this provider namespace is valid\"\n $failedProviders += \",$provider\"\n if ($failedProviders.length -gt 0) {\n $output = $failedProviders.substring(1)\n }\n $DeploymentScriptOutputs['failedProvidersRegistrations'] = $output\n }\n # Registering resource providers features\n $features = $providers[$provider]\n if ($features.length -gt 0) {\n foreach ($feature in $features) {\n try {\n # Define variables\n $featureStatus = (Get-AzProviderFeature -ListAvailable | Where-Object FeatureName -EQ $feature).RegistrationState\n # Check if the feature is registered\n if ($featureStatus -eq 'NotRegistered' -or $featureStatus -eq 'Unregistered') {\n Write-Output \"`n Registering the '$feature' feature\"\n if (Register-AzProviderFeature -FeatureName $feature -ProviderNamespace $provider) {\n Write-Output \"`n The The registration for feature '$feature' has started successfully\"\n } else {\n Write-Output \"`n The '$feature' feature has not been registered successfully\"\n $failedFeatures += \",$feature\"\n }\n } elseif ($null -eq $featureStatus) {\n Write-Output \"`n The '$feature' feature doesn't exist.\"\n $failedFeatures += \",$feature\"\n }\n if ($failedFeatures.length -gt 0) {\n $output = $failedFeatures.substring(1)\n } else {\n $output = 'No failures'\n }\n $DeploymentScriptOutputs['failedFeaturesRegistrations'] = $output\n } catch {\n Write-Output \"`n There was a problem registering the '$feature' feature. Please make sure this feature name is valid\"\n $failedFeatures += \",$feature\"\n if ($failedFeatures.length -gt 0) {\n $output = $failedFeatures.substring(1)\n }\n $DeploymentScriptOutputs['failedFeaturesRegistrations'] = $output\n }\n }\n } else {\n $output = 'No failures'\n $DeploymentScriptOutputs['failedFeaturesRegistrations'] = $output\n }\n }\n} else {\n Write-Output \"`n No providers or features to register\"\n}\n", + "$fxv#0": "Param(\n [string]$subscriptionId,\n [string]$resourceProviders\n)\n\n$ErrorActionPreference = 'SilentlyContinue'\n# Selecting the right subscription\nSelect-AzSubscription -SubscriptionId $subscriptionId\n\n# Defining variables\n$providers = $resourceProviders | ConvertFrom-Json -AsHashtable\n$failedProviders = ''\n$failedFeatures = ''\n$DeploymentScriptOutputs = @{}\n\n##############################################\n## Registering resource providers and features\n##############################################\n\nif ($providers.Count -gt 0) {\n foreach ($provider in $providers.keys) {\n try {\n # Registering resource providers\n $providerStatus = (Get-AzResourceProvider -ListAvailable | Where-Object ProviderNamespace -EQ $provider).registrationState\n # Check if the providered is registered\n if ($providerStatus -eq 'NotRegistered') {\n Write-Output \"`n Registering the '$provider' provider\"\n if (Register-AzResourceProvider -ProviderNamespace $provider) {\n Write-Output \"`n The registration for provider'$provider' has started successfully\"\n } else {\n Write-Output \"`n The '$provider' provider has not been registered successfully\"\n $failedProviders += \",$provider\"\n }\n } elseif ($providerStatus -eq 'Registering') {\n Write-Output \"`n The '$provider' provider is in registering state\"\n $failedProviders += \",$provider\"\n } elseif ( $null -eq $providerStatus) {\n Write-Output \"`n There was a problem registering the '$provider' provider. Please make sure this provider namespace is valid\"\n $failedProviders += \",$provider\"\n }\n\n if ($failedProviders.length -gt 0) {\n $output = $failedProviders.substring(1)\n } else {\n $output = 'No failures'\n }\n $DeploymentScriptOutputs['failedProvidersRegistrations'] = $output\n } catch {\n Write-Output \"`n There was a problem registering the '$provider' provider. Please make sure this provider namespace is valid\"\n $failedProviders += \",$provider\"\n if ($failedProviders.length -gt 0) {\n $output = $failedProviders.substring(1)\n }\n $DeploymentScriptOutputs['failedProvidersRegistrations'] = $output\n }\n # Registering resource providers features\n $features = $providers[$provider]\n if ($features.length -gt 0) {\n foreach ($feature in $features) {\n try {\n # Define variables\n $featureStatus = (Get-AzProviderFeature -ListAvailable | Where-Object FeatureName -EQ $feature).RegistrationState\n # Check if the feature is registered\n if ($featureStatus -eq 'NotRegistered' -or $featureStatus -eq 'Unregistered') {\n Write-Output \"`n Registering the '$feature' feature\"\n if (Register-AzProviderFeature -FeatureName $feature -ProviderNamespace $provider) {\n Write-Output \"`n The The registration for feature '$feature' has started successfully\"\n } else {\n Write-Output \"`n The '$feature' feature has not been registered successfully\"\n $failedFeatures += \",$feature\"\n }\n } elseif ($null -eq $featureStatus) {\n Write-Output \"`n The '$feature' feature doesn't exist.\"\n $failedFeatures += \",$feature\"\n }\n if ($failedFeatures.length -gt 0) {\n $output = $failedFeatures.substring(1)\n } else {\n $output = 'No failures'\n }\n $DeploymentScriptOutputs['failedFeaturesRegistrations'] = $output\n } catch {\n Write-Output \"`n There was a problem registering the '$feature' feature. Please make sure this feature name is valid\"\n $failedFeatures += \",$feature\"\n if ($failedFeatures.length -gt 0) {\n $output = $failedFeatures.substring(1)\n }\n $DeploymentScriptOutputs['failedFeaturesRegistrations'] = $output\n }\n }\n } else {\n $output = 'No failures'\n $DeploymentScriptOutputs['failedFeaturesRegistrations'] = $output\n }\n }\n} else {\n Write-Output \"`n No providers or features to register\"\n}\n", "deploymentNames": { + "moveSubscriptionToManagementGroupDelay": "[take(format('lz-vend-move-sub-delay-{0}', uniqueString(parameters('subscriptionId'), parameters('subscriptionManagementGroupId'), deployment().name)), 64)]", "moveSubscriptionToManagementGroup": "[take(format('lz-vend-move-sub-{0}', uniqueString(parameters('subscriptionId'), parameters('subscriptionManagementGroupId'), deployment().name)), 64)]", "tagSubscription": "[take(format('lz-vend-tag-sub-{0}', uniqueString(parameters('subscriptionId'), deployment().name)), 64)]", "createResourceGroupForLzNetworking": "[take(format('lz-vend-rsg-create-{0}', uniqueString(parameters('subscriptionId'), parameters('virtualNetworkResourceGroupName'), parameters('virtualNetworkLocation'), deployment().name)), 64)]", @@ -1002,6 +1020,27 @@ "resourceProvidersFormatted": "[replace(string(parameters('resourceProviders')), '\"', '\\\"')]" }, "resources": [ + { + "copy": { + "name": "moveSubscriptionToManagementGroupDelay", + "count": "[length(range(0, parameters('managementGroupAssociationDelayCount')))]", + "mode": "serial", + "batchSize": 1 + }, + "condition": "[and(parameters('subscriptionManagementGroupAssociationEnabled'), not(empty(parameters('subscriptionManagementGroupId'))))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('{0}-{1}', variables('deploymentNames').moveSubscriptionToManagementGroupDelay, copyIndex())]", + "location": "[parameters('virtualNetworkLocation')]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [] + } + } + }, { "condition": "[and(parameters('subscriptionManagementGroupAssociationEnabled'), not(empty(parameters('subscriptionManagementGroupId'))))]", "type": "Microsoft.Resources/deployments", @@ -1055,7 +1094,10 @@ } ] } - } + }, + "dependsOn": [ + "moveSubscriptionToManagementGroupDelay" + ] }, { "condition": "[not(empty(parameters('subscriptionTags')))]", diff --git a/avm/ptn/lz/sub-vending/modules/subResourceWrapper.bicep b/avm/ptn/lz/sub-vending/modules/subResourceWrapper.bicep index ab9684a5a6..d0b80795eb 100644 --- a/avm/ptn/lz/sub-vending/modules/subResourceWrapper.bicep +++ b/avm/ptn/lz/sub-vending/modules/subResourceWrapper.bicep @@ -188,11 +188,18 @@ param deploymentScriptManagedIdentityName string @sys.description('The name of the storage account for the deployment script.') param deploymentScriptStorageAccountName string +@sys.description('Optional. The number of blank ARM deployments to create sequentially to introduce a delay to the Subscription being moved to the target Management Group being, if set, to allow for background platform RBAC inheritance to occur.') +param managementGroupAssociationDelayCount int = 15 + // VARIABLES // Deployment name variables // LIMITS: Tenant = 64, Management Group = 64, Subscription = 64, Resource Group = 64 var deploymentNames = { + moveSubscriptionToManagementGroupDelay: take( + 'lz-vend-move-sub-delay-${uniqueString(subscriptionId, subscriptionManagementGroupId, deployment().name)}', + 64 + ) moveSubscriptionToManagementGroup: take( 'lz-vend-move-sub-${uniqueString(subscriptionId, subscriptionManagementGroupId, deployment().name)}', 64 @@ -313,8 +320,28 @@ var resourceProvidersFormatted = replace(string(resourceProviders), '"', '\\"') // RESOURCES & MODULES +@batchSize(1) +#disable-next-line no-deployments-resources +resource moveSubscriptionToManagementGroupDelay 'Microsoft.Resources/deployments@2024-03-01' = [ + for (cycle, i) in range(0, managementGroupAssociationDelayCount): if (subscriptionManagementGroupAssociationEnabled && !empty(subscriptionManagementGroupId)) { + name: '${deploymentNames.moveSubscriptionToManagementGroupDelay}-${i}' + location: virtualNetworkLocation + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } + } +] + module moveSubscriptionToManagementGroup './managementGroupSubscription.bicep' = if (subscriptionManagementGroupAssociationEnabled && !empty(subscriptionManagementGroupId)) { scope: managementGroup(subscriptionManagementGroupId) + dependsOn: [ + moveSubscriptionToManagementGroupDelay + ] name: deploymentNames.moveSubscriptionToManagementGroup params: { subscriptionManagementGroupId: subscriptionManagementGroupId diff --git a/avm/ptn/lz/sub-vending/scripts/Register-SubscriptionResourceProviderList.ps1 b/avm/ptn/lz/sub-vending/scripts/Register-SubscriptionResourceProviderList.ps1 index 3bbc201cf5..57396617c6 100644 --- a/avm/ptn/lz/sub-vending/scripts/Register-SubscriptionResourceProviderList.ps1 +++ b/avm/ptn/lz/sub-vending/scripts/Register-SubscriptionResourceProviderList.ps1 @@ -1,6 +1,6 @@ Param( -[string]$subscriptionId, -[string]$resourceProviders + [string]$subscriptionId, + [string]$resourceProviders ) $ErrorActionPreference = 'SilentlyContinue' @@ -18,81 +18,81 @@ $DeploymentScriptOutputs = @{} ############################################## if ($providers.Count -gt 0) { - foreach ($provider in $providers.keys) { - try { - # Registering resource providers - $providerStatus = (Get-AzResourceProvider -ListAvailable | Where-Object ProviderNamespace -EQ $provider).registrationState - # Check if the providered is registered - if ($providerStatus -eq 'NotRegistered') { - Write-Output "`n Registering the '$provider' provider" - if (Register-AzResourceProvider -ProviderNamespace $provider) { - Write-Output "`n The registration for provider'$provider' has started successfully" - } else { - Write-Output "`n The '$provider' provider has not been registered successfully" - $failedProviders += ",$provider" - } - } elseif ($providerStatus -eq 'Registering') { - Write-Output "`n The '$provider' provider is in registering state" - $failedProviders += ",$provider" - } elseif ( $null -eq $providerStatus) { - Write-Output "`n There was a problem registering the '$provider' provider. Please make sure this provider namespace is valid" - $failedProviders += ",$provider" - } - - if ($failedProviders.length -gt 0) { - $output = $failedProviders.substring(1) - } else { - $output = 'No failures' - } - $DeploymentScriptOutputs['failedProvidersRegistrations'] = $output - } catch { - Write-Output "`n There was a problem registering the '$provider' provider. Please make sure this provider namespace is valid" - $failedProviders += ",$provider" - if ($failedProviders.length -gt 0) { - $output = $failedProviders.substring(1) - } - $DeploymentScriptOutputs['failedProvidersRegistrations'] = $output - } - # Registering resource providers features - $features = $providers[$provider] - if ($features.length -gt 0) { - foreach ($feature in $features) { + foreach ($provider in $providers.keys) { try { - # Define variables - $featureStatus = (Get-AzProviderFeature -ListAvailable | Where-Object FeatureName -EQ $feature).RegistrationState - # Check if the feature is registered - if ($featureStatus -eq 'NotRegistered' -or $featureStatus -eq 'Unregistered') { - Write-Output "`n Registering the '$feature' feature" - if (Register-AzProviderFeature -FeatureName $feature -ProviderNamespace $provider) { - Write-Output "`n The The registration for feature '$feature' has started successfully" + # Registering resource providers + $providerStatus = (Get-AzResourceProvider -ListAvailable | Where-Object ProviderNamespace -EQ $provider).registrationState + # Check if the providered is registered + if ($providerStatus -eq 'NotRegistered') { + Write-Output "`n Registering the '$provider' provider" + if (Register-AzResourceProvider -ProviderNamespace $provider) { + Write-Output "`n The registration for provider'$provider' has started successfully" + } else { + Write-Output "`n The '$provider' provider has not been registered successfully" + $failedProviders += ",$provider" + } + } elseif ($providerStatus -eq 'Registering') { + Write-Output "`n The '$provider' provider is in registering state" + $failedProviders += ",$provider" + } elseif ( $null -eq $providerStatus) { + Write-Output "`n There was a problem registering the '$provider' provider. Please make sure this provider namespace is valid" + $failedProviders += ",$provider" + } + + if ($failedProviders.length -gt 0) { + $output = $failedProviders.substring(1) } else { - Write-Output "`n The '$feature' feature has not been registered successfully" - $failedFeatures += ",$feature" + $output = 'No failures' } - } elseif ($null -eq $featureStatus) { - Write-Output "`n The '$feature' feature doesn't exist." - $failedFeatures += ",$feature" - } - if ($failedFeatures.length -gt 0) { - $output = $failedFeatures.substring(1) - } else { - $output = 'No failures' - } - $DeploymentScriptOutputs['failedFeaturesRegistrations'] = $output + $DeploymentScriptOutputs['failedProvidersRegistrations'] = $output } catch { - Write-Output "`n There was a problem registering the '$feature' feature. Please make sure this feature name is valid" - $failedFeatures += ",$feature" - if ($failedFeatures.length -gt 0) { - $output = $failedFeatures.substring(1) - } - $DeploymentScriptOutputs['failedFeaturesRegistrations'] = $output + Write-Output "`n There was a problem registering the '$provider' provider. Please make sure this provider namespace is valid" + $failedProviders += ",$provider" + if ($failedProviders.length -gt 0) { + $output = $failedProviders.substring(1) + } + $DeploymentScriptOutputs['failedProvidersRegistrations'] = $output + } + # Registering resource providers features + $features = $providers[$provider] + if ($features.length -gt 0) { + foreach ($feature in $features) { + try { + # Define variables + $featureStatus = (Get-AzProviderFeature -ListAvailable | Where-Object FeatureName -EQ $feature).RegistrationState + # Check if the feature is registered + if ($featureStatus -eq 'NotRegistered' -or $featureStatus -eq 'Unregistered') { + Write-Output "`n Registering the '$feature' feature" + if (Register-AzProviderFeature -FeatureName $feature -ProviderNamespace $provider) { + Write-Output "`n The The registration for feature '$feature' has started successfully" + } else { + Write-Output "`n The '$feature' feature has not been registered successfully" + $failedFeatures += ",$feature" + } + } elseif ($null -eq $featureStatus) { + Write-Output "`n The '$feature' feature doesn't exist." + $failedFeatures += ",$feature" + } + if ($failedFeatures.length -gt 0) { + $output = $failedFeatures.substring(1) + } else { + $output = 'No failures' + } + $DeploymentScriptOutputs['failedFeaturesRegistrations'] = $output + } catch { + Write-Output "`n There was a problem registering the '$feature' feature. Please make sure this feature name is valid" + $failedFeatures += ",$feature" + if ($failedFeatures.length -gt 0) { + $output = $failedFeatures.substring(1) + } + $DeploymentScriptOutputs['failedFeaturesRegistrations'] = $output + } + } + } else { + $output = 'No failures' + $DeploymentScriptOutputs['failedFeaturesRegistrations'] = $output } - } - } else { - $output = 'No failures' - $DeploymentScriptOutputs['failedFeaturesRegistrations'] = $output } - } } else { - Write-Output "`n No providers or features to register" + Write-Output "`n No providers or features to register" }