22
Terraform - Code Structure
The previous Terraform blog gave us a basic introduction to Terraform. We also discussed writing a simple Terraform code to create an AWS EC2 instance with minimal code.
Maintaining all codebases in a single
main.tf
file is good for beginners. However, this approach will lead to maintainability issues as our underlying infrastructure grows. Moreover, in practical situations, you might also need to deal with multiple environments (e.g. DTAP - dev/test/acceptance/production).Other deciding factors for code modularization are as follows-
- Count of Terraform Providers involved
- Count of Infra resources to be maintained by Terraform
It is recommended to logically split the source code as follows:
provider.tf
- contains provider configuration in root modulemain.tf
- call modules, locals, and data sources to create all resourcesvariables.tf
- contains variable declarations used in main.tf
outputs.tf
- contains outputs from the resources created in main.tf
terraform.tfvars
- contains variable definitions to provide default variable values. Terraform will automatically load variables from those files.As shown in the above image,
provider.tf
main.tf
As we treat Terraform as IaC, we should ensure there are no hardcodings. These must be configured in
variables.tf
. The following block must be defined for every variable.variable "aws_region" {
type = string
description = "AWS Region"
# default value is optional.
default = "us-east-1"
}
A default value can be configured (as shown above) for a variable. However, we can override this value while executing the code at runtime.
terraform apply -var aws_region="eu-west-1"
Also, Terraform can search the environment of its own process for environment variables named
TF_VAR_
followed by the name of a declared variable. This can be useful when running Terraform in automation.export TF_VAR_aws_region = eu-west-1
For bulk values, it is of convenience to specify their values in a variable definitions file (with a filename ending in either
.tfvars
or .tfvars.json
)Terraform also automatically loads a number of variable definitions files if they are present:
terraform.tfvars
or terraform.tfvars.json
..auto.tfvars
or .auto.tfvars.json
.This variable can then be used to replace the hardcodings.
region = var.aws_region
Our code post formatting will look as follows:

terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>3.0"
}
}
}
provider "aws" {
region = var.aws_region
default_tags {
tags = {
"Environment" = "dev"
"Owner" = "g33kzone"
}
}
}
variable "aws_region" {
type = string
description = "AWS Region"
}
variable "instance_type" {
type = string
description = "AWS EC2 Instance Type"
}
variable "aws_ec2_ami" {
type = string
description = "EC2 AMI for Amazon Linux 2"
}
resource "aws_instance" "web" {
instance_type = var.instance_type
ami = var.aws_ec2_ami
tags = {
"Name" = "aws-ec2-demo"
}
}
aws_region = "us-east-1"
instance_type = "t2.micro"
aws_ec2_ami = "ami-04d29b6f966df1537"
We are done with the coding. Let us execute this Terraform code with the following commands:
# open your shell in the same project folder
# download the terraform core components
# and initialize terraform in this directory
terraform init
# Validate changes to be made in AWS after the execution
terraform plan
# -auto-approve is used to skip manual approval prompt
terraform apply -auto-approve
Do not forget to delete the infrastructure created to avoid incurring any costs.
# running this command will destroy all the resources
terraform destroy -auto-approve
Github Repo - https://github.com/g33kzone/tf-aws-ec2.git
In future posts, I will delve into Terraform Modules.