TFLAB14-for Expressions: Transforming Lists and Maps

for Expressions: Transforming Lists and Maps

🔧 Terraform Core ⭐ Intermediate [for ...] {for ...} Filtering with if Transformations

Scenario

You have a list of server names and need to transform them — add a prefix, convert to uppercase, filter only production servers, or restructure data from lists to maps. for expressions let you transform, filter, and reshape data inline without writing any external scripts.

Your Objectives
  • Use [for ... ] to transform a list (add prefix, uppercase).
  • Use {for ... } to convert a list into a map.
  • Use if inside a for expression to filter elements.
  • Use a for expression to iterate over a map's key-value pairs.
  • Output the results to see exactly what each expression produces.

Additional Context

[for ...] (square brackets) produces a list. {for ...} (curly braces) produces a map. The if clause at the end filters which items are included.

These are expressions, not blocks. They can be used anywhere a value is expected — in locals, outputs, resource attributes, variable defaults, etc.

main.tf

# main.tf — no cloud resources needed, just expressions and outputs

terraform {
  required_version = ">= 1.5.0"
}

variable "servers" {
  type    = list(string)
  default = ["web-prod-01", "web-dev-01", "api-prod-01", "api-dev-01", "db-prod-01"]
}

variable "team_members" {
  type = map(string)
  default = {
    alice   = "admin"
    bob     = "developer"
    charlie = "developer"
    dave    = "viewer"
  }
}

locals {
  # ─── LIST → LIST: Transform each element ───
  # [for item in list : expression]
  uppercased = [for s in var.servers : upper(s)]
  prefixed   = [for s in var.servers : "srv-${s}"]

  # ─── LIST → LIST: Filter with if ───
  # Only include items that match a condition
  prod_servers = [for s in var.servers : s if can(regex("prod", s))]
  dev_servers  = [for s in var.servers : s if can(regex("dev", s))]

  # ─── LIST → MAP: Convert list to map ───
  # {for item in list : key_expr => value_expr}
  server_map = { for s in var.servers : s => upper(s) }

  # ─── MAP → LIST: Extract from map ───
  admin_users = [for name, role in var.team_members : name if role == "admin"]
  dev_users   = [for name, role in var.team_members : name if role == "developer"]

  # ─── MAP → MAP: Transform values ───
  uppercase_roles = { for name, role in var.team_members : name => upper(role) }

  # ─── Indexed for (with index) ───
  indexed_servers = { for i, s in var.servers : i => s }
}

outputs.tf

# List transformations
output "uppercased"       { value = local.uppercased }
output "prefixed"         { value = local.prefixed }

# Filtered lists
output "prod_servers"     { value = local.prod_servers }
output "dev_servers"      { value = local.dev_servers }

# List → Map
output "server_map"       { value = local.server_map }

# Map filtering and transformation
output "admin_users"      { value = local.admin_users }
output "dev_users"        { value = local.dev_users }
output "uppercase_roles"  { value = local.uppercase_roles }

# Indexed
output "indexed_servers"  { value = local.indexed_servers }

Workflow Commands

# No provider needed — just expressions
terraform init && terraform apply

terraform output prod_servers
terraform output -json uppercase_roles
✓ Expected Outputs
admin_users      = ["alice"]
dev_servers      = ["web-dev-01", "api-dev-01"]
dev_users        = ["bob", "charlie"]
indexed_servers  = { "0" = "web-prod-01", "1" = "web-dev-01", ... }
prefixed         = ["srv-web-prod-01", "srv-web-dev-01", ...]
prod_servers     = ["web-prod-01", "api-prod-01", "db-prod-01"]
server_map       = {
  "api-dev-01"  = "API-DEV-01"
  "api-prod-01" = "API-PROD-01"
  "db-prod-01"  = "DB-PROD-01"
  "web-dev-01"  = "WEB-DEV-01"
  "web-prod-01" = "WEB-PROD-01"
}
uppercase_roles  = {
  "alice"   = "ADMIN"
  "bob"     = "DEVELOPER"
  "charlie" = "DEVELOPER"
  "dave"    = "VIEWER"
}
uppercased       = ["WEB-PROD-01", "WEB-DEV-01", ...]