Terraform:合并列表的映射并合并来自重复键的列表 [英] Terraform: merge maps of lists and combine the lists from duplicate keys

查看:60
本文介绍了Terraform:合并列表的映射并合并来自重复键的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的事情

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

我希望我的模块能够导出自己的角色列表,例如

I want my modules to be able to export their own list of roles like

roles = [
    {
      role = "roles/viewer"
      members = ["user:newperson@example.com"]
    }
]

然后能够将这些东西合并在一起得到

And then be able to merge these things together to get

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

我知道如果我将所有内容都存储为地图,我可以合并地图,只要没有重复的键,它就可以正常工作.但在这种情况下,我明确希望能够拥有重复的键,这样一个模块就不需要关心任何其他模块.

I know if I stored everything as maps I could merge the maps and it would work fine as long as there are no duplicate keys. But in this case I explicitly want to be able to have duplicate keys so that one module doesn't need to care about any of the other modules.

更新我能够通过这样做来实现这一点:

Update I was able to achieve this by doing something like so:

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
        ])))
      }
    ]
  ]))

推荐答案

这似乎是一个很好的for 表达式 使用 ... 分组修饰符,它可以通过键分组生成列表映射.

This seems like a good application for a for expression using the ... grouping modifier, which can produce a map of lists by grouping by the keys.

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 是列表的映射,如下所示:

In the above, local.merged_roles is a map of lists, like this:

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

您可以直接使用该地图,但为了以防对象列表表单很重要,我包含了 local.merged_roles_list,它应该与您提出的问题的结构相匹配.

You could potentially use that map directly, but just in case the list-of-objects form was important I included local.merged_roles_list which should match the structure you asked for your question.

这篇关于Terraform:合并列表的映射并合并来自重复键的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