StefanIvemo/stefanivemo.github.io

Using-loops-with-Bicep/

Opened this issue · 8 comments

Using loops with Bicep! 💪 – Stefan Ivemo – A blog about Microsoft Azure, Microsoft 365 and other tech stuff.

With 💪Bicep v0.3 we finally got loop support and now we can start to do some really cool stuff using Bicep. I must say I really like the new loop syntax, it’s clean, easy to read and removes a lot of the complexity we did see in ARM template copy loops. This post is dedicated to copy loops where I will show some different examples on how you can use loops in Bicep. The Bicep Loops specification can be found here.

https://blog.ivemo.se/Using-loops-with-Bicep/

I am still unable to get my code to work using loops. Is this because I am creating a loop of properties inside a loop of arrays. I have a loop of multiple arrays that have variable length arrays of properties within. In other words am I trying to create a loop that is still not supported?, or it should work but there is something wrong with my code or environment? Bicep version 4.63 and I get this error, BCP124 "Property value for-expression cannot be nested." Is there a work around?
CODE:
backendAddressPools: [for be in ApplicationGatewayBack: {

    name: be.ApplicationGatewayBackName
    properties: {
     backendAddresses: [for ip in be.ApplicationGatewayBKIP: {
          ipAddress: ip.ipaddress
      }]
    }
}]

Hello Stefan, thank you for this post, it was really usefull ! I'd like your opinion about using loops at the resource level. Let's say you deploy 10 vnets with a loop. Then, in another resource you want to reference a special vnet, you will need to know the index of the array output which is not convenient at all. Maybe I miss something. What do you think ?

Something you don't seem to cover is a group of objects inside an object.

The loop to create this:

      azureStorageAccounts: {
        fileshare1: {
          type: 'AzureFiles'
          accountName: 'yyyyy'
          shareName: 'fileshare1'
          mountPath: '/fileshare1'
          accessKey: 'xxx'
        }
        fileshare2: {
          type: 'AzureFiles'
          accountName: 'yyyyy'
          shareName: 'fileshare2'
          mountPath: '/var/www/html/fileshare2'
          accessKey: 'xxx'
        }
    }

is not documented anywhere that I can find.

I can find examples to create an array of objects, but not an object filled with objects.

I don't know this will help anyone, but I think I got around my problem as follows.

I declared an array of arrays.

ApplicationGatewayBack: [
  {
    ApplicationGatewayBackName:  '${Environment}-hub-agw-Back-01'

   ApplicationGatewayBKIP: [   
     {
        ipaddress: 'x.x.x.x'
      }
      {
        ipaddress: 'x.x.x.x'
      }
   ]
  }
]

And I call those arrays like this

backendAddressPools:  [for pools in ApplicationGatewayBack: {
  
    name: pools.ApplicationGatewayBackName
    properties: {
     backendAddresses: pools.ApplicationGatewayBKIP
    }
}]

Thank you, these are very good examples and good information.
I wonder if number 5 would still work with Types

param vnets vnetsType, then the param is defined in the .bicepparam file.

Hi,

I am stuck on the same issue which @edgreenberg mentioned.

azureStorageAccounts: {
fileshare1: {
type: 'AzureFiles'
accountName: 'yyyyy'
shareName: 'fileshare1'
mountPath: '/fileshare1'
accessKey: 'xxx'
}
fileshare2: {
type: 'AzureFiles'
accountName: 'yyyyy'
shareName: 'fileshare2'
mountPath: '/var/www/html/fileshare2'
accessKey: 'xxx'
}
}

Has anyone found a way to loop this yet?

Hi,

Hope that you are doing well.

I am stuck on a similar issue. Trying to filter a specific value from Output.

Here my config

param groupUsage array = [
'admins'
'businessadmins'
]

resource entraIdGroup 'Microsoft.Graph/groups@v1.0' = [for usage in groupUsage: {
displayName: toUpper('appgrp_${prRegionCode}${productName}${usage}${env}')
mailEnabled: false
mailNickname: toUpper('appgrp
${prRegionCode}${productName}${usage}${env}')
securityEnabled: true
uniqueName: toUpper('appgrp
${prRegionCode}${productName}${usage}_${env}')
members: members
owners: GroupOwner
}]

output aadGroupPro array = [for (usage, i) in groupUsage: {
aadGroupUsage: usage
aadGroupName: entraIdGroup[i].uniqueName
aadGroupId: entraIdGroup[i].id
}]

I'm trying to filter the output to get the group Id of the group containing the word "admins".

I try this with no success

first(filter(entraIdGroup.outputs.aadGroupPro, x => x.aadGroupUsage == 'admins')).id

Can you help please.