Unable to retrive nested elements using for_each

Hi Terraform Gurus!

I am using for_each to import specific policies using import blocks. However, I am facing difficulty in getting the ‘for_each’ function right for iterating over the policy. I need help correcting my ‘for_each’ function. My ultimate goal is to correctly import the policies. I would appreciate your assistance with this matter.

Here is my code

variable "users" {
  type = list(object({
    name     = string
    policies = list(string)
  }))
  default = [
    { name = "user1", policies = ["p1", "p2", "p99", "p200"] },
    { name = "user2", policies = ["p3", "p4"] },
    { name = "user3", policies = ["p5", "p6"] },
    { name = "user4", policies = ["p7", "p8"] },
  ]
}

import {
  for_each = [for u in var.users : toset([for p in u.policies : p])]
  to       = aws_iam_policy.this[each.value.policies]
  id       = format("arn:aws:iam::054445454545:policy/%s", each.value.policies)
}

resource "aws_iam_policy" "this" {
  for_each = [for u in var.users : toset([for p in u.policies : p])]
  policy   = each.value.policies
}

Hi @h2oearth,

Can you show exactly what the intended results should be? Your for_each expression creates a list of sets, which doesn’t align with how you are using the value. The use of each.value.policies implies you want an object with a policies attribute, but that would not be valid as a string argument in format.

Hi @jbardin ,

Thank you for your reply!

I have been experimenting with the for :-(. The goal is to be able iterate over the policies link to each user and use the individual policies on further steps.
The expected result from the format is arn:aws:iam::054445454545:policy/p1, arn:aws:iam::054445454545:policy/p2 ...

If I understand correctly, you are looking for the set of all policies, which could be written as:

toset(concat([for u in var.users : u.policies]...))
1 Like

I did not know that spread syntax was a possible :-O.

will this be the currect implementation? am I still able to retrive each policy by using each.value?

variable "users" {
  type = list(object({
    name     = string
    policies = list(string)
  }))
  default = [
    { name = "user1", policies = ["p1", "p2", "p99", "p200"] },
    { name = "user2", policies = ["p3", "p4"] },
    { name = "user3", policies = ["p5", "p6"] },
    { name = "user4", policies = ["p7", "p8"] },
  ]
}

import {
  for_each = toset(concat([for u in var.users : u.policies]...))
  to       = aws_iam_policy.this[each.value]
  id       = format("arn:aws:iam::054445454545:policy/%s", each.value)
}

Thank you, @jbardin, for your help! You made my day. :slight_smile:

The spread syntax isn’t required, there’s a few ways to structure the same outcome, depending on what you find more readable

toset(flatten(var.users[*].policies))

If that configuration gives you the result you’re after, then it’s the correct implementation :wink:

1 Like