Step by Step ARM Templates - What is in an ARM Template - Understanding Components 3 - Variables

@20aman    Aug 26, 2016

Index of all blogs in this Step by Step ARM Templates series is located here: Step by Step Azure Resource Manager (ARM) Templates - Index

If you haven't checked the previous blog on the overall structure of the ARM template, I suggest you give it a quick read before checking the component described in this post in detail.

  1. Understanding all components
  2. Parameters
  3. Variables - This blog post
  4. Resources
  5. Outputs


Variables are values that you either know beforehand or you can construct from the input parameters. These variables can then be reused at multiple locations in the resources section. If you later want to change the value of a variable then it automatically gets updated at all other locations. They can be used to define a resource property.

Defining Variables

Variable is a one huge JSON object. Each property can be one of the simple data type (like integer, bool, string etc.) or can be another complex JSON object. The general structure is as shown below:

"variables": {
      "variable 1" : "value 1",
      "variable 2" : "value 2",
      "variable 3" : 1024,
      "variable 4" : {}

Note that in the above example, the first 3 variables are of simple value type. The 4rth variable is however of a complex JSON object type.

Let's now check a real variables section from an actual ARM template:

"variables": {
        "vmSize": "Standard_A2",
        "virtualNetworkName": "MyVNETName",
        "vnetId1": "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]",
        "vnetId2": "[resourceId(parameters('vNetRG'),'Microsoft.Network/virtualNetworks',parameters('virtualNetworkName'))]",
        "subnetRef": "[concat(variables('vnetId'), '/subnets/', variables('subnetName'))]",
        "vhdStorageName": "[concat('vhdstorage', uniqueString(resourceGroup().id))]",
        "storageAccountResourceGroup": "[resourcegroup().name]",
        "location": "[resourceGroup().location]",
        "subscriptionId": "[subscription().subscriptionId]"

There are lots of key constructs in the above code snippet. I have tried to capture as many different constructs in this snippets as I could. Let us decode each variable one by one.

  1. vmSize - Simple String
  2. virtualNetworkName - Simple string name
  3. vnetId1 - This uses a special function named "resourceId" to find out the resource ID of the virtual network. This function is invoked by using the syntax "[resourceId(Input)]" . This gets the resource ID of a resource which is defined by the Input to this. Also, note the use of another variable as an input to this.
  4. vnetId2 - This also fetches the resource Id of a virtual network using "resourceId" method. Note the use of the value of a parameter in this to find out Resource Group of the existing Virtual network (parameter "vNetRG").
  5. subnetRef - This variable uses another function "concat" in ARM template i.e. "[concat(input1,input2,...)]". This function can take many inputs and will concatinate (i.e. club together) the value of all the inputs provided. You can use parameters or another variable.
  6. vhdStorageName - This also uses concat function to dynamically generate a storage name. However it uses "resourcegroup" function as "[resourcegroup()]". This function always returns the resource group to which you are deploying the current ARM template. Then the variable uses the id property of the resource group returned.
  7. storageAccountResourceGroup - This uses the "name" property of the current resource group
  8. location - This uses the "location" property of the current resource group.
  9. subscriptionId - This uses the "subscription" function as "[subscription()]" to find out the current subscription to which the current ARM template is being deployed. Then it uses the subscription Id property of the subscription to get the required Id.

Note that these constructs are very powerfull and can be used to dynamically construct your ARM template. These constructs are also known as Helper Functions and are explained in detail here: Step by Step ARM Templates - Helper Functions

Using Variables

Using variables is very easy and is similar to using parameters. In fact, you already saw the usage of variables above, while defining other variables.

You use the square parenthesis to indicate to the ARM engine to evaluate whatever is inside the parenthesis. You use the "variable" keyword and then you pass the name of the variable as input. Check the example below.

"storageAccountName": "[variables('storageAccountName')]"

Best Practices

Best practices are similar to the Parameters.

  • Provide complete descriptive names, no matter how long.
  • Use Pascal Casing to name your parameters. i.e. First letter should be a small letter. Then every new word will have the first letter as a capital. No space between words. E.g. storageAccountName
  • Use the constructs explained in the previous section to dynamically generate variables. This reduces any human errors.
  • Anything that is used more than once and is not required to be entered by an end user, should be created as a variable. Later on, this helps by minimizing the number of places you need to change the value.

That's all there is to Variables in ARM Templates. If you have any doubts, please comment in the below section. Use the links at the Top to know all about other components in an ARM Template.

Comments powered by Disqus