skip to Main Content

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.

2

Answers


  1. 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. 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.

    Login or Signup to reply.
  2. 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
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search