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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 02:05:58