Terraform Variables (Part 2)

Harshit SahuHarshit Sahu
6 min read

Variables are fundamental constructs in every programming language because they are inherently useful in building dynamic programs. We use variables to store temporary values so that they can assist programming logic in simple as well as complex programs.

In this post, we discuss the types of Terraform variables and how they are used in Terraform.

We will create a variables.tf which will hold all the variables.

Create a Directory for terraform variables

cd terraform-course
mkdir terraform-variable
cd terraform-variable

First create a local resource for the recap

# vi main.tf
resource "local_file" "devops" {
    filename = "/home/ubuntu/terraform-course/terraform-variables/devops.txt"
    content = "Here we are learning terraform"
}

Terraform initplanapply

But suppose if you want to change the location or the content of the file then you have to change it in main.tf file. This is not a good approach as per the industry standards, always change the configurations of the file which is being stored in a variable folder.

Let’s make a variable folder

# vi variables.tf
variable "filename" {
        default = "/home/ubuntu/terraform-course/terraform-variables/devops_automated.txt"
}

variable "content" {
        default = "This text is generated by variables"
}

Now implement this in main.tf

# main.tf
resource "local_file" "devops" {
    filename = "/home/ubuntu/terraform-course/terraform-variables/devops.txt"
    content = "Here we are learning terraform"
}

resource "local_file" "devops_auto" {
        filename = var.filename
        content = var.content
}

Terraform plan

Terraform apply

Let’s cross check also in the instance

Environment Variables

As a fallback for the other ways of defining variables, Terraform searches the environment of its own process for environment variables named TF_VAR_ followed by the name of a declared variable.

# variables.tf
variable "filename" {
        default = "/home/ubuntu/terraform-course/terraform-variables/devops_automated.txt"
}

variable "content" {
        default = "This text is generated by variables"
}

variable "myname" {} # declaritive variable without initialization

Changes in main.tf

# main.tf
resource "local_file" "devops" {
    filename = "/home/ubuntu/terraform-course/terraform-variables/devops.txt"
    content = "Here we are learning terraform"
}

resource "local_file" "devops_auto" {
        filename = var.filename
        content = var.content
}

output "myname" {  # output for the variable which is taken from environment
value = var.myname
}

Run the command to enter the value of myname variable in environment

export TF_VAR_myname=Harshit

Terraform plan

Terraform apply

Let check by changing the value in environment

export TF_VAR_myname=Harshit_Sahu
terraform apply --auto-approve

Data types in variables

  • Type = MAP → It is like dictionary in python in which we have to put data in form of key and value.
# variables.tf
variable "filename" {
        default = "/home/ubuntu/terraform-course/terraform-variables/devops_automated.txt"
}

variable "content" {
        default = "This text is generated by variables"
}

variable "myname" {} # declaritive variable without initialization

variable "content_map"{
        type = map
        default = {
                "content1" = "This blog is good"
                "content2" = "This blog is great"
}
}
# main.tf
resource "local_file" "devops" {
    filename = "/home/ubuntu/terraform-course/terraform-variables/devops.txt"
    content = var.content_map["content1"] # Here we use content1
}

resource "local_file" "devops_auto" {
        filename = var.filename
        content = var.content_map["content2"] # Here we use content2
}

output "myname" {
value = var.myname
}

Terraform apply

You can be noticed from logs that terraform destroys the initial configuration and then put the new configuration in the process of replacement.

Cross-Check also

ls
cat devops.txt
cat devops_automated.txt

  • Type = LIST → This is similar to python’s list in which same types of data are being stored in a box called list.

# variables
variable "filename" {
        default = "/home/ubuntu/terraform-course/terraform-variables/devops_automated.txt"
}

variable "content" {
        default = "This text is generated by variables"
}

variable "myname" {} # declaritive variable without initialization

variable "content_map"{
        type = map
        default = {
                "content1" = "This blog is good"
                "content2" = "This blog is great"
}
}

variable "file_list" {
    type = list
    default = ["/home/ubuntu/terraform-course/terraform-variables/first.txt","/home/ubuntu/terraform-course/terraform-variables/second.txt"]
}
# main.tf
resource "local_file" "devops" {
    filename = var.file_list[0] # Here we are accessing list 1st item through its index 0
    content = var.content_map["content1"]
}

