🎯 Goal: Add safety rails to your configs — validate inputs, handle time, read files, and crunch numbers safely.

✅ You’ll master:


🛡️ 1. Validation Functions — Fail Fast, Fail Safe

✏️ variables.tf — Safe Instance Types

variable "instance_type" {
  description = "EC2 instance type (T2/T3 only)"
  type        = string
  default     = "t3.micro"

  validation {
    # 🔹 Rule 1: Length 2–20 chars
    condition = (
      length(var.instance_type) >= 2 &&
      length(var.instance_type) <= 20
    )
    error_message = "Instance type must be 2–20 characters."
  }

  validation {
    # 🔹 Rule 2: Must match t2./t3. (e.g., t3.micro)
    condition = can(regex("^t[23]\\\\\\\\.\\\\\\\\w+$", var.instance_type))
    error_message = "Instance type must be t2.* or t3.* (e.g., t3.micro)."
  }
}

How can(regex(...)) works:

💡 Pro Tip:

Use can() with any error-prone function: can(cidrhost(...)), can(jsondecode(...)).


✅ Bonus: endswith() & sensitive

# Enforce backup naming: "db-prod-backup"
variable "backup_name" {
  type = string
  validation {
    condition     = endswith(var.backup_name, "-backup")
    error_message = "Backup name must end with '-backup'."
  }
}

# Hide secrets in logs/state
variable "api_key" {
  type      = string
  sensitive = true  # 🔒 Masks in `plan`/`output`
  # ⚠️ Still base64-encoded in state — use Vault/SSM for true secrets!
}


🔢 2. Numeric Functions — Math with Lists

Problem: Calculate Costs from Mixed Signs

variable "monthly_costs" {
  type    = list(number)
  default = [200, -50, 300, 75]  # Negative = credit
}

✅ Solution: for + abs() + sum(...)

(Yes — the spread operator ... is critical!)

locals {
  # 🔹 Convert all to positive (abs per element)
  positive_costs = [for c in var.monthly_costs : abs(c)]
  # → [200, 50, 300, 75]

  # 🔹 Use `...` to unpack list → args for sum/max/min
  total_cost = sum(local.positive_costs...)    # → 625
  max_cost   = max(local.positive_costs...)    # → 300
  min_cost   = min(local.positive_costs...)    # → 50
  avg_cost   = local.total_cost / length(local.positive_costs)  # → 156.25
}