How Do I Retrieve VPC Names Via Terraform?
Overview
At some point in your AWS and Terraform journey, you may need the names of the VPCs in a given AWS region. You’d normally look to use a data source lookup, but the name field is not exposed as an attribute for aws_vpcs
. Here’s a quick way to get those VPC names.
Lesson
You will still need to use the aws_vpcs
data source to get a list of all the VPC IDs in a given region:
data "aws_vpcs" "in_region" {}
This will give you information on the VPCs in your region based on the AWS credentials you provide to Terraform. Most notably, it will give you the VPC IDs.
You will now need to pass the list of VPC IDs to the aws_vpc
(singular) to expose more information about each VPC:
data "aws_vpc" "selected" {
for_each = toset(data.aws_vpcs.in_region.ids)
id = each.value
}
If you output the aws_vpc
data source, you will see a lot of information, most of which you don’t need. To organize and filter the output a bit more, we’ll create a map with the VPC’s name as the key
and VPC’s ID as the value
in a local variable:
locals {
vpc_map = { for vpc_id, vpc_info in data.aws_vpc.selected : vpc_info.tags["Name"] => vpc_id }
}
In the vpc_map
local variable, we’re looping over what the aws_vpc
data source returned and creating a map of key value pairs with the VPC’s Name
tag value. The =>
separates the key
from the value
and then the vpc_id
is set as the value. You can validate the map by creating an output and running terraform plan/apply:
output "vpc_map" {
value = local.vpc_map
}
NOTE:If you get an error, there’s a good chance that a VPC in your region does not have a Name
tag associated with it. To remedy this problem, either log into the AWS console or use awscli
to give each VPC in the region a proper Name
tag.
If you are just interested in a list of the VPC names, you can add another local variable called vpc_names_all
:
locals {
vpc_map = { for vpc_id, vpc_info in data.aws_vpc.selected : vpc_info.tags["Name"] => vpc_id }
vpc_names_all = [for vpc_name, vpc_id in local.vpc_map : vpc_name]
}
Notice how we’re using square brackets instead of curly brackets this time to signify that this new vpc_names_all
local variable should output a list
instead of a map
. We’re using for
again to loop through the vpc_map
local variable and just adding the VPC’s name to the list.
There may be times where you will need to exclude specific VPCs from the VPC names list. You can do this by creating another local variable list:
locals {
vpc_map = { for vpc_id, vpc_info in data.aws_vpc.selected : vpc_info.tags["Name"] => vpc_id }
vpc_names_all = [for vpc_name, vpc_id in local.vpc_map : vpc_name]
vpc_names_filtered = [for vpc_name, vpc_id in local.vpc_map : vpc_name if !contains(["default"], vpc_name)]
}
The new vpc_names_filtered
local variable is based on the vpc_names_all
local variable that we previously created with an additional if
statement. This basically says “add this vpc_name
if it isn’t in this list (["default"]
.) You can also assign a variable with a list of excluded vpc names to keep this local variable tidy. Having an option to exclude VPCs allows you to do things like de-provision/rebuild a resource in specific VPCs without disturbing other deployments.
Adding outputs for vpc_names_all
and vpc_names_filtered
should result in a terraform plan
like the one below:
Changes to Outputs:
+ vpc_map = {
+ birria = "vpc-0123456789abcdefg"
+ default = "vpc-12345678"
+ flan = "vpc-abcdefghij0123456"
}
+ vpc_names_all = [
+ "birria",
+ "default",
+ "flan",
]
+ vpc_names_filtered = [
+ "birria",
+ "flan",
]
Here is the full code from the above steps:
variables.tf
data "aws_vpcs" "in_region" {}
data "aws_vpc" "selected" {
for_each = toset(data.aws_vpcs.in_region.ids)
id = each.value
}
locals {
vpc_map = { for vpc_id, vpc_info in data.aws_vpc.selected : vpc_info.tags["Name"] => vpc_id }
vpc_names_all = [for vpc_name, vpc_id in local.vpc_map : vpc_name]
vpc_names_filtered = [for vpc_name, vpc_id in local.vpc_map : vpc_name if !contains(["default"], vpc_name)]
}
output "vpc_map" {
value = local.vpc_map
}
output "vpc_names_all" {
value = local.vpc_names_all
}
output "vpc_names_filtered" {
value = local.vpc_names_filtered
}
In Review
Ok now we have the VPC information that we need, how do we use it? You can now pass these lists to terraform modules using for_each
to simplify your deployments in a given region. If a new VPC comes online, no changes to the code needs to happen, a terraform apply
should remediate any differences. These are a couple of the benefits when it comes to working with multiple VPCs. You can also use this same exact method to pull tag information from other data source lookups where the information you need isn’t built into the AWS response.
As always, feel free to reach out on twitter via @taccoform for questions and/or feedback on this post