Home > Blockchain >  Conditionals Inside Nested For Loops
Conditionals Inside Nested For Loops

Time:01-25

I am trying to figure out a way to skip the iteration of an inner for loop if a particular attribute does not exist - in this case variables. However, I am beginning to wonder if I am expecting too much from a declarative language.

This is my input:

locals {
  environments = {
    dev : {
      name: "development"
      project : "gcp-project-1"
      protected : false
      variables : [
        {
          key: "GCP_PROJECT"
          value: "gcp-project-1"
          environment_scope: "development"
          protected: true
        },
        {
          key: "ANOTHER_VAR"
          value: "some-value"
          environment_scope: "development"
          protected: true
        }
      ]
    }
    prod : {
      name : "production"
      project : "gcp-project-2"
      protected : true
      variables : [
        {
          key: "GCP_PROJECT"
          value: "gcp-project-2"
          environment_scope: "production"
          protected: true
        }
      ]
    }
  }
}

environments is consumed here, which basically iterates through variables to convert and store it in a data structure that is easier to work with later on:

locals {
  variables = flatten([
    for k, env in local.environments : [
      for var, var in env.variables : { <--- Is there a way to skip an iteration if env.variables does not exist?
        key: var.key
        value: var.value
      }
    ]
  ])
}

This loop will output something similar to this:

variables = [
  {
    key   = "KEY"
    value = "VALUE"
  }
]

Which ultimately is used here:

resource "gitlab_project_variable" "variable" {
  for_each = {
    for i, v in local.variables : v.terraform_id => v
  }

  key   = each.value.key
  value = each.value.value
}

CodePudding user response:

You can use lookup:

locals {
  variables = flatten([
    for k, env in local.environments : [
      for var, var in lookup(env, "variables", {}) : { 
        key: var.key
        value: var.value
      }
    ]
  ])
}

CodePudding user response:

I would typically recommend setting object attributes to null when you aren't using them so that the object type remains consistent in all cases, and then you can use comparison with null as the filter:

locals {
  variables = flatten([
    for k, env in local.environments : [
      for var, var in env.variables : { 
        key: var.key
        value: var.value
      }
    ]
    if env.variables != null
  ])
}

You could also set the inapplicable ones to be an empty list and then your expression would work without any extra conditions at all.

If you really do want to use inconsistent object types for your environment objects then it's not so clean to handle but you can still get something similar to the above by using the can function to detect when accessing the variables attribute would fail:

locals {
  variables = flatten([
    for k, env in local.environments : [
      for var, var in env.variables : { 
        key: var.key
        value: var.value
      }
    ]
    if can(env.variables)
  ])
}
  • Related