Search code examples
amazon-web-servicesterraformterraform-provider-aws

For_each and count in same terraform AWS resource


I'm trying to create "aws_route" in terraform iterating over a list of route_tables with vpc_peering of another service. The other service vpc destination_cidr_block is a list.

variable "route_tables" {
  type        = set(string)
  description = "Set of route table entries eg : rt-1, rt-2 , rt-3"
}


variable "ext_service_destination_cidr_blocks"{
  type = list(string)
  description = "list of destination cidr blocks of external service, eg:[\"10.10.1.1/20\", \"10.2.10.1/10\"]"
}


resource "aws_route" "ext_service_route" {
 // iterating over route tables [ rt-1, rt-2 , rt-3 ]
  for_each = var.route_tables
  route_table_id = each.key

// Iterating over cidr list 
  count = var.ext_service_destination_cidr_blocks
  destination_cidr_block = var.ext_service_destination_cidr_blocks[count.index]
  vpc_peering_connection_id = var.ext_service_peering_connection_id
}

Here, I would like to iterate over list of destination_cidr_block. Simply put, I need a nested loop, count inside for_each. I can't have both count and for_each in the same block, is there any workaround for this? Or is there any way I can split this into two modules?


Solution

  • We can use setproduct to compute the Cartesian product of those two collections and create a map based on that. This map can be used to do for_each on it:

    resource "aws_route" "ext_service_route" {
      for_each                  = { for i, pair in tolist(setproduct(var.route_tables, var.ext_service_destination_cidr_blocks)) : "route-${i}" => { "name" : pair[0], "cidr" : pair[1] } }
      route_table_id            = each.value.name
      destination_cidr_block    = each.value.cidr
      vpc_peering_connection_id = var.ext_service_peering_connection_id
    }