Hi @tluv2006,
When working with for_each
our task is to construct a collection that has one element for each of the instances we want to create. In your case, it seems like you want three instances per each element in your collection. A different way to say that is that you want one instance for each unique combination of elements from local.zone
and elements from the sequence [0, 1, 2]
.
We can construct a sequence like [0, 1, 2]
using the range
function:
> range(3)
[0, 1, 2]
To combine that with your set of zones we can use nested for
expressions along with flatten
so that the result is just a flat list, rather than a list of lists:
locals {
# (I renamed the zones to letters so that they'd
# be more distinct from the instance indices.)
zones = ["a", "b", "c"]
instance_idxs = range(var.itemcount)
instances = flatten([
for z in local.zones : [
for i in local.instance_idxs : {
zone = z
index = i
}
]
])
}
The local.instances
value will now look something like this:
[
{ zone = "a", index = 0 },
{ zone = "a", index = 1 },
{ zone = "a", index = 2 },
{ zone = "b", index = 0 },
{ zone = "b", index = 1 },
{ zone = "b", index = 2 },
{ zone = "c", index = 0 },
{ zone = "c", index = 1 },
{ zone = "c", index = 2 },
]
That list contains one element per instance of azurerm_windows_virtual_machine
you want to create, so all that remains is to project that into a map in the for_each
expression so that the map keys can be used to track each individual instance:
resource "azurerm_windows_virtual_machine" "main" {
for_each = { for inst in local.instances : "${i.zone}_${i.index}" => i }
name = "example_${each.key}"
zone = each.value.zone
# ...
}
The above tells Terraform to track these instances using addresses like this:
azurerm_windows_virtual_machine.main["a_0"]
azurerm_windows_virtual_machine.main["a_1"]
azurerm_windows_virtual_machine.main["a_2"]
azurerm_windows_virtual_machine.main["b_0"]
azurerm_windows_virtual_machine.main["b_1"]
- …
This means that if you add a new item d
to local.zones
, Terraform will understand that as a request to create three new instances and leave the others undisturbed:
azurerm_windows_virtual_machine.main["d_0"]
azurerm_windows_virtual_machine.main["d_1"]
azurerm_windows_virtual_machine.main["d_2"]
…and if you decrease var.itemcount
to 2 then Terraform will understand that as a request to delete all of the ones with index 2, leaving indices 0 and 1 intact:
azurerm_windows_virtual_machine.main["a_2"]
azurerm_windows_virtual_machine.main["b_2"]
azurerm_windows_virtual_machine.main["c_2"]
azurerm_windows_virtual_machine.main["d_2"]
For this reason, it’s important to ensure that the keys in the for_each
map capture your intended unique identifier for each instance: Terraform will use the keys to understand how to interpret a change to the input as a planned change to the remote objects you’re managing with Terraform.