How to refer to data source instance from resource using for_each loop

I’m trying to convert some code which currently works using count to for_each (to resolve the indexing issues) and have the following problem:
How should one refer to a data_source instance generated by a for_each/count loop in the context of a resource that is also using for_each over the same set?

Consider that I have as input a map containing as key a VM identifier and as values the Management IP for that VM and the Datastore.
Eg:

CwVMs = {
  "vm0" = {
    ManagementIPv4Address = "172.25.87.82",
    Datastore             = "datastore3"
  }
}

Sample code using for_each (not working)

  variable "CwVMs" {
      type = map(object({
        ManagementIPv4Address  = string
        Datastore              = string
      }))
    }

data "vsphere_datastore" "datastore" {
  count         = length(keys(var.CwVMs))
  name          = "${var.CwVMs[count.index].Datastore}"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

resource "vsphere_virtual_machine" "dev-vm" {
  for_each = var.CwVMs
  name  = "crosswork-${each.key}"

  datastore_id     = "${data.vsphere_datastore.datastore[count.index].id}"
                                                      ^^^^^^^^^^^^^^
...
}

When using the count in the resource index instead of for_each the above works ok, but has that nasty indexing issue when changing the entries

Hi @wdec,

The most direct change to what you had before would be to also switch to using for_each for your data "vsphere_datastore" block:

data "vsphere_datastore" "datastore" {
  for_each = var.CwVMs

  name          = each.value.Datastore
  datacenter_id = data.vsphere_datacenter.dc.id
}

resource "vsphere_virtual_machine" "dev-vm" {
  for_each = var.CwVMs
  name  = "crosswork-${each.key}"

  datastore_id     = data.vsphere_datastore.datastore[each.key].id
}

If you need to continue using count for that data resource for some reason then the solution will be more involved because you’ll need to find some way to correlate the numbered data resource instances with the key-based managed resource instances.

Tried, and after correcting a few typos. Thanks.
The following explained it to me:

data.<DATA TYPE>.<NAME> is an object representing a data resource of the given data source type and name. If the resource has the count argument set, the value is a list of objects representing its instances. If the resource has the for_each argument set, the value is a map of objects representing its instances.

Hi @wdec,

I think something else must be going on here that isn’t clear from what you shared. A data resource with for_each should, just like a managed resource, appear as a mapping.

Something I glossed over in your initial comment was your note that you are converting some existing code. Did you mean by this that you’re modifying a configuration that already has existing remote objects associated with it, identified by their indexes? If so, the problem here might be with your latest state snapshot rather than with the configuration.

Would you mind running terraform state list in your existing configuration directory and sharing what it produces? That should show what objects Terraform is already tracking and help to see if we need to do some work on the state first, before updating the configuration.

(Specifically I’m going to be looking to see which resources have instances with numbered indexes, like [0], and which ones have key-based identifiers like ["vm0"].)

Ahh, I see you edited your post while I was replying to it! :smiley:

Yeah, sorry. I edited the wrong resource with the the for_each. After correcting that, it worked as you described.