šŸ¶
Terraform

Terraform Global Variables: Definition and Usage Guide

By Filip on 11/19/2024

Learn how to define and manage global variables in Terraform for efficient and reusable infrastructure code.

Terraform Global Variables: Definition and Usage Guide

Table of Contents

Introduction

Terraform, by design, doesn't have a built-in "global variable" feature. However, there are several ways to manage and share values across your Terraform configurations, effectively achieving the same outcome. This article outlines five common approaches to handle values that you might typically want to use globally: using variables in the root module, passing variables to modules, leveraging Terraform Cloud or Enterprise workspaces, utilizing tools like Terragrunt or Terramate, and employing data sources for shared values. Each approach has its own strengths and is suited for different scenarios depending on your project's structure and specific needs.

Step-by-Step Guide

While Terraform doesn't have a built-in concept of "global variables", you can achieve similar results using different approaches depending on your use case:

1. Variables in Root Module:

  • Define variables in a file like variables.tf in your root module.

    variable "region" {
      default = "us-west-2"
    }
  • Access these variables directly within any .tf file in your root module.

    resource "aws_instance" "example" {
      region = var.region
    }

2. Passing Variables to Modules:

  • Define variables in your root module's variables.tf.

  • Pass these variables as arguments when calling modules.

    module "my_module" {
      source = "./modules/my-module"
      region = var.region
    }
  • Access passed variables within your module.

    # Inside modules/my-module/main.tf
    resource "aws_instance" "example" {
      region = var.region
    }

3. Terraform Cloud/Enterprise Workspaces:

  • Define variables at the workspace or project level in Terraform Cloud/Enterprise.

  • These variables are accessible within the specific workspace or project.

4. Tools like Terragrunt or Terramate:

  • These tools provide features like hierarchical configuration and global variables.

  • Terragrunt Example: Define variables in a terragrunt.hcl file.

    locals {
      region = "us-west-2"
    }
    
    terraform {
      source = "./modules/my-module"
    }
    
    inputs = {
      region = local.region
    }

5. Data Sources for Shared Values:

  • Use data sources to fetch values from external systems or shared resources.
    data "aws_ami" "example" {
      most_recent = true
    
      filter {
        name   = "name"
        values = ["amzn-ami-hvm-*-x86_64-gp2"]
      }
    
      owners = ["amazon"]
    }
    
    resource "aws_instance" "example" {
      ami           = data.aws_ami.example.id
      # ... other configurations
    }

Remember to choose the approach that best suits your project structure and requirements.

Code Example

This code demonstrates different ways to use "global variables" in Terraform. It shows how to define variables in the root module and access them in resource configurations. It also covers passing variables to modules, using Terraform Cloud/Enterprise workspaces, leveraging Terragrunt for variable management, and utilizing data sources like AWS SSM Parameter Store for shared values. Each approach provides a way to centralize and manage common configuration values, promoting code reusability and consistency across Terraform projects.

This document provides code examples for achieving "global variable" functionality in Terraform using different approaches.

1. Variables in Root Module:

variables.tf:

variable "region" {
  default = "us-west-2"
}

variable "instance_type" {
  default = "t2.micro"
}

main.tf:

resource "aws_instance" "example" {
  ami           = data.aws_ami.example.id
  instance_type = var.instance_type
  region = var.region
}

data "aws_ami" "example" {
  most_recent = true

  filter {
    name   = "name"
    values = ["amzn-ami-hvm-*-x86_64-gp2"]
  }

  owners = ["amazon"]
}

2. Passing Variables to Modules:

root/variables.tf:

variable "region" {
  default = "us-west-2"
}

root/main.tf:

module "my_module" {
  source = "./modules/my-module"
  region = var.region
}

modules/my-module/main.tf:

variable "region" {}

resource "aws_instance" "example" {
  ami           = data.aws_ami.example.id
  instance_type = "t2.micro"
  region = var.region
}

data "aws_ami" "example" {
  most_recent = true

  filter {
    name   = "name"
    values = ["amzn-ami-hvm-*-x86_64-gp2"]
  }

  owners = ["amazon"]
}

