Hi Everyone
I am trying to do the following
- Create subnets from a data structure (based as input variable)
- Then create VPC endpoints (Gateway Load balancer Endpoints) for each subnet from above
Target Environment = AWS Terraform Version = latest
Module - subnet
data "aws_availability_zones" "available" {}
locals {
all_subnets = flatten([
for type, details in var.subnets_cidr_details : [
for cidr in details.cidr : {
type = type
index = index(details.cidr, cidr)
cidr = cidr
}
]
])
}
resource "aws_subnet" "subnets" {
for_each = {
for subnet in local.all_subnets : subnet.cidr => subnet
}
vpc_id = var.vpc_id
cidr_block = each.value.cidr
availability_zone = data.aws_availability_zones.available.names[each.value.index]
tags = {
Name = "${var.service_name}-${each.value.type}-${regex("..$", data.aws_availability_zones.available.names[each.value.index])}"
Service = each.value.type
}
Module - endpoints
resource "aws_vpc_endpoint" "main" {
for_each = var.endpoint_subnets.id
service_name = var.endpoint_service_name
subnet_ids = [each.key]
vpc_endpoint_type = "GatewayLoadBalancer"
vpc_id = var.vpc_id
}
The main.tf looks like this
module "subnets" {
depends_on = [
module.vpc_main]
source = "./modules/subnets"
service_name = var.service_name
subnets_cidr_details = var.subnets_cidr_details
vpc_id = module.vpc_main.vpc_id
}
module "endpoints" {
depends_on = [
module.endpointservice, module.subnets]
source = "./modules/endpoints"
endpoint_service_name = module.endpointservice.endpoint_service_name
vpc_id = module.vpc_main.vpc_id
endpoint_subntes = [for x in module.subnets.subnets_info: x.id if x.tags_all["Service"] == "endpoints"]
service_name = var.service_name
}
terraform.autovars
subnets_cidr_details = {
endpoints = {
cidr = ["10.0.0.11/28", "10.0.0.12/28", "10.0.0.13/28"]
},
public = {
cidr = ["10.1.2.120/28", "10.1.2.140/28", "10.1.2.150/28"]
}
}
When i run this, I get the following error “var.endpoints_subnets.id will be known only after apply
│
│ The “for_each” value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to
│ first apply only the resources that the for_each depends on.”
I understand that for_each does not for values that will be known after apply . But how do i create other resources like nats, endpoints based on number of subnets ?
One way I found is if i create the subnet and the endpoints in same module it works
For example
locals {
endpoint_subnets = flatten([
for type, details in var.endpoint_cidrs : [
for cidr in details.cidr : {
type = type
index = index(details.cidr, cidr)
cidr = cidr
}
]
])
}
resource "aws_subnet" "endpoint_subnets" {
for_each = {
for subnet in local.endpoint_subnets : subnet.cidr => subnet
}
vpc_id = var.vpc_id
cidr_block = each.value.cidr
availability_zone = data.aws_availability_zones.available.names[each.value.index]
tags = {
Name = "${var.service_name}-endpoint-${each.value.type}-${regex("..$", data.aws_availability_zones.available.names[each.value.index])}"
}
}
resource "aws_vpc_endpoint" "main" {
for_each = aws_subnet.endpoint_subnets
service_name = var.endpoint_service_name
subnet_ids = [each.key]
vpc_endpoint_type = "GatewayLoadBalancer"
vpc_id = var.vpc_id
}
This works however as you see , I need to provide separate input for each type of subnet I want to create.