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

Terraform中for循环处理映射列表的问题排查求助

Terraform AWS OU 创建的 for_each 配置错误分析与修正

初始配置的错误点

初始locals结构

locals {
  l3_crm = [
    { parent: "crm", child: ["crm-sap", "crm-sf"] },
    { parent: "fin", child: ["fin-mon"] },
  ] 
}

模块调用的错误

module "l3_crm" {
  source = "./modules/ou"
  for_each   = { for idx, val in local.l3_crm : idx => val }
  ou_name    = [each.value.child]
  parent_id  = module.l2[each.key.parent].ou_ids[0]
  depends_on = [module.l2]
  ou_tags    = var.l2_ou_tags
}

报错原因

  • each.key是数组循环的索引(字符串类型的"0"、"1"),并非包含parent属性的对象,each.key.parent属于错误的属性调用,正确应使用each.value.parent获取父OU名称。
  • ou_name = [each.value.child]会将子OU数组嵌套为二维数组(如[["crm-sap", "crm-sf"]]),但模块的ou_name变量要求单个字符串类型值,此处未遍历单个子OU,而是传递了整组子OU的数组。

第二种尝试配置的错误点

第二种locals结构

locals {
  l3_crm = [
    { "rnd" : ["crm-sap", "crm-sf"] },
    { "trade" : ["fin-mon"] }
  ]
}

模块调用的错误

module "l3_rnd" {
  source     = "./modules/ou"
  for_each   = { for parent, child in local.l3_crm : parent => child }
  ou_name    = [each.value]
  parent_id  = module.l2[each.key].ou_ids[0]
  depends_on = [module.l2]
  ou_tags    = var.l2_ou_tags
}

报错原因

  • 遍历数组local.l3_crm时,parent会被赋值为数组索引("0"、"1"),而非对象中的键名("rnd"、"trade"),导致each.key与module.l2的有效键不匹配,触发索引错误。
  • each.value是数组中的单个对象(如{"rnd": ["crm-sap", "crm-sf"]}),ou_name = [each.value]传递的是对象而非字符串,完全不符合模块变量的类型要求。

正确配置方案

第一步:扁平化数据结构

先将嵌套的子OU数组展开,生成每个子OU对应的父-子关系条目,确保每个模块实例对应一个单独的AWS OU:

locals {
  l3_crm = [
    { parent: "crm", child: ["crm-sap", "crm-sf"] },
    { parent: "fin", child: ["fin-mon"] },
  ]

  # 扁平化数据,拆分出每个子OU的独立条目
  flattened_l3_ous = flatten([
    for item in local.l3_crm : [
      for child_ou in item.child : {
        parent_name = item.parent
        ou_name     = child_ou
      }
    ]
  ])

  # 转换为for_each所需的映射结构,用"父OU-子OU"作为唯一键
  l3_ous_map = {
    for ou in local.flattened_l3_ous : "${ou.parent_name}-${ou.ou_name}" => ou
  }
}

第二步:正确调用模块

module "l3_crm" {
  source = "./modules/ou"
  # 使用扁平化后的映射,每个实例对应一个子OU
  for_each   = local.l3_ous_map
  # 直接传递字符串类型的子OU名称
  ou_name    = each.value.ou_name
  # 通过parent_name匹配module.l2中的父OU ID
  parent_id  = module.l2[each.value.parent_name].ou_ids[0]
  depends_on = [module.l2]
  ou_tags    = var.l2_ou_tags
}

关键修正点

  • 扁平化数据:将一组子OU拆分为单个条目,符合Terraform每个模块实例对应一个资源的最佳实践。
  • for_each键:采用父OU-子OU的组合键,确保键在apply前可预测,避免索引导致的歧义。
  • 属性调用:用each.value.parent_name正确获取父OU名称,替代错误的索引属性调用。
  • 变量传递:直接传递字符串类型的子OU名称,匹配模块变量的类型要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 08:01:28