Motti Dadison
Motti Dadison

Reputation: 19

terraform how to iterate over a map of objects with different values

I have the following local with different values. I'm trying to iterate over the following map inside a dynamic block:

local {
  toleration = {
    0 = {
      key    = "node-role.kubernetes.io/master"
      effect = "NoSchedule"
    }
    1 = {
      key      = "dedicated"
      operator = "Equal"
      value    = "worker"
      effect   = "NoSchedule"
    }
  }
}

In the helm_release I'm using a "set" dynamic block, I've tried many combinations but none worked for me. I thought the following will work but it doesn't.

  dynamic "set" {
    for_each = { for k,v in local.toleration: {for key,value in v : key=>value}}
content {
      name  = "tolerations[${set.key}].${set.key}"
      value = set.value # but I can't use value for the same
    }
  }

I need my output to look like this:

name  = "tolerations[0].key"
value = "node-role.kubernetes.io/master" 

name  = "tolerations[0].effect"
value = "NoSchedule" 

name  = "tolerations[1].key"
value = "dedicated" 
...

what am I doing wrong?

Upvotes: 1

Views: 9888

Answers (1)

Martin Atkins
Martin Atkins

Reputation: 74694

In the example you shared you've set for_each inside the dynamic "set" block to be a map of maps, whereas in your example of desired output you show value being set to individual strings and so I assume what you want to do is flatten the two levels of map into a single series of set blocks where name will include the keys from both levels.

I'm not sure which resource type this is for and so I'm guessing a bit as to what would be valid here but I think the following would get the result you intended:

  dynamic "set" {
    for_each = flatten([
      for tkey, values in local.toleration : [
        for key, value in values : {
          toleration_key = tkey
          value_key      = key
          value          = value
        }
      ]
    ])
    content {
      name  = "tolerations[${set.value.toleration_key}].${set.value.value_key}"
      value = set.value.value
    }
  }

This uses the flatten function along with nested for expressions to construct a list of objects to use as the repetition collection of the dynamic block:

[
  {
    toleration_key = "0"
    value_key      = "key"
    value          = "node-role.kubernetes.io/master"
  },
  {
    toleration_key = "0"
    value_key      = "effect"
    value          = "NoSchedule"
  },
  {
    toleration_key = "1"
    value_key      = "key"
    value          = "dedicated"
  },
  # ...
]

That is then sufficient information to both construct the compound name strings, using both toleration_key and value_key together, and populate the value from value.

The symbol and attribute names I used here are non-ideal because both "key" and "value" are meaning various different things at different points in this, but I don't have sufficient context about your problem to choose more meaningful names. If possible, I would suggest choosing names that better distinguish all of these different settings so that this will be easier to read for a future maintainer.

Upvotes: 1

Related Questions