resource "local_file" "devops_auto" {
        filename = var.file_list[1]  # Here we are accessing list 2nd item through its index 1
        content = var.content_map["content2"] 
}

output "myname" {
value = var.myname
}

Terraform apply

Check by ls

  • Type = OBJECT → It is the multi type user-defined data type which is used as storing multiple data types in map.
# variables.tf
variable "filename" {
        default = "/home/ubuntu/terraform-course/terraform-variables/devops_automated.txt"
}

variable "content" {
        default = "This text is generated by variables"
}

variable "myname" {} # declaritive variable without initialization

variable "content_map"{
        type = map
        default = {
                "content1" = "This blog is good"
                "content2" = "This blog is great"
}
}

variable "file_list" {
    type = list
    default = ["/home/ubuntu/terraform-course/terraform-variables/first.txt","/home/ubuntu/terraform-course/terraform-variables/second.txt"]
}

variable "aws_ec2_object" { # object type variables
type = object({ # Defining the object
        name = string
        instances = number
        keys = list(string)
        ami = string
})
default = { # Declaring its default values
        name = "test-instance"
        instances = 4
        keys = ["key1.pem","key2.pem"]
        ami = "ubuntu-fa87fafh89a"
}
}
# main.tf
resource "local_file" "devops" {
    filename = var.file_list[0]
    content = var.content_map["content1"]
}

resource "local_file" "devops_auto" {
        filename = var.file_list[1]
        content = var.content_map["content2"]
}

output "myname" {
value = var.myname
}

output "aws_ec2_instances" {
    value = var.aws_ec2_object.instances    
}

Terraform apply

If you want to see whole object:

# main.tf
output "aws_ec2_instances" {
    value = var.aws_ec2_object   
}

Variable Definitions (.tfvars) Files

To set lots of variables, it is more convenient to specify their values in a variable definitions file (with a filename ending in either .tfvars or .tfvars.json) and then specify that file on the command line with -var-file:

terraform apply -var-file="testing.tfvars"

Implementation

Make a variable in variable.tf

# variable.tf
variable "Linkedin" {}
variable "Hashnode" {}

Make a file prod.tfvars.json

vim prod.tfvars.json
# Content
{
    "Linkedin": 4300,  # it is written in json form
    "Hashnode": 1300
}

Make an output block in main.tf

# main.tf
resource "local_file" "devops" {
    filename = var.file_list[0]
    content = var.content_map["content1"]
}

resource "local_file" "devops_auto" {
        filename = var.file_list[1]
        content = var.content_map["content2"]
}

output "myname" {
value = var.myname
}

output "aws_ec2_instances" {
    value = var.aws_ec2_object.instances    
}

output "tf_linkedin_followers" {
    value = var.Linkedin
}

Run the command to apply changes

terraform apply -var-file=prod.tfvars.json

Terraform Refresh

Use Terraform refresh to refresh the state by your configuration file, reloads the variables.

Terraform State

Whenever we do terraform init, the plugins are installed.

Whenever we do terraform plan, the execution plan is generated.

Whenever we do terraform apply, the execution is done and state is maintained.

If we don’t have state we can still run the above commands, but state is useful to keep a record of why and how infrastructure was created at the first place. State is like a blueprint of the Real world infrastructure with some unique ids and attributes.

Used to improve performance, dependency management, etc.

Terraform state basically store metadata of the infrastructure which it further utilizes to check the current state before applying the code to ignore redundancy and also ensures specific modules, packages, providers being installed or not.

Remove State

State is a necessary requirement for Terraform to function. It is often asked if it is possible for Terraform to work without state, or for Terraform to not use state and just inspect real world resources on every run.

The main.tf exists so you can create the whole infrastructure again, so if terraform.tfstate get deleted also main base file has still existed which can make your infrastructure.

More Terraform commands:

terraform fmt
terraform validate
terraform show
terraform state list
0
Subscribe to my newsletter

Read articles from Harshit Sahu directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Harshit Sahu
Harshit Sahu

Enthusiastic about DevOps tools like Docker, Kubernetes, Maven, Nagios, Chef, and Ansible and currently learning and gaining experience by doing some hands-on projects on these tools. Also, started learning about AWS and GCP (Cloud Computing Platforms).