如何在Terraform的for_each中从映射列表获取子项及对应父项信息
问题:Terraform中通过for_each遍历子项并关联父项信息
本地映射结构
locals { l4_rnd = [ { parent = "crm", child = ["crm-sap", "crm-sf"] }, { parent = "fin", child = ["fin-mon"] }, ] }
需求
遍历每个child子项,同时获取该子项对应的parent信息,在for_each中实现每个子项对应一个模块实例,且能传递父项参数。
尝试的代码及错误
尝试的代码:
module "l4_rnd" { source = "./modules/ou" for_each = toset([local.l4_rnd]) ou_name = [each.value] parent_id = "ou-alft-pt1bfaa9" depends_on = [module.l3_rnd] ou_tags = var.l2_ou_tags }
出现的错误:
│ Error: Invalid for_each set argument │ │ on main.tf line 43, in module "l4_rnd": │ 43: for_each = toset([local.l4_rnd]) │ ├──────────────── │ │ local.l4_rnd is tuple with 2 elements │ │ The given "for_each" argument value is unsuitable: "for_each" supports maps and sets of strings, but you have provided a set containing type tuple.
解决方案
1. 扁平化本地变量结构
首先将嵌套的parent-child结构扁平化,生成每个子项带对应父项的一维列表:
locals { l4_rnd_flattened = flatten([ for parent_item in local.l4_rnd : [ for child in parent_item.child : { parent = parent_item.parent child = child } ] ]) }
这段代码的作用是:遍历每个父项对象,再遍历该父项下的所有子项,为每个子项生成包含父项名称和子项名称的对象,最后用flatten将嵌套列表转为一维列表。
2. 构建for_each可用的Map
将扁平化后的列表转为Map(以子项名称作为唯一键,确保每个模块实例的键唯一):
for_each = { for item in local.l4_rnd_flattened : item.child => item }
3. 修正后的模块调用代码
module "l4_rnd" { source = "./modules/ou" for_each = { for item in local.l4_rnd_flattened : item.child => item } ou_name = each.value.child # 传递子项名称 parent_id = "ou-alft-pt1bfaa9" # 如果需要根据父项名称动态获取ID,可改为类似 module.l3_rnd[each.value.parent].id depends_on = [module.l3_rnd] ou_tags = var.l2_ou_tags }
错误原因说明
原代码中toset([local.l4_rnd])将整个包含复杂对象的元组放入Set中,而Terraform的for_each仅支持字符串类型的Set,或键为字符串的Map。通过扁平化结构并转为Map,就能满足for_each的参数要求,同时实现子项与父项的关联。
内容的提问来源于stack exchange,提问作者Felixrobin antony
相关产品推荐
相关产品推荐

