How to get an object from a list of objects in Terraform?

You can't nested multiple levels of square brackets to get n levels inside a data structure. However you can use the interpolation functions to retrieve such values. In this case you'll want to use the lookup function to retrieve the value from the map which itself has been accessed with square brackets, that will look like this...

${lookup(var.objects[1], "id")}

Rowan is correct, complex data structures are difficult to work with in current versions of Terraform. However it looks like it won't be too long before we can expect better support in this area. The upcoming version 0.12 will include rich types adding improvements to lists and maps.


You get the map with id="name2" with the following expression:

var.objects[index(var.objects.*.id, "name2")]

For a quick test, run the following one-liner in terraform console:

[{id = "name1", attribute = "a"}, {id = "name2", attribute = "a,b"}, {id = "name3", attribute = "d"}][index([{id = "name1", attribute = "a"}, {id = "name2", attribute = "a,b"}, {id = "name3", attribute = "d"}].*.id, "name2")]

If you're looking to create a set of vsphere_virtual_machine resources from a list of IPs and hostnames, I might try this:

resource "vsphere_virtual_machine" "vm" {
  count = "${length(var.virtual_machine_ips)}"

  // the rest of your virtual machine config
  // such as template ID, CPUs, memory, disks...

  vapp {
    properties {
      // your vApp properties may vary based on what your template actually is.
      // these examples are for the CoreOS template.

      "guestinfo.hostname" = "${index(var.virtual_machine_hostnames, count.index)}"
      "guestinfo.interface.0.ip.0.address" = "${index(var.virtual_machine_ips, count.index)}"
    }
  }
}

(This is assuming that you are setting IP and hostname via vApp config; if not then it may look similar but put the hostname and IP addresses somewhere outside the vsphere_virtual_machine.vapp.properties block.)

Where the terraform.tfvars file might look like this:

virtual_machine_ips = ["10.0.2.2", "10.0.2.3", "10.0.2.4"]
virtual_machine_hostnames = ["banana", "pineapple", "coconut"]

This is a simpler and more idiomatic way of accomplishing what you're trying to do, since working with complex objects in Terraform interpolation syntax is not easy.

Tags:

Terraform