在主目录通过for_each引用模块的list(object)类型变量报错
解决Terraform中list(object)类型变量的for_each遍历问题
问题场景
在Terraform模块中定义了list(object)类型的forwarded_ports变量用于配置端口转发规则,尝试用for_each遍历该变量创建iptables_nat资源时,两种写法均报错:
报错1(直接使用列表)
for_each = [for k in var.forwarded_ports : k]
│ Error: Invalid for_each argument │ │ on proxmox-instance\main.tf line 37, in resource "iptables_nat" "dnat-front": │ 37: for_each = [for k in var.forwarded_ports : k] │ ├──────────────── │ │ var.forwarded_ports is list of object with 2 elements │ │ The given "for_each" argument value is unsuitable: the "for_each" argument must be a map, or set of strings, and you have provided a value of type tuple.
报错2(转换为对象集合)
for_each = toset([for k in var.forwarded_ports : k])
│ Error: Invalid for_each set argument │ │ on proxmox-instance\main.tf line 37, in resource "iptables_nat" "dnat-front": │ 37: for_each = toset([for k in var.forwarded_ports : k]) │ ├──────────────── │ │ var.forwarded_ports is list of object 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 object.
原因分析
Terraform的for_each仅支持**字符串集合(set(string))或映射(map)**类型的输入,无法直接处理对象列表或对象集合,因此两种写法都不符合要求。
解决方案
将list(object)转换为映射(map(object)),用唯一字符串作为每个对象的键。由于端口转发规则中host_port和guest_port的组合具有唯一性,可以将其拼接成字符串作为键:
修改模块中iptables_nat资源的for_each表达式:
resource "iptables_nat" "dnat-front" { for_each = { for port in var.forwarded_ports : "${port.host_port}-${port.guest_port}" => port } name = "iptable-${var.vm_name}-${each.value.host_port}-to-${each.value.guest_port}" on_cidr_blocks = ["195.201.172.34"] # Proxmox network device IP here dnat { iface = "enp7s0" protocol = "tcp" to_port = each.value.host_port nat_ip = "${proxmox_vm_qemu.vm.default_ipv4_address}:${each.value.guest_port}" } }
说明
{ for port in var.forwarded_ports : "${port.host_port}-${port.guest_port}" => port }是Terraform的for表达式,将输入列表转换为映射:- 键:由
host_port和guest_port拼接成的唯一字符串(如"2222-22") - 值:原列表中的端口对象
- 键:由
- 转换后的映射完全符合
for_each的类型要求,遍历过程中可通过each.value访问对象的host_port和guest_port属性。
内容的提问来源于stack exchange,提问作者ellie hodjayev
相关产品推荐
相关产品推荐

