ARM template functions in deployment scopes
With Azure Resource Manager templates (ARM templates), you can deploy to resource groups, subscriptions, management groups, or tenants. Generally, ARM template functions work the same for all scopes. This article describes the differences that exist for some functions depending on the scope.
Supported functions
When deploying to different scopes, there are some important considerations:
The resourceGroup() function is supported for resource group deployments.
The subscription() function is supported for resource group and subscription deployments.
The reference() and list() functions are supported for all scopes.
Use resourceId() to get the ID for a resource deployed at the resources group.
"subnet": { "id": "[resourceId(parameters('virtualNetworkResourceGroup'), 'Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkName'), parameters('subnet1Name'))]" }
Use the subscriptionResourceId() function to get the ID for a resource deployed at the subscription.
For example, to get the resource ID for a policy definition that is deployed to a subscription, use:
"roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]"
Use the extensionResourceId() function for resources that are implemented as extensions of the management group. Custom policy definitions that are deployed to the management group are extensions of the management group.
To get the resource ID for a custom policy definition at the management group level, use:
"policyDefinitionId": "[extensionResourceId(variables('mgScope'), 'Microsoft.Authorization/policyDefinitions', parameters('policyDefinitionID'))]"
Use the tenantResourceId() function to get the ID for a resource deployed at the tenant. Built-in policy definitions are tenant level resources. When assigning a built-in policy at the management group level, use the tenantResourceId function.
To get the resource ID for a built-in policy definition, use:
"policyDefinitionId": "[tenantResourceId('Microsoft.Authorization/policyDefinitions', parameters('policyDefinitionID'))]"
Function resolution in scopes
When you deploy to more than one scope, the resourceGroup() and subscription() functions resolve differently based on how you specify the template. When you link to an external template, the functions always resolve to the scope for that template. When you nest a template within a parent template, use the expressionEvaluationOptions
property to specify whether the functions resolve to the resource group and subscription for the parent template or the nested template. Set the property to inner
to resolve to the scope for the nested template. Set the property to outer
to resolve to the scope of the parent template.
The following table shows whether the functions resolve to the parent or embedded resource group and subscription.
Template type | Scope | Resolution |
---|---|---|
nested | outer (default) | Parent resource group |
nested | inner | Sub resource group |
linked | N/A | Sub resource group |
The following example template shows:
- nested template with default (outer) scope
- nested template with inner scope
- linked template
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "defaultScopeTemplate",
"resourceGroup": "inlineGroup",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
],
"outputs": {
"resourceGroupOutput": {
"type": "string",
"value": "[resourceGroup().name]"
}
}
},
"parameters": {}
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "innerScopeTemplate",
"resourceGroup": "inlineGroup",
"properties": {
"expressionEvaluationOptions": {
"scope": "inner"
},
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
],
"outputs": {
"resourceGroupOutput": {
"type": "string",
"value": "[resourceGroup().name]"
}
}
},
"parameters": {}
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "linkedTemplate",
"resourceGroup": "linkedGroup",
"properties": {
"mode": "Incremental",
"templateLink": {
"contentVersion": "1.0.0.0",
"uri": "https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/azure-resource-manager/resourcegroupname.json"
},
"parameters": {}
}
}
],
"outputs": {
"parentRG": {
"type": "string",
"value": "[concat('Parent resource group is ', resourceGroup().name)]"
},
"defaultScopeRG": {
"type": "string",
"value": "[concat('Default scope resource group is ', reference('defaultScopeTemplate').outputs.resourceGroupOutput.value)]"
},
"innerScopeRG": {
"type": "string",
"value": "[concat('Inner scope resource group is ', reference('innerScopeTemplate').outputs.resourceGroupOutput.value)]"
},
"linkedRG": {
"type": "string",
"value": "[concat('Linked resource group is ', reference('linkedTemplate').outputs.resourceGroupOutput.value)]"
}
}
}
To test the preceding template and see the results, use PowerShell or Azure CLI.
New-AzResourceGroup -Name parentGroup -Location chinaeast
New-AzResourceGroup -Name inlineGroup -Location chinaeast
New-AzResourceGroup -Name linkedGroup -Location chinaeast
New-AzResourceGroupDeployment `
-ResourceGroupName parentGroup `
-TemplateUri https://raw.githubusercontent.com/Azure/azure-docs-json-samples/master/azure-resource-manager/crossresourcegroupproperties.json
The output from the preceding example is:
Name Type Value
=============== ========================= ==========
parentRG String Parent resource group is parentGroup
defaultScopeRG String Default scope resource group is parentGroup
innerScopeRG String Inner scope resource group is inlineGroup
linkedRG String Linked resource group is linkedgroup
Next steps
- To understand how to define parameters in your template, see Understand the structure and syntax of ARM templates.
- For tips on resolving common deployment errors, see Troubleshoot common Azure deployment errors with Azure Resource Manager.
- For information about deploying a template that requires a SAS token, see Deploy private ARM template with SAS token.