Reputation: 435
Context: I'm aware of the similar questions:
but I think mine is a bit different and it might be fixed by refactoring TF code since there's an additional input restriction.
My original example is very long so I came up with a minimum viable example instead:
I've got an input variable of type map
that maps all possible numbers to names:
# tfvars.terraform
all_names_by_number = {
"1" = "alex",
"3" = "james",
"5" = "ann",
"8" = "paul",
}
# main.tf
locals {
# active_names_by_number is a map as well
# but it's a subset of all_names_by_number
# all_names_by_number = {
# "3" = "james",
# "5" = "ann",
# }
active_names_by_number = people_resource.example.active_names_map
}
# Resource that depedns on active_names_by_number
resource "foo" "active_items" {
for_each = local.active_names_by_number
name = "abc-${each.key}"
location = var.location
sub_id = data.zoo.sub[each.key].id
bar {
bar_name = each.value
}
}
When I run the terraform configuration above via terraform plan
, I get:
Error: Invalid for_each argument
on main.tf line 286, in resource "foo" "active_items":
286: for_each = for_each = local.active_names_by_number
The "for_each" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the for_each depends on.
which totally makes sense since people_resource.example.active_names_map
is "initialized" in runtime from another resource (response)
locals {
active_names_by_number = people_resource.example.active_names_map
}
but given the fact that active_names_by_number
is a subset of all_names_by_number
(input variable), how can I refactor the terraform configuration to show TF that local.active_names_by_number
is bounded?
My ideas so far:
count
instead of for_each
as other answers suggest but I do need to use each.value
in my example (and I can't use all_names_by_number
to create extra resources.local.active_names_by_number
and use var.all_names_by_number
instead -- the major downside is TF will create extra resources which is pretty expensive.for
loop:# pseudocode
for name in var.all_names_by_number:
if name is in people_resource.example.active_names_map:
# create an instance of foo.active_item
Upvotes: 1
Views: 6456
Reputation: 1
I also faced the same issue, so I followed the method of splitting it into two modules which @Alex Kuzminov suggested. Thanks for that.
So Instead of using for_each
, use count and along with that use try
block.
locals {
active_names_by_number = try(people_resource.example.active_names_map, tolist(["a", "b", "c", "d"]))
}
So initial exception will be resolved while terraform apply, then while actual resource running, it will replace with the actual content instead of a,b,c,d.
I hope this helps. Thanks.
Upvotes: 0