attributesterraformterraform0.12+terraform-template-fileterraform-provider

Terraform - how to use exported attributes?


I'm learning terraform, in the example below the first section puts a VM and returns the id of that VM. The second section adds an extra disk to vm. I have to enter an id in the virtual_machine_id parameter, but I don't know how (cloudstack_instance.worker[$name].id not working). Could someone have a hint?

resource "cloudstack_instance" "worker" {
  for_each = {
    for name, machine in var.machines :
    name => machine
    if machine.node_type == "worker"
  }
  name = "${var.prefix}-${each.key}"
  service_offering = "K8S-RBD"
  network_id = var.network_id
  template = var.template_id
  zone = var.zone
  project = var.project_id
  expunge = true
  group = var.prefix
  keypair = var.keypair
  tags = {
    name = "Terraform-VM"
  }
}

resource "cloudstack_disk" "worker" {
  for_each = {
    for name, machine in var.machines :
    name => machine
    if machine.node_type == "worker"
  }
  name = "${var.prefix}-${each.key}"
  attach = "true"
  disk_offering = "Custom-RBD"
  size = 50
  virtual_machine_id = cloudstack_instance.worker[$name].id
  zone = var.zone
  project = var.project_id

  depends_on = [cloudstack_instance.worker]
}


Solution

  • From your configuration it seems like your intent here is to declare one disk per virtual machine, with the disks each connected to their corresponding virtual machine.

    That situation is a good use for Chaining for_each Between Resources, which means to use an upstream resource directly as the for_each for a downstream one, and thus quite literally declare that the disks correlate with the VMs:

    resource "cloudstack_disk" "worker" {
      for_each = cloudstack_instance.worker
    
      name               = "${var.prefix}-${each.key}"
      attach             = "true"
      disk_offering      = "Custom-RBD"
      size               = 50
      virtual_machine_id = each.value.id
      zone               = var.zone
      project            = var.project_id
    }
    

    Because the cloudstack_instance resource also has for_each declared, cloudstack_instance.worker evaluates to a map from instance keys to objects. That means that in the above example each.value refers to whatever element value in cloudstack_instance.worker corresponds with the key each.key.

    I also removed the depends_on argument, because it's redundant: Terraform can already see that dependency because for_each contains a reference to that resource.