Tomer
Tomer

Reputation: 1

terraform list and count

I'm trying to deploy 3 vm's in proxmox with terraform but I have errors and I don't know why.


│ Error: Incorrect attribute value type
│
│   on ../resources/proxmox/main.tf line 2, in resource "proxmox_vm_qemu" "vm":
│    2:   name        = var.vm_name
│     ├────────────────
│     │ var.vm_name is a list of string
│
│ Inappropriate value for attribute "name": string required.
╵

│ Error: Incorrect attribute value type
│
│   on ../resources/proxmox/main.tf line 4, in resource "proxmox_vm_qemu" "vm":
│    4:   vmid        = var.vmid
│     ├────────────────
│     │ var.vmid is a list of number
│
│ Inappropriate value for attribute "vmid": number required.

main.tf

module "vm" {
  source                  = "../resources/proxmox"
  vm_name                 = var.vm_name
  vmid                    = var.vmid
  agent                   = 1
  vm_count                = var.vm_count
  pve_node                = "pve"
  template_name           = var.template_name
  full_clone              = true
  proxmox_api_url         = var.proxmox_api_url
  proxmox_api_user        = var.proxmox_api_user
  proxmox_api_password    = var.proxmox_api_password 
  }

variable.tf

variable "proxmox_api_url" {
  type = string
}


variable "proxmox_api_user" {
  type = string
  sensitive = true
}


variable "proxmox_api_password" {
  type = string
  sensitive = true
}


variable "vm_name" {
  type = list(string)
}


variable "vmid" {
  type = list(number)
}

variable "template_name" {
  type = string
}


variable "vm_count" {
  type = number
}

env.tfvars

proxmox_api_url      = "https://10.0.0.1:8006/api2/json"
proxmox_api_user     = "user@pve"
proxmox_api_password = "hiddenpass"


vm_name              = ["host0", "host1", "host2"]
vmid                 = [240, 241, 242]
template_name        = "ubuntu-24"
vm_count             = 3

Trying to deploy 3 ubuntu machines in Proxmox

Upvotes: -2

Views: 173

Answers (3)

Tomer
Tomer

Reputation: 1

Eventually I found an option to add count.index inside the resource and it works.

Just for example

resource "proxmox_vm_qemu" "vm" {
  name            = var.vm_name[count.index]
  vmid            = var.vmid[count.index]
  vm_state        = var.vm_state
  count           = var.vm_count
}

Upvotes: 0

Lorenzo Felletti
Lorenzo Felletti

Reputation: 563

In Terraform, each resource/module block accounts to 1 resource/module call only, unless you use either a count or a for_each to specify that you want to create N instances of that resource/module.

From my understanding of what you are trying to do, you may want to refactor the vm_name and vmid variables into something like this:

variable "vms" {
  description = "Map of vmid to VM name."
  type        = map(string)
}

Then refactor the module call block as follows (vm_count variable is not useful anymore):

module "vm" {
  source   = "../resources/proxmox"

  vms                     = var.vms
  agent                   = 1
  pve_node                = "pve"
  template_name           = var.template_name
  full_clone              = true
  proxmox_api_url         = var.proxmox_api_url
  proxmox_api_user        = var.proxmox_api_user
  proxmox_api_password    = var.proxmox_api_password 
  }

Then you need to refactor the internals of your module (which you did not share) to create the vm resource using the for_each syntax as well. E.g.:

resource "proxmox_vm_qemu" "this" {
  for_each = var.vms

  name = each.value
  vmid = each.key
  # ... all other properties
}

Change you env.tfvars to have the following:

vms = {
  240 => "host0"
  241 => "host1"
  242 => "host2" 
}

Useful docs pages


P.S. (a few suggestions): the error is in the module's main, not in the main.tf code you shared (as per the error: on ../resources/proxmox/main.tf line 2).
Also I needed to search & guess to infer the provider you used for the proxmox vm resource, it is useful if you share it in the question.

Upvotes: 1

Ross Bush
Ross Bush

Reputation: 15185

I am not sure what is going on in that module, however, if creating multiple instances with a count set to 1 is permissible then you may be able to combine the vm properties in a list and iterate that list. If there is a name for the resource, then you may want to specify that to easily identify each instance. Have not tested this but you can use it as an idea.

In variables.tf

variable "vm_list" {
    type = list(object({
      name = string,    
      id = number
  })
  )
} 

In dev.tfvar

vm_list = [
  {name = "host0",id = 240},
  {name = "host1",id = 241},
  {name = "host2",id = 242}
]

Use in resource

module "vm" {
  source                  = "../resources/proxmox"
  for_each = { for vm in var.vm_list : vm.name => vm }
  name                    = each.value.name
  vm_name                 = each.value.name
  vmid                    = each.value.id
  agent                   = 1
  vm_count                = 1
  pve_node                = "pve"
  template_name           = var.template_name
  full_clone              = true
  proxmox_api_url         = var.proxmox_api_url
  proxmox_api_user        = var.proxmox_api_user
  proxmox_api_password    = var.proxmox_api_password 
}

Upvotes: 1

Related Questions