Skip main navigation

Azure Resource Manager Template Structure

Hello and welcome back. We are in the second video for this third module on templates. Now we talked a little bit about Azure resource manager, and we briefly touched on the template capability that it offers. Now this is the video where we will start to go into the next level of detail on templates, trying to understand the basic formats used within templates, what it means, and how it works and then look at a demo where we will deploy our first resource group by applying our first template that we will create together in this demo, all right? So first off, what is an Azure Resource Manager template?
As I said before, the evolution from Classic, Azure Classic, Azure Service Manager, or Azure V1, was just an XML template whereas now, you have a JSON-based notification, which is very lightweight. So Azure Resource Manager leverages the JSON file notification– the object notification format to define the set of resources that need to be applied to provision your environment. And in the process of doing that, it takes the responsibility of managing the dependencies and guarantees that if you rerun the template again, then it’s not going to just reprovision another set of those resources but ensure that they remain in the state that was prescribed in the template as it was first created.
OK, so if we look at the Azure template core structure, it really has a few things. And you know, this is the default structure that you kind of have to put in into any template that you create. The bit that you see at the top where it says schema is the actual schema that dictates the format of the template. Now it has the API version in it as well, and the actual schema definition is available on open source. So if you go on GitHub, for example– and I’ll share the exact location of that on the next slide– you can see that the schemas are available there. The schema definitions are available there.
At the same time, their units has backing the schema as well. So if you just wanted to understand the implementation better, then you can do so by looking there. The schema enforces the definition, and tools that allow you to create JSON template leverage that capability to provide you Intellisense. So Visual Studio code, for example, I talked about a little bit earlier in the presentations has an extension for JSON ARM templates as well. So if you instal that extension, you would get full Intellisense support to create templates. And we look at a bit of that when we start creating our own template for this demo. The content version bit that you see here is really just for you.
It’s for you to help version your own templates. If you left this value 1.0.0 every time you change the version of this template, then the system’s not going to find any problems with that. But as a good practise, you would probably trade through the minor and the major versions as you start to introduce breaking changes or just incremental changes into the template. The section parameters is for you to specify any parameters that you expect to use as part of the resource provisioning process. Now just to give you a feel for parameters, things like specify the VM size– it’s an input that you’re probably taking from the user. What is the username of the VM that gets provisioned?
Again, that’s a parameter. That’s an input you take from the user. You can define that under the Parameter section. The next section is Variables. Now Variables is great because while with parameters, you can get certain information from the user, Variables is for you to use that information to create reusable literals that you can start referring within your script. Now just to give you an example, if I’m taking an input from the user on the size of the VM that they would like to provision, I could then use that to create a URI which I can output back to the user.
So I will create a variable which is a concatenation of a couple of parameters that I’ve taken from the user and then use that variable name to output the results back to the customer. And we’ll get into more detail on that when we start looking at the specifics of variables. The next thing you would notice here is Resources. Now clearly, Resources is not a curly braces. It’s a square braces. That means it’s an area, which is a good sign because you’re not always going to have just one resource that you will deploy in a resource group. You will probably have a collection of many– so things like network, storage, IP, public IP, network interface card.
All of these are resources, and all of them would probably be go into the Resources section. Now what you don’t have to do is figure out the order that they need to go in because Azure Resource Manager is intelligent enough to work out the dependencies and orchestrate the order by itself. And last but not least, the output gives you an opportunity to publish the output back after the execution of this resource template. So as I promised, this is the open source repository where the Azure Resource Manager’s template schemas are available. You know, go off, have a look at it. Look at the unit tests. It’s quite impressive. It’s got over 134.
So people are trying to create separate implementations by looking at the schema that Microsoft’s created here. OK, so diving deeper into each of these aspects, the first one is the ARM template parameters. Now let’s take the example, and the template that we’re going to build as part of this demo is a template that simply provisions a resource group and, within that resource group, simply provisions a storage. That’s it– simple enough, right? Of course, later on, we’ll look at more complex scenarios such as provisioning storage, provisioning other resources that you kind of need to get something substantial out there, but just trying to keep it simple for this demo so we can understand the concepts. So storage account type, right?
You have to define the type. And this is quite important. Now in this storage account type, the type is string. The type could be integer. The type could be Boolean. The type could be array and so on and so forth. It’s always good to specify default value because the template is expecting a value, and if the user fails to provide a value, then it would fail. So using this key word as you’re defining your parameters is always a good practise. Allowed values I kind of encourage because, say, for example, it gives the user an option to select from dropdown the values that they want to select.
If you don’t put in allowed values, well, they can put in any string, right? They could just say lalala. Well, that’s going to mean nothing in terms of storage account type. But if you narrow down the allowed values to standard LRS, GRS, ZRS, and premium LRS, well, then the user is kind of forced to select one of these. Again, it’s quite easy to create but as a best practise really makes the error handling easier. Now this tag metadata gets missed out. Rarely have I seen anyone using it. And that’s because it’s optional. But the reason to have it is you’re providing a description for this parameter.
If you come back to this script in a few months time and you look at a parameter that you have created, well, looking at the description explains what the purpose of that parameter was. Again, it’s a free text field that you can use to explain the parameters, but sometimes, if the parameters are too straightforward or simple or too less, then it doesn’t make sense including it. But I tend to include it on all the templates I create. And then you can have more than one parameter. In this section, we have these storage account type. We also have a name parameter– again, following the same convention, defining a type, defining a default value, and defining the metadata for it.
OK, so that’s parameters. Next thing, let’s look at the ARM template variables. So variables are great because you get out of box functions with them as well, functions that are common, functions like concatenation, functions like unique string, right? Every time you create a template which is going to provision one resource, it’s fine. But if you are creating an Azure Resource Manager template which is going to deploy 50 instances of web apps, you’re not going to code 50 separate names in your parameter file. Instead, what you will do is specify a prefix and say, Azure, figure out a unique string from this combination. And it will just postfix that with the name.
So when it creates the next instance, it’s got a new name. When it creates the next instance, it’s got a new name. I find this function quite useful, and I’m sure as you get going creating your own ARM templates, you’re going to find the benefits that this function provides. Again, functions like split– for example, what I’m doing here is I’m taking the parameter input, which was the storage account type from the previous slide, and I’m splitting it with the literal underscore and then taking the first part of the split. That’s because I want to include that as part of the storage account name parameter that I come up with.
So as I said, the storage account name variable that I’m defining, I’m concatenating the prefix, the storage account, and, in the end, appending a minus sa in it. And that kind of becomes my unique name for deploying the storage account. Next up, parameter files– now if you’re using one too many parameters in your ARM template, chances are, you’re probably going to create a parameter file. If you’re only pushing one parameter, you would probably pass it. But if you have a combination of 10, 15 parameters, you’re not going to key each one in at the time of provisioning. So parameter files are quite useful, and I find them useful, especially when you’re deploying to known environments.
You know, when you’re provisioning a UAT kind of environment, you have a feel for what the parameters need to be called, and you can pre-capture them in a parameter file. And then that just makes the deployment process easy. Again, if you’re using CICD tools like Jenkins, like Visual Studio Team Services, like Team City, then you have a way of overriding these values on the fly as well. Next up, let’s look at the ARM template resources. Now this is the area where you can define your resources. And I’m using the provider here, the namespace– microsoft.storag e/storageaccounts. And the variable that we created in the previous web is the variable that we will use to identify the name for the storage account.
We’re specifying the API version again using the resource provider stuff that I showed you in the last demo. You can figure out what API version you want to use. And the location, we’re simply going to piggy bank on the location where the resource group resides within which the storage account needs to be created. Again, you don’t have to put the resource group and the storage account in the same location, but it’s kind of preferred. It makes more logical sense. But again, it’s not a best practise to do it.
And then you can specify the SKU or the payment mode for that specific storage account– whether it’s free, whether it’s low subscription, medium subscription, so on, and so forth– and of course the kind of storage. OK, and last but not the least, the ARM template output– in this case, we’re just spitting out the name of the storage account that we’re provisioning.

