Terraform:合并列表的地图并合并来自重复关键点的列表

Terraform:合并列表的地图并合并来自重复关键点的列表,terraform,Terraform,我有类似的事情 locals { roles = [ { role = "roles/admin" members = ["user:user@example.com"] }, { role = "roles/viewer" members = ["user:user2@example.com"] } ] } 我希望我的模块能够导出自己的角色列表,如 roles = [ { role =

我有类似的事情

locals {
  roles = [
    {
      role = "roles/admin"
      members = ["user:user@example.com"]
    },
    {
      role = "roles/viewer"
      members = ["user:user2@example.com"]
    }
  ]
}
我希望我的模块能够导出自己的角色列表,如

roles = [
    {
      role = "roles/viewer"
      members = ["user:newperson@example.com"]
    }
]
然后能够把这些东西合并在一起

locals {
  roles = [
    {
      role = "roles/admin"
      members = ["user:user@example.com"]
    },
    {
      role = "roles/viewer"
      members = ["user:user2@example.com", "user:newperson@example.com"]
    }
  ]
}
我知道,如果我将所有内容都存储为地图,我可以合并地图,只要没有重复的键,它就可以正常工作。但是在这种情况下,我明确地希望能够有重复的密钥,这样一个模块就不需要关心任何其他模块

更新我通过这样做实现了这一点:

roles = distinct(flatten([
    for rm in local.role_maps : [
      for role, members in rm :
      {
        role = role
        members = sort(distinct(flatten([
          for m in local.role_maps :
          m[role] if lookup(m, role, null) != null
        ])))
      }
    ]
  ]))

这似乎是一个很好的应用程序,可以使用
分组修饰符,通过按键分组来生成列表的映射

variable "custom_roles" {
  type = list(object({
    role    = string
    members = list(string)
  })
}

locals {
  default_roles = [
    {
      role    = "roles/admin"
      members = ["user:user@example.com"]
    },
    {
      role    = "roles/viewer"
      members = ["user:user2@example.com"]
    }
  ]
  all_roles = concat(
    local.default_roles,
    var.custom_roles,
  )

  # First we'll project the inputs so that we have one
  # role/member pair per element.
  flat_roles = flatten([
    for r in locals.all_roles : [
      for m in r.members : {
        role   = r.role
        member = m
      }
    ]
  ])

  # Then we can use that flattened list to produce a map
  # grouped by unique role key.
  merged_roles = {
    for k, v in local.all_roles : k => v...
  }

  # Finally, if the list-of-objects representation was
  # important then we can recover it by projecting that
  # merged_roles map back into the list shape.
  merged_roles_list = tolist([
    for role, members in local.merged_roles : {
      role    = role
      members = tolist(members)
    }
  ])
}
在上面的示例中,
local.merged_roles
是列表的映射,如下所示:

{
  "roles/admin"  = ["user:user@example.com"]
  "roles/viewer" = ["user:user2@example.com", "user:newperson@example.com"]
}

您可以直接使用该映射,但为了防止对象列表表单很重要,我包含了
local.merged\u roles\u list
,它应该与您提出的问题的结构相匹配。

这是一个很好且易于遵循的解决方案,但我认为您的
merged\u roles
不太正确。我认为您希望操作
平面角色
,而不是
所有角色