Template Functions
We’ve deployed our first resource - a Storage Account, but its definition has some drawbacks:
- The
location
is set to West US - The
name
is hard-coded too, which means we wouldn’t be able to deploy this to multiple resource groups (e.g., in a test, staging, and production environments)
Let’s solve these problems.
Functions
Values in ARM templates may be defined in terms of fixed literals, as we did before. However, they also support expressions. An expression is wrapped with square brackets []
. Expressions may contain function invocations. Here is a call to an imaginary function someFunction
:
...
"value": "[someFunction('parameter1', 'parameter2').property1]",
You can see that we can pass arguments and evaluate the properties of the result.
Inherit Location from the resource group
One commonly-used function is resourceGroup()
. It returns the properties of the current Resource Group that the template is deployed to.
Most probably, we want to deploy the Storage Account into the same Azure region where the Resource Group resides. This goal can be achieved with the resourceGroup()
function and the location
property of its result:
{
"type": "Microsoft.Storage/storageAccounts",
"name": "name-you-used-on-the-previous-step",
"apiVersion": "2018-02-01",
"location": "[resourceGroup().location]",
"kind": "StorageV2",
"sku": {
"name": "Standard_LRS"
}
}
Try deploying the modified template.
Unfortunately, you are going to get another error:
Azure Error: InvalidResourceLocation
Message: The resource 'mysauniquename' already exists in location 'westus' in resource
group 'arm-workshop'. A resource with the same name cannot be created in location
'westeurope'. Please select a new resource name.
The good news is that the location has clearly changed. Let’s do something with the account name.
Generating a unique name
We could keep changing the name of the Storage Account, but that seems sub-optimal. This account is actually not our primary target: we just need it to start working with Azure Functions. It would be perfectly fine to give it some unique machine-generated name just to be able to proceed. The uniquestring
function can do this for us.
Change the account definition to the following:
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[uniquestring(resourceGroup().id)]",
"apiVersion": "2018-02-01",
"location": "[resourceGroup().location]",
"kind": "StorageV2",
"sku": {
"name": "Standard_LRS"
}
}
The uniquestring
function performs a 64-bit hash of the provided strings to create a unique string. We provide the ID of the current Resource Group as the input argument, so the name is going to differ per Resource Group. Very useful for multiple deployments!
Rerun the deployment, and it should succeed this time.
Checkpoint
List the resources in your Resource Group.
$ az resource list -g arm-workshop -o table
Name ResourceGroup Location Type
-------------- ------------- ----------- ---------------------------------
mysauniquename arm-workshop westus Microsoft.Storage/storageAccounts
42tsnvw2a6dlc arm-workshop westeurope Microsoft.Storage/storageAccounts
You should see both a new account in the Resource Group’s region, as well as the old one in West US. We’ll remove the old account at the next step.
If you have any difficulties, compare your code with this sample.