11 — Master HCL, CLI & Glossary Cheatsheet
Code: 01 - basics / cheatsheet / main . tf · All 02 - gcp - terraform / roots
1. All-in-One Annotated HCL Template
# ============================================================================
# 1. TERRAFORM & PROVIDERS (versions.tf / providers.tf / backend.tf)
# ============================================================================
terraform {
required_version = ">= 1.7, < 2.0" # Pin CLI version
required_providers { # Read during `terraform init`
local = {
source = "hashicorp/local"
version = "~> 2.4.1" # Patch updates only (>= 2.4.1, < 2.5.0)
}
google = {
source = "hashicorp/google"
version = "~> 8.0" # Minor updates allowed (>= 8.0, < 9.0)
}
}
backend "gcs" { # Partial config: pass bucket/prefix via -backend-config
# bucket = "my-tfstate-bucket"
# prefix = "app/state"
}
}
provider "google" { # Default provider (read during plan/apply)
project = var.project_id # Fallback default if resource omits `project`
region = "us-central1"
}
provider "google" { # Aliased provider for multi-region/project
alias = "us_east"
project = var.project_id
region = "us-east1"
}
# ============================================================================
# 2. VARIABLES & LOCALS (variables.tf / locals.tf)
# Precedence (low -> high): default < TF_VAR_x < terraform.tfvars < *.auto.tfvars < -var/-var-file
# ============================================================================
variable "project_id" {
description = "Target GCP project ID"
type = string
}
variable "environments" {
type = set ( string ) # Use `set(string)` or `map` for `for_each`
default = [ "dev", "staging" ]
validation {
condition = alltrue ([ for e in var.environments : contains ([ "dev", "staging", "prod" ], e )])
error_message = "Allowed environments: dev, staging, prod."
}
}
variable "api_token" {
type = string
sensitive = true # Masks CLI stdout only; still plaintext in state!
}
locals { # Block is plural `locals`, reference is singular `local.`
name_prefix = "acme-${terraform.workspace}"
is_prod = terraform.workspace == "prod"
common_labels = { managed_by = "terraform" , env = terraform.workspace }
}
# ============================================================================
# 3. DATA SOURCES (data.tf) — Queried LIVE on every plan/apply; never destroyed
# ============================================================================
data "google_project" "current" {
project_id = var.project_id
}
data "google_client_config" "default" {} # Fresh 1-hour OAuth token on every run
# ============================================================================
# 4. RESOURCES, META-ARGUMENTS & MODULES (main.tf)
# ============================================================================
resource "google_service_account" "env_sa" {
for_each = var.environments # Keyed state address: google_service_account.env_sa["dev"]
account_id = "${local.name_prefix}-${each.key}"
display_name = "SA for ${each.value}"
lifecycle {
prevent_destroy = false
create_before_destroy = true
ignore_changes = [ display_name ] # Attribute identifiers, never quoted strings
}
}
resource "google_project_iam_member" "sql_client" {
for_each = google_service_account.env_sa # Chained `for_each` guarantees matching keys
project = var.project_id
role = "roles/cloudsql.client"
member = "serviceAccount:${each.value.email}" # Implicit dependency edge
}
resource "google_storage_bucket" "east_logs" {
count = local.is_prod ? 1 : 0 # Conditional 0/1 list
provider = google.us_east # Route to aliased provider
name = "${local.name_prefix}-east-logs-${var.project_id}"
location = "US-EAST1"
uniform_bucket_level_access = true
dynamic "lifecycle_rule" { # Repeats nested blocks inside 1 resource
for_each = [{ age = 30 , class = "NEARLINE" }, { age = 90, class = "COLDLINE" }]
content {
condition { age = lifecycle_rule.value.age }
action {
type = "SetStorageClass"
storage_class = lifecycle_rule.value.class
}
}
}
depends_on = [ google_project_iam_member.sql_client ] # Only for edges invisible to HCL
}
module "app_vm" {
source = "./modules/gcp-vm"
providers = { google = google.us_east } # Aliased providers must be passed explicitly
zone = "us-east1-b"
}
# ============================================================================
# 5. OUTPUTS (outputs.tf)
# ============================================================================
output "sa_emails" { # Structured output -> read with `terraform output -json`
value = { for k , sa in google_service_account.env_sa : k = > sa.email }
}
output "east_bucket_name" { # Safe read of `count = 0/1` resource via `one()`
value = one ( google_storage_bucket.east_logs [ * ]. name )
}
2. Complete CLI Reference
Core Lifecycle & Validation
Command
Purpose
terraform init
Download provider plugins into .terraform / , initialize backend, write .terraform.lock.hcl
terraform init -upgrade
Re-resolve newest provider/module versions allowed by constraints and update lock file
terraform init -migrate-state
Reconfigure backend and interactively migrate existing state to the new backend
terraform fmt -check -recursive
Check canonical HCL formatting across all subdirectories (exits non-zero on drift)
terraform validate
Verify syntax, types, and attribute names offline (no API calls)
terraform plan -out=tf.plan
Refresh state, compute 3-way diff, and save an immutable execution plan artifact
terraform apply tf.plan
Execute an already-reviewed plan artifact without re-prompting
terraform destroy
Destroy all resources tracked in the current workspace's state (data sources untouched)
Targeting, Replacement & Variables
Command
Purpose
terraform plan - var = "k=v"
Override variable with highest CLI precedence
terraform plan - var - file = "prod.tfvars"
Explicitly load a . tfvars file
terraform plan -refresh=false
Skip live API refresh; compute plan against cached state (emergency outage use only)
terraform apply - replace =< addr >
Force destroy + recreate of a specific resource instance (replaces terraform taint)
terraform plan - target =< addr >
Scope plan/apply to one resource/module and its upstream dependencies (debugging only)
State Inspection & Surgery
Command
Purpose
terraform state list
List all resource addresses tracked in current state
terraform state show < addr >
Inspect all recorded attributes of a single resource in state
terraform state mv <old> <new>
Rename resource address in state without destroying/recreating real infra
terraform state rm < addr >
Remove resource from state management without deleting the real cloud resource
terraform import < addr > < cloud_id >
Bind an existing unmanaged cloud resource to an HCL address in state
terraform state pull > state.json
Download raw state JSON from remote backend to stdout
terraform force-unlock <LOCK_ID>
Break a stale backend mutex lock after verifying no other process is running
Outputs, Graph, Workspaces & Debugging
Command
Purpose
terraform output -raw <name>
Print bare primitive output string (for shell variable assignment)
terraform output -json <name>
Print structured map/list output as JSON (pipe to jq)
terraform console
Interactive REPL to test for , try(), jsondecode(), and local expressions against state
terraform graph \| dot -Tsvg > graph.svg
Render the resource dependency DAG via Graphviz
terraform workspace list / show / new / select
Inspect, create, or switch isolated state workspaces
TF_LOG=DEBUG TF_LOG_PATH=tf.log terraform plan
Capture verbose provider/API HTTP traces to a file
3. Architectural Glossary (One-Line Lookup)
Term
Architect's Definition
ADC
Application Default Credentials (~/.config/gcloud/application_default_credentials.json); stores a long-lived OAuth refresh token used automatically by the google provider.
Backend
Storage + locking engine for terraform.tfstate (e.g., local, gcs); configured at init time and cannot interpolate variables.
Blast Radius
The set of resources sharing a single root module and terraform.tfstate file.
Data Source (data)
Read-only block queried live on every plan/apply; fails immediately if the target object is missing.
Drift
Divergence between live cloud reality and terraform.tfstate caused by out-of-band changes; corrected toward HCL on next apply.
dynamic Block
Repeats nested configuration blocks inside a single resource without creating multiple resource instances.
Force Replacement (ForceNew)
Provider schema rule requiring destroy + create when an immutable cloud attribute (e.g., account_id, machine_type ) is modified.
Guard Propagation
Architectural requirement that every downstream for_each or reference consuming a conditionally filtered map must use the same filtered keyset or a null-safe wrapper (try/one).
Implicit Dependency
A DAG ordering edge automatically inferred by Terraform Core when Resource B references an attribute of Resource A.
Lock File (.terraform.lock.hcl )
Committed file recording exact provider versions and cryptographic hashes selected during terraform init.
Meta-Argument
Core-interpreted argument valid across all resource types: count, for_each, depends_on, provider, lifecycle.
Workload Identity
Keyless GKE authentication mechanism linking a Kubernetes ServiceAccount (via annotation) to a GCP IAM Service Account (via roles / iam . workloadIdentityUser ).
Answered: 0 / 0
Correct: 0 / 0
Reset