Search code examples
amazon-web-servicesterraformterraform-provider-awsterraform0.12+

Concatenate a list and resource output in Terraform v1.0


I have the following local list:

locals {
  default_iam_policies = [
    "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy",
    "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
    "arn:aws:iam::aws:policy/AWSDeviceFarmFullAccess"   
  ]
}

I am planning to attach these policies to a role along with a custom policy using this:

resource "aws_iam_role_policy_attachment" "default-policy-attachment" {
  for_each = toset(concat(
    local.default_iam_policies,
    [aws_iam_policy.custom-policy.arn]
  ))

  role       = aws_iam_role.this.name
  policy_arn = each.value
}

but I'm getting this error message:

│ Error: Invalid for_each argument
│
│   on main.tf line 113, in resource "aws_iam_role_policy_attachment" "default-policy-attachment":
│  113:   for_each = toset(concat(
│  114:     local.default_iam_policies,
│  115:     [aws_iam_policy.custom-policy.arn]
│  116:     ))
│     ├────────────────
│     │ aws_iam_policy.custom-policy.arn is a string, known only after apply
│     │ local.default_iam_policies is tuple with 3 elements
│
│ The "for_each" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created.
│ To work around this, use the -target argument to first apply only the resources that the for_each depends on.

I think I can split this into two aws_iam_role_policy_attachment blocks but I wanted to see if it's possible to just use one.


Solution

  • As already explained, you can't use for_each. But in your case you can use count:

    
    locals {
      default_iam_policies = [
        "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy",
        "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
        "arn:aws:iam::aws:policy/AWSDeviceFarmFullAccess"   
      ]
      
      full_list = concat(local.default_iam_policies,[aws_iam_policy.this.arn])
    }
    
    
    resource "aws_iam_role_policy_attachment" "default-policy-attachment" {
      count      = length(local.full_list)
    
      role       = aws_iam_role.this.name
      policy_arn = local.full_list[count.index]
    }