0

Normally when creating Azure resources through Bicep modules I would have 2 files. One file designated to hold the parameterized resource and another file, the main file, which will consume that module.

As an example for creating an action group my resource file looks like:

action-group.bicep

param actionGroupName string
param groupShortName string
param emailReceivers array = []

// Alerting Action Group
resource action_group 'microsoft.insights/actionGroups@2019-06-01' = {
  name: actionGroupName
  location: 'global'
  tags: {}
  properties: {
    groupShortName: groupShortName
    enabled: true
    emailReceivers: emailReceivers
  }
}

This resource is then consumed as a module in the main file, main.bicep:

// Alerting Action Group
module actionGroup '../modules/alerts/alert-group.bicep' = {
  name: 'action-group-dply'
  params: {
    actionGroupName: actionGroupName
    groupShortName: actionGroupShortName
    emailReceivers: [
      {        
        name: '<Name of email receivers>'
        emailAddress: alertEmailList
      }
    ]
  }
}

My pipeline references main.bicep and will deploy the listed resources in the file. My question is, is there a way to add a third file in the mix? One file to still hold the parameterized resource, one file to hold the associated resource modules, and the main.bicep file. The idea is to create various alerts throughout my existing resources but I don't want to add a ton of modules to main.bicep as it will quickly increase the complexity and amount of code in this file.

Is there a way that I can have this file of modules, and reference the entire file in main.bicep to still deployment from the original pipeline?

As an example: alerts.bicep

param metricAlertsName string
param description string
param severity int
param enabled bool = true
param scopes array = []
param evaluationFrequency string
param windowSize string
param targetResourceRegion string = resourceGroup().location
param allOf array = []
param actionGroupName string

var actionGroupId = resourceId(resourceGroup().name, 'microsoft.insights/actionGroups', actionGroupName)

resource dealsMetricAlerts 'Microsoft.Insights/metricAlerts@2018-03-01' = {
  name: metricAlertsName
  location: 'global'
  tags: {}
  properties: {
    description: description
    severity: severity
    enabled: enabled
    scopes: scopes
    evaluationFrequency: evaluationFrequency
    windowSize: windowSize
    targetResourceRegion: targetResourceRegion
    criteria: {
      'odata.type': 'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria'
      allOf: allOf
    }
    actions: [
      {
        actionGroupId: actionGroupId
      }
    ]
  }

alert-modules.bicep

// Function/Web Apps 403 Error
module appServicePlan403Errors '../modules/alerts/alerts.bicep' = {
   // Alert Logic
}

// Function/Web Apps 500 Error
module appServicePlan500Errors '../modules/alerts/alerts.bicep' = {
  // Alert Logic
}

main.bicep

// Some reference to alert-modules.bicep so when the pipeline runs and looks for main.bicep, it will still deploy all the resources
agw2021
  • 266
  • 2
  • 22

1 Answers1

1

You can call the module multiple times (in main.bicep or a module) using looping:

https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/loops

e.g.

param alertsCollection array = [
  {
    actionGroupName: 'group1'
    groupShortName: 'g1'
    emailReceivers: []
  }
  {
    actionGroupName: 'group2'
    groupShortName: 'g2'
    emailReceivers: [
      'foo@bar.com'
      'bar@baz.com'
    ]
  }
]

module alerts '../modules/alerts/alert-group.bicep' = [for alert in alertsCollection): {
  name: '${alert.actionGroupName}'
  params: {
    actionGroupName: alert.actionGroupName
    groupShortName: alert.groupShortName
    emailReceivers: alert.emailReceivers
 }
}]

You could simplify the params passing via:

module alerts '../modules/alerts/alert-group.bicep' = [for alert in alertsCollection): {
  name: '${alert.actionGroupName}'
  params: alert
}]

But you need to be really strict on the schema of the alertsCollection parameter...

That help?

bmoore-msft
  • 8,376
  • 20
  • 22
  • So I can have a file of all my modules, then in main.bicep I can iterate over all of the modules? That is exactly what I'm looking to do. How does alertsCollection need to be configured and how do I reference it in main.bicep? – agw2021 Oct 28 '21 at 20:23
  • Yes. It depends a bit on what your input to main.bicep looks like... but conceptually alertsCollection is an array of objects that have properties for the parameters you need for that module. Lemme edit the response a bit... – bmoore-msft Oct 29 '21 at 20:15
  • So I was able to get it mostly working with a variant of your answer but I'm having an issue with the scopes param as I'm trying to add the alerts to multiple resources. Would you be able to take a look? https://stackoverflow.com/questions/69791261/why-cant-i-loop-twice-in-an-azure-resource-module – agw2021 Oct 31 '21 at 23:10