In this guide, we will explore provisioning an AWS VPC using Terraform. Terraform enables you to create and manage infrastructure with code and codes can be stored in version control. This concept is known as Infrastructure as code, i.e. provisioning infrastructure resources in as code.
We are going to create an AWS VPC, with public and private subnets in multiple availability zones. We are also going to create an internet gateway for the public subnets, a nat gateway for the private subnets and a default vpc security group. We will also create Custom Route Tables and associate them with subnets
We are going to create a VPC
terraform module that will allow us to launch as many vpcs as we want. A terraform module is a container for multiple resources that are used together.
Prerequisites
To follow along this guide, you need the following:
- AWS IAM credentials with permissions to manage VPCs – access key and secret key
- AWS cli installed in your system. Install it here if you don’t have
- Terraform installed in your machine, get terraform from (here)[https://www.terraform.io/downloads.html] if you don’t have it
This is the terraform version I am using:
➜ terraform --version
Terraform v1.0.7
on darwin_amd64
Export aws credentials in your terminal
export AWS_ACCESS_KEY_ID=your-key-id-here
export AWS_SECRET_ACCESS_KEY=youe-access-key-here
export AWS_DEFAULT_REGION=aws-region
Creating the module
For our resources, we will create a module to create them. This will enable us to re create the same resources as many times as we want.
The module will contain the following:
vars.tf
– this is the variables supplied to our module. Variables are things that change each time we use the module. These are things likename
that we supply, we want to have different name each time we create a vpcmain.tf
– this is where the aws resources are definend.outputs.tf
– these are values that are exported and can be used to perform other action. e.g. for our vpc, we can export the vpc id.
This is my directory structure:
➜ tree
.
├── Makefile
├── main.tf
├── modules
│ └── vpc
│ ├── main.tf
│ ├── outputs.tf
│ └── vars.tf
2 directories, 8 files```
Code
Let us define some variables. Save this in the file vars.tf
in our module directory modules/vpc
variable "region" {
type = string
default = "eu-west-3"
}
variable "vpc_cidr" {
type = string
}
variable "name" {
type = string
}
variable "env" {
type = string
}
variable "public_subnets_cidr" {
type = list(string)
}
variable "availability_zones" {
type = list(string)
}
variable "private_subnets_cidr" {
type = list(string)
}
Next, let us define the resources that we want to create in the file main.tf
in modules/vpc
:
provider "aws" {
region = var.region
}
resource "aws_vpc" "vpc" {
cidr_block = var.vpc_cidr
tags = {
Name = var.name
Env = var.env
}
}
# This will be used by the public subnets
resource "aws_internet_gateway" "ig" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.name}-igw"
Env = var.env
}
}
# elastic ip for the nat gateway
resource "aws_eip" "nat_eip" {
vpc = true
depends_on = [aws_internet_gateway.ig]
}
# Nat gateway for the private subnets
resource "aws_nat_gateway" "nat" {
allocation_id = aws_eip.nat_eip.id
subnet_id = element(aws_subnet.public.*.id, 0)
depends_on = [aws_internet_gateway.ig]
tags = {
Name = "${var.name}-nat"
Env = var.env
}
}
# Public subnet
resource "aws_subnet" "public" {
vpc_id = aws_vpc.vpc.id
count = length(var.public_subnets_cidr)
cidr_block = element(var.public_subnets_cidr, count.index)
availability_zone = element(var.availability_zones, count.index)
map_public_ip_on_launch = true
tags = {
Name = "${var.env}-${element(var.availability_zones, count.index)}-public"
Env = var.env
}
}
# Private subnets
resource "aws_subnet" "private" {
vpc_id = aws_vpc.vpc.id
count = length(var.private_subnets_cidr)
cidr_block = element(var.private_subnets_cidr, count.index)
availability_zone = element(var.availability_zones, count.index)
map_public_ip_on_launch = false
tags = {
Name = "${var.env}-${element(var.availability_zones, count.index)}-private"
Env = var.env
}
}
# Private subnets route table
resource "aws_route_table" "private" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.name}-private-route-table"
Environment = var.env
}
}
# Public subnets route table
resource "aws_route_table" "public" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.name}-public-route-table"
Environment = var.env
}
}
# Add route for public route table to internet gateway
resource "aws_route" "public_internet_gateway" {
route_table_id = aws_route_table.public.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.ig.id
}
# Add route for private route table to nat gateway
resource "aws_route" "private_nat_gateway" {
route_table_id = aws_route_table.private.id
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat.id
}
# Associate the public route table to public subnets
resource "aws_route_table_association" "public" {
count = length(var.public_subnets_cidr)
subnet_id = element(aws_subnet.public.*.id, count.index)
route_table_id = aws_route_table.public.id
}
# Associate the public route table to public subnets
resource "aws_route_table_association" "private" {
count = length(var.private_subnets_cidr)
subnet_id = element(aws_subnet.private.*.id, count.index)
route_table_id = aws_route_table.private.id
}
# Create a default security for the vpc
resource "aws_security_group" "default" {
name = "${var.name}-default-sg"
description = "Default security group to allow inbound/outbound from the VPC"
vpc_id = aws_vpc.vpc.id
depends_on = [aws_vpc.vpc]
ingress {
from_port = "0"
to_port = "0"
protocol = "-1"
self = true
}
egress {
from_port = "0"
to_port = "0"
protocol = "-1"
self = "true"
}
tags = {
Env = var.env
}
}
Then lets create a file outputs.tf
to export the created resources values:
output "vpc_id" {
value = aws_vpc.vpc.id
}
output "vpc_arn" {
value = aws_vpc.vpc.arn
}
output "public_subnet_id" {
value = join("", aws_subnet.public[*].id)
}
output "private_subnet_id" {
value = join("", aws_subnet.private[*].id)
}
Using the module
Now that our module is done, can use it. Let’s create two VPCs – a uat
and prod
one.
In the current working directory, create a main.tf
file with this content:
module "uat-vpc" {
source = "./modules/vpc"
region = "eu-west-3"
vpc_cidr = "10.10.0.0/16"
name = "uat-vpc"
env = "uat"
public_subnets_cidr = ["10.10.0.0/24", "10.10.1.0/24", "10.10.2.0/24"]
private_subnets_cidr = ["10.10.3.0/24", "10.10.4.0/24", "10.10.5.0/24"]
availability_zones = ["eu-west-3a", "eu-west-3b", "eu-west-3c"]
}
module "prod-vpc" {
source = "./modules/vpc"
region = "eu-west-3"
vpc_cidr = "10.11.0.0/16"
name = "prod-vpc"
env = "prod"
public_subnets_cidr = ["10.11.0.0/24", "10.11.1.0/24", "10.11.2.0/24"]
private_subnets_cidr = ["10.11.3.0/24", "10.11.4.0/24", "10.11.5.0/24"]
availability_zones = ["eu-west-3a", "eu-west-3b", "eu-west-3c"]
}
The above code uses the module we defined (source = "./modules/vpc"
) and passes the defined variables. Let us create the resources in AWS using this command.
Creating resources
To create resources, we first need to initialize. This will download any dependencies required by terraform:
terraform init
To check that everything is working as expected, use this command:
terraform validate
Then check what resources will be created:
terraform plan
If all is well, then apply the changes with:
terraform apply
I like to simplify the process with a makefile. I have a Makefile with this content that will chain the above terraform commands:
all: clean apply
init:
terraform init
terraform get
plan: validate
terraform plan -out=tf.plan
apply: plan
terraform apply tf.plan
clean:
rm -f tf.plan
rm -rf .terraform
rm -rf *.tfstate*
validate: init
terraform validate
destroy:
terraform destroy
For the code above, this is my output:
➜ make apply
terraform init
Initializing modules...
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v3.59.0
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
terraform get
terraform validate
Success! The configuration is valid.
terraform plan -out=tf.plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
+ create
Terraform will perform the following actions:
# module.prod-vpc.aws_eip.nat_eip will be created
+ resource "aws_eip" "nat_eip" {
+ allocation_id = (known after apply)
+ association_id = (known after apply)
+ carrier_ip = (known after apply)
+ customer_owned_ip = (known after apply)
+ domain = (known after apply)
+ id = (known after apply)
+ instance = (known after apply)
+ network_border_group = (known after apply)
+ network_interface = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ public_ipv4_pool = (known after apply)
+ tags_all = (known after apply)
+ vpc = true
}
# module.prod-vpc.aws_internet_gateway.ig will be created
+ resource "aws_internet_gateway" "ig" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "prod"
+ "Name" = "prod-vpc-igw"
}
+ tags_all = {
+ "Env" = "prod"
+ "Name" = "prod-vpc-igw"
}
+ vpc_id = (known after apply)
}
# module.prod-vpc.aws_nat_gateway.nat will be created
+ resource "aws_nat_gateway" "nat" {
+ allocation_id = (known after apply)
+ connectivity_type = "public"
+ id = (known after apply)
+ network_interface_id = (known after apply)
+ private_ip = (known after apply)
+ public_ip = (known after apply)
+ subnet_id = (known after apply)
+ tags = {
+ "Env" = "prod"
+ "Name" = "prod-vpc-nat"
}
+ tags_all = {
+ "Env" = "prod"
+ "Name" = "prod-vpc-nat"
}
}
# module.prod-vpc.aws_route.private_nat_gateway will be created
+ resource "aws_route" "private_nat_gateway" {
+ destination_cidr_block = "0.0.0.0/0"
+ id = (known after apply)
+ instance_id = (known after apply)
+ instance_owner_id = (known after apply)
+ nat_gateway_id = (known after apply)
+ network_interface_id = (known after apply)
+ origin = (known after apply)
+ route_table_id = (known after apply)
+ state = (known after apply)
}
# module.prod-vpc.aws_route.public_internet_gateway will be created
+ resource "aws_route" "public_internet_gateway" {
+ destination_cidr_block = "0.0.0.0/0"
+ gateway_id = (known after apply)
+ id = (known after apply)
+ instance_id = (known after apply)
+ instance_owner_id = (known after apply)
+ network_interface_id = (known after apply)
+ origin = (known after apply)
+ route_table_id = (known after apply)
+ state = (known after apply)
}
# module.prod-vpc.aws_route_table.private will be created
+ resource "aws_route_table" "private" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ propagating_vgws = (known after apply)
+ route = (known after apply)
+ tags = {
+ "Environment" = "prod"
+ "Name" = "prod-vpc-private-route-table"
}
+ tags_all = {
+ "Environment" = "prod"
+ "Name" = "prod-vpc-private-route-table"
}
+ vpc_id = (known after apply)
}
# module.prod-vpc.aws_route_table.public will be created
+ resource "aws_route_table" "public" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ propagating_vgws = (known after apply)
+ route = (known after apply)
+ tags = {
+ "Environment" = "prod"
+ "Name" = "prod-vpc-public-route-table"
}
+ tags_all = {
+ "Environment" = "prod"
+ "Name" = "prod-vpc-public-route-table"
}
+ vpc_id = (known after apply)
}
# module.prod-vpc.aws_route_table_association.private[0] will be created
+ resource "aws_route_table_association" "private" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.prod-vpc.aws_route_table_association.private[1] will be created
+ resource "aws_route_table_association" "private" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.prod-vpc.aws_route_table_association.private[2] will be created
+ resource "aws_route_table_association" "private" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.prod-vpc.aws_route_table_association.public[0] will be created
+ resource "aws_route_table_association" "public" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.prod-vpc.aws_route_table_association.public[1] will be created
+ resource "aws_route_table_association" "public" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.prod-vpc.aws_route_table_association.public[2] will be created
+ resource "aws_route_table_association" "public" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.prod-vpc.aws_security_group.default will be created
+ resource "aws_security_group" "default" {
+ arn = (known after apply)
+ description = "Default security group to allow inbound/outbound from the VPC"
+ egress = [
+ {
+ cidr_blocks = []
+ description = ""
+ from_port = 0
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "-1"
+ security_groups = []
+ self = true
+ to_port = 0
},
]
+ id = (known after apply)
+ ingress = [
+ {
+ cidr_blocks = []
+ description = ""
+ from_port = 0
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "-1"
+ security_groups = []
+ self = true
+ to_port = 0
},
]
+ name = "prod-vpc-default-sg"
+ name_prefix = (known after apply)
+ owner_id = (known after apply)
+ revoke_rules_on_delete = false
+ tags = {
+ "Env" = "prod"
}
+ tags_all = {
+ "Env" = "prod"
}
+ vpc_id = (known after apply)
}
# module.prod-vpc.aws_subnet.private[0] will be created
+ resource "aws_subnet" "private" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "eu-west-31"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.11.3.0/24"
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = false
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "prod"
+ "Name" = "prod-eu-west-31-private"
}
+ tags_all = {
+ "Env" = "prod"
+ "Name" = "prod-eu-west-31-private"
}
+ vpc_id = (known after apply)
}
# module.prod-vpc.aws_subnet.private[1] will be created
+ resource "aws_subnet" "private" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "eu-west-3b"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.11.4.0/24"
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = false
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "prod"
+ "Name" = "prod-eu-west-3b-private"
}
+ tags_all = {
+ "Env" = "prod"
+ "Name" = "prod-eu-west-3b-private"
}
+ vpc_id = (known after apply)
}
# module.prod-vpc.aws_subnet.private[2] will be created
+ resource "aws_subnet" "private" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "eu-west-3c"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.11.5.0/24"
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = false
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "prod"
+ "Name" = "prod-eu-west-3c-private"
}
+ tags_all = {
+ "Env" = "prod"
+ "Name" = "prod-eu-west-3c-private"
}
+ vpc_id = (known after apply)
}
# module.prod-vpc.aws_subnet.public[0] will be created
+ resource "aws_subnet" "public" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "eu-west-31"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.11.0.0/24"
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = true
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "prod"
+ "Name" = "prod-eu-west-31-public"
}
+ tags_all = {
+ "Env" = "prod"
+ "Name" = "prod-eu-west-31-public"
}
+ vpc_id = (known after apply)
}
# module.prod-vpc.aws_subnet.public[1] will be created
+ resource "aws_subnet" "public" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "eu-west-3b"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.11.1.0/24"
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = true
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "prod"
+ "Name" = "prod-eu-west-3b-public"
}
+ tags_all = {
+ "Env" = "prod"
+ "Name" = "prod-eu-west-3b-public"
}
+ vpc_id = (known after apply)
}
# module.prod-vpc.aws_subnet.public[2] will be created
+ resource "aws_subnet" "public" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "eu-west-3c"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.11.2.0/24"
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = true
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "prod"
+ "Name" = "prod-eu-west-3c-public"
}
+ tags_all = {
+ "Env" = "prod"
+ "Name" = "prod-eu-west-3c-public"
}
+ vpc_id = (known after apply)
}
# module.prod-vpc.aws_vpc.vpc will be created
+ resource "aws_vpc" "vpc" {
+ arn = (known after apply)
+ assign_generated_ipv6_cidr_block = false
+ cidr_block = "10.11.0.0/16"
+ default_network_acl_id = (known after apply)
+ default_route_table_id = (known after apply)
+ default_security_group_id = (known after apply)
+ dhcp_options_id = (known after apply)
+ enable_classiclink = (known after apply)
+ enable_classiclink_dns_support = (known after apply)
+ enable_dns_hostnames = (known after apply)
+ enable_dns_support = true
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "prod"
+ "Name" = "prod-vpc"
}
+ tags_all = {
+ "Env" = "prod"
+ "Name" = "prod-vpc"
}
}
# module.uat-vpc.aws_eip.nat_eip will be created
+ resource "aws_eip" "nat_eip" {
+ allocation_id = (known after apply)
+ association_id = (known after apply)
+ carrier_ip = (known after apply)
+ customer_owned_ip = (known after apply)
+ domain = (known after apply)
+ id = (known after apply)
+ instance = (known after apply)
+ network_border_group = (known after apply)
+ network_interface = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ public_ipv4_pool = (known after apply)
+ tags_all = (known after apply)
+ vpc = true
}
# module.uat-vpc.aws_internet_gateway.ig will be created
+ resource "aws_internet_gateway" "ig" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "uat"
+ "Name" = "uat-vpc-igw"
}
+ tags_all = {
+ "Env" = "uat"
+ "Name" = "uat-vpc-igw"
}
+ vpc_id = (known after apply)
}
# module.uat-vpc.aws_nat_gateway.nat will be created
+ resource "aws_nat_gateway" "nat" {
+ allocation_id = (known after apply)
+ connectivity_type = "public"
+ id = (known after apply)
+ network_interface_id = (known after apply)
+ private_ip = (known after apply)
+ public_ip = (known after apply)
+ subnet_id = (known after apply)
+ tags = {
+ "Env" = "uat"
+ "Name" = "uat-vpc-nat"
}
+ tags_all = {
+ "Env" = "uat"
+ "Name" = "uat-vpc-nat"
}
}
# module.uat-vpc.aws_route.private_nat_gateway will be created
+ resource "aws_route" "private_nat_gateway" {
+ destination_cidr_block = "0.0.0.0/0"
+ id = (known after apply)
+ instance_id = (known after apply)
+ instance_owner_id = (known after apply)
+ nat_gateway_id = (known after apply)
+ network_interface_id = (known after apply)
+ origin = (known after apply)
+ route_table_id = (known after apply)
+ state = (known after apply)
}
# module.uat-vpc.aws_route.public_internet_gateway will be created
+ resource "aws_route" "public_internet_gateway" {
+ destination_cidr_block = "0.0.0.0/0"
+ gateway_id = (known after apply)
+ id = (known after apply)
+ instance_id = (known after apply)
+ instance_owner_id = (known after apply)
+ network_interface_id = (known after apply)
+ origin = (known after apply)
+ route_table_id = (known after apply)
+ state = (known after apply)
}
# module.uat-vpc.aws_route_table.private will be created
+ resource "aws_route_table" "private" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ propagating_vgws = (known after apply)
+ route = (known after apply)
+ tags = {
+ "Environment" = "uat"
+ "Name" = "uat-vpc-private-route-table"
}
+ tags_all = {
+ "Environment" = "uat"
+ "Name" = "uat-vpc-private-route-table"
}
+ vpc_id = (known after apply)
}
# module.uat-vpc.aws_route_table.public will be created
+ resource "aws_route_table" "public" {
+ arn = (known after apply)
+ id = (known after apply)
+ owner_id = (known after apply)
+ propagating_vgws = (known after apply)
+ route = (known after apply)
+ tags = {
+ "Environment" = "uat"
+ "Name" = "uat-vpc-public-route-table"
}
+ tags_all = {
+ "Environment" = "uat"
+ "Name" = "uat-vpc-public-route-table"
}
+ vpc_id = (known after apply)
}
# module.uat-vpc.aws_route_table_association.private[0] will be created
+ resource "aws_route_table_association" "private" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.uat-vpc.aws_route_table_association.private[1] will be created
+ resource "aws_route_table_association" "private" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.uat-vpc.aws_route_table_association.private[2] will be created
+ resource "aws_route_table_association" "private" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.uat-vpc.aws_route_table_association.public[0] will be created
+ resource "aws_route_table_association" "public" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.uat-vpc.aws_route_table_association.public[1] will be created
+ resource "aws_route_table_association" "public" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.uat-vpc.aws_route_table_association.public[2] will be created
+ resource "aws_route_table_association" "public" {
+ id = (known after apply)
+ route_table_id = (known after apply)
+ subnet_id = (known after apply)
}
# module.uat-vpc.aws_security_group.default will be created
+ resource "aws_security_group" "default" {
+ arn = (known after apply)
+ description = "Default security group to allow inbound/outbound from the VPC"
+ egress = [
+ {
+ cidr_blocks = []
+ description = ""
+ from_port = 0
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "-1"
+ security_groups = []
+ self = true
+ to_port = 0
},
]
+ id = (known after apply)
+ ingress = [
+ {
+ cidr_blocks = []
+ description = ""
+ from_port = 0
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "-1"
+ security_groups = []
+ self = true
+ to_port = 0
},
]
+ name = "uat-vpc-default-sg"
+ name_prefix = (known after apply)
+ owner_id = (known after apply)
+ revoke_rules_on_delete = false
+ tags = {
+ "Env" = "uat"
}
+ tags_all = {
+ "Env" = "uat"
}
+ vpc_id = (known after apply)
}
# module.uat-vpc.aws_subnet.private[0] will be created
+ resource "aws_subnet" "private" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "eu-west-31"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.10.3.0/24"
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = false
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "uat"
+ "Name" = "uat-eu-west-31-private"
}
+ tags_all = {
+ "Env" = "uat"
+ "Name" = "uat-eu-west-31-private"
}
+ vpc_id = (known after apply)
}
# module.uat-vpc.aws_subnet.private[1] will be created
+ resource "aws_subnet" "private" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "eu-west-3b"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.10.4.0/24"
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = false
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "uat"
+ "Name" = "uat-eu-west-3b-private"
}
+ tags_all = {
+ "Env" = "uat"
+ "Name" = "uat-eu-west-3b-private"
}
+ vpc_id = (known after apply)
}
# module.uat-vpc.aws_subnet.private[2] will be created
+ resource "aws_subnet" "private" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "eu-west-3c"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.10.5.0/24"
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = false
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "uat"
+ "Name" = "uat-eu-west-3c-private"
}
+ tags_all = {
+ "Env" = "uat"
+ "Name" = "uat-eu-west-3c-private"
}
+ vpc_id = (known after apply)
}
# module.uat-vpc.aws_subnet.public[0] will be created
+ resource "aws_subnet" "public" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "eu-west-31"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.10.0.0/24"
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = true
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "uat"
+ "Name" = "uat-eu-west-31-public"
}
+ tags_all = {
+ "Env" = "uat"
+ "Name" = "uat-eu-west-31-public"
}
+ vpc_id = (known after apply)
}
# module.uat-vpc.aws_subnet.public[1] will be created
+ resource "aws_subnet" "public" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "eu-west-3b"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.10.1.0/24"
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = true
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "uat"
+ "Name" = "uat-eu-west-3b-public"
}
+ tags_all = {
+ "Env" = "uat"
+ "Name" = "uat-eu-west-3b-public"
}
+ vpc_id = (known after apply)
}
# module.uat-vpc.aws_subnet.public[2] will be created
+ resource "aws_subnet" "public" {
+ arn = (known after apply)
+ assign_ipv6_address_on_creation = false
+ availability_zone = "eu-west-3c"
+ availability_zone_id = (known after apply)
+ cidr_block = "10.10.2.0/24"
+ id = (known after apply)
+ ipv6_cidr_block_association_id = (known after apply)
+ map_public_ip_on_launch = true
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "uat"
+ "Name" = "uat-eu-west-3c-public"
}
+ tags_all = {
+ "Env" = "uat"
+ "Name" = "uat-eu-west-3c-public"
}
+ vpc_id = (known after apply)
}
# module.uat-vpc.aws_vpc.vpc will be created
+ resource "aws_vpc" "vpc" {
+ arn = (known after apply)
+ assign_generated_ipv6_cidr_block = false
+ cidr_block = "10.10.0.0/16"
+ default_network_acl_id = (known after apply)
+ default_route_table_id = (known after apply)
+ default_security_group_id = (known after apply)
+ dhcp_options_id = (known after apply)
+ enable_classiclink = (known after apply)
+ enable_classiclink_dns_support = (known after apply)
+ enable_dns_hostnames = (known after apply)
+ enable_dns_support = true
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ tags = {
+ "Env" = "uat"
+ "Name" = "uat-vpc"
}
+ tags_all = {
+ "Env" = "uat"
+ "Name" = "uat-vpc"
}
}
Plan: 42 to add, 0 to change, 0 to destroy.
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Saved the plan to: tf.plan
To perform exactly these actions, run the following command to apply:
terraform apply "tf.plan"
Our VPCs are not set up and ready to use. Login to aws console to confirm.