HashiCorp Terraform / OpenTofu · 6-Phase IaC Deep Dive · HCL, Modules, State, CI/CD & Testing
Live Terraform progress across all teammates
Test your Terraform knowledge
Sync Terraform lab progress across devices.
Essential commands, HCL syntax & patterns — quick reference
| terraform init | Download providers & modules, init backend |
| terraform validate | Check HCL syntax (no API calls) |
| terraform fmt | Auto-format HCL to canonical style |
| terraform plan -out=tfplan | Preview changes, save plan file |
| terraform apply tfplan | Apply saved plan (no prompt) |
| terraform apply -auto-approve | Apply without confirmation (CI) |
| terraform destroy -target=res | Destroy specific resource only |
| terraform output -json | Outputs as machine-readable JSON |
| terraform refresh | Sync state with real cloud (deprecated) |
| terraform plan -refresh-only | Modern drift detection v1.1+ |
| terraform state list | List all managed resource addresses |
| terraform state show <addr> | Show attributes of a resource |
| terraform state mv A B | Rename/move resource in state |
| terraform state rm <addr> | Remove resource from state (not cloud) |
| terraform import <addr> <id> | Import existing cloud resource |
| terraform state pull | Download & print remote state |
| terraform state push <file> | Upload state file Dangerous |
| terraform workspace new dev | Create new workspace |
| terraform workspace select prod | Switch workspace |
variable "instance_type" { type = string default = "t3.micro" description = "EC2 instance type" sensitive = false validation { condition = contains(["t3.micro","t3.small"], var.instance_type) error_message = "Invalid instance type." } } output "bucket_arn" { value = aws_s3_bucket.demo.arn sensitive = false } locals { name_prefix = "${var.project}-${var.env}" common_tags = { Env = var.env, Owner = "ops" } }
# count — simple repetition resource "aws_iam_user" "devs" { count = 3 name = "dev-${count.index}" } # for_each — named resources resource "aws_iam_user" "team" { for_each = toset(["alice","bob"]) name = each.key } # lifecycle lifecycle { create_before_destroy = true prevent_destroy = true ignore_changes = [tags] }
# Local module module "vpc" { source = "./modules/vpc" vpc_cidr = "10.0.0.0/16" environment = var.environment } # Registry module module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0" cidr = "10.0.0.0/16" } # Access output resource ... { vpc_id = module.vpc.vpc_id }
# S3 backend with DynamoDB locking terraform { required_version = ">= 1.5" required_providers { aws = { source = "hashicorp/aws", version = "~> 5.0" } } backend "s3" { bucket = "my-tf-state" key = "prod/terraform.tfstate" region = "us-east-1" dynamodb_table = "tf-lock" encrypt = true } }
| toset(list) | Convert list → set (dedup) |
| tomap(obj) | Convert object → map |
| flatten(list) | Flatten nested lists |
| merge(m1,m2) | Merge maps (m2 overrides) |
| lookup(map,key,def) | Safe map key lookup |
| length(val) | Count items in list/map/string |
| contains(list,val) | Check list membership |
| format(fmt,args...) | String formatting |
| file(path) | Read file contents as string |
| jsonencode(val) | Encode value as JSON string |
| TF_VAR_name=val | Set variable via env var |
| TF_LOG=DEBUG | Enable verbose logging |
| checkov -d . | Scan IaC for misconfigurations |
| tfsec . | Security static analysis |
| terraform test | Run .tftest.hcl tests v1.6+ |
| terragrunt run-all plan | Plan across all modules |
| -var-file=prod.tfvars | Load env-specific variables |
You've completed all Terraform labs!