Understanding Terraform: Locals vs Variables vs Data Sources

Terraform is a powerful Infrastructure as Code (IaC) tool that allows you to define and manage your infrastructure using declarative configuration files. Three important concepts in Terraform that often confuse beginners are locals, variables, and data sources. In this blog post, we’ll explore each of these concepts, their use cases, and how they differ from one another.

Variables

Variables in Terraform are used to parameterize your configurations, making them more flexible and reusable.

Key characteristics:

  • Defined using the variable block
  • Can have default values
  • Can be overridden at runtime
  • Useful for values that might change between environments or deployments

Example:

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

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

Locals

Locals in Terraform are like local variables in programming. They allow you to assign a name to an expression, which you can then use multiple times within a module.

Key characteristics:

  • Defined using the locals block
  • Computed once and reused
  • Cannot be overridden from outside the module
  • Useful for simplifying complex expressions or calculations

Example:

locals {
  common_tags = {
    Environment = "Production"
    Project     = "MyApp"
  }
}

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  tags          = local.common_tags
}

Data Sources

Data sources in Terraform allow you to fetch or compute data that you can use elsewhere in your configuration. They’re a way to query external systems for information.

Key characteristics:

  • Defined using the data block
  • Read-only
  • Used to fetch existing information, not to create or modify resources
  • Useful for retrieving information about existing infrastructure or external services

Example:

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }
}

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

Comparison

FeatureVariablesLocalsData Sources
PurposeParameterizationSimplificationExternal data retrieval
ScopeModule and child modulesCurrent module onlyCurrent module and child modules
ModifiableYes, at runtimeNoNo
ComputedNoYesYes
External InputYesNoYes

When to Use Each

  • Use variables when you need to accept input that might change between different uses of your module or when you want to allow users of your module to customize its behavior.
  • Use locals when you have expressions that you’ll reuse multiple times in your configuration or when you want to simplify complex calculations.
  • Use data sources when you need to fetch information about existing resources or when you need to query external systems for data to use in your Terraform configuration.

By understanding and properly utilizing these three concepts, you can create more flexible, maintainable, and powerful Terraform configurations.

Remember, the key to mastering Terraform is practice. Try incorporating these concepts into your next infrastructure project and see how they can improve your workflow!