This repository contains a different version of VPC templates, where each VPC provisions the resources for networking such as:
- VPC (Virtual Private Cloud)
- Three Public and Private subnets
- Internet Gateway
- Nat Gateway
- Public Route Table
- Public Route Table Association
- Private Route Table
- Private Route Table Association
- Version
vpc_v_1.0is reusable template with variables, it is easy to read and great if you just started of with Terraform. Another reason for having this example I wanted to compare and show, how you can shorten your code using functions and meta-argumets. The only trick we used here is on tags section, we usedmergefunction since we don't want to repeat the same environment and project name we used locals.tf file for it, where common tags were defined, and in the resource blocks we merged the common tags with the name of the resouce which are unique.
locals.tf
locals {
common_tags = {
Environment = var.env
Project = var.project_name
}
}
vpc.tf tags
tags = merge(
local.common_tags,
{
Name = "${var.env}_vpc"
}
)
- Version
vpc_v_1.2configured with count meta-argument.
This version of VPC template is configured with count meta-argument, element, lenght, index and merge functions, for tags locals were used. When we have similar resources such as public/private subnets and public/private route table associations we can use count to avoid repeating. With one public/private subnet resource block we are able to provision three public/private subnets and instead of repeating the route table association three times we cofigured it with one resource block. In tfvars/dev.tf we used list(strings) value type for passing the values of attributes. For tags we used merge function for common_tags same as on previous example it's helpful to make your code clean and short.
variables.tf where we defined our variables.
# Subnet variables
variable "subnet_azs" {
type = list(string)
description = "The availabitily zones where terraform deploys your infra"
}
variable "pub_cidr_subnet" {
type = list(string)
description = "cird blocks for the public subnets"
}
variable "priv_cidr_subnet" {
type = list(string)
description = "cidr blocks for the private subnets"
}
tfvars/dev.tf contains values for attributes given in variables.tf
# Subnet
subnet_azs = ["us-east-1a", "us-east-1b","us-east-1c" ]
pub_cidr_subnet = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24" ]
priv_cidr_subnet = ["10.0.11.0/24", "10.0.12.0/24", "10.0.13.0/24"]
Public subnet resource block
# Public Subnets
resource "aws_subnet" "public_subnet" {
count = length(var.subnet_azs)
vpc_id = aws_vpc.my_vpc.id
cidr_block = element(var.pub_cidr_subnet, count.index)
availability_zone = element(var.subnet_azs, count.index)
tags = merge(
local.common_tags,
{
Name = "${var.env}_pub_sub_${count.index}"
}
)
}
Public Subnet Association
# Public Route Table Association
resource "aws_route_table_association" "pub_subnets" {
count = length(var.subnet_azs)
subnet_id = element(aws_subnet.public_subnet.*.id, count.index)
route_table_id = element(aws_route_table.pub_rtb.*.id, count.index)
}
Also outputs.tf file is added in this case, which will output subnets ids and cidr blocks, and vpc id.
output "vpc_id" {
value = aws_vpc.my_vpc.id
}
output "public_subnets" {
value = aws_subnet.public_subnet[*].id
}
output "private_subnets" {
value = aws_subnet.private_subnet[*].id
}
- Version
vpc_v_1.3with for_each meta-argument.
In this template we used for_each meta-argument with locals and we used key, value, merge functions, using listed above hepls us to create three subnets with one resource block and three route table association with another resource block. In this case we are working with map value type for the attribute values, although for_each can work with list and sets as well. We are passing different values for each subnet in locals.tf and for_each is looping and getting values for each subnet and generating multiple subnets as well as route table association.
locals.tf
locals {
public_subnet = {
1 = { availability_zone = "us-east-1a", cidr_block = "10.0.1.0/24" },
2 = { availability_zone = "us-east-1b", cidr_block = "10.0.2.0/24" },
3 = { availability_zone = "us-east-1c", cidr_block = "10.0.3.0/24" }
}
}
vpc.tf public subnet part
# Public Subnets
resource "aws_subnet" "public_subnet_" {
for_each = local.public_subnet
vpc_id = aws_vpc.my_vpc.id
availability_zone = each.value.availability_zone
cidr_block = each.value.cidr_block
tags = merge(
local.common_tags,
{
Name = "${var.env}_pub_sub_${each.key}"
}
)
}
vpc.tf public route table association
# Public Route Table Association
resource "aws_route_table_association" "pub_subnet" {
for_each = local.public_subnet
subnet_id = aws_subnet.public_subnet_[each.key].id
route_table_id = aws_route_table.pub_rtb.id
}
-
You can not use both
countandfor_eachin one resource or module block, it has to be one of them. -
If your instances are almost identical,
countis appropriate. If some of their arguments need distinct values that can't be directly derived from an integer, it's safer to usefor_each.
Manage Similar Resources with For Each
Manage Similar Resources with Count
Functions: element Function, length Function, index Function, merge Function, keys Function, values Function