简体   繁体   中英

Accessing for_each variables of type list(object) from a module

I've created a module which does port-forwarding for VM's and theres a variable inside of type list(object) which I am having trouble referring to.

There's a main.tf file inside proxmox-instance (tree included below) with our variable inside of it. It has a for_each loop and I am trying to use the objects inside the variable loop of./proxmox-instance/main.tf on a different directry - the. directory inside./main.tf.

.
├── main.tf
├── output.tf
└── proxmox-instance
    ├── main.tf
    ├── output.tf
    ├── providers.tf
    └── variables.tf

I do not fully understand how the syntax works when referring variables from a different folder.

Here's the code snippet

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
  }]
}

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 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 error happens in the code section below while trying to refer to

forwarded_ports.host_port forwarded_ports.guest_port

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
  forwarded_ports.guest_port = 22
}

I've tried playing with the syntax for host / guest port but couldn't fully understand it and so and kept receving errors..

Output 1/2

  forwarded_ports.host_port  = 2222
  forwarded_ports.guest_port = 22

Error: Argument or block definition required
│
│   on main.tf line 17, in module "instance":
│   17:   forwarded_ports.guest_port = 22
│
│ An argument or block definition is required here. To set an argument, use the equals sign "=" to introduce the argument value.

Output 2/2

 forwarded_ports = [{
    host_port  = 2222
    guest_port = 22
  }]

│ Error: Missing required argument
│
│   on main.tf line 5, in module "instance":
│    5: module "instance" {
│
│ The argument "host_port" is required, but no definition was found.

│ Error: Missing required argument
│
│   on main.tf line 5, in module "instance":
│    5: module "instance" {
│
│ The argument "guest_port" is required, but no definition was found.

In my opinion, at least two things are wrong [could be more because of missing code I can not commit]

1: In your ./proxmox-instance/main.tf the for_each = [for k in forwarded_ports: k] needs to refer to a variable defined in terraform.

Correct Reference:

resource "iptables_nat" "dnat-front" {
  # Creates an entry for each template specified
  for_each = [for k in var.forwarded_ports : k] ## change is ** var.forwarded_ports **

  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
  }
}

[for k in var.forwarded_ports: k] will give you following tuple on which you have work in your module interface call.

[
  {
    "guest_port" = 22
    "host_port" = 2222
  },
]

you can verify this in terraform console. More Details on Terraform Console at here

2: Your module interface call is also wrong, the error message An argument or block definition is required here. To set an argument, use the equals sign "=" to introduce the argument value. An argument or block definition is required here. To set an argument, use the equals sign "=" to introduce the argument value. is complaining about the forwarded_ports.host_port = 2222 and forwarded_ports.guest_port = 22 .

As the code snippet pasted is not complete here, seems like a few other variables and resources are missing. Please try to use something like

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"

  ## module will refer to the variables and then pass them in the correct type.
  forwarded_ports = [
    {
      host_port = 2222
      guest_port = 22
    },
    {
      host_port = another_value
      guest_port = another_value
    },
  ]
}

I hope this helps.

When using an object in a variable, you have to define it in much the same way that your default is used within the module.

The first error you get explains it best:

Error: Argument or block definition required
│
│   on main.tf line 17, in module "instance":
│   17:   forwarded_ports.guest_port = 22
│
│ An argument or block definition is required here. To set an argument, use the equals sign "=" to introduce the argument value.

To reference the forwarded_ports variable in your module, you should pass it as an argument to the module.

Here is the correct syntax:

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
  }]
}

variables inside of modules are inputs in the module block. Any variable that does NOT contain a default is required, and those that contain a default are optional.

The second error from Output 2/2 :

│ Error: Missing required argument
│
│   on main.tf line 5, in module "instance":
│    5: module "instance" {
│
│ The argument "host_port" is required, but no definition was found.

Indicates that there are additional variables named host_port and guest_port that are unrelated to the forwarded_ports variable and are apparently required. Your code isn't showing this, but I suspect you'll find both of these in your module variables.tf file. The likely reason you're seeing this error is because you're correctly defining forwarded_ports in that example, but missing other unrelated arguments with names that are confusing you.

To understand more about module inputs, see Terraform's documentation on Input Variables .

./proxmox-instance/main.tf

resource "iptables_nat" "dnat-front" {
  # Creates an entry for each template specified
  for_each = [for k in forwarded_ports : k]
...

This should be var.forwarded_ports and should look something like this:

resource "iptables_nat" "dnat-front" {
  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     
    nat_ip   = "${proxmox_vm_qemu.vm.default_ipv4_address}:${each.value.guest_port}" # VM Internal IP here
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM