Terraform: Iterate over objects where at least one has not a special attribute

Viewed 156

I try to get the information from a local variable that contains objects, if at least one of the objects has the attribute "assign" with the value "true" ( assign = true ). My code works, if all of the objects have an attribute "assign" but it fails if any object is missing the attribute.

locals {  
  assignments = {
      users = {
        "u1" = {per = ["push"], assign = true}
        "u2" = {per = ["push"], assign = false}
      }
      groups = {
        "gr1" = {per = ["o,l"], assign = true}
        "gr2" = {per = ["o"]}
        "gr3" = {per = ["k"], assign = false}
      }
    }
}

output "atLeastOneAssign" {
  value = anytrue(values(merge(local.assignments.users, local.assignments.groups))[*].assign)
}

So because "gr2" is missing the attribute "assign" the whole thing fails with "This object does not have an attribute named "assign"." I tried it with "try" and "can" but nothing worked. It works like expected, if any object has this attribute but it cannot be guaranteed.

Please help. Thanks in advance.

1 Answers

This behavior with difficulty accessing optional keys in objects is essentially because of the way Golang serializes objects. We can refactor your output to achieve the desired behavior:

output "at_least_one_assign" {
  value = contains([for entity in merge(local.assignments.users, local.assignments.groups) : try(entity.assign, false)], true)
}

The users and groups Map are merged together. The for expression iterates over the combined nested Map where the values are the assigned objects. For each iteration, we store the object value in the temporary lambda variable entity. We then attempt to access the value for the assign key in each entity, and use the try function to default to a boolean of false if no assign key exists (exploiting the fact that all we care about here is the existence of true). A list constructor assembles all of the for expression values for assign into a list(bool). Finally, the contains function asserts if a single true is in the list, and returns true if so, and false otherwise. Essentially, this is equivalent to a return of true if any of the assign value is true, and false otherwise. This is the desired behavior.

Related