How to filter aws subnets in terraform

Viewed 3236

I am porting a custom made deployment infrastructure to terraform. In that custom codebase there is something that says - fetch all available subnets from default region vpc but only those that have 20 or more available IPv4 addresses.

So I was experimenting with this code

data "aws_vpc" "main" {
  default = true
}

data "aws_subnets" "vpcsubnets" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.main.id]
  }
  filter {
    name   = "default-for-az"
    values = [true]
  }
  filter {
    name   = "state"
    values = ["available"]
  }
}

output "ids2" {
  value = {
    for k, v in data.aws_subnets.vpcsubnets : k => v if v.available_ip_address_count > 20
  }
}

But I get errors like these

 Error: Invalid reference
│ 
│   on main.tf line 51, in output "ids2":
│   51:     for k, vid in data.aws_subnets.vpcsubnets : k => v if v.available_ip_address_count > 20
│ 
│ A reference to a resource type must be followed by at least one attribute access, specifying the resource name.

Using Terraform 1.0.8 and aws provider 3.62

2 Answers

You need an extra intermediary step here. The full list of available subnets is available in the attribute data.aws_subnets.vpcsubnets.ids, but the attribute available_ip_address_count will only be available from the aws_subnet data. You need to retrieve that information for each available subnet in an intermediary data:

data "aws_subnet" "vpcsubnet" {
  for_each = toset(data.aws_subnets.vpcsubnets.ids)

  id = each.value
}

Now the attribute is available in the namespace data.aws_subnet.vpcsubnet["<id>"].available_ip_address_count. You can easily make a small update to your output for this:

output "ids2" {
  value = {
    for id, attributes in data.aws_subnet.vpcsubnet : id => attributes if attributes.available_ip_address_count > 20
  }
}

where I also renamed the temporary lambda variables for clarity.

This works

data "aws_vpc" "main" {
  default = true
}

data "aws_subnets" "vpcsubnets" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.main.id]
  }
  filter {
    name   = "default-for-az"
    values = [true]
  }
  filter {
    name   = "state"
    values = ["available"]
  }
}

data "aws_subnet" "vpcsubnet" {
  for_each = { for index, subnetid in data.aws_subnets.vpcsubnets.ids : index => subnetid }
  id       = each.value
}

output "ids2" {
  value = [
    for v in data.aws_subnet.vpcsubnet : v if v.available_ip_address_count > 20
  ]
}
Related