The network module that you are going to implement has the following folder structure:
network/
│
├── vpc/
│
├── locals.tf
│
├── main.tf
│
├── outputs.tf
│
└── variables.tf
You then start building the submodules and configuration files required for the network module.
1. The network/vpc submodule is defined by the following structure:
network/
│
├── vpc/
│ │
│ ├── locals.tf
│ │
│ ├── main.tf
│ │
│ ├── outputs.tf
│ │
│ └── variables.tf
└── ...
Fill the following lines of code to network/vpc/locals.tf:
locals {
has_public_subnet = var.public_subnets != null && length(var.public_subnets) > 0
all_ips = "0.0.0.0/0"
}
Fill the following lines of code to network/vpc/variables.tf:
variable "name" {
description = "The name of the vpc"
type = string
}
variable "environment" {
description = "The environment to which the vpc delploys"
type = string
}
variable "vpc_cidr" {
description = "The cidr block of the vpc"
type = string
}
variable "azs" {
description = "The choosen azs to allocate resources in the vpc"
type = list(string)
default = []
}
variable "public_subnets" {
description = "The cidr blocks for the public subnets"
type = list(object({
cidr = string,
tier = optional(string)
}))
default = []
}
variable "public_subnet_prefix" {
description = "Prefix to append to public subnets name"
type = string
default = "public"
}
variable "private_subnets" {
description = "The cidr blocks for the private subnets"
type = list(object({
cidr = string,
tier = optional(string)
}))
default = []
}
variable "private_subnet_prefix" {
description = "Prefix to append to private subnets name"
type = string
default = "private"
}
Fill the following lines of code to network/vpc/main.tf:
#----------------------------------------------------------------------
# Vpc
#----------------------------------------------------------------------
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = var.name
}
}
#----------------------------------------------------------------------
# Internet Gateway
#----------------------------------------------------------------------
resource "aws_internet_gateway" "main" {
count = local.has_public_subnet ? 1 : 0
tags = {
Name = var.name
}
}
resource "aws_internet_gateway_attachment" "main" {
count = local.has_public_subnet ? 1 : 0
vpc_id = aws_vpc.main.id
internet_gateway_id = aws_internet_gateway.main[0].id
}
#----------------------------------------------------------------------
# Subnets
#----------------------------------------------------------------------
resource "aws_subnet" "public" {
count = length(var.public_subnets)
vpc_id = aws_vpc.main.id
availability_zone = element(var.azs, count.index)
cidr_block = var.public_subnets[count.index].cidr
map_public_ip_on_launch = true
tags = {
Name = "${var.name}-${var.public_subnet_prefix}-${element(var.azs, count.index)}"
Tier = coalesce(var.public_subnets[count.index].tier, var.public_subnet_prefix)
Type = var.public_subnet_prefix
}
}
resource "aws_subnet" "private" {
count = length(var.private_subnets)
vpc_id = aws_vpc.main.id
availability_zone = element(var.azs, count.index)
cidr_block = var.private_subnets[count.index].cidr
tags = {
Name = "${var.name}-${var.private_subnet_prefix}-${element(var.azs, count.index)}"
Tier = coalesce(var.private_subnets[count.index].tier, var.private_subnet_prefix)
Type = var.private_subnet_prefix
}
}
#----------------------------------------------------------------------
# Route Tables
#----------------------------------------------------------------------
resource "aws_route_table" "public" {
count = local.has_public_subnet ? 1 : 0
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.name}-public"
}
}
resource "aws_route" "to_igw" {
count = local.has_public_subnet ? 1 : 0
route_table_id = aws_route_table.public[0].id
destination_cidr_block = local.all_ips
gateway_id = aws_internet_gateway.main[0].id
}
resource "aws_route_table_association" "public" {
count = length(aws_subnet.public)
route_table_id = aws_route_table.public[0].id
subnet_id = aws_subnet.public[count.index].id
}
resource "aws_route_table" "private" {
count = length(var.private_subnets) / length(var.azs)
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.name}-private"
}
}
resource "aws_route_table_association" "private" {
count = length(aws_subnet.private)
route_table_id = element(aws_route_table.private[*].id, floor(length(aws_route_table.private) / length(var.azs)))
subnet_id = aws_subnet.private[count.index].id
}
Fill the following lines of code to network/vpc/outputs.tf:
output "vpc_id" {
description = "The id of the vpc"
value = aws_vpc.main.id
}
output "vpc_arn" {
description = "The arn of the vpc"
value = aws_vpc.main.arn
}
output "public_subnet_ids" {
description = "The ids of the public subnets"
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
description = "The ids of the private subnets"
value = aws_subnet.private[*].id
}
output "subnet_ids" {
description = "The ids of the subnets"
value = concat(aws_subnet.public[*].id, aws_subnet.private[*].id)
}
output "public_route_table_id" {
description = "The id of the public route table"
value = aws_route_table.public[0].id
}
2. You now implement the Terraform configuration files for network module.
Fill the following lines of code to network/variables.tf:
variable "environment" {
description = "The environment to which the network resources delploy"
type = string
default = "dev"
}
variable "project_name" {
description = "The name of the project"
type = string
}
variable "vpc_cidr" {
description = "The cidr block of the vpc"
type = string
}
variable "azs" {
description = "The choosen azs to allocate resources in the vpc"
type = list(string)
default = []
}
variable "public_subnets" {
description = "The cidr blocks for the public subnets"
type = list(object({
cidr = string,
tier = optional(string)
}))
default = []
}
variable "public_subnet_prefix" {
description = "Prefix to append to public subnets name"
type = string
default = "public"
}
variable "private_subnets" {
description = "The cidr blocks for the private subnets"
type = list(object({
cidr = string,
tier = optional(string)
}))
default = []
}
variable "private_subnet_prefix" {
description = "Prefix to append to private subnets name"
type = string
default = "private"
}
Fill the following lines of code to network/main.tf:
locals {
resource_name = "${var.environment}-${var.project_name}"
}
Fill the following lines of code to network/main.tf:
module "vpc" {
source = "./vpc"
name = local.resource_name
environment = var.environment
vpc_cidr = var.vpc_cidr
azs = var.azs
public_subnets = var.public_subnets
public_subnet_prefix = var.public_subnet_prefix
private_subnets = var.private_subnets
private_subnet_prefix = var.private_subnet_prefix
}
Fill the following lines of code to network/outputs.tf:
output "vpc_id" {
description = "The id of the vpc"
value = module.vpc.vpc_id
}
output "vpc_arn" {
description = "The arn of the vpc"
value = module.vpc.vpc_arn
}
output "public_subnet_ids" {
description = "The ids of the public subnets"
value = module.vpc.public_subnet_ids
}
output "private_subnet_ids" {
description = "The ids of the private subnets"
value = module.vpc.private_subnet_ids
}
output "subnet_ids" {
description = "The ids of the subnets"
value = module.vpc.subnet_ids
}
3. Remove the .gitkeep file.
rm .gitkeep
4. Commit and push the module to the GitHub repository.
git add . && \
git commit -m "remove .gitkeep and add network module" && \
git push