Terraform:如何在纯数据模块中保留for_each功能?
问题
项目里有大量重复的网络数据,打算把所有子网数据迁移到独立的纯数据模块(data-only module),这样能在所有DTAP环境复用,减少重复代码。但原模块调用时配置了for_each,迁移后代码里的each.value没法引用了,直接把原代码复制到数据模块后for_each完全不生效。
带each.value的原输出示例:
output "subnets" { value = [ { group = "example-vnet" address_space = cidrsubnet(each.value, 22 - split("/", each.value)[1], 0) prefix = "24" members = [subnet data] } ] }
原模块的引用方式:
module "spoke_network_prd" { for_each = local.region_spoke_network_prd source = "../modules/spoke_network_module" subnets = # 原本这里用的是上面输出的subnets值,能直接用each.value }
怎么才能让for_each的功能继续生效?
解决方案
核心逻辑是把数据模块里依赖each.value的代码,改成通过外部参数传入,让调用它的原模块来传递each.value,而不是让数据模块自己去用each.value。具体操作分三步:
1. 重构纯数据模块
把数据模块改成接受外部传入的子网配置,不再依赖自身的for_each。示例代码:
# data-only module/main.tf variable "subnet_configs" { type = list(string) # 要是你的配置是更复杂的对象,就改成list(object({...})) description = "传入的子网CIDR列表或完整配置" } output "subnets" { value = [ for cidr in var.subnet_configs : { group = "example-vnet" address_space = cidrsubnet(cidr, 22 - split("/", cidr)[1], 0) prefix = "24" members = [subnet data] # 这里的子网数据也要改成依赖var.subnet_configs的逻辑 } ] }
2. 调整原模块的调用逻辑
在原模块(spoke_network_module)里调用数据模块时,把each.value作为参数传给数据模块的subnet_configs,原模块的for_each保留不动:
# spoke_network_module/main.tf 中调用数据模块 module "subnet_data" { source = "../modules/data-only-module" # 根据each.value的实际结构传参,如果是单个CIDR就直接传[each.value],是集合就直接传each.value subnet_configs = [each.value] } # 原模块的subnets输出直接引用数据模块的结果 output "subnets" { value = module.subnet_data.subnets }
3. 顶层调用保持不变
原来调用spoke_network_module的代码不需要改,for_each依然能正常循环,因为循环逻辑是在顶层控制的,数据模块只负责处理传入的参数:
module "spoke_network_prd" { for_each = local.region_spoke_network_prd source = "../modules/spoke_network_module" # 原模块需要的其他参数正常传递即可 }
如果你的子网配置是键值对形式的map,也可以把数据模块的subnet_configs改成map类型,调用时直接传each.value对应的整个map对象,灵活性更高。
内容的提问来源于stack exchange,提问作者TFUser123
相关产品推荐
相关产品推荐