3. Terraform Cloud/Enterprise Workspaces:

(This example demonstrates the concept, but you'll need to configure variables within your Terraform Cloud/Enterprise workspace.)

main.tf:

resource "aws_instance" "example" {
  ami           = data.aws_ami.example.id
  instance_type = "t2.micro"
  region = terraform.workspace # Accessing workspace variable
}

# ... other configurations

4. Terragrunt Example:

terragrunt.hcl:

locals {
  region = "us-west-2"
}

terraform {
  source = "./modules/my-module"
}

inputs = {
  region = local.region
}

modules/my-module/main.tf:

variable "region" {}

resource "aws_instance" "example" {
  ami           = data.aws_ami.example.id
  instance_type = "t2.micro"
  region = var.region
}

# ... other configurations

5. Data Sources for Shared Values:

main.tf:

data "aws_ssm_parameter" "region" {
  name  = "/my-app/region"
}

resource "aws_instance" "example" {
  ami           = data.aws_ami.example.id
  instance_type = "t2.micro"
  region = data.aws_ssm_parameter.region.value
}

# ... other configurations

This example retrieves the region value from an AWS SSM Parameter Store parameter.

Remember to adapt these examples to your specific needs and choose the approach that best suits your project structure and requirements.

Additional Notes

General Considerations:

  • Trade-offs: Each approach has its own advantages and disadvantages in terms of complexity, maintainability, and flexibility. Consider your project's scale and structure when choosing the best fit.
  • No True Global Scope: Terraform's design emphasizes modularity and encapsulation. While these methods simulate global variables, remember that values are still scoped within modules or workspaces.
  • Naming Conventions: Use clear and consistent naming conventions for variables and data sources to improve code readability and avoid conflicts.

Specific to Approaches:

  • Root Module Variables:
    • Best for small projects or values truly shared across the entire configuration.
    • Can become harder to manage as the project grows and variables become numerous.
  • Passing Variables to Modules:
    • Promotes modularity and reusability of modules.
    • Can lead to "variable sprawl" if many values need to be passed down multiple levels.
  • Terraform Cloud/Enterprise Workspaces:
    • Ideal for managing environment-specific values (e.g., dev, staging, production).
    • Requires access to Terraform Cloud/Enterprise.
  • Terragrunt/Terramate:
    • Offers powerful features for managing complex configurations and shared values.
    • Introduces additional tooling and learning curve.
  • Data Sources:
    • Suitable for fetching dynamic values or secrets from external systems.
    • Adds a dependency on the data source and its availability.

Best Practices:

  • Minimize Global State: Strive to keep the number of "global" values to a minimum. Overuse can hinder modularity and make code harder to reason about.
  • Document Clearly: Document the purpose and usage of any simulated global variables to improve code understanding and maintainability.
  • Version Control: Always keep your Terraform code, including variable definitions and data sources, under version control.

By understanding these nuances and following best practices, you can effectively manage shared values in your Terraform projects while maintaining a clean and maintainable codebase.

Summary

While Terraform lacks built-in global variables, you can achieve similar functionality through various methods:

| Approach | Description

Conclusion

In conclusion, while Terraform itself doesn't offer a dedicated "global variable" functionality, the platform's flexibility allows for several effective workarounds. By employing techniques such as defining variables in the root module, strategically passing variables to modules, utilizing Terraform Cloud/Enterprise workspaces, integrating tools like Terragrunt or Terramate, or leveraging data sources for shared values, developers can achieve the desired outcome of managing and sharing values across their Terraform configurations. The key is to select the approach that best aligns with the specific needs and structure of your project, ensuring a balance between centralized management and modularity. As your project scales, remember to prioritize clear documentation and consistent naming conventions to maintain a clean and understandable codebase. By understanding these different approaches and their respective strengths, you can effectively manage shared values in your Terraform projects, promoting code reusability and consistency without compromising the platform's core principles of modularity and encapsulation.

References

Were You Able to Follow the Instructions?

šŸ˜Love it!
šŸ˜ŠYes
šŸ˜Meh-gical
šŸ˜žNo
šŸ¤®Clickbait