Nested templates

Nested templates are similar in nature to linked templates. Just as linked templates allow the execution of a separate template from the master template, nested templates help to execute others. However, there are notable differences between the two types.

While linked templates are separate templates and thus stored separately, nested templates are instead defined within the same master template file. While linked templates should be available at a well-defined URI accessible to the master template, there is no such requirement for a nested template. In addition, linked templates should be protected from unauthorized access, while nested templates need not.

However, there are certain constraints to consider before working with nested templates. For example, nested templates do not have the ability to define their own parameters; nor do they return any values using the template's output feature. Nested templates can still access the parameters and variables available at a parent template level, however.

So, what does a nested template look like? We'll show you using an example.

In this example, we will be provisioning two service bus namespaces using a single ARM template. The first service bus namespace, or the primary namespace, will be provisioned just like any other resource and will also be declared at the top level in the resources section. The second service bus namespace, or secondary namespace, will be provisioned through a nested template. 

The code for this entire template is available in the chapter-3 - listing 6.txt file with the accompanying chapter code.

The following template takes four parameters—two parameters for each service bus namespace. The first parameter defines the namespace, while the second parameter determines the namespace SKU. There are parameters for both the primary and secondary service bus namespace, as shown in the following example:

"parameters": {
"primaryServiceBusNamespaceName": {
"type": "string",
"metadata": {
"description": "Service Bus namespace name"
}
},
"primaryServiceBusSku": {
"type": "string",
"metadata": {
"description": "Service bus SKU"
}
},
"secondaryServiceBusNamespaceName": {
"type": "string",
"metadata": {
"description": "Service Bus namespace name"
}
},
"secondaryServiceBusSku": {
"type": "string",
"metadata": {
"description": "Service bus SKU"
}
}
}

Within the resource section, we have two resources. The primary service bus namespace, Microsoft.ServiceBus/namespaces, is declared as top-level resource as shown in the following code. It uses the first two parameters from the parameters section. The location is decided based on the resource group region:

    {
"apiVersion": "2017-04-01",
"name": "[parameters('primaryServiceBusNamespaceName')]",
"type": "Microsoft.ServiceBus/namespaces",
"location": "[resourceGroup().location]",
"sku": {
"name": "[parameters('primaryServiceBusSku')]"
}
}

The second resource in this template is of Microsoft.Resources/deployments type. This resource type can invoke both linked as well as nested templates. It contains the definition of an entire template within its properties section, as shown in next code listing. Notice that both the parameters and outputs sections are missing in the nested template, although this restriction may be lifted in the future. The following code lists the two parameters relating to the secondary service bus namespace:

{
"apiVersion": "2018-01-01",
"name": "nestedTemplate",
"type": "Microsoft.Resources/deployments",
"dependsOn": [
"[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"apiVersion": "2017-04-01",
"name": "[parameters('secondaryServiceBusNamespaceName')]",
"type": "Microsoft.ServiceBus/namespaces",
"location": "[resourceGroup().location]",
"sku": {
"name": "[parameters('secondaryServiceBusSku')]"
}
}
]
}
}
}

Nested templates are especially useful when you do not want to maintain separate ARM template files, but still, want to define resources separately. Further advantages of nested templates are discussed in greater depth in Chapter 7,  Design Patterns.

Within an ARM template, it is not possible to have two resources with the same name and type; you cannot have two virtual networks with the same name in the same template. However, there are still cases where we might need to declare the same resource twice, and this is where nested templates are useful. Readers should refer to Chapter 7Design Patterns, for more detail.