Search code examples
arraysazureazure-resource-managerazure-bicep

How to loop over multiple arrays for a resource


I want to create a resource for many regions, environments, apps, etc at once. I'd like to do something like this:

param apps array = [
  'app1'
  'app2'
  'app3'
]

param environments array = [
  'alpha'
  'beta'
]

param regions array = [
  'ne'
  'we'
  'uks'
]


resource origin_group 'Microsoft.Cdn/profiles/origingroups@2021-06-01' = [ for region in regions: {
[ for env in environments: {
[ for app in apps: {
  parent: profiles_global_fd_name_resource
  name: '${env}-${region}-${app}-origin-group'
  properties: {
    loadBalancingSettings: {
      sampleSize: 4
      successfulSamplesRequired: 3
      additionalLatencyInMilliseconds: 50
    }
    healthProbeSettings: {
      probePath: '/'
      probeRequestType: 'HEAD'
      probeProtocol: 'Http'
      probeIntervalInSeconds: 100
    }
    sessionAffinityState: 'Disabled'
  }
}]
}]
}]

All docs mentioning nested loops talk about looping inside a resource to create many sub-resources. Not what I'm after. Perhaps another way would be to somehow merge all these arrays into a single array of objects of every possible iteration. Not sure where to start with that either.

Any help much appreciated.


Solution

  • This is not supported for the moment but it will (see Is there plans to support nested loop on resources?).

    EDIT April 2023

    Bicep now supports lambda functions. The reduce and map function could be use to generate all the possible combinations:

    param environments array = [ 'alpha', 'beta' ]
    param regions array = [ 'ne', 'we', 'uks' ]
    param apps array = [ 'app1', 'app2', 'app3' ]
    
    // Create an array of env-region
    var envRegions = reduce(environments, [], (cur, next) => concat(cur, map(regions, region => '${next}-${region}')))
    
    // Add the app to the previously created array env-region-app
    output envRegionApps array = reduce(envRegions, [], (cur, next) => concat(cur, map(apps, app => '${next}-${app}')))
    

    ORIGINAL ANSWER

    Using a little bit of math, you could achieve what you'd like (Not sure if you should):

    param environments array = [ 'alpha', 'beta' ]
    param regions array = [ 'ne', 'we', 'uks' ]
    param apps array = [ 'app1', 'app2', 'app3' ]
    
    // Setting some variables for clarity
    var envCount = length(environments)
    var regionCount = length(regions)
    var appCount = length(apps)
    
    // Setting the total number of combination
    var originGroupCount = envCount * regionCount * appCount
    
    // Iterate all possible combinations
    output originGroupNames array = [for i in range(0, originGroupCount): {
      name: '${environments[i / (regionCount * appCount) % envCount]}-${regions[i / appCount % regionCount]}-${apps[i % appCount]}-origin-group'
    }]
    

    this will output all possible combinations (I think) for origin group name.