About ARM templates
Tags: azure, devops, automation
Published: 2024-01-22 14:05:33

An **ARM template** is a JSON file that defines your resources. Any resource can be create using an ARM template.
An **ARM template** is submitted to Azure Resource Manager for deployment via Azure Portal, Azure CLI, Azure Powershell, REST API and Azure Cloud Shell.
Azure Resource Manager converts the template into REST API operations.
You can export a template from Azure portal or you can write one manually. There is also a community template library you can use.

#ARM Template Format
The template follows a specific structure and includes several key sections. However, it is important to know that a template doesn't have to have all the sections, some are optional. Here's an overview of the basic structure of an ARM template:

```
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "",
"apiProfile": "",
"parameters": { },
"variables": { },
"functions": { },
"resources": [ ],
"outputs": { }
}
```
#####Schema
The "$schema" property at the root level of the template specifies the location of the JSON schema file that defines the structure of ARM templates. It specifies the version of the Azure Resource Manager schema that the template uses. This is usually set to a specific URI.

```
{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    ...
}
```
The schema URL includes a version identifier (e.g., "2019-04-01" in the example URL).
This versioning helps ensure that the template is interpreted correctly based on the specified ARM schema version. As Azure introduces new features or changes, the schema version is updated accordingly. 
The "**schema**" property allows tools, such as Azure PowerShell or Azure CLI, to validate the template against the expected structure and rules defined by the schema. This helps catch errors and ensure that templates conform to the ARM specifications.
The "**schema**" property should be placed at the beginning of the template, and its value should be a string specifying the URL of the schema. Any deviation from the correct syntax may result in validation errors.  
#####Content Version
Indicates the version of the template. It's useful for tracking changes to the template over time. 

```
{
    "contentVersion": "1.0.0.0",
    ...
}
```
#####Resources
This is the main section where you define the Azure resources you want to deploy. Each resource is represented as an object within the "resources" array.

```
{
    "resources": [
        {
            "type": "Microsoft.Compute/virtualMachines",
            "apiVersion": "2019-03-01",
            "name": "exampleVM",
            ...
        },
        {
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2019-06-01",
            "name": "exampleStorage",
            ...
        },
        ...
    ],
    ...
}
```
In an **Azure Resource Manager (ARM)** template, the **apiVersion **in the "resources" section specifies the version of the Azure Resource Manager API that should be used for the deployment of the particular resource. It helps ensure compatibility between the template and the Azure services.

The **apiVersion **is composed of the year and month of the API version in the format "YYYY-MM." It is associated with a specific release of the **Azure Resource Manager** provider for a given resource type. For example:
In this example, the first resource (a virtual machine) uses the API version "2019-03-01," and the second resource (a storage account) uses the API version "2019-06-01."

It's essential to specify the correct **apiVersion **for each resource type to ensure that the template is compatible with the version of the Azure Resource Manager API available at the time of deployment. You can usually find the supported API versions in the [Azure documentation](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-providers-and-types#azure-portal) for each specific resource type.
#####Parameters
Parameters make the template more flexible and reusable. They are defined in the parameters section of the ARM template. Parameters define values that are provided when the template is deployed. They can also allow linking multiple ARM templates, passing parameters between them for complex solutions.  
Each parameter has a name, type, and optional properties like default values and descriptions. Parameters **have specific data types** such as string, int, bool, array, object, secureObject, and secureString. Specifying the **correct data type** is essential for validation and proper parameter usage. 
You can provide **default values** for parameters to make them optional during deployment. **Default values** are specified using the **defaultValue** property. 
You can **restrict parameter** values to a specific set using the **allowedValues** property, this helps enforce constraints on acceptable input. 
Parameters can include **metadata** such as descriptions, which help document the purpose of the parameter. Descriptive information makes templates more understandable and maintainable. Finally, understanding how to **debug parameter-related issues** is crucial. Azure provides detailed error messages during deployment, helping identify problems with parameter values.
```
{
    "parameters": {
        "location": {
            "type": "string",
            "defaultValue": "East US",
            ...
        },
        "vmSize": {
            "type": "string",
            "defaultValue": "Standard_DS1_v2",
            ...
        },
        ...
    },
    ...
}
```
#####Variables
Allows you to declare variables that can be used within the template. Variables can simplify the template and make it more readable.

```
{
    "variables": {
        "adminUsername": "adminUser",
        "networkSecurityGroupName": "[concat('nsg-', uniqueString(resourceGroup().id))]",
        ...
    },
    ...
}
```
#####Outputs
Defines values that are returned after the template deployment is complete. These values can be useful for obtaining information about the deployed resources.

```
{
    "outputs": {
        "vmName": {
            "type": "string",
            "value": "[concat('VM-', uniqueString(resourceGroup().id))]"
        },
        ...
    },
    ...
}
```