David C
David C

Reputation: 521

Can you do Nested Copy loops in ARM Templates?

I'm trying to dynamically generate path mappings to route incoming traffic to the correct backend pool of an App Gateway.

For example we have 20 tenants, and we allow 5 tenants per backend pool, meaning we will generate 4 backend pools.

I need to create the path mappings dynamically such that Backend Pool One serves tenants1-5, Backend Pool Two serves tenants6-10, etc.

The desired array that I'd like to generate is:

[
    [ "tenant1", "tenant2", "tenant3", "tenant4", "tenant5"],
    ["tenant6", "tenant7", "tenant8", "tenant9", "tenant10"],
    ["tenant11", "tenant12", "tenant13", "tenant14", "tenant15"],
    ["tenant16", "tenant17", "tenant18", "tenant19", "tenant20"]
]

With this array formed, I can then create the backend pools and join the sub array strings to form the path mappings I need.

Here is a quick prototype of one of the attempts made...

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
  },
  "variables": {
    "totalTenants": 20,
    "tenantsPerBackendPool": 5,
    "copy": [
      {
        "name": "outerCopy",
        "count": "[div(variables('totalTenants'), variables('tenantsPerBackendPool'))]",
        "input": {
          "copy": {
            "count": "[variables('totalTenants')]",
            "name": "innerCopy",
            "input": "[if(equals(div(copyIndex('innerCopy'), 5), copyIndex('outerCopy')), concat('/tenant', copyIndex('innerCopy'), '/*'), json('null'))]"
          }
        }
      }
    ]
  },
  "resources": [
    // Multiple backend pools will be created here, and use the path mappings to route correctly
  ],
  "outputs": {
    "pathMappings": {
      "type": "array",
      "value": "[variables('outerCopy')]"
    }
  }
}

However I'm getting the following exception: New-AzResourceGroupDeployment: 16:01:18 - Error: Code=InvalidTemplate; Message=Deployment template language expression evaluation failed: 'The template language function 'copyIndex' has an invalid argument. The provided copy name 'innerCopy' doesn't exist in the resource.

Upvotes: 3

Views: 3195

Answers (1)

bmoore-msft
bmoore-msft

Reputation: 8717

I'm pretty sure you can't do the nesting approach in the OP, but I think you can produce the array of arrays that you want:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {},
    "variables": {
        "totalTenants": 20,
        "tenantsPerBackendPool": 5,
        "copy": [
            {
                "name": "firstPass",
                "count": "[variables('totalTenants')]",
                "input": "[concat('/tenant', copyIndex('firstPass', 1), '/*')]"
            },
            {
                "name": "finalpass",
                "count": "[div(variables('totalTenants'), variables('tenantsPerBackendPool'))]",
                "input": "[take(skip(variables('firstPass'), mul(variables('tenantsPerBackendPool'), copyIndex('finalPass'))), variables('tenantsPerBackendPool'))]"
            }
        ]
    },
    "resources": [ ],
    "outputs": {
        "firstPass": {
            "type": "array",
            "value": "[variables('firstPass')]"
        },
        "finalPass": {
            "type": "array",
            "value": "[variables('finalpass')]"
        }
    }
}

That help?

Upvotes: 3

Related Questions