By now you should have an understanding of Azure Resource Manager and the template capability it has to offer. In this step, we’ll delve into the details of Azure Resource Manager templates and understand what it means and how it works.

What is an Azure Resource Manager Template?

The Azure Resource Manager service provisions resources in an Azure account and enables you to work with the resources in your solution (virtual machines, storage accounts, and virtual networks, for example) as a group. You can deploy, update, or delete all the resources in your solution as a group. You use a template for deployment, and that template can work for different environments.

Azure Resource Manager Template Structure

An Azure Resource Manager template consists of JSON and expressions that you can use to construct values for your deployment. You must limit the size of your template to 1 megabyte (MB), and each parameter file to 64 kilobytes (KB). The 1 MB limit applies to the final state of the template after it has been expanded with iterative resource definitions and values for variables and parameters.


**"$schema": "",**

**"contentVersion": "",**

**"parameters": {**** ****},**

**"variables": {**** ****},**

**"resources": [**** ****],**

**"outputs": {**** ****}**


  • Schema: Location of the JSON schema file that describes the version of the template language.
  • ContentVersion: Version of the template (such as
  • Parameters: Optional values that are provided when deployment is executed to customise resource deployment.
  • Resources: A manageable item that is available through Azure. Some common resources are a virtual machine, storage account, web app, database, and virtual network, but there are many more.
  • Outputs: Values that are returned after deployment.
This article is from the free online

Microsoft Future Ready: DevOps Development, Implementation and Azure Automation

Created by
FutureLearn - Learning For Life

Our purpose is to transform access to education.

We offer a diverse selection of courses from leading universities and cultural institutions from around the world. These are delivered one step at a time, and are accessible on mobile, tablet and desktop, so you can fit learning around your life.

We believe learning should be an enjoyable, social experience, so our courses offer the opportunity to discuss what you’re learning with others as you go, helping you make fresh discoveries and form new ideas.
You can unlock new opportunities with unlimited access to hundreds of online short courses for a year by subscribing to our Unlimited package. Build your knowledge with top universities and organisations.

Learn more about how FutureLearn is transforming access to education