agentskills.codes
TE

terraform-values

Manage Terraform values including input variables, local values, and output values. Use when asked about "variables", "locals", "outputs", "input values", "how to pass values", "variable validation", "sensitive values", or when defining module interfaces, reusing expressions, or exposing data. Cover

Install

mkdir -p .claude/skills/terraform-values-luscii && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15331" && unzip -o skill.zip -d .claude/skills/terraform-values-luscii && rm skill.zip

Installs to .claude/skills/terraform-values-luscii

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Manage Terraform values including input variables, local values, and output values. Use when asked about "variables", "locals", "outputs", "input values", "how to pass values", "variable validation", "sensitive values", or when defining module interfaces, reusing expressions, or exposing data. Covers variable types, defaults, validation, precedence, locals usage patterns, and output configuration.
400 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)

About this skill

Terraform Values

Comprehensive guide to managing values in Terraform modules including input variables, local values, and output values. Learn how to create flexible, composable, and reusable modules.

When to Use This Skill

  • User asks about "variables", "locals", "outputs", "input values"
  • Questions about "how to pass values to modules"
  • "Variable validation", "type constraints", "sensitive values"
  • Defining module interfaces and boundaries
  • Reusing expressions within modules
  • Exposing module data to CLI, HCP Terraform, or other configurations
  • Variable precedence and assignment methods

Value Types Overview

Object Syntax in Lists and Maps

HCL object syntax rules:

  • Single-line object: Always use commas between key-value pairs. Example:
    log_sources = [
      { name = "php", container = "app" },
      { name = "nginx", container = "web" }
    ]
    
  • Multi-line object: Each key on a separate line, no commas needed. Example:
    log_sources = [
      {
        name      = "php"
        container = "app"
      },
      {
        name      = "nginx"
        container = "web"
      }
    ]
    

Maps and objects in variables, locals, and tests must follow these conventions.

Terraform uses three types of values to manage data flow:

TypePurposeScopeReference
VariablesModule inputsModule-specificvar.<NAME>
LocalsReusable expressionsModule-scopedlocal.<NAME>
OutputsModule data exportCross-moduleoutput.<NAME> or module.<NAME>.<OUTPUT>

Value Flow:

Variables (input) → Locals (processing) → Resources → Outputs (export)

Input Variables

Variables define the input interface of your module, letting consumers customize behavior without modifying source code.

Variable Definition

Basic Syntax:

variable "name" {
  type        = type_constraint
  description = "Description of the variable"
  default     = default_value
  sensitive   = true/false
  nullable    = true/false
  validation {
    # Validation rules
  }
}

Complete Example:

variable "instance_type" {
  type        = string
  description = "EC2 instance type for the web server"
  default     = "t2.micro"

  validation {
    condition     = can(regex("^t[23]\\.", var.instance_type))
    error_message = "Instance type must be t2 or t3 family."
  }
}

variable "subnet_id" {
  type        = string
  description = "Subnet ID where the web server will be deployed"
  # No default - required input
}

variable "environment" {
  type        = string
  description = "Deployment environment name"
  default     = "dev"

  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Environment must be dev, staging, or prod."
  }
}

Variable Arguments

type

Specifies the value type constraint:

Simple Types:

variable "name" {
  type = string
}

variable "count" {
  type = number
}

variable "enabled" {
  type = bool
}

Collection Types:

variable "tags" {
  type = map(string)
}

variable "subnet_ids" {
  type = list(string)
}

variable "ports" {
  type = set(number)
}

Structural Types:

variable "config" {
  type = object({
    name    = string
    port    = number
    enabled = bool
  })
}

variable "instances" {
  type = list(object({
    name = string
    size = string
  }))
}

variable "settings" {
  type = map(object({
    value   = string
    enabled = bool
  }))
}

Optional Attributes:

variable "server" {
  type = object({
    name     = string
    port     = optional(number, 80)      # Default: 80
    enabled  = optional(bool, true)       # Default: true
    tags     = optional(map(string), {})  # Default: {}
  })
}

Any Type:

variable "custom_data" {
  type        = any
  description = "Custom data of any type"
}

description

Always provide clear descriptions:

# ✅ Good - Specific and helpful
variable "subnet_id" {
  type        = string
  description = "Subnet ID where the web server will be deployed"
}

# ❌ Bad - Vague
variable "subnet_id" {
  type        = string
  description = "Subnet"
}

default

Makes variables optional:

# Required variable (no default)
variable "vpc_id" {
  type        = string
  description = "VPC ID for resource deployment"
}

# Optional variable (has default)
variable "instance_type" {
  type        = string
  description = "EC2 instance type"
  default     = "t2.micro"
}

