In our introduction to Azure Resource Manager Templates, we wrote a template from scratch. Whenever we used a name for a resource, we had to use the full name. Imagine having to change this value. Sure, you could find and replace all instances, but we all know how this could go wrong.
For a basic introduction, also see our previous article on Azure Resource Manager Templates 101.
Variables
Of course, ARM has mechanisms to deal with this. Under the variables
property, you can define key-value pairs. Later, you reference the value by its key. That way, when you want to change the value, you only have to do it once.
"variables": {
"aspName": "demo-asp1",
"aspSku": "F1",
"aspCapacity": "1"
}
To reference the value, use the variables
function.
"resources": [
{
"name": "[variables('aspName')]",
"sku": {
"name": "[variables('aspSku')]",
"capacity": "[variables('aspCapacity')]"
}
}
]
You can also compose variables using other variables and functions.
"variables": {
"prefix": "demo-",
"aspName": "[concat(variables('prefix'),'asp1')]",
"location": "[resourceGroup().location]"
}
Deployment Parameters
Variables centralize the values you have to use throughout your template, but they still live in your deployment files. Imagine you want to deploy the same set of resources for production, staging, and development environments. Ideally, you’d work from one master deployment file.
You can achieve this by using ARM parameters. You can supply the values for these parameters from a file, via the command line, or the user interface.
The parameters
property accepts a set of parameter names and the expected type.
"parameters": {
"name": {
"type": "string"
},
"db": {
"type": "string",
"minLength": 3,
"maxLength": 50,
"metadata": {
"description": "Name of the database to create"
}
}
}
type
is the only required property for every parameter. To provide a description of the parameter, add the metadata
property as shown. This is available for any type.
Available types are:
string
(e.g., “alice”),int
(e.g., 42),bool
(e.g.,true
orfalse
),object
(e.g.,{ "firstName": "alice", "lastName": "doe" }
),array
(e.g.,[1,2,3]
or["a","b","c"]
).
"parameters": {
"instances": {
"type": "int",
"minValue": 1,
"maxValue": 10,
"metadata": {
"description": "Number of instances to create"
}
},
"names": {
"type": "array",
"minLength": 1,
"maxLength": 10,
"metadata": {
"description": "Names of instances"
}
},
"level": {
"type": "string",
"allowedValues": ["Small", "Medium", "Large"],
"defaultValue": "Small"
}
}
The minLength
and maxLength
properties are available for string
and array
. For the latter, these define how many values must be provided at least and at most.
"parameters": {
"level": {
"type": "string",
"allowedValues": ["Small", "Medium", "Large"],
"defaultValue": "Small"
}
}
To restrict the values a parameter may have, use the allowedValues
property. You can specify a default using the defaultValue
property. This works for string
and int
.
Using parameters is analogous to variables:
"count": "[parameters('level')]"
Deploying with Parameters
You can specify each parameter in the PowerShell command:
New-AzureRmResourceGroupDeployment -Name Demo -ResourceGroupName Demo -TemplateFile demo.json -prefix demoprefix
You can also create a parameters file. The contents are similar to a resource definition file but contain only the schema
, contentVersion
, and parameters
properties.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"prefix": {
"value": "demoprefix"
}
}
}
Then you run the PowerShell command using the TemplateParameterFile
parameter:
New-AzureRmResourceGroupDeployment -Name Demo -ResourceGroupName Demo -TemplateFile demo.json -TemplateParameterFile demo.params.json
To load the file from a remote URI instead, use the TemplateParameterUri
parameter.
See Microsoft Docs for more information on deploying Azure Resource Manager Templates.
Functions
You can use a number of functions when setting values in templates. Some commonly used ones are:
int("1")
: converts a string to an integer.add(1,2)
,mul(1,2)
,sub(2,1)
,div(4,2)
: arithmetic operations.concat("abc","def")
orconcat([a,b,c],[d,e,f])
: concatenates strings or arrays.replace("a.b.c", ".", "-")
: replaces parts of strings (result: “a-b-c”).split("a.b.c", ".")
: splits a string into an array (result:["a","b","c"]
).substring("azure",2,1)
: returns a specific substring (result: “u”).toLower
,toUpper
: converts strings to lowercase or uppercase.uniqueString("a","b","c","d")
: creates a hash of the input values.
Note: You cannot use functions (or any dynamic expressions) in parameter files.
See Microsoft Docs for more information on Azure Resource Manager Template functions.
Loops
If you want to create a resource multiple times, there are two options: copy-paste the resource definition, or use a parameter to decide how many resources to create.
For this, you can use the special copy
property on the resource definition:
"resources": [
{
"name": "[concat(variables('aspName'), copyIndex())]",
"sku": {
"name": "[variables('aspSku')]",
"capacity": "[variables('aspCapacity')]"
},
"copy": {
"name": "aspcopy",
"count": "[parameters('aspCount')]"
}
}
]
Note the copyIndex
function used as a suffix in the name. This adds a unique number to the resource name, ensuring names remain unique. If you prefer to start with 1, use copyIndex(1)
.
You cannot use copy
on child resources, only on top-level resources.
Another helpful use case is using copy together with an array of names. Assume for example you want to create 3 identical resources but with different names.
"parameters": {
"country": {
"type": "array",
"defaultValue": [
"Vienna",
"Berlin",
"Barcelona"
]
}
},
"resources": [
{
"name": "[concat(variables('aspName'), '-', parameters('country')[copyIndex()])]",
"copy": {
"name": "countrywebsite",
"count": "[length(parameters('country'))]"
}
}
]
You pass an array of countries in as a parameter. The copy count then uses the length function to determine how many items were passed. Then the suffix for the name is read from that same array using copyIndex
.
See Microsoft Docs for more information on loops in Azure Resource Manager Templates.