Mastering Terraform Variables and Outputs: A Comprehensive Guide

Terraform, the popular infrastructure-as-code tool, empowers users to define, provision, and manage cloud infrastructure in a declarative manner. Two essential features that enhance Terraform’s flexibility and modularity are variables and outputs. This article provides a deep dive into these concepts, including how to define and use variables, secure sensitive data, work with outputs, and leverage .tfvars files for seamless environment management.


Understanding Variables in Terraform

What Are Variables?

Variables in Terraform allow you to parameterize your configuration, making it dynamic and reusable. They enable users to pass values at runtime rather than hardcoding them into configuration files.


Defining Variables

Variables are defined using the variable block and can include attributes like type, default values, descriptions, and sensitivity settings.

Example:

variable "region" {
  description = "AWS region where resources will be created"
  type        = string
  default     = "us-east-1"
}

Attributes:

  • type: Specifies the expected data type (string, number, bool, list, map, object, or any).

  • default: Provides a fallback value if none is specified.

  • description: Describes the purpose of the variable.

  • sensitive: Marks variables as sensitive to hide their values in outputs and logs.


Using Variables

Once defined, variables can be referenced using var.<variable_name>.

Example:

provider "aws" {
  region = var.region
}

Variable Types

Terraform supports both primitive and complex types:

  • Primitive Types: string, number, bool

  • Complex Types: list, map, object, tuple

  • Dynamic Type: any

Example of a Map Type Variable:

variable "tags" {
  type    = map(string)
  default = {
    Environment = "Dev"
    Project     = "TerraformDemo"
  }
}

Sensitive Variables

To handle sensitive data like passwords or API keys, set the sensitive attribute to true.

Example:

variable "db_password" {
  description = "Database password"
  type        = string
  sensitive   = true
}

Sensitive variables ensure that their values are not displayed in Terraform logs or output.


Understanding Outputs in Terraform

What Are Outputs?

Outputs in Terraform allow you to extract and expose specific values from your infrastructure configuration. They are useful for debugging, sharing data between modules, and passing values to external tools or systems.


Defining Outputs

Outputs are defined using the output block and include attributes like value, description, and sensitivity.

Example:

output "bucket_name" {
  value       = aws_s3_bucket.my_bucket.bucket
  description = "The name of the S3 bucket"
}

Attributes:

  • value: Specifies the value to expose.

  • description: Provides context for the output.

  • sensitive: Hides the value in command-line output.


Use Cases for Outputs

  1. Passing Values Between Modules: Outputs can pass data from one module to another.

  2. Providing Information: Outputs display important resource attributes to users (e.g., IP addresses, URLs).

  3. Integration with External Tools: Outputs make data accessible for CI/CD pipelines or monitoring tools.


Working with .tfvars Files

What is a .tfvars File?

A .tfvars file stores variable values separately from the Terraform configuration. This enables environment-specific configurations without modifying the main .tf files.

Example dev.tfvars:

region         = "us-west-2"
instance_type  = "t3.micro"
tags = {
  Environment = "Development"
  Owner       = "DevOpsTeam"
}

Loading .tfvars Files

Terraform automatically loads a file named terraform.tfvars in the root directory. Alternatively, you can specify a custom file using the -var-file flag.

Command Example:

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

Advantages of .tfvars Files

  • Environment Management: Use different .tfvars files for development, staging, and production.

  • Separation of Concerns: Keep configuration values separate from code.

  • Reusability: Apply the same Terraform module with different configurations.


Creating a Reusable Terraform Module with Variables and Outputs

Scenario

We’ll create a reusable module to deploy an AWS S3 bucket with tagging and expose its name.


Step 1: Define the Module

main.tf (Module):

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

variables.tf (Module):

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

variable "tags" {
  description = "Tags for the S3 bucket"
  type        = map(string)
  default     = {}
}

outputs.tf (Module):

output "s3_bucket_name" {
  value       = aws_s3_bucket.bucket.id
  description = "The name of the created S3 bucket"
}

Step 2: Call the Module

Root Module main.tf:

module "s3_bucket" {
  source      = "./s3_bucket_module"
  bucket_name = "my-demo-bucket"
  tags = {
    Environment = "Dev"
    Project     = "TerraformExample"
  }
}

output "created_bucket_name" {
  value = module.s3_bucket.s3_bucket_name
}

Step 3: Execute Terraform Commands

  1. Initialize the configuration:

     terraform init
    
  2. Apply the configuration with variables:

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

Expected Output:

Outputs:

created_bucket_name = "my-demo-bucket"

Best Practices for Variables and Outputs

  1. Use .tfvars Files for Environment-Specific Configurations: Keep separate .tfvars files for development, staging, and production environments.

  2. Leverage Sensitive Variables: Avoid exposing sensitive data in logs or outputs.

  3. Version Control: Exclude .tfvars files with sensitive data from version control by adding them to .gitignore.

  4. Descriptive Variable and Output Names: Use meaningful names and descriptions to improve readability and maintainability.

  5. Keep Outputs Modular: Avoid exposing unnecessary details; only output what is required.


Conclusion

Terraform’s variables and outputs are indispensable tools for creating scalable, reusable, and modular infrastructure. By understanding how to define and use variables, secure sensitive data, and leverage .tfvars files, you can streamline configuration management across multiple environments. Outputs further enhance the workflow by exposing critical values for integration and debugging. Together, these features unlock the full potential of Terraform for managing infrastructure as code.