You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform如何从集合列表创建单个集合供for_each使用

Terraform 合并嵌套IAM角色集合为for_each可用的单集合

问题场景

创建预定义IAM角色集合时,初始本地变量配置如下:

locals {
    default_iam_roles = {
        group1 = {
            name = "group:group1-group@mydomain.com"
            roles = toset([
                "roles/viewer"
            ])
        }
        group2 = {
            name = "group:group2-group@mydomain.com"
            roles = toset([
                "roles/owner"
            ])
        }
    }

    formatted_iam_roles = [ for member in local.default_iam_roles : setproduct([member.name], member.roles) ]
}

打印输出local.formatted_iam_roles时,得到的是包含多个独立集合的嵌套列表,结构如下:

[
  toset([
    [
      "group:group1-group@mydomain.com",
      "roles/viewer",
    ],
  ]),
  toset([
    [
      "group:group2-group@mydomain.com",
      "roles/owner",
    ],
  ]),
]

需要将列表中所有成员-角色组合合并为单个集合,作为入参传递给资源的for_each语句使用,期望输出结构如下:

toset([
  [
    "group:group1-group@mydomain.com",
    "roles/viewer",
  ],
  [
    "group:group2-group@mydomain.com",
    "roles/owner",
  ]
])

解决方法

修改formatted_iam_roles的定义,用flatten函数打平嵌套结构后再转集合即可:

locals {
    default_iam_roles = {
        group1 = {
            name = "group:group1-group@mydomain.com"
            roles = toset([
                "roles/viewer"
            ])
        }
        group2 = {
            name = "group:group2-group@mydomain.com"
            roles = toset([
                "roles/owner"
            ])
        }
    }

    formatted_iam_roles = toset(flatten([
      for member in local.default_iam_roles : setproduct([member.name], member.roles)
    ]))
}

逻辑说明

  • 原写法中for表达式每次迭代返回setproduct生成的独立角色绑定集合,最终输出是「集合组成的嵌套列表」,不符合for_each的入参要求
  • flatten函数会递归消除列表、集合的嵌套层级,把所有底层的[成员标识, 角色名]二元组提取到同一层级
  • 外层包裹toset()后,最终输出就是完全匹配预期的单层集合,每个元素都是唯一的成员-角色绑定对,可以直接传给for_each使用,不会出现类型不兼容的报错。

内容的提问来源于stack exchange,提问作者Luiscri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 09:54:22