# Complex default
variable "tags" {
  type        = map(string)
  description = "Resource tags"
  default = {
    Terraform = "true"
    ManagedBy = "terraform"
  }
}

sensitive

Prevents values from appearing in CLI output:

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

Behavior:

$ terraform plan
# Password value not shown in plan output

$ terraform output database_password
database_password = <sensitive>

Warning: Sensitive values are still stored in state. Use ephemeral (Terraform 1.10+) to omit from state entirely.

nullable

Controls whether null is accepted:

# Allows null (default behavior)
variable "optional_value" {
  type     = string
  nullable = true
  default  = null
}

# Rejects null
variable "required_value" {
  type     = string
  nullable = false
  # If no value provided, Terraform errors
}

validation

Add custom validation rules:

Basic Validation:

variable "environment" {
  type        = string
  description = "Deployment environment"

  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Environment must be dev, staging, or prod."
  }
}

Regex Validation:

variable "subnet_id" {
  type        = string
  description = "AWS subnet ID"

  validation {
    condition     = can(regex("^subnet-[a-f0-9]{8,17}$", var.subnet_id))
    error_message = "Subnet ID must be a valid AWS subnet ID format."
  }
}

Numeric Range Validation:

variable "max_size" {
  type        = number
  description = "Maximum cluster size"

  validation {
    condition     = var.max_size >= 1 && var.max_size <= 10
    error_message = "Max size must be between 1 and 10."
  }
}

Multiple Validations:

variable "instance_config" {
  type = object({
    type = string
    size = number
  })

  validation {
    condition     = contains(["t2.micro", "t2.small", "t2.medium"], var.instance_config.type)
    error_message = "Instance type must be t2.micro, t2.small, or t2.medium."
  }

  validation {
    condition     = var.instance_config.size >= 8 && var.instance_config.size <= 100
    error_message = "Instance size must be between 8 and 100 GB."
  }
}

Cross-Field Validation:

variable "min_size" {
  type = number
}

variable "max_size" {
  type = number

  validation {
    condition     = var.max_size >= var.min_size
    error_message = "Max size must be greater than or equal to min size."
  }
}

Referencing Variables

Use var.<NAME> syntax:

resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = var.instance_type
  subnet_id     = var.subnet_id

  tags = {
    Environment = var.environment
    Name        = "${var.environment}-web-server"
  }
}

Assigning Variable Values

Value Precedence

Terraform applies variable values in this order (highest to lowest):

  1. Command-line flags (-var, -var-file) and HCP Terraform variables
  2. Auto-loaded files (*.auto.tfvars, *.auto.tfvars.json) in lexical order
  3. terraform.tfvars.json
  4. terraform.tfvars
  5. Environment variables (TF_VAR_*)
  6. Variable default argument

Later sources override earlier ones.

Command-Line Variables

# Single variable
terraform apply -var="instance_type=t3.medium"

# Multiple variables
terraform apply \
  -var="instance_type=t3.medium" \
  -var="environment=prod"

# Complex types (use JSON)
terraform apply -var='subnet_ids=["subnet-12345","subnet-67890"]'

Variable Definition Files

Create .tfvars files:

# production.tfvars
instance_type     = "t3.large"
environment      = "prod"
subnet_ids       = ["subnet-12345", "subnet-67890"]
enable_monitoring = true

Auto-loaded files:

  • *.auto.tfvars (loaded automatically)
  • *.auto.tfvars.json (loaded automatically)
  • terraform.tfvars (loaded automatically)
  • terraform.tfvars.json (loaded automatically)

Manual loading:

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

JSON format:

{
  "instance_type": "t3.large",
  "environment": "prod",
  "subnet_ids": ["subnet-12345", "subnet-67890"],
  "enable_monitoring": true
}

Environment Variables

Use TF_VAR_ prefix:

# Simple values
export TF_VAR_instance_type=t3.medium
export TF_VAR_environment=staging

# Complex values (use JSON)
export TF_VAR_subnet_ids='["subnet-12345","subnet-67890"]'
export TF_VAR_config='{"key": "value", "enabled": true}'

terraform apply

HCP Terraform Variables

Set variables in workspace settings:

  • Terraform Variables - Input to configuration
  • Environment Variables - Shell environment (e.g., AWS_ACCESS_KEY_ID)
  • Variable Sets - Reusable groups applied to multiple workspaces

Variable Best Practices

Do's:

Always add descriptions

variable "instance_type" {
  type        = string
  description = "EC2 instance type for the web server"
  default     = "t2.micro"
}

Use type constraints

variable "tags" {
  type = map(string)
}

Add validation for important values

validation {
  condition     = contains(["dev", "staging", "prod"], var.environment)
  error_message = "Environment must be dev, staging, or prod."
}


Content truncated.

Search skills

Search the agent skills registry