skip to Main Content

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.

2

Answers


  1. You didn’t specify what error you get but your for loops are missing one argument:

    [for s in toset(local.environments) : s if s != "prod"]
    

    And:

    [for s in toset(local.environments) : s if s == "prod"]
    

    Also I`m not sure if you need this toset there. It might be required to put the whole for loop inside toset and not local.environments.

    Login or Signup to reply.
  2. There are a few different problems with the following expression:

      for_each = {
         [for s in toset(local.environments) : if s != "prod"] 
      }
    
    1. The for expression is missing its result clause after the colon. If you intend to just return s directly then you can just specify that variable alone between the colon and the if keyword:

      [for s in toset(local.environments) : s if s != "prod"] 
      
    2. The braces { } around this for expression are not valid. That syntax is for constructing an object-typed value, but for that to work you’d need to specify an attribute to assign the result of the for expression to.

      Since var.environments seems to be just a bunch of strings, I expect you probably want to construct a set of strings directly, without any wrapping map/object, like this:

      for_each = toset([for s in local.environments : s if s != "prod"])
      
    3. The inner toset you previously had for local.environments is not really adding anything here because a for expression effectively treats a set of strings like a list of those strings in lexical order. You can safely remove it like I did in my most recent example above, and that would be sufficient for this particular use of `local.environments.

      If you want to communicate that local.environments itself is semantically a set — which might be helpful for future maintainers of your module trying to understand what you intended — then you might choose to place the toset in the definition of the local value instead:

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

      Doing this would have no effect on the for_each expression this question is about though, so this would be a meaningful change only if local.environments is used in other locations that should also treat it as a set, and that’s beyond the scope of this question.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search