Search code examples
azureazure-rm-template

Exclude resource deployment within copyIndex


I'm trying to deploy a virtual network, subnets and NSGs from a parameter object

        "vnetSettings": {
        "value": {
            "name": "myVnet",
            "addressPrefixes": [
                {
                    "name": "addressSpace",
                    "addressPrefix": "172.25.196.0/22"
                }
            ],
            "subnets": [
                {
                    "name": "data-subnet",
                    "subnetPrefix": "172.25.196.0/27"
                },
                {
                    "name": "app-subnet",
                    "subnetPrefix": "172.25.196.32/27"
                },
                {
                    "name": "web-subnet",
                    "subnetPrefix": "172.25.196.64/27"
                },
                {
                    "name": "pridmz-subnet",
                    "subnetPrefix": "172.25.196.96/27"
                },
                {
                    "name": "pubdmz-subnet",
                    "subnetPrefix": "172.25.196.128/27"
                },
                {
                    "name": "AzureFirewallSubnet",
                    "subnetPrefix": "172.25.196.160/28"
                }
            ]

        }
    }

From this parameter object, I need to iterate through each item and create the virtual network, subnets, and NSG and assign each subnet an NSG - This is fine except I need to exclude creating an NSG for the Azure Firewall and exclude needing to assign the firewall subnet an NSG

So I'm trying to find a way to do this within the copyIndex

        {
        "apiVersion": "2017-06-01",
        "type": "Microsoft.Network/networkSecurityGroups",
        "copy": {
                "name": "iterator",
                "count": "[length(parameters('VNetSettings').subnets)]"
            },
        "name": "[if(equals(parameters('VNetSettings').subnets[copyIndex()].name, 'AzureFirewallSubnet'), json('null'), toUpper(concat(parameters('VNetSettings').name , '-', resourceGroup().location, '-',  parameters('VNetSettings').subnets[copyIndex()].name, '-nsg')))]",
        "location":"[resourceGroup().location]",
        "properties": {            
          "securityRules": []
        }
    },

This errors with

'The template resource '[if(equals(parameters('VNetSettings').subnets[copyIndex()].name, 'AzureFirewallSubnet'), json('null'), toUpper(concat(parameters('VNetSettings').name , '-', resourceGroup().location, '-',  parameters('VNetSettings').subnets[copyIndex()].name, '-nsg')))]' at line '1' and column '467' is not valid: Evaluation result of language expression '[if(equals(parameters('VNetSettings').subnets[copyIndex()].name, 'AzureFirewallSubnet'), json('null'), toUpper(concat(parameters('VNetSettings').name , '-', resourceGroup().location, '-',  parameters('VNetSettings').subnets[copyIndex()].name, '-nsg')))]' is type 'Null', expected type is 'String'

I can get around this error by passing in a string rather than JSON('null') which then creates all NSGs, but the problem I get is when iterating through the copyIndex for the subnets.

{
        "apiVersion": "2020-04-01",
        "name": "[toUpper(concat(parameters('VNetSettings').name, '-', resourceGroup().location, '-vnet'))]",
        "dependsOn": [
           "iterator"
        ],
        "type": "Microsoft.Network/virtualNetworks",
        "location":"[resourceGroup().location]",
        "properties": {
            "addressSpace": {
                "addressPrefixes": [
                    "[parameters('virtualNetworkaddressSpace')]"
                ]
            },
            "copy":[
                {
                    "name": "subnets",
                    "count":6,
                    "input": {
                        "name": "[if(equals(parameters('VNetSettings').subnets[copyIndex('subnets')].name, 'AzureFirewallSubnet'), variables('azureFirewallSubnetName'), concat(parameters('VNetSettings').name,'-', resourceGroup().location, '-', parameters('VNetSettings').subnets[copyIndex('subnets')].name))]",
                        "properties": {
                        "addressPrefix": "[parameters('VNetSettings').subnets[copyIndex('subnets')].subnetPrefix]",
                        "networkSecurityGroup": {
                           "id": "[if(equals(parameters('VNetSettings').subnets[copyIndex('subnets')].name, 'AzureFirewallSubnet'), json('null'), resourceId('Microsoft.Network/networkSecurityGroups/', concat(parameters('VNetSettings').name, '-', resourceGroup().location, '-', parameters('VNetSettings').subnets[copyIndex('subnets')].name, '-nsg')))]"
                       },

I hope this makes sense, and someone can help?

Thanks


Solution

  • Instead of trying to fit the odd case in with the others, I'd just separate it out:

    "vnetSettings": {
        "value": {
            "name": "myVnet",
            "addressPrefixes": [
                {
                    "name": "addressSpace",
                    "addressPrefix": "172.25.196.0/22"
                }
            ],
            "subnets": [
                {
                    "name": "data-subnet",
                    "subnetPrefix": "172.25.196.0/27"
                },
                {
                    "name": "app-subnet",
                    "subnetPrefix": "172.25.196.32/27"
                },
                {
                    "name": "web-subnet",
                    "subnetPrefix": "172.25.196.64/27"
                },
                {
                    "name": "pridmz-subnet",
                    "subnetPrefix": "172.25.196.96/27"
                },
                {
                    "name": "pubdmz-subnet",
                    "subnetPrefix": "172.25.196.128/27"
                }//,
                //{
                //    "name": "AzureFirewallSubnet",
                //    "subnetPrefix": "172.25.196.160/28"
                //}
            ],
            "firewallSubnetPrefix":"172.25.196.160/28"
        }
    }
    

    And then create the firewall subnet as a top-level resource:

    "resources: [
        {
            "apiVersion": "2020-04-01",
            "name": "[toUpper(concat(parameters('VNetSettings').name, '-', resourceGroup().location, '-vnet'))]",
            "type": "Microsoft.Network/virtualNetworks",
            //...
        },
        {
          "name": "AzureFirewallSubnet",
          "type": "Microsoft.Network/virtualNetworks/subnets",
          "apiVersion": "2020-04-01",
          "properties": {
            "addressPrefix": "[parameters('vnetSettings').firewallSubnetPrefix]",
          },
          "dependsOn": [
            "[toUpper(concat(parameters('VNetSettings').name, '-', resourceGroup().location, '-vnet'))]"
          ],
          //...
        }      
    ]