Search code examples
terraform

How to run this terraform nested for loop?


I've been trying to make this work, but just can't figure it out. Can you please help? It should iterate over the private and public route, but also over the cidr_blocks for each type of route.

locals {
  routes = {
    private = {
      route_table_ids  = module.vpc.private_route_table_ids
      cidr_blocks      = ["10.1.0.0/16", "10.2.0.0/16", "10.5.0.0/16"]
    }
    public = {
      route_table_ids  = module.vpc.public_route_table_ids
      cidr_blocks      = ["10.1.0.0/16", "10.2.0.0/16", "10.5.0.0/16"]
    }
  }
}

resource "aws_route" "vpc_route" {
  for_each = {
    for route in local.routes :
      for cidr in route.cidr_blocks : "${route}-${cidr}" => {
        route_table_id         = route.route_table_ids
        destination_cidr_block = cidr
      }
  }

  route_table_id         = each.value.route_table_id
  destination_cidr_block = each.value.destination_cidr_block
  gateway_id             = module.vpc.vgw_id
}

The error I get here is:

╷
│ Error: Invalid 'for' expression
│ 
│   on routes.tf line 17, in resource "aws_route" "vpc_meta_route":
│   15:   for_each = {
│   16:     for route in local.routes :
│   17:       for cidr in route.cidr_blocks : "${route}-${cidr}" => {
│   18:         route_table_id         = route.route_table_ids
│   19:         destination_cidr_block = cidr
│   20:       }
│   21:   }
│ 
│ Key expression is required when building an object.
╵
╷
│ Error: Invalid 'for' expression
│ 
│   on routes.tf line 17, in resource "aws_route" "vpc_meta_route":
│   15:   for_each = {
│   16:     for route in local.routes :
│   17:       for cidr in route.cidr_blocks : "${route}-${cidr}" => {
│ 
│ Extra characters after the end of the 'for' expression.
╵
FAIL

Solution

  • I ended up changing it to this, which worked fine.

    locals {
      route_table_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids)
      cidr_blocks     = ["10.1.0.0/16", "10.2.0.0/16", "10.5.0.0/16"]
    }
    
    resource "aws_route" "vpc_meta_route" {
      for_each = {
        for pair in setproduct(local.route_table_ids, local.cidr_blocks) :
        "${pair[0]}-${pair[1]}" => {
          route_table_id         = pair[0]
          destination_cidr_block = pair[1]
        }
      }
    
      route_table_id         = each.value.route_table_id
      destination_cidr_block = each.value.destination_cidr_block
      gateway_id             = module.vpc.vgw_id
    }