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

如何合并多个for_each资源输出以用于另一for_each资源

问题描述

我有一个用于配置Gitlab仓库的Terraform项目:

variable "backend_repos" {
  type    = list(string)
  default = ["backend-1", "backend-2"]
}

variable "web_repos" {
  type    = list(string)
  default = ["web-1", "web-2"]
}

resource "gitlab_project" "backend" {
  for_each = var.backend_repos
  name = each.key
  ...
}

resource "gitlab_project" "web" {
  for_each = var.web_repos
  name = each.key
  ...
}

我需要为backend和web仓库配置完全相同的分支保护,但找不到合并这两个资源集合的方法。尝试过多种写法均无效:

  • { for project in concat(gitlab_project.backend, gitlab_project.web) : project.name -> project.id }
  • { for project in concat(gitlab_project.backend[*], gitlab_project.web[*]) : project.name -> project.id }
  • { for project in setunion(gitlab_project.backend, gitlab_project.web) : project.name -> project.id }
  • { for project in setunion(gitlab_project.backend[*], gitlab_project.web[*]) : project.name -> project.id }

但单独针对其中一个资源配置时可以正常工作:

resource "gitlab_branch_protection" "develop" {
  for_each = { for project in gitlab_project.backend : project.name -> project.id }
  project = each.value
  branch  = "develop"
  ...
}
解决方案

方法一:用merge合并映射(推荐)

直接合并两个for_each生成的资源映射,是最简洁的方式:

resource "gitlab_branch_protection" "develop" {
  for_each = merge(
    { for k, p in gitlab_project.backend : p.name => p.id },
    { for k, p in gitlab_project.web : p.name => p.id }
  )

  project = each.value
  branch  = "develop"
  # 补充你的分支保护规则,比如:
  # push_access_level = "maintainer"
  # merge_access_level = "developer"
}

如果存在backend和web仓库同名的情况,为避免键冲突,可以给键加上前缀区分:

resource "gitlab_branch_protection" "develop" {
  for_each = merge(
    { for k, p in gitlab_project.backend : "backend-${k}" => p.id },
    { for k, p in gitlab_project.web : "web-${k}" => p.id }
  )

  project = each.value
  branch  = "develop"
  # 分支保护配置...
}

方法二:转换为列表后合并

先通过values()将映射转为资源对象列表,再用concat合并,最后重新构建映射:

resource "gitlab_branch_protection" "develop" {
  for_each = { 
    for p in concat(values(gitlab_project.backend), values(gitlab_project.web)) : 
    p.name => p.id 
  }

  project = each.value
  branch  = "develop"
  # 分支保护配置...
}
原因解析
  • 用for_each创建的资源(如gitlab_project.backend)本质是映射(map)类型,而concat、setunion仅支持列表类型,直接传入映射会导致类型不匹配错误。
  • merge函数专门用于合并多个映射,完美适配for_each对映射输入的要求;而values()可以把映射的所有值提取为列表,让concat能正常处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 21:58:23