Hi @vmorkunas,
Routing table ids are not good candidates to use as identifiers for instances in for_each
because those ids cannot be predicted during planning: the remote system allocates them only during actual creation.
When working with for_each
we must use keys built from values that are chosen in the configuration, not in the remote system. With what you’ve shared here I’m not sure exactly what values to suggest, but if your module "extapp_vpc"
has some argument that somehow specifies where to create route tables – perhaps a set of availability zone names? – then I’d make that private_route_table_ids
output instead be a map from whatever name the caller specified to the chosen ids.
Then you can use the keys from that map to identify your route instances, instead of the route table ids:
for_each = {
for rt_key, rt_id in var.routing.src_rt_ids :
format("%s-%s", var.routing.name, rt_key) => rt_id
if var.routing.src_provider == "aws.stack"
}
I also have a side-note based on something else in your example: it looks like you’re building this module to allow the routes to be created between objects in different AWS provider instances aws.stack
and aws.ops
, and are using duplicated resource
blocks to allow a switch between the two configurations based on an input variable.
The intended way to address that in Terraform is for your child module to declare its two proxy provider configurations (presumably you already have those for declaring aws.stack
and aws.ops
) using nomenclature that makes sense in the context of that module, such as src
and dst
in your case:
provider "aws" {
alias = "src"
}
provider "aws" {
alias = "dst"
}
Then in the calling module you can pass whichever provider configuration makes sense for each one, and remove the extra src_provider
and dst_provider
input variables and associated duplication in the module:
module "routing_extapp_data" {
source = "../../modules/Stack/Routing"
routing = {
src_rt_ids = module.extapp_vpc.private_route_table_ids
dst_rt_ids = module.data_vpc.private_route_table_ids
src_cidr = module.extapp_vpc.vpc.cidr_block
dst_cidr = module.data_vpc.vpc.cidr_block
peering_connection_id = module.peering_extapp_data.peering_connection_ids
name = "extapp-data"
}
providers = {
aws.src = aws.stack
aws.dst = aws.stack
}
}
In the above case, both aws.src
and aws.dst
should be pointed to aws.stack
in the calling module, getting the desired effect. A different instance of this module could set them both to aws.ops
instead, or set one to aws.stack
and the other to aws.ops
to route between them.
Your resource block for “src”'s route can then refer to aws.src
:
resource "aws_route" "src" {
provider = aws.src
for_each = {
for rt_key, rt_id in var.routing.src_rt_ids :
format("%s-%s", var.routing.name, rt_key) => rt_id
}
# (and all the other arguments as before)
}