Terraform 0.12嵌套循环

时间:2019-05-08 18:54:22

标签: nested-loops terraform

我正在尝试使用Terraform 0.12的新功能来实现嵌套循环,以便遍历AWS IAM用户,每个用户都可以附加一个或多个策略。用于表示此列表的变量的类型为map(list(string)),看起来像这样:

{
  "user 1" = [ "policy1", "policy2" ],
  "user 2" = [ "policy1" ]
}

通过keys()很容易获得要创建的用户列表,但是由于当前在Terraform中没有用于嵌套循环资源创建的机制,因此,策略附件必须以独立于每个用户的单个循环的形式发生。因此,我正在尝试从地图输入中构建一个user:policy关联的列表,该列表基于上述示例看起来像这样:

[
  [ "user1", "policy1" ],
  [ "user1", "policy2" ],
  [ "user2", "policy1" ]
]

我正在尝试构造该列表并将其存储在本地变量中,例如var.iam-user-policy-map是输入映射:

locals {
  ...
  association-list = [
    for user in keys(var.iam-user-policy-map):
    [
      for policy in var.iam-user-policy-map[user]:
      [user, policy]
    ]
  ]
  ...
}

但是,尝试访问该嵌套列表中的值时出现错误。我正在尝试使用引用local.association-list[count.index][0]和策略local.association-list[count.index][1]访问关联的用户部分,但是在运行terraform plan时会出错:

Error: Incorrect attribute value type

  on main.tf line 27, in resource "aws_iam_user_policy_attachment" "test-attach":
  27:   user = local.association-list[count.index][0]

Inappropriate value for attribute "user": string required.


Error: Incorrect attribute value type

  on main.tf line 27, in resource "aws_iam_user_policy_attachment" "test-attach":
  27:   user = local.association-list[count.index][0]

Inappropriate value for attribute "user": string required.


Error: Invalid index

  on main.tf line 28, in resource "aws_iam_user_policy_attachment" "test-attach":
  28:   policy_arn = "arn:aws-us-gov:iam::aws:policy/${local.association-list[count.index][1]}"
    |----------------
    | count.index is 0
    | local.association-list is tuple with 2 elements

The given key does not identify an element in this collection value.


Error: Invalid template interpolation value

  on main.tf line 28, in resource "aws_iam_user_policy_attachment" "test-attach":
  28:   policy_arn = "arn:aws-us-gov:iam::aws:policy/${local.association-list[count.index][1]}"
    |----------------
    | count.index is 1
    | local.association-list is tuple with 2 elements

Cannot include the given value in a string template: string required.

我在做什么错了?

1 个答案:

答案 0 :(得分:2)

您的本地值for中的association-list表达式正在生成一个字符串列表列表,但是您对其的引用将其视为字符串列表列表。

要获得所需的扁平化表示,可以使用flatten函数,但是因为否则它将把所有内容分组为单个平面列表,我建议将最里面的值设为对象。 (这还将使对它的引用更清晰。)

locals {
  association-list = flatten([
    for user in keys(var.iam-user-policy-map) : [
      for policy in var.iam-user-policy-map[user] : {
        user   = user
        policy = policy
      }
    ]
  ])
}

此表达式的结果将具有以下形状:

[
  { user = "user1", policy = "policy1" },
  { user = "user1", policy = "policy2" },
  { user = "user2", policy = "policy2" },
]

您对它的引用可以采用以下格式:

user = local.association-list[count.index].user
policy_arn = "arn:aws-us-gov:iam::aws:policy/${local.association-list[count.index].policy}"