Terraform: using dynamic blocks to add multiple disks on a vsphere_virtual_machine

If the Terraform resource you are creating supports multiple dependent entities (e.g. a single VM with multiple disks or networks), but only by adding hardcoded duplicate text blocks, then you should consider Terraform dynamic blocks.

For example, if you are creating a vsphere_virtual_machine with two additional data disks, then here is a snippet showing how you must explicitly type out 2 additional “disk” blocks.  Unfortunately, you are unable to use “for_each” or “count” to express a generic number of data disks.

resource "vsphere_virtual_machine" "vm" {
name = "mytestvm1"

# first boot disk
disk {
  label       = "disk0"
  unit_number = 0
  size        = 40
}
# second and third data disk
disk { 
  label = "disk1"
  unit_number = 1
  size = 10
}
disk {
  label = "disk2"
  unit_number = 2
  size=20
}

Dynamic blocks provide the syntactic sugar that allows you to express a variable block of text within a resource without hardcoding “N” number of blocks.  Below is how you can express a variable number of data disks on a VM resource.

locals {
  # flexible number of data disks for VM
  disks = [
    { "id":1, "dev":"sdb", "sizeGB":10 },
    { "id":2, "dev":"sdc", "sizeGB":20  }
  ]
}

resource "vsphere_virtual_machine" "vm" {
name = "mytestvm1"

# first boot disk 
disk { 
  label = "disk0" 
  unit_number = 0
  size = 40 
} 

# creates variable number of data disks for VM
dynamic "disk" {
  for_each = [ for disk in local.disks: disk ]

  content {
   label       = "disk${disk.value.id}"
   unit_number = disk.value.id
   size        = disk.value.sizeGB
  }
}

I’m using a local variable construct to create a list to iterate over, but you could use a regular variable or data just as easily.  In fact, the for_each is even more permissive in this inside context and will accept lists as well as sets.

  for_each = [ for disk in local.disks: disk ]

By default, the iterator name is not “each” and is instead the name of the dynamic block, “disk” in our case.

Summary

The use of dynamic blocks can greatly simply the expression of a variable number of blocks in a resource, and help you avoid hardcoded variants.

Here is a link to a full example of creating a vsphere vm with a variable number of data disks using dynamic blocks.

 

REFERENCES

terraform, dynamic blocks

vsphere_virtual_machine spec

count meta-argument

https://github.com/ewypych/terraform-vsphere-single-vm-disk

https://discuss.hashicorp.com/t/dynamic-blocks-involving-data-sources/1695

https://github.com/hashicorp/terraform-provider-vsphere/issues/415

https://unix.stackexchange.com/questions/200582/scripteable-gpt-partitions-using-parted