azureforeachterraformazure-monitoringterraform-loop

Using Terraform For_Each and For commands to filter elements


I have a Terraform locals.tf file like the below snippet, which contains my environment definition.

locals {
    environments = [
    "dev", 
    "test", 
    "preprod",
    "prod"
   ]
}

I am now looking to create an identical resource, an Azure monitor metric alert in this case, for each of the listed environments (except prod). I am attempting to do so using a For_Each loop in the resource block of my main.tf file, a snippet of which is shown below:

resource "azurerm_monitor_metric_alert" "main" {
  for_each = {
     [for s in toset(local.environments) : if s != "prod"] 
  }   
  name = "${each.key}-metric-alert"
  resource_group_name = azurerm_resource_group.rg.name
  scopes              = [azurerm_storage_account.to_monitor[each.key].id]
  [..........ADDITIONAL NON-PROD RESOURCE CONFIG...........]

For the prod environment though, the monitor alert requires a slightly different set of configuration from the others, and so what I'd like to do is filter out that environment from the locals.tf file and then using another azurerm_monitor_metric_alert resource block, configure it along the lines of the below snippet:

   resource "azurerm_monitor_metric_alert" "main" {
      for_each = {
         [for s in toset(local.environments) : if s == "prod"] 
      } 
      name = "${each.key}-metric-alert"
      resource_group_name = azurerm_resource_group.rg.name
      scopes              = [azurerm_storage_account.to_monitor[each.key].id] 
      [..........ADDITIONAL PROD CONFIG...........]

I have the tried the above and various other implementations, but unfortunately I simply can't get this to work. Would greatly appreciate some assistance here.


Solution

  • So thanks to the wonderful contribution of Martin Atkins, coupled with some further research and experiments, I managed to successfully construct my solution mainly by way of the following file updates which may help others in future:

    locals.tf

    locals {
      environments = toset([
        "dev", 
        "test", 
        "preprod",
        "prod",
      ])
    }
    
    
    
     
    

    main.tf

    Non-Prod Environments
    resource "azurerm_monitor_action_group" "non-prod" { 
       for_each = {for p in toset(local.environments): p => p if p != "prod" }    
           name                = "${each.key}-actiongroup"
           resource_group_name = azurerm_resource_group.rg.name
           short_name          = "non-prod-acg"
           webhook_receiver {
              name        = "callmyapi"
              service_uri = "http://example.com/alert"
            }
              email_receiver {
              name          = "John Doe"
              email_address = "jdoe@myemail.com"
            }
        }
        
    resource "azurerm_monitor_metric_alert" "non-prod" {
       for_each = {for p in toset(local.environments): p => p if p != "prod" }        
           name = "${each.key}-metric-alert"
           resource_group_name = azurerm_resource_group.rg.name
           scopes             = [azurerm_storage_account.to_monitor[each.key].id]
           description        = "each.value.description"
           criteria {
              metric_namespace = "Microsoft.Storage/storageAccounts"
              metric_name      = "Transactions"
              aggregation      = "Total"
              operator         = "GreaterThan"
              threshold        = 50
              dimension {
                name     = "ApiName"
                operator = "Include"
                values   = ["*"]
              }
            }
            action {
              action_group_id = azurerm_monitor_action_group.non-prod[each.key].id
            }
        }
    
    Prod Environment
      resource "azurerm_monitor_action_group" "prod" {
        for_each = {for p in toset(local.environments): p => p if p == "prod" }   
        name                = "${each.key}-actiongroup"
        resource_group_name = azurerm_resource_group.rg.name
        short_name          = "prod-acg"
        webhook_receiver {
          name        = "callmyapi"
          service_uri = "http://example.com/alert"
        }
          email_receiver {
          name          = "D Smith"
          email_address = "dsmith44@myemail.com"
        }
      }
    
    
    resource "azurerm_monitor_metric_alert" "prod" {
      for_each = {for p in toset(local.environments): p => p if p == "prod" }    
          name = "${each.key}-metric-alert"
          resource_group_name = azurerm_resource_group.rg.name
          scopes              = [azurerm_storage_account.to_monitor[each.key].id]
          description         = "${each.key} - Action will be triggered when Transactions count is greater than 60"
          criteria {
            metric_namespace = "Microsoft.Storage/storageAccounts"
            metric_name      = "Transactions"
            aggregation      = "Total"
            operator         = "GreaterThan"
            threshold        = 60
            dimension {
              name     = "ApiName"
              operator = "Include"
              values   = ["*"]
            }
          }
          action {
              action_group_id = azurerm_monitor_action_group.prod[each.key].id
          }
      }