使用Terraform locals+for_each调用安全组模块时ingress参数报错如何解决
Terraform批量创建安全组问题解答
需求可行性
该需求完全可以实现,属于Terraform基于for_each批量创建同类型资源的标准用法,你最初的设计思路是正确的。
报错原因
你收到的报错由模块调用时的语法错误导致:each.value.ingress_with_cidr_blocks是你在local中预先定义好的、包含2条规则的数组(tuple类型),你试图直接访问each.value.ingress_with_cidr_blocks.from_port,数组本身不存在from_port属性,只有数组内的单个对象才有该属性,因此触发类型不匹配报错。
同时你不需要手动重写ingress_with_cidr_blocks的参数值,你local中定义的规则结构完全符合模块参数要求,直接透传即可。
修复方案
1. 可选优化:修正local变量的小瑕疵
你local定义中第二条规则的cidr_blocks为字符串类型,模块要求该字段为数组,建议提前修正避免后续警告:
locals { aws_security_group = { "sg-test1" = { name = "test1" description = "test1" vpc_id = var.vpc_destiny ingress_cidr_blocks = ["0.0.0.0/16"] ingress_rules = ["https-443-tcp"] ingress_with_cidr_blocks = [ { description = "ingress test rules 1" protocol = "tcp" from_port = 443 to_port = 443 cidr_blocks = ["192.168.36.0/23"] }, { description = "ingress test rules 2" rule = "postgresql-tcp" cidr_blocks = ["0.0.0.0/0"] # 修正为数组格式 }, ] } # 后续新增其他安全组直接在此处添加配置即可 } }
2. 修正模块调用代码
删除手动硬写的ingress_with_cidr_blocks数组,直接透传local中定义的规则:
module "test_sg" { source = "terraform-aws-modules/security-group/aws" version = "~> 5.0" # 建议固定大版本避免兼容性问题 for_each = local.aws_security_group name = each.key description = each.value.description vpc_id = each.value.vpc_id ingress_cidr_blocks = each.value.ingress_cidr_blocks ingress_rules = each.value.ingress_rules ingress_with_cidr_blocks = each.value.ingress_with_cidr_blocks # 直接透传规则数组 }
扩展说明
后续需要新增更多安全组时,只需要在local.aws_security_group的map中新增对应key的配置即可,不需要修改模块调用代码,for_each会自动遍历所有配置完成批量创建,每个安全组的规则完全独立,互不影响。
内容的提问来源于stack exchange,提问作者Javier Bewater
相关产品推荐
相关产品推荐

