Search code examples
jsonazureazure-rm-templatevnet

Azure ARM copy Index not working in Json


I am trying to deploy multiple Azure VNETs using the code below,it

it gives error below

{
  "error": {
    "code": "InvalidTemplate",
    "details": null,
    "message": "Deployment template validation failed: 'The template resource '[concat(variables('namePrefix'), parameters('VNetSettings').vnets.name, [copyIndex(1)])]' at line '1' and column '923' is not valid: The language expression property 'name' has an invalid array index.. Please see https://aka.ms/arm-template-expressions for usage details.'.",
    "target": null
  },
  "properties": null
}

This is my Code below. I want to use coyIndex to loop through multiple instances of azure virtual networks. Based on number of vnet names provided i want it get number of instances to be created.

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "VNetSettings": {
            "type": "object"
        },
        "namingSettings": {
            "type": "object"
        }
    },
    "variables": {
        "namePrefix": "[concat(parameters('namingSettings').name.org,'-',parameters('namingSettings').name.accountEnv,'-',parameters('namingSettings').name.sdlcEnv,'-',parameters('namingSettings').name.region,'-',parameters('namingSettings').name.appname,'-')]"
    },
    "resources": [
        {
            "apiVersion": "2018-04-01",
            "type": "Microsoft.Network/virtualNetworks",
            "name": "[concat(variables('namePrefix'), parameters('VNetSettings').vnets.name, [copyIndex(1)])]",
            "location": "[resourceGroup().location]",
            "copy": {
                "name": "vnetcopy",
                "count": "[length(parameters('VNetSettings').vnets.name)]"
            },
            "scale": null,
            "properties": {
                "addressSpace": {
                    "addressPrefixes": [
                        "[parameters('VNetSettings').vnets.cidr]"
                    ]
                }
            }
        }
    ]
}

Update

Parameter fileenter code here

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",

  "parameters":{
     "namingSettings": {
      "value": {
        "name": {
          "org": "it",
          "accountEnv": "nonprod",
          "sdlcEnv": "it-test",
          "region": "eastus2",
          "tier": "",
          "object": "",
          "networkbuild": "network",
          "auditbuild": "audit",
          "automationbuild": "automation",
          "dnsbuild": "dns",
          "appname": "network"
        }
      }
    },
     "VNetSettings": {
      "value": {
        "vnets": [
          {
            "name": "vnet0",
            "cidr": "10.10.10.0/24",
          }
        ],

        }
    }
}
}

Solution

  • Your concat() input is wrong. copyIndex() should not be inside []. Try this:

    "[concat(variables('namePrefix'), parameters('VNetSettings').vnets.name, copyIndex(1))]"
    

    copyIndex() is just another function, you only wrap the string with [] once no matter how many functions are inside

    you need to adjust your template to reflect the fact you are iterating over an array (right now you iterate over the name, and vnets.name is not a valid construct in the ARM Templates).

    you need to do something like this:

    {
        "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "parameters": {
            "VNetSettings": {
                "type": "object"
            },
            "namingSettings": {
                "type": "object"
            }
        },
        "variables": {
            "namePrefix": "[concat(parameters('namingSettings').name.org,'-',parameters('namingSettings').name.accountEnv,'-',parameters('namingSettings').name.sdlcEnv,'-',parameters('namingSettings').name.region,'-',parameters('namingSettings').name.appname,'-')]"
        },
        "resources": [
            {
                "apiVersion": "2018-04-01",
                "type": "Microsoft.Network/virtualNetworks",
                "name": "[concat(variables('namePrefix'), parameters('VNetSettings').vnets[copyIndex()].name)]",
                "location": "[resourceGroup().location]",
                "copy": {
                    "name": "vnetcopy",
                    "count": "[length(parameters('VNetSettings').vnets)]"
                },
                "scale": null,
                "properties": {
                    "addressSpace": {
                        "addressPrefixes": [
                            "[parameters('VNetSettings').vnets[copyIndex()].cidr]"
                        ]
                    }
                }
            }
        ]
    }
    

    notice you need to use copyIndex() to get to the current vnet in your array and you need to use the .vnet to determine length