For Each Iteration, with list of strings

Hello, again. I’ve created a route table however routes it self assigning only to the first route table, while I have 3 of them (The length of Availability zones).

So aws_route_table has been created with count and the aws_route with for_each
Now when I’m trying to assign route_table_id from aws_route_table it takes only 1st id is there any way to map properly?

Here is my code:

resource "aws_route_table" "public"              {
   count  = length(local.routing.public.ipvf)
   vpc_id = lookup(var.parameters[0], "network", "")
   tags   = var.tag_map
}

resource "aws_route" "public_ipv4"         {
   for_each                  = { for idx, route in local.routing.public : idx => route }
   route_table_id            = element([ for key, value in aws_route_table.public : value.id ], each.key) << Here is the problem
 
   gateway_id.               = lookup(each.value, "internet",  "" )
   instance_id               = lookup(each.value, "instance",  "" )
   nat_gateway_id            = element(concat(compact(split(",", lookup(each.value, "nat", ""))), [""]), each.key)
   vpc_endpoint_id           = lookup(each.value, "endpoint",  "" )
   local_gateway_id          = lookup(each.value, "local",     "" )
   transit_gateway_id        = lookup(each.value, "transit",   "" )
   network_interface_id      = lookup(each.value, "interface", "" )
   vpc_peering_connection_id = lookup(each.value, "peering",   "" )
   destination_cidr_block    = lookup(each.value, "cidrblock", "" )
}

locals {
   routing  = {
     public  = [
       { 
         name      = "Public Route Table IPv4 - With ${local.network.gateway.name[0].internet}"
         nat       =  module.gateways.nat_ids
         cidrblock = "120.0.10.0/0"
       }
     ]
}

As said already the code is working, but route_table_id assigning only 1st id of route table
Here is the proof of, that other resources are exists

  + nat_list = [
      + "nat-0980ffedd5471b76d",
      + "nat-053701e207f6e92b2",
      + "nat-0be06d45baf164edc",
    ]

  + subnets  = [
      + "subnet-04c920f8908d7e502",
      + "subnet-0e9e9333180cab627",
      + "subnet-0caae55b544e4b63d",
    ]

Public Subnet · 10.0.16.0/24 | EU-WEST-1A
Public Subnet · 10.0.32.0/24 | EU-WEST-1B
Public Subnet · 10.0.48.0/24 | EU-WEST-1C

Public Route · 10.0.16.0/24 | EU-WEST-1A
Public Route · 10.0.32.0/24 | EU-WEST-1B
Public Route · 10.0.48.0/24 | EU-WEST-1C

NAT Gateway · 10.0.16.0/24 | EU-WEST-1A
NAT Gateway · 10.0.32.0/24 | EU-WEST-1B
NAT Gateway · 10.0.48.0/24 | EU-WEST-1C

Hi @unity-unity,

as per my understanding the loop has to be enriched with AZ information / index. What do you want to use a index within the route resource?

So a start for doing so could be (code fragments are a bit limiting to test):

locals {
   azs = ["abc1", "abc2", "abc3"]
   routing  = {
     public  = [
       { 
         name      = "Public Route Table IPv4 - "
         nat       =  "nat-123456"
         cidrblock = "120.0.10.0/24"
       }
     ]
   }
  azs_routing = { for id in range(0,length(local.azs) ) : id => { for idx, route in local.routing.public : idx => route } }
}

output azs_routing {
  value = local.azs_routing
}

resource "aws_route_table" "public" {
   count  = length(local.azs)
   vpc_id = "123456"
}


resource "aws_route" "public_ipv4_new"         {
   for_each                  = local.azs_routing
   route_table_id            = each.key #element([ for key, value in aws_route_table.public : value.id ], each.key) #<< Here is the problem

   gateway_id                = lookup(each.value[0], "internet",  "" )
   instance_id               = lookup(each.value[0], "instance",  "" )
   nat_gateway_id            = element(concat(compact(split(",", lookup(each.value[0], "nat", ""))), [""]), each.key)
   vpc_endpoint_id           = lookup(each.value[0], "endpoint",  "" )
   local_gateway_id          = lookup(each.value[0], "local",     "" )
   transit_gateway_id        = lookup(each.value[0], "transit",   "" )
   network_interface_id      = lookup(each.value[0], "interface", "" )
   vpc_peering_connection_id = lookup(each.value[0], "peering",   "" )
   destination_cidr_block    = lookup(each.value[0], "cidrblock", "" )
}



1 Like

Most probably a data source is required to get the proper matching of subnet and AZ.

1 Like

Hello, @tbugfinder I’ve faced a new issue, Error: A valid target type is missing. It seems it does not goes through the list, somehow maybe you know why? I’ve provided proper data source for azs, it was planned without any problem, however there is no route rules

The ID of route table is missing:

  • resource “aws_route” “public_ipv4-a” {
    + hided___to__reduce__output
    + route_table_id = “0”
    + hided___to__reduce__output
    }

  • resource “aws_route” “public_ipv4-b” {
    + hided___to__reduce__output
    + route_table_id = “1”
    + hided___to__reduce__output
    }

  • resource “aws_route” “public_ipv4-c” {
    + hided___to__reduce__output
    + route_table_id = “2”
    + hided___to__reduce__output
    }

However it was fixed by adding

route_table_id = aws_route_table.public[each.key].id

But the error is same Error: A valid target type is missing.

The issue also fixed, by adding lookup(each.value[each.key], "internet", "" )

The task has been solved by @tbugfinder perfectly done, no workarounds just like I needed
Thank you again @tbugfinder