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-

  • Project Complexity
    • Count of Terraform Providers involved
    • Count of Infra resources to be maintained by Terraform
  • Cadence of Infrastructure changes - daily / weekly / monthly
  • Deployment Strategy - CI/CD Pipeline, GitOps, etc.

It is recommended to logically split the source code as follows:

  • provider.tf - contains provider configuration in root module
  • main.tf - call modules, locals, and data sources to create all resources
  • variables.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.

Let us refer to the initial Terraform code and understand how we can logically break it down further. terraform-getting-started.png

As shown in the above image,

  • Red block will be part of provider.tf
  • Green block will be part of main.tf

Using Input Variable Values

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"
}

Variables on the Command Line

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"

Environment Variables

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

Variable Definitions (.tfvars) Files

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:

  • Files named exactly terraform.tfvars or terraform.tfvars.json.
  • Any files with names ending in .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:

provider.tf

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "~>3.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
  default_tags {
    tags = {
      "Environment" = "dev"
      "Owner" = "g33kzone"
    }
  }
}

variables.tf

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"
}

main.tf

resource "aws_instance" "web" {
  instance_type = var.instance_type
  ami = var.aws_ec2_ami

  tags = {
    "Name" = "aws-ec2-demo"
  }
}

terraform.tfvars

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

Very Important

Clean Up

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

In future posts, I will delve into Terraform Modules.

17