I responded to a question recently with someone having trouble creating a dynamically variable number of storage devices for a Proxmox VM using the Telmate/proxmox provider:
Is there any way to turn those scsi<N> blocks into a loop or something like that? I tried dynamic, but that only works if they all have the same block type.
resource "proxmox_vm_qemu" "this" {
# […]
disks {
scsi {
scsi0 {
disk {
discard = true
format = "raw"
size = each.value.storage_size
storage = "ssd1"
}
}
scsi1 {
ignore = true
}
scsi2 {
ignore = true
}
scsi3 {
ignore = true
}
scsi4 {
ignore = true
}
scsi5 {
ignore = true
}
# […]
scsi31 {
ignore = true
}
}
[…]
}
}
Well, this is a problem with the way the provider has been written. There is a newer bpg/proxmox provider that has been written that attempts to address this, but it isn’t at 1.0, yet, and it doesn’t seem to be gaining much traction. So, I opened an issue with the original to see if it can be resolved. It not, perhaps we can draw attention to the newer provider.
Anyhow, the current resource prevents the use of dynamic blocks and requires redundant nesting with the type as a nested block, as well. Just make a generic device {} nested block with arguments for “interface” and “type”:
resource "proxmox_vm_qemu" "_" {
device {
interface = "scsi0"
type = "disk"
}
device {
interface = "scsi1"
type = "cdrom"
}
# ...
}
This allows for dynamic block and less opinionated/more reusable code:
locals {
valid_disk_interfaces = [
"ide",
"sata",
"scsi",
"virtio"
]
}
variable "device" {
default = {}
description = "Maps of devices to create for VM with the key as the interface ID."
type = map(object({
backup = optional(bool)
iso = optional(string)
storage = optional(string)
type = optional(string, "disk")
}))
validation {
condition = alltrue([
for device in keys(var.devices) :
contains(
local.valid_device_interfaces,
trim(device, "0123456789")
)
])
error_message = format(
"Invalid device interface. Valid interfaces are: '%s'",
join("', '", local.valid_device_interfaces)
)
}
}
resource "proxmox_vm_qemu" "_" {
dynamic "device" {
for_each = var.devices
content {
interface = device.key
type = device.value.type
}
}
# ...
}
Not being familiar with Proxmox, are there plans to support non-QEMU VMs? If not, why have the “_qemu” suffix on the resource?
Since this would be a major breaking change, perhaps a new proxmox_vm resource with all of this reworked and then a way to incorporate other types through arguments, if that is a possible direction.
