Azure Resource Manager Template 101

Introduction to ARM template

NaS IT
8 min readJul 2, 2017

Context

Currently two deployment models are co-existing in Microsoft Azure: Classic and Resource Manager. Resource Manager has been introduced in 2015 and should be the preferred way to deploy new resources to Azure.

Microsoft brought in this new model to overcome the weakness of their initial platform. DevOps practice popularity grew in the last few years, so more and more companies are expecting this to be facilitated by their Cloud provider.

Azure Resource Manager template is one of the solutions brought in to help with things like continuous deployment and scaling. With ARM templates, you can deploy resources in a predictable and repeatable way. We are living in a time where everything is software defined and developers are kings. ARM templates fits in the Infrastructure as Code concept, and we can deploy and configure resources following the declarative paradigm.

Also Microsoft started to embrace more Open Source and industry standards (or trends) in their quest to become an universal Cloud provider (chasing on AWS). Following this new mindset, they switched from XML used in Classic (or Service Management) model to JSON for the Azure Resource Management template.

What is JSON?

All developers should be familiar with this format, but it might be less known by the infrastructure crowd. JSON stands for JavaScript Object Notation.

I think it’s important to understand this format before looking at the ARM template itself. JSON is comparable to XML, but nowadays JSON is generally preferred over XML. This format is mainly used to exchange data in APIs and Web apps / services.

Below an example of a simple JSON file. When you are writing in JSON, you are describing an object which is made of name-value pairs.

The object is defined between the braces {}. In this example there is only one pair, with the name “server” and value “DC001”. The name is always a string and the value can be of the following type: string, number, object, array, boolean or null.

Pairs in an object are separated by a comma.

An array will be represented between brackets [] and with elements separated by comma.

Objects can be nested in objects and arrays can contain objects like below.

I think that covers the basic of JSON format and knowing that will help reading and authoring ARM templates.

Before going further, two tools that can help greatly:

Once you are familiar with JSON, I bet you will want to use it in your PowerShell scripts. You can use the cmdlets below to import and export JSON.

The basic ARM template

When you will deploy an ARM template, the JSON file will be consumed by the Azure Resource Manager API. The API needs to understand the file your sending, so it’s necessary to respect both the JSON formatting and the API schema. The schema will impose you the structure and expected inputs in your ARM templates.

Now let’s have a look at the bare Azure Resource Manager template structure.

As you can see the template is an object composed of 6 pairs:

  • $schema: URI to the schema definition | string |required
  • contentVersion: version of your template file | string | required
  • parameters: define specific inputs at deployment | object | not required
  • variables: define reusable values | object | not required
  • resources: define the resources to be deployed | array | required
  • outputs: define specific results of deployment | object | not required

On 6 pairs only 3 are mandatory, but beside really simple deployment, you will probably want to use at least parameters and variables.

ARM template syntax

Now you know the basic template format, but you are probably wondering what should or could come in the different sections. The example below contains all the syntax you can use in a template.

$Schema and contentVersion probably don’t need much explanations, but let’s see a bit more in detail the other sections.

Parameters:

Line 4 to 15. Each parameter is an object for which you can define the characteristics. The elements name and type are always required. The other elements are here to put limitations on the parameter value, which should be entered at deployment. You can cascade multiple parameters (but keep it simple), just remember to separate them with a comma.

Variables:

Line 18 to 22. The variables can be a simple pair with a name and a static value, or more complex object and even dynamically generated (more on this after). So you can define the variables a bit like you want / need, it just needs to respect JSON format. Like Parameters, Variables are meant to be used in the Resources.

Resources:

Line 24 to 59. Resources can have quite a lot of elements, apiVersion, type and name are always required. The requirement for more elements depends on the type and apiVersion. In the type you can see resource-provider-namespace, because in fact different resources will depend on different Resource Provider. Resource Manager is the main API, but resources are created by the Resource Provider APIs.

Some Resource Providers will require more details on the resource to deploy, like sku and properties.

One more interesting element to highlight is copy, which indicates that the resources should be replicated multiple times. And please note the dependsOn element, indicating that this resource needs one or more other resources to be deployed prior to it.

Outputs:

Line 60 to 65. In this section, outputName, type and value are all required. This allows you to retrieve results of the deployment, however this can’t really be used without knowing Functions (coming below).

At this point, we can already see that an ARM template can get quite complex if we need to deploy few resources with multiple parameters and variables… but there is more to it.

Functions

The values in the template can be generated using functions that are evaluated at deployment. With Functions you can create values that you want to be specific or unique. You can retrieve and manipulate values from the deployment context, variables and parameters. More than 50 Functions are available, but we will just see few from the example below.

From this example, the first thing to notice, is that the Functions are between brackets [] and inside the quotes “” as value of a pair. The Functions are in the format: functionName() and can take parameters inside the parenthesis (if you know JavaScript, it should be familiar to you). Furthermore, the result of a function can be of different type like an object, an array, a string… so it’s also important to know what kind of result you will get from a function.

In this example, 4 different functions are used.

concat(a, b ,c): simply concatenate strings

copyIndex(): returns the index of the copy loop

uniqueString(): returns a unique string and take the resource group ID as parameter

resourceGroup(): returns information of the current resource group

When an object is returned from a function, the dot operator should be used, like shown in this example resourceGroup().location and resourceGroup().id. To retrieve value from an array, the operator [index] should be used.

I will not go much more in the details of Functions. However we are missing 2 essential functions, as you might wonder how to retrieve your parameters and variables values.

variables(‘variable-name’): returns the value of the desired variable

parameters(‘parameter-name’): returns the value of the desired parameter

See below for an example.

If you made it here, you should be now almost fluent in ARM template. At least you should be able to read and understand a template, but writing one…

Authoring ARM template

As we saw before, depending on the Resource Provider, the elements needed to deploy a resource can be different and composed of quite a lot of properties. That makes writing ARM template on your own nearly impossible. Hopefully, a GitHub repository has been created to collect many different example of templates.

So when you want to write an AMR template, you can go have a look there first and find something similar to what you are trying to achieve. Then you can just copy / paste and build on this.

You will also need the right tool to write your ARM templates.

You can either use Visual Studio Code with Azure Resource Manager Tools, or Visual Studio IDE which contains the Azure SDK. Both will give you IntelliSense which is a great help especially to write your resources. Based on the schema and the Resource Provider, IntelliSense will give you the existing and required elements for the resource.

Deploying ARM template

Different options are available to deploy an Azure Resource Manager template. If you are writing your template in Visual Studio IDE, you can simply deploy from there.

You can also do it from the Azure portal, click + and search for template deployment. Then click create and build your own template in the editor.

Azure Resource Manager template editor in the portal

From here you can load your template and even edit it. The online editor has some nice features too, but at this moment there was a bug with the schema URI.

Custom template deployment from the portal

To deploy, just select the resource group and the location. This template doesn’t have any parameters to fill in, but if your template has some, you will be request to enter the values before deploying.

Note the button to launch the deployment is named Purchase, makes you think twice ;)

Deploying with PowerShell is also quite simple (depending on your parameters), see the code below.

And here is the example of deployment with Azure CLI 2.0.

--

--