Home > Mobile >  Terraform loop over subnet ids
Terraform loop over subnet ids

Time:08-22

I have a VPC module which creates private subnets

resource "aws_subnet" "private" {
  for_each          = { for index, az_name in local.az_names : index => az_name }
  vpc_id            = aws_vpc.network.id
  cidr_block        = cidrsubnet(aws_vpc.network.cidr_block, 8, each.key   11)
  availability_zone = local.az_names[each.key]
  tags = {
    Name        = "${var.env}-private-${local.az_names[each.key]}"
    Description = local.az_names[each.key]
    Type = "private"
  }
}

And an output

output "private_subnet" {
  value = aws_subnet.private
}

Now I am trying to create an EFS module which will create a mount target for each private subnet

resource "aws_efs_mount_target" "efs-mt" {
  count = length(var.private_subnet)
  file_system_id  = aws_efs_file_system.efs.id
  subnet_id = var.private_subnet[count.index].id
  security_groups = var.security_groups
}

main.tf

module "efs" {
  source              = "./modules/efs"
  env                 = var.env
  vpc_id           = module.vpc.vpc_id
  security_groups = [module.security.efs_sg_ids]
  private_subnet = module.vpc.private_subnet
}

But I am getting these errors

│ Error: Invalid index
│ 
│   on modules/efs/main.tf line 14, in resource "aws_efs_mount_target" "efs-mt":
│   14:   subnet_id = var.private_subnet[count.index].id
│     ├────────────────
│     │ count.index is a number, known only after apply
│     │ var.private_subnet is a string, known only after apply
│ 
│ This value does not have any indices.

CodePudding user response:

You are mixing count and for_each meta-arguments which is not a good idea. To fix that, you could do the following:

  1. Leave the count meta-argument in the EFS resource but change the output of the VPC module
  2. Use for_each with the EFS module as well

Even though I would suggest the second approach, I will provide both options. In the output in the VPC module, you can switch to:

output "private_subnet" {
  value = values(aws_subnet.private)[*].id
}

The values built-in function [1] will return a list of subnet IDs which you can then use as the intended input for the EFS module. In this case, you would have to change the module input variable type from string to list(string):

variable "private_subnet" {
  type        = list(string)
  description = "List of subnet IDs."
} 

On the other hand, you could try switching the EFS resource to use for_each instead of count and passing it the output value of the VPC module the way it currently is:

resource "aws_efs_mount_target" "efs-mt" {
  for_each        = var.private_subnet
  file_system_id  = aws_efs_file_system.efs.id
  subnet_id       = each.value.id
  security_groups = var.security_groups
}

In this case, you would have to change the module input variable type from string to map(any):

variable "private_subnet" {
  type        = map(any)
  description = "Map of all the values returned by the subnet resource."
} 

[1] https://www.terraform.io/language/functions/values

  • Related