Search code examples
terraformterraform-provider

Terraform dynamic/conditional resource creation


I'm using terraform with the libvirt provider and generate 4 guests (index: 0,1,2,3) using this snippet:

[...]
resource "libvirt_domain" "worker" {
    count   = var.worker["count"]
    name    = "${var.cluster_id}-worker-${count.index}"
    memory  = var.worker.memory
    vcpu    = var.worker.vcpu

    coreos_ignition = libvirt_ignition.worker[count.index].id

    disk {
        volume_id = libvirt_volume.worker[count.index].id
    }
    console {
        type        = "pty"
        target_port = 0
    }
    cpu = {
        mode = var.cpu_mode
    }
    network_interface {
        network_id  = var.network_id
        hostname    = "worker-${count.index}.${var.cluster_id}.${var.cluster_domain}"
        mac         = var.worker_macs[count.index]
    }
}
[...]

Now I want to add a conditional statement, that the first two workers get GPUs assigned. So in python pseudo code sth. like

if ${count.index} == 0:
    # Add GPU 0 to worker ${count.index} (--> worker0)
elif ${count.index} == 1:
    # Add GPU 1 to worker ${count.index} (--> worker1)
else:
    # Don't assign a GPU to a worker

From the libvirt provider documentation I saw that I have to use XML and xslt which I already checked with a simpler script and that works.

Now I tried it in this more complex setup with conditional statements as well as dynamic blocks but I cannot get it working. Currently it looks like this:

resource "libvirt_domain" "worker" {
    count   = var.worker["count"]
    name    = "${var.cluster_id}-worker-${count.index}"
    memory  = var.worker.memory
    vcpu    = var.worker.vcpu

    coreos_ignition = libvirt_ignition.worker[count.index].id

    disk {
        volume_id = libvirt_volume.worker[count.index].id
    }
    console {
        type        = "pty"
        target_port = 0
    }
    cpu = {
        mode = var.cpu_mode
    }
    network_interface {
        network_id  = var.network_id
        hostname    = "worker-${count.index}.${var.cluster_id}.${var.cluster_domain}"
        mac         = var.worker_macs[count.index]
    }

    dynamic "xml" {
        for_each = var.worker
        content {
            xslt = file("add_gpu_w${count.index}.xsl")
        }
    }
}

I feel like dynamic blocks might be the wrong approach because it is looping through all workers, but I also didn't get it working with the conditional statement appraoch.

Any help is appreciated - thanks!


Solution

  • This is certainly an interesting case, and yes I think the the dynamic block can do what you need we just need a condition there, something like:

      dynamic "xml" {
        for_each = count.index < 2 ? ["1"]: []
        content {
          xslt = file("add_gpu_w${count.index}.xsl")
        }
      }
    

    The key on that code is:
    count.index < 2 ? ["1"]: []

    Just a condition on the index, for 0 and 1 we give an array with one element inside, everything else gets an empty array, that should bypass the assignment of the GPU.