Advanced Functions
Imagine your Lego city has grown huge. Now you need smarter rules: if it’s a hospital, add an ambulance bay; if it’s a school, add a playground. You also need ways to look up addresses, merge neighborhoods, and handle missing data gracefully.
Terraform’s advanced functions give you this power. They let you apply conditional logic, perform dynamic lookups, and manipulate collections in ways that make your infrastructure truly adaptive.
Key Concepts
1. Conditional Expressions
- Use case: Switch values based on environment flags.
Ternary operator (? :) → Inline conditional logic.
output "env_type" {
value = var.is_prod ? "production" : "development"
}
2. Coalesce Function
- Use case: Provide fallback values when inputs are missing.
coalesce() → Returns the first non‑null value.
output "db_url" {
value = coalesce(var.db_url, "default-db.local")
}
3. Lookup Function
- Use case: Safely access map values without errors.
lookup() → Retrieves a value from a map with a default.
variable "settings" {
default = {
region = "us-east-1"
size = "t2.micro"
}
}
output "region" {
value = lookup(var.settings, "region", "us-west-1")
}
4. Merge Function
- Use case: Build dynamic configurations by merging defaults with overrides.
merge() → Combines multiple maps into one.
output "combined" {
value = merge(
{ region = "us-east-1" },
{ size = "t2.micro" }
)
}
5. Flatten Function
- Use case: Simplify nested structures for iteration.
flatten() → Converts nested lists into a single list.
output "flat_list" {
value = flatten([["a", "b"], ["c", "d"]])
}
``` → `["a", "b", "c", "d"]`
6. Advanced Collection Handling
for expressions → Transform collections dynamically.hcl
output "tags" {
value = { for subnet in var.subnets : subnet => "tagged" }
}
zipmap() → Create a map from two lists.
output "map" {
value = zipmap(["a", "b"], [1, 2])
}
``` → `{ a = 1, b = 2 }`
Hands‑On Lab / Demo
Lab: Dynamic Environment Configuration
- Run
terraform apply→ Outputs:env_type = developmentflat_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]tags = { "10.0.1.0/24" = "env-dev", "10.0.2.0/24" = "env-dev", "10.0.3.0/24" = "env-dev" }
Use advanced functions:
output "env_type" {
value = var.is_prod ? "production" : "development"
}
output "flat_subnets" {
value = flatten(var.subnets)
}
output "tags" {
value = { for subnet in flatten(var.subnets) : subnet => "env-" + (var.is_prod ? "prod" : "dev") }
}
Define variables:
variable "is_prod" {
default = false
}
variable "subnets" {
default = [["10.0.1.0/24"], ["10.0.2.0/24", "10.0.3.0/24"]]
}
Pro Tips & Best Practices
- Use conditional logic for environment‑specific values.
- Always provide defaults with
lookup()andcoalesce(). - Flatten nested lists before iteration.
- Merge maps to combine defaults with overrides.
- Keep expressions readable - complex one‑liners can be hard to maintain.
Summary & Cheatsheet
- Conditional:
? :for inline logic. - Fallbacks:
coalesce()for first non‑null. - Safe lookups:
lookup()with defaults. - Map handling:
merge(),zipmap(). - List handling:
flatten(),forexpressions.
Quick mnemonic: “Condition, Fallback, Lookup, Merge, Flatten.”
The Hackers Notebook
Advanced functions are the alchemy of Terraform. They let you apply conditional logic, handle missing values, and transform complex collections into usable structures. By mastering these, you gain the power to build infrastructure that adapts intelligently to different environments.