Terraform中如何将两个内部映射的元素合并为单个映射
解决方案
要将嵌套的命名空间映射扁平化,直接得到以命名空间名为顶层键的结构,有两种可行方法:
方法一:直接生成目标结构
修改原有的for表达式,跳过按项目分组的步骤,直接遍历所有命名空间并关联对应的项目信息:
locals { ns_per_project = { for ns_name, ns in data.kubernetes_namespace.ns : ns_name => { clusterId = rancher2_cluster.cluster.id projectId = lookup(ns.metadata[0].annotations, "field.cattle.io/projectId", null) # 通过projectId匹配对应的项目名称 projectName = [ for proj_name, proj in rancher2_project.pr : proj_name if proj.id == lookup(ns.metadata[0].annotations, "field.cattle.io/projectId", null) ][0] } # 过滤掉没有关联项目的命名空间 if lookup(ns.metadata[0].annotations, "field.cattle.io/projectId", null) != null } }
这个表达式会直接遍历所有命名空间,通过projectId匹配到所属项目的名称,最终生成你期望的单层映射结构。
方法二:扁平化已有的嵌套映射
如果你想保留原有的ns_per_project结构,再生成扁平化版本,可以利用merge函数结合values和展开运算符(...):
locals { # 原有的嵌套结构 ns_per_project = merge({ for proj, projvalue in local.projects: proj => { for key,value in data.kubernetes_namespace.ns: key=>{ clusterId = rancher2_cluster.cluster.id projectId = lookup(value.metadata[0].annotations, "field.cattle.io/projectId", null) projectName = proj } if (lookup(value.metadata[0].annotations, "field.cattle.io/projectId", null)) == rancher2_project.pr["${proj}"].id } }) # 扁平化后的结构 ns_per_project_flat = merge(values(local.ns_per_project)...) }
原理说明:
values(local.ns_per_project)会提取嵌套结构中所有项目对应的命名空间映射,返回一个列表(比如[{default = ...}, {cattle-dashboards = ..., ...}])- 展开运算符
...会将列表中的每个映射作为独立参数传入merge,merge会自动合并这些映射,最终得到单层的目标结构。
你之前尝试的问题分析
- 原代码中的
merge未生效:因为你只传入了一个映射参数(for表达式生成的项目到命名空间的映射),merge只有在传入多个映射时才会执行合并操作。 - 后续尝试生成了列表而非映射:你用
for表达式生成了包含多个映射的列表,但没有将这些列表元素合并成单个映射,所以需要用merge结合展开运算符来完成合并。
内容的提问来源于stack exchange,提问作者papanito
相关产品推荐
相关产品推荐

