Looping multiple nested lists with multiple values

Good day. Currently, I am creating a module for AWS VPC Endpoints and get the values from terraform.tfvars

terraform.tfvars

vpc_endpoint_settings = {
  VPC1 = {
    vpc_id = "vpc-111111"
    route_table_id = ["rtb-123456", "rtb-54321", "rtb-00000"]
    subnet_id = ["subnet-123456", "subnet-54321", "subnet-00000"]
  }
 VPC2 = {
    vpc_id = "vpc-222222"
    route_table_id = ["rtb-123456", "rtb-54321", "rtb-00000"]
    subnet_id = ["subnet-123456", "subnet-54321", "subnet-00000"]
  }  
}

vpc_endpoints.tf

module "vpc_endpoint" {
  source = "../modules/vpc-endpoints"

  for_each = var.vpc_endpoint_settings

  vpc_id                = each.value.vpc_id
  #route_table_id        =  each.value.route_table_id (not working)

}

modules/main.tf

resource "aws_vpc_endpoint" "s3_vpc_endpoint" {
  vpc_id             = var.vpc_id
  vpc_endpoint_type  = "Gateway"
  service_name       = "com.amazonaws.ap-northeast-1.s3"
  private_dns_enabled = false
  tags               = var.tags 
}

resource "aws_vpc_endpoint_route_table_association" "service_route_table_association_s3" {
  for_each        = toset(var.availability_zones)
  route_table_id  = var.route_table_id
  vpc_endpoint_id = aws_vpc_endpoint.s3_vpc_endpoint.id
}

modules/variables.tf

variable "vpc_id" {
  description = "The VPC Id of which the VPC Endpoint will be located"
  type        = string
}

variable "availability_zones" {
  type        = list(string)
  description = "The Availability Zones in the region"
  default     = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
}

variable "route_table_id" {
  type        = list(string)
  description = "The Route Tables Used for Gateway VPC Endpoints"
  default     = []
}

Currently, I am able to loop in the map created to get the VPC IDs since it is only 1 value. But for route_table_ids, I come with the same error in which says the following:

β”‚ Error: Incorrect attribute value type
β”‚
β”‚   on ../modules/site/vpc-endpoints/main.tf line 131, in resource "aws_vpc_endpoint_route_table_association" "service_route_table_association_dynamo_db":
β”‚  131:   route_table_id  = var.route_table_id
β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚     β”‚ var.route_table_id is a list of string, known only after apply
β”‚
β”‚ Inappropriate value for attribute "route_table_id": string require

I’ve also tried different solutions like using flatten() to be able to have multiple values as well and I also plan to add subnet_id in my module sooner or late for other VPC Endpoints in the future.

May I ask if there is any other better way to create this?

I know very little about AWS, but something seems wrong here, since you’re not referencing each anywhere in your resource block that has a for_each.

Perhaps you want:

resource "aws_vpc_endpoint_route_table_association" "service_route_table_association_s3" {
  for_each        = toset(var.route_table_id)
  route_table_id  = each.key
  vpc_endpoint_id = aws_vpc_endpoint.s3_vpc_endpoint.id
}

?

1 Like

Thanks, it worked! I also changed my method when call thing the list of objects.