Creating Terraform module for AWS VPC creation

Creating VPC involves a lot of steps like creating the VPC first and then creating a subnet and then routing tables and gateways. So I decided to create a module to make this process easy.

Here is the the terraform registry link:
smc181002/vpc/aws | Terraform Registry

Creating a Terraform VPC launcing module

First, we need to create a directory with a minimal file tree being:

.
├─ LICENSE
├─ main.tf
├─ outputs.tf
├─ README.md
├─ variables.tf

I have used the MIT LICENSE for this module. There are a lot other OpenSource Licenses available like the Apache 2.0.

Now lets start with the variables.tf file where the inputs for the module are defined.

variable "vpc_name" {
type = string
default = null
}
variable "vpc_cidr_block" {
type = string
validation {
condition = can(regex("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\/([0-9]|[1-2][0-9]|3[0-2]))?$", var.vpc_cidr_block))
error_message = "The VPC cidr block is an invalid network name. Choose a valid network network name."
}
}
variable "subnet_names" {
type = list(any)
default = null
}
variable "subnet_cidr_block" {
type = list(any)
validation {
condition = can([for cidr in var.subnet_cidr_block : regex("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\/([0-9]|[1-2][0-9]|3[0-2]))?$", cidr)])
error_message = "The Subnet cidr block is an invalid network name. Choose a valid network network name."
}
}
variable "gateway_name" {
type = string
default = null
}
variable "route_table_name" {
type = string
default = null
}

There are 2 required values (the vpc cidr and subnet cidr blocks). I have decieded to validate the input with regex which checks for the the network name of the format 10.0.0.0/16 and it rejects invalid network names like 10.0.0.256/24 and 10.0.0.0/33

There are 3 more variables which are optional. Visit the smc181002/vpc/aws | Terraform Registry page to check the documentation.

Now coming to the main.tf file, the code is given below

resource "aws_vpc" "mod_vpc" {
cidr_block = var.vpc_cidr_block
tags = {
Name = var.vpc_name
}
}
resource "aws_subnet" "mod_subnet" {
depends_on = [
aws_vpc.mod_vpc
]
count = length(var.subnet_cidr_block)
vpc_id = aws_vpc.mod_vpc.id
cidr_block = element(var.subnet_cidr_block, count.index)
tags = {
Name = element(var.subnet_names, count.index)
}
}
resource "aws_internet_gateway" "mod_igw" {
depends_on = [
aws_vpc.mod_vpc
]
vpc_id = aws_vpc.mod_vpc.id
tags = {
Name = var.gateway_name
}
}
resource "aws_route_table" "mod_route_table" {
depends_on = [
aws_vpc.mod_vpc
]
vpc_id = aws_vpc.mod_vpc.idroute {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.mod_igw.id
}
tags = {
Name = var.route_table_name
}
}resource "aws_route_table_association" "mod_route_association" {
depends_on = [
aws_vpc.mod_vpc,
aws_subnet.mod_subnet
]
count = length(aws_subnet.mod_subnet)
subnet_id = aws_subnet.mod_subnet[count.index].id
route_table_id = aws_route_table.mod_route_table.id
}

The Above code is just a basic VPC creation with public route tables being associated to the subnets.

Now coming to the outputs.tf, we have

output "vpc" {
value = aws_vpc.mod_vpc
}
output "subnet" {
value = aws_subnet.mod_subnet
}
output "gateway" {
value = aws_internet_gateway.mod_igw
}

Here the VPC, Subnet and the gateway information are outputted. Wee have the subnet as a list in this case because multiple subnets can be launched in the instance.

Publishing module to Terraform registry

There are certain guidelines for creating a terraform registry mentioned in the documentation Terraform Registry — Publishing Modules — Terraform by HashiCorp. But I will be giving a gist of what to do here.

  • First, we need to create a GitHub repo. There is a convention for the naming of the GitHub repo.
    The name should be of the format terraform-<PROVIDER>-<NAME>. In this article, I have created an AWS provider based module for VPC operations. So I named it terraform-aws-vpc. smc181002/terraform-aws-vpc (github.com)
  • Then we need to upload our code to the repository.
  • After uploading to the registry, we need to create a release in GitHub with a tag for the release which follows semantic versioning. Some examples of semantic versioning are v1.0 or v2.3.4 or v0.2-alpha or v5.9-beta.3 .
  • Now all we need to do is to go to the https://registry.terraform.io/ and we can publish from GitHub from this link.
  • There is an option at the top right to publish a module and the terraform will search for the GitHub repos in the account which follows the above requirements
  • Once when we click on the repo we want to publish, it will be automatically published to the registry.

🎉 we now have published a new module to the terraform registry.
Here is an example code that you can try for launching your own VPC.

If you liked the article, Please applaud for this story and drop a star in the GitHub repository

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store