Terraform_variables
Chapter 35: Terraform Variables
Section titled “Chapter 35: Terraform Variables”This chapter covers input variables, output values, and local values in Terraform.
Input Variables
Section titled “Input Variables”Input variables let you parameterize your Terraform configurations, making them flexible and reusable.
┌─────────────────────────────────────────────────────────────────────────────┐│ Input Variables Overview │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌───────────────────────────────────────────────────────────────────┐ ││ │ Variable Declaration │ ││ │ │ ││ │ variable "name" { │ ││ │ type = string # or number, bool, list, map │ ││ │ description = "Explanation" │ ││ │ default = "value" # Optional │ ││ │ validation = { ... } # Optional │ ││ │ sensitive = false # Optional │ ││ │ nullable = true # Optional │ ││ │ } │ ││ └───────────────────────────────────────────────────────────────────┘ ││ ││ Variable Types: ││ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ││ │ string │ │ number │ │ bool │ │ list │ │ map │ ││ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ││ │└─────────────────────────────────────────────────────────────────────────────┘Variable Types
Section titled “Variable Types”# String variablevariable "environment" { description = "Environment name" type = string default = "dev"}
# Number variablevariable "instance_count" { description = "Number of instances to create" type = number default = 3}
# Boolean variablevariable "enable_monitoring" { description = "Enable CloudWatch monitoring" type = bool default = true}
# List (array) variablevariable "availability_zones" { description = "AZs for subnets" type = list(string) default = ["us-east-1a", "us-east-1b", "us-east-1c"]}
# Map variablevariable "instance_tags" { description = "Tags for instances" type = map(string) default = { Environment = "Production" Team = "Platform" Project = "WebApp" }}
# Set variablevariable "allowed_cidrs" { description = "Allowed CIDR blocks" type = set(string) default = ["10.0.0.0/16", "192.168.0.0/24"]}
# Object variablevariable "web_server_config" { description = "Web server configuration" type = object({ instance_type = string volume_size = number ami_id = string }) default = { instance_type = "t3.medium" volume_size = 50 ami_id = "ami-0c55b159cbfafe1f0" }}
# Tuple variablevariable "config_values" { description = "Configuration values" type = tuple([string, number, bool]) default = ["value1", 42, true]}Variable Validation
Section titled “Variable Validation”variable "environment" { description = "Deployment environment" type = string
validation { condition = contains(["dev", "staging", "prod"], var.environment) error_message = "Environment must be dev, staging, or prod." }}
variable "instance_type" { description = "EC2 instance type" type = string
validation { condition = can(regex("^t[23]\\..*", var.instance_type)) error_message = "Instance type must be t2 or t3 family." }}
variable "port" { description = "Port number" type = number
validation { condition = var.port > 0 && var.port < 65536 error_message = "Port must be between 1 and 65535." }}Using Variables in Configuration
Section titled “Using Variables in Configuration”# In main.tfvariable "region" { description = "AWS region" type = string default = "us-east-1"}
variable "vpc_cidr" { description = "VPC CIDR block" type = string default = "10.0.0.0/16"}
variable "instance_type" { description = "EC2 instance type" type = string default = "t3.micro"}
variable "environment" { description = "Environment name" type = string}
# Using variables in resourcesprovider "aws" { region = var.region}
resource "aws_vpc" "main" { cidr_block = var.vpc_cidr
tags = { Name = "${var.environment}-vpc" Environment = var.environment }}
resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = var.instance_type
count = var.instance_count
tags = { Name = "${var.environment}-web-${count.index + 1}" }}Variable Sources
Section titled “Variable Sources”Variables can be provided from multiple sources, in order of precedence:
┌─────────────────────────────────────────────────────────────────────────────┐│ Variable Precedence (Highest to Lowest) │├─────────────────────────────────────────────────────────────────────────────┤│ ││ 1. Command line: -var='name=value' ← Highest priority ││ 2. Command line: -var-file=file.tfvars ││ 3. Environment variables: TF_VAR_name ││ 4. terraform.tfvars file ││ 5. terraform.tfvars.json file ││ 6. *.auto.tfvars file ││ 7. Default value in variable declaration ← Lowest priority ││ │└─────────────────────────────────────────────────────────────────────────────┘Variable Files
Section titled “Variable Files”environment = "production"region = "us-east-1"instance_type = "t3.small"
# Or JSON format: terraform.tfvars.json{ "environment": "production", "region": "us-east-1", "instance_type": "t3.small"}
# environment.tfvars - environment-specificenvironment = "staging"instance_type = "t3.medium"
# prod.tfvarsenvironment = "prod"instance_type = "t3.large"Environment Variables
Section titled “Environment Variables”# Set as environment variablesexport TF_VAR_region="us-west-2"export TF_VAR_environment="production"export TF_VAR_instance_type="t3.large"
# Terraform automatically reads theseterraform planCommand Line Variables
Section titled “Command Line Variables”# Single variableterraform apply -var="environment=prod"
# Multiple variablesterraform apply -var="environment=prod" -var="region=us-west-2"
# Variable fileterraform apply -var-file="prod.tfvars"
# Override defaultterraform apply -var="instance_type=t3.large" -var-file="prod.tfvars"Output Values
Section titled “Output Values”Output values expose values from your Terraform configuration.
┌─────────────────────────────────────────────────────────────────────────────┐│ Output Values Concept │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌───────────────────────────────────────────────────────────────────┐ ││ │ Output Declaration │ ││ │ │ ││ │ output "name" { │ ││ │ description = "Explanation" │ ││ │ value = resource.attribute │ ││ │ sensitive = false # Optional │ ││ │ depends_on = [...] # Optional │ ││ │ } │ ││ └───────────────────────────────────────────────────────────────────┘ ││ ││ Use cases: ││ ✓ Pass outputs to other configurations ││ ✓ Display information after apply ││ ✓ Share data between modules ││ │└─────────────────────────────────────────────────────────────────────────────┘Output Examples
Section titled “Output Examples”# Basic outputoutput "instance_id" { description = "ID of the EC2 instance" value = aws_instance.web.id}
# Multiple outputsoutput "vpc_info" { description = "VPC information" value = { id = aws_vpc.main.id cidr = aws_vpc.main.cidr_block subnets = aws_subnet.public[*].id }}
# Sensitive output (won't display in console)output "database_password" { description = "Database password" value = aws_db_instance.main.password sensitive = true}
# Conditional outputoutput "elb_dns" { description = "Load balancer DNS" value = aws_lb.web.dns_name # Only show if load balancer exists}
# Output with depends_onoutput "instance_ip" { description = "Public IP of instance" value = aws_instance.web.public_ip depends_on = [aws_instance.web]}Local Values
Section titled “Local Values”Local values assign a name to an expression, making configurations more readable.
┌─────────────────────────────────────────────────────────────────────────────┐│ Local Values Concept │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌───────────────────────────────────────────────────────────────────┐ ││ │ Locals Block │ ││ │ │ ││ │ locals { │ ││ │ name = expression │ ││ │ } │ ││ └───────────────────────────────────────────────────────────────────┘ ││ ││ Benefits: ││ ✓ Reduce repetition ││ ✓ Improve readability ││ ✓ Calculate derived values ││ │└─────────────────────────────────────────────────────────────────────────────┘Local Examples
Section titled “Local Examples”# Basic localslocals { environment = "production" project_name = "myapp"
# Common tags applied to all resources common_tags = { Project = local.project_name Environment = local.environment ManagedBy = "Terraform" }}
# Using locals in resourcesresource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t3.micro"
tags = local.common_tags}
resource "aws_s3_bucket" "data" { bucket = "${local.project_name}-data-${var.environment}"
tags = local.common_tags}
# Complex expressions in localslocals { # Merge maps tags = merge(var.custom_tags, { Environment = var.environment Project = "MyApp" })
# Conditional values instance_type = var.environment == "prod" ? "t3.large" : "t3.micro"
# String interpolation name_prefix = "${var.project}-${var.environment}"
# List operations subnet_count = length(var.availability_zones)}
# Using functions in localslocals { # String functions lowercase_name = lower(var.Name) sanitized_name = replace(var.Name, "/[^a-z0-9-]/", "-")
# Map functions environment_map = { dev = { instance_type = "t3.micro", replicas = 1 } staging = { instance_type = "t3.small", replicas = 2 } prod = { instance_type = "t3.large", replicas = 3 } }
selected_config = local.environment_map[var.environment]}Complete Example
Section titled “Complete Example”variable "project" { description = "Project name" type = string}
variable "environment" { description = "Environment (dev/staging/prod)" type = string default = "dev"}
variable "region" { description = "AWS region" type = string default = "us-east-1"}
variable "vpc_cidr" { description = "VPC CIDR block" type = string default = "10.0.0.0/16"}
variable "instance_type" { description = "EC2 instance type" type = string default = "t3.micro"}
variable "instance_count" { description = "Number of instances" type = number default = 1}
# locals.tflocals { name_prefix = "${var.project}-${var.environment}"
common_tags = { Project = var.project Environment = var.environment ManagedBy = "Terraform" }}
# outputs.tfoutput "vpc_id" { description = "ID of the VPC" value = aws_vpc.main.id}
output "instance_ids" { description = "IDs of EC2 instances" value = aws_instance.web[*].id}
output "instance_ips" { description = "Public IPs of EC2 instances" value = aws_instance.web[*].public_ip}
# main.tfprovider "aws" { region = var.region}
resource "aws_vpc" "main" { cidr_block = var.vpc_cidr
tags = local.common_tags}
resource "aws_instance" "web" { count = var.instance_count
ami = "ami-0c55b159cbfafe1f0" instance_type = var.instance_type subnet_id = aws_subnet.main[0].id
tags = merge(local.common_tags, { Name = "${local.name_prefix}-web-${count.index + 1}" })}
resource "aws_subnet" "main" { count = var.instance_count > 1 ? 2 : 1
vpc_id = aws_vpc.main.id cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index) availability_zone = var.region == "us-east-1" ? "us-east-1${["a", "b"][count.index]}" : "us-west-2${["a", "b"][count.index]}"
tags = local.common_tags}Summary
Section titled “Summary”In this chapter, you learned:
- Input Variables: Types (string, number, bool, list, map, object), validation
- Variable Sources: CLI, files, environment variables, defaults
- Output Values: Exposing resource attributes, sensitive outputs
- Local Values: Reducing repetition, improving readability