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

在主目录通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 22:40:37