I have created a variable of type list(object) on a module directory. My goal is to call this variable under a different directory using a for_each loop. (Tree attached below)
.
├── main.tf
├── output.tf
└── proxmox-instance
├── main.tf
├── output.tf
├── providers.tf
└── variables.tf
The variable.tf file looks like this
variable "forwarded_ports" {
description = "Your Template name - Will be cloned from this template"
type = list(object({
host_port = number
guest_port = number
}))
default = [{
"host_port" = 2222,
"guest_port" = 22
}]
}
While the ./proxmox-instance/main.tf looks like this
resource "iptables_nat" "dnat-front" {
# Creates an entry for each template specified
for_each = [for k in var.forwarded_ports : k]
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 # Custom Port for ingress connections
nat_ip = "${proxmox_vm_qemu.vm.default_ipv4_address}:${each.value.guest_port}" # VM Internal IP here
}
}
The issue occurs while trying to refer the code at the forwarded_ports
section below
module "instance" {
source = "./proxmox-instance"
vm_name = "Terraform"
template_name = "ubuntu-20.04"
# cloud-init settings
ipconfig0 = "ip=dhcp"
cloud_init_user = "ubuntu"
cloud_init_password = "password"
forwarded_ports = [
{
host_port = 2222
guest_port = 22
},
{
host_port = 5555
guest_port = 22
},
]
}
I’ve tried playing with the syntax abit and got different results
Output 1/2
for_each = [for k in var.forwarded_ports : k]
│ Error: Invalid for_each argument
│
│ on proxmox-instancemain.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.
Output 2/2
for_each = toset([for k in var.forwarded_ports : k])
│ Error: Invalid for_each set argument
│
│ on proxmox-instancemain.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.
2
Answers
You are providing a variable of type
list(objects)
and you are trying to use a list withfor_each
(which error output shows you it is not possible) while it can work only with maps or sets. What you could try is the following:Alternatively, you could define a
locals
block and create the map you want there:And then in the resource block:
forwarded_ports
is a list.for_each
works with maps. You can easly convert list to map as follows: