Search code examples
azureazure-devopsazure-resource-managerazure-rm-template

ARM Templates - Multiple Linked Templates in a master template not allowed


We are trying to create an ARM template using linked templates. So i started with vnet and subnet and created 2 different linked templates. Now i tried to create a master.json and master.parameters.json . The parameters file has the values for name and address space of network and one subnet. Now, in the master template i tried to use 2 linked templates and the release in azure devops is failing with the following error: Deployment template validation failed: 'The resource 'Microsoft.Resources/deployments/LinkedTemplate' at line '37' and column '5' is defined multiple times in a template. Task failed while creating or updating the template deployment.

networkSubnetTest.json

"{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
    "vnetName": {
        "type": "string",
        "metadata": {
            "description": "Name of the Virtual Network"
        }
    },
    "vnetAddressPrefix": {
        "type": "string",
        "metadata": {
            "description": "The IP Address pool for the virtual network in CIDR format."
            }
    },
    "subnetPrefix": {
        "type": "string",
        "metadata": {
            "description": "The IP Address pool for the Subnet in CIDR format."
        }
    },
      "subnetName": {
        "type": "string",
        "metadata": {
            "description": "Name of the Subnet"
        }
    }
},

"variables": {
"templateBaseUrl": "https://github.com/something/",
"virtualNetworkTemplateUrl": "[concat(variables('templateBaseUrl'), 'VirtualNetwork.json')]",
"subnetTemplateUrl": "[concat(variables('templateBaseUrl'), 'Subnet.json')]",
"parametersUrl": "[concat(variables('templateBaseUrl'), 'networksubnetnsgtest.parameters.json')]"
},

"resources": [
{
   "apiVersion": "2017-05-10",
   "name": "LinkedTemplate",
   "type": "Microsoft.Resources/deployments",
   "properties": {
     "mode": "Incremental",
     "templateLink": {
        "uri":"[parameters('virtualNetworkTemplateUrl')]"
     },
     "parameters": {
      "uri":"[parameters('parametersUrl')]"
      }
   }
},
{
  "apiVersion": "2017-05-10",
  "name": "LinkedTemplate",
  "type": "Microsoft.Resources/deployments",
  "properties": {
    "mode": "Incremental",
    "templateLink": {
       "uri":"[parameters('subnetTemplateUrl')]"
    },
    "parameters": {
      "uri":"[parameters('parametersUrl')]"
     },
     "dependsOn": [
      "LinkedTemplate",
      "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetName'))]"
     ]
    }
},
],

"outputs": {
    "returnedVnetName": {
        "type": "string",
        "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetName'))]"
    },
    "returnedVnetAddressPrefix": {
        "type": "string",
        "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetAddressPrefix'))]"
    }
  }
}

The question here is is it not possible to have one master template and have multiple linked templates? I am aware of having one giant template with everything written in it but we dont want it.


Solution

  • Here is my version of the ARM template that works. The template name values definitely need to be different during simultaneous deployment. As shown in the deployments record, there are three deployments created by the one master template.

    I made three noted changes plus others to handle the URIs. See diff output at bottom.

    enter image description here

    {
      "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "vnetName": {
          "type": "string",
          "metadata": {
            "description": "Name of the Virtual Network"
          }
        },
        "vnetAddressPrefix": {
          "type": "string",
          "metadata": {
            "description": "The IP Address pool for the virtual network in CIDR format."
          }
        },
        "subnetPrefix": {
          "type": "string",
          "metadata": {
            "description": "The IP Address pool for the Subnet in CIDR format."
          }
        },
        "subnetName": {
          "type": "string",
          "metadata": {
            "description": "Name of the Subnet"
          }
        }
      },
      "variables": {
        "templateBaseUrl": "[deployment().properties.templateLink.uri]",
        "virtualNetworkTemplateUrl": "[uri(variables('templateBaseUrl'), 'VirtualNetwork.json')]",
        "subnetTemplateUrl": "[uri(variables('templateBaseUrl'), 'Subnet.json')]",
        "parametersUrl": "[uri(variables('templateBaseUrl'), 'networksubnetnsgtest.parameters.json')]"
      },
      "resources": [
        {
          "apiVersion": "2017-05-10",
          "name": "VnetDeployment",
          "type": "Microsoft.Resources/deployments",
          "properties": {
            "mode": "Incremental",
            "templateLink": {
              "uri": "[variables('virtualNetworkTemplateUrl')]"
            },
            "parameters": {
              "uri": {
                "value": "[variables('parametersUrl')]"
              }
            }
          }
        },
        {
          "apiVersion": "2017-05-10",
          "name": "SubnetDeployment",
          "type": "Microsoft.Resources/deployments",
          "properties": {
            "mode": "Incremental",
            "templateLink": {
              "uri": "[variables('subnetTemplateUrl')]"
            },
            "parameters": {
              "uri": {
                "value": "[variables('parametersUrl')]"
              }
            }
          },
          "dependsOn": [
            "VnetDeployment"
          ]
        }
      ],
      "outputs": {
        "returnedVnetName": {
          "type": "string",
          "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetName'))]"
        },
        "returnedVnetAddressPrefix": {
          "type": "string",
          "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetAddressPrefix'))]"
        }
      }
    }
    

    Diff Output enter image description here

    Parts of the PowerShell used to execute:

    $templateUri = 'https://<storageAccountName>.blob.core.windows.net/<containerName>/Lab/Master-Fixed.json'
    $parameters = @{ 'vnetName' = 'myvnet'; 'vnetAddressPrefix' = '10.0.0.0/16'; 'subnetPrefix' = '10.0.0.0/24'; 'subnetName' = 'mysubnet'; }
    New-AzureRmResourceGroupDeployment -Name "brstring-20190124" -ResourceGroupName $resourceGroupName -TemplateUri $templateUri @parameters