Home > Net >  Attach each EIP to each Nat Gatway in Terraform
Attach each EIP to each Nat Gatway in Terraform

Time:05-24

I'm creating two public subnets that will each contain a nat gateay. My code, attempts to create these nats per subnet, and then allocate the eip to each. However, since my for each starts the code block, it looks like the allocation id became us-east-* instead of the id of the eip.

Variables.tf:

    variable "public_subnet_numbers" {
  type = map(number)
 
  description = "Map of AZ to a number that should be used for public subnets"
 
  default = {
    "us-east-1a" = 1
    "us-east-1b" = 2
    #"us-east-1c" = 3
  }
}
 
variable "private_subnet_numbers" {
  type = map(number)
 
  description = "Map of AZ to a number that should be used for private subnets"
 
  default = {
    "us-east-1a" = 4
    "us-east-1b" = 5
    #"us-east-1c" = 6
  }
}
 
variable "vpc_cidr" {
  type        = string
  description = "The IP range to use for the VPC"
  default     = "192.168.0.0/16"
}

Main.tf:

    resource "aws_eip" "nat" {
  count = 2
  vpc = true
 
  lifecycle {
    # prevent_destroy = true
  }
 
  tags = {
    Name        = "cf-${var.infra_env}-eip"
    Project     = "cf.io"
    Environment = var.infra_env
    VPC         = aws_vpc.vpc.id
    ManagedBy   = "terraform"
    Role        = "private"
  }
}
 

resource "aws_nat_gateway" "ngw" {
  for_each = var.private_subnet_numbers
  subnet_id = each.value.id #aws_subnet.public[each.key].id
  allocation_id = aws_eip.nat[each.key].id
 
 
  tags = {
    Name        = "cf-${var.infra_env}-ngw"
    Project     = "cf.io"
    VPC         = aws_vpc.vpc.id
    Environment = var.infra_env
    ManagedBy   = "terraform"
    Role        = "private"
  }
}

Error:

    Error: Invalid index
│ 
│   on ../terraform/modules/networking/gateways.tf line 42, in resource "aws_nat_gateway" "ngw":
│   42:   allocation_id = aws_eip.nat[each.key].id
│     ├────────────────
│     │ aws_eip.nat is tuple with 2 elements
│     │ each.key is "us-east-1a"
│ 
│ The given key does not identify an element in this collection value: a number is required.
╵
╷
│ Error: Invalid index
│ 
│   on ../terraform/modules/networking/gateways.tf line 42, in resource "aws_nat_gateway" "ngw":
│   42:   allocation_id = aws_eip.nat[each.key].id
│     ├────────────────
│     │ aws_eip.nat is tuple with 2 elements
│     │ each.key is "us-east-1b"
│ 
│ The given key does not identify an element in this collection value: a number is required.

CodePudding user response:

You're mixing count and for_each. The easiest way to solve this would be to use for_each in your EIP creation as well, which makes sense because you are creating an EIP for each NAT. That would also make your code work better if you decided to add another subnet later, you wouldn't need to go in and change the count from 2 to 3.

Otherwise, you need to use the index function to convert the each value to an index number.

CodePudding user response:

As Mark B mentioned mixing the count and for_each is not recommended. In your current setup using exclusively for_each is the way to go based on the private_subnet_numbers variable.

In your aws_eip.nat resource change count to for_each

resource "aws_eip" "nat" {
  for_each = var.private_subnet_numbers
  vpc = true
}

Next in your resource aws_nat_gateway.ngw you should refer to subnet ids using each

resource "aws_nat_gateway" "ngw" {
  for_each      = var.private_subnet_numbers
  subnet_id     = aws_subnet.public[each.key].id
  ....
}

And the code as a whole for clarity

resource "aws_vpc" "vpc" {
 ... vpc configurations ...
}

resource "aws_subnet" "public" {
  for_each = var.private_subnet_numbers
  vpc_id   = aws_vpc.vpc.id
 ... subnet configurations ...
}

resource "aws_eip" "nat" {
  for_each = var.private_subnet_numbers
  vpc      = true

  lifecycle {
    # prevent_destroy = true
  }

  tags = {
    Name        = "cf-${var.infra_env}-eip"
    Project     = "cf.io"
    Environment = var.infra_env
    VPC         = aws_vpc.vpc.id
    ManagedBy   = "terraform"
    Role        = "private"
  }
}

resource "aws_nat_gateway" "ngw" {
  for_each      = var.private_subnet_numbers
  subnet_id     = aws_subnet.public[each.key].id
  allocation_id = aws_eip.nat[each.key].id


  tags = {
    Name        = "cf-${var.infra_env}-ngw"
    Project     = "cf.io"
    VPC         = aws_vpc.vpc.id
    Environment = var.infra_env
    ManagedBy   = "terraform"
    Role        = "private"
  }
}
  • Related