Understanding Terraform Variables

RohitRohit
4 min read

1. Terraform Input Variables

Definition

Input variables allow you to customize your Terraform modules, passing different values during deployment without hardcoding them into the configurations. They act like parameters, making your code flexible for different environments.

Syntax

An input variable is defined using the variable block. Here’s an example:

variable "instance_type" {
  description = "Type of EC2 instance"
  type        = string
  default     = "t2.micro"
}

Assigning Input Variable Values

  1. Default Value: As shown above, a default value is set within the variable definition.

  2. Environment Variables: You can pass variable values using environment variables prefixed with TF_VAR_. For example:

     export TF_VAR_instance_type="t3.large"
    
  3. Terraform CLI: Variables can be passed via the command line using the -var flag:

     terraform apply -var="instance_type=t3.medium"
    
  4. Variable Files (.tfvars): Store variable values in .tfvars files or auto-loaded terraform.tfvars file:

     instance_type = "t3.micro"
    

Example

Consider a Terraform file that provisions an EC2 instance:

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = var.instance_type
}

In this case, the instance_type can be passed dynamically during execution, making the module adaptable.

2. Terraform Output Variables

Definition

Output variables allow you to display information about the infrastructure after Terraform has run, such as an EC2 instance ID or an IP address. They help in sharing values between different Terraform configurations or passing data to external tools.

Syntax

Here’s a simple example of an output variable:

output "instance_ip" {
  description = "Public IP address of the instance"
  value       = aws_instance.example.public_ip
}

When the terraform apply is complete, the output will display the public IP address of the EC2 instance.

Sensitive Output

Output variables can also be marked as sensitive to hide values from the CLI output:

output "db_password" {
  description = "Database password"
  value       = aws_db_instance.example.password
  sensitive   = true
}

When marked as sensitive, Terraform will not display the value in the CLI output, providing an extra layer of security.

3. Variable Precedence

Terraform provides multiple ways to pass input variables, and understanding how Terraform resolves them is critical to avoiding confusion. Variables are evaluated in the following order of precedence (highest to lowest):

  1. Command-line flags (-var or -var-file): Variables passed via command-line flags override all others.

     terraform apply -var="instance_type=t3.large"
    
  2. Environment variables: Variables defined as environment variables take precedence over .tfvars files and defaults.

     export TF_VAR_instance_type="t3.medium"
    
  3. Terraform .tfvars files: These are automatically loaded if named terraform.tfvars or *.auto.tfvars. Other .tfvars files can be passed using the -var-file flag.

     terraform apply -var-file="production.tfvars"
    
  4. Default value: If no value is provided through the above methods, Terraform will use the default value defined in the variable block.

Example

Let’s consider the following scenario:

  • You define a default value for instance_type as t2.micro.

  • You pass a different value using an environment variable: t3.large.

  • You also pass another value using the CLI: t3.medium.

Here’s how Terraform resolves it:

  • The value passed via CLI (t3.medium) will take precedence.

4. The sensitive Meta-Argument

The sensitive argument ensures that the variable values do not get logged or exposed in the output. This is particularly useful for sensitive information such as passwords, access keys, or any other secrets.

Using Sensitive Input Variables

You can mark input variables as sensitive using the sensitive attribute:

variable "db_password" {
  description = "Password for the RDS instance"
  type        = string
  sensitive   = true
}

By marking the variable as sensitive, Terraform will:

  • Not display the value during terraform plan or terraform apply.

  • Not store the value in the state file in plain text (though the state file itself can still be a sensitive asset, so ensure it is secured).

Example: Handling Sensitive Variables

variable "db_password" {
  description = "Password for the database"
  type        = string
  sensitive   = true
}

resource "aws_db_instance" "example" {
  allocated_storage    = 10
  engine               = "mysql"
  engine_version       = "5.7"
  instance_class       = "db.t2.micro"
  name                 = "mydb"
  username             = "admin"
  password             = var.db_password  # Sensitive variable
}

Sensitive Output Example

Output values marked as sensitive won’t display their actual content:

output "db_instance_password" {
  value     = aws_db_instance.example.password
  sensitive = true
}

The output will only show:

Outputs:

db_instance_password = <sensitive>

5. Combining Input and Output Variables

Sometimes, you may want to combine input variables with outputs. For instance, you can create a resource using input variables and output some of its attributes:

variable "bucket_name" {
  description = "Name of the S3 bucket"
  type        = string
}

resource "aws_s3_bucket" "example" {
  bucket = var.bucket_name
}

output "bucket_id" {
  value = aws_s3_bucket.example.id
}

In this case, the bucket_name is passed as an input, and after provisioning, Terraform outputs the bucket_id.

Conclusion

Terraform variables, both input and output, provide a great deal of flexibility and reusability to your infrastructure code. By understanding variable precedence, you can control which values Terraform uses during execution. Additionally, the sensitive meta-argument is a powerful tool for securing sensitive information, ensuring it’s not displayed in outputs or logs.

0
Subscribe to my newsletter

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

Written by

Rohit
Rohit

I'm a results-driven professional skilled in both DevOps and Web Development. Here's a snapshot of what I bring to the table: 💻 DevOps Expertise: AWS Certified Solutions Architect Associate: Proficient in deploying and managing applications in the cloud. Automation Enthusiast: Leveraging Python for task automation, enhancing development workflows. 🔧 Tools & Technologies: Ansible, Terraform, Docker, Prometheus, Kubernetes, Linux, Git, Github Actions, EC2, S3, VPC, R53 and other AWS services. 🌐 Web Development: Proficient in HTML, CSS, JavaScript, React, Redux-toolkit, Node.js, Express.js and Tailwind CSS. Specialized in building high-performance websites with Gatsby.js. Let's connect to discuss how my DevOps skills and frontend expertise can contribute to your projects or team. Open to collaboration and always eager to learn! Aside from my work, I've also contributed to open-source projects, like adding a feature for Focalboard Mattermost.