Terraform Tutorial — Workflow Practice Exercises
Practice the Terraform init → plan → apply → destroy workflow.
Exercise 1: First Project Workflow
Task: You have a new directory with a main.tf that creates an S3 bucket. List the exact commands you would run in order to create the bucket.
Answer
$ terraform init # Download AWS provider
$ terraform validate # Check configuration syntax
$ terraform fmt # Format files consistently
$ terraform plan # Preview what will be created
$ terraform apply # Create the S3 bucket (type 'yes' to confirm)
Exercise 2: CI/CD Pipeline
Task: Write the Terraform commands for a CI/CD pipeline where: plan runs automatically, but apply requires manual approval.
Answer
# Automated plan stage
terraform init -input=false
terraform validate
terraform fmt -check -recursive
terraform plan -out=tfplan -input=false -detailed-exitcode
# After manual approval
terraform apply -input=false tfplan
Key flags:
-input=falseprevents interactive prompts-out=tfplansaves the plan for later-detailed-exitcodereturns exit code 2 if changes exist (useful for pipeline logic)
Exercise 3: Partial Apply
Task: You have 10 resources but only want to apply changes to aws_instance.web. What command do you use and what’s the risk?
Answer
$ terraform apply -target=aws_instance.web
Risk: -target skips dependent resources. If aws_instance.web depends on a security group that also changed, the security group change won’t be applied. Use targeting only for debugging, not regular workflow.
Exercise 4: Recovering from a Failed Apply
Task: Your terraform apply created a VPC and subnet, but failed when creating the EC2 instance (API timeout). What happens to the state and what should you do?
Answer
Terraform saves the state with the VPC and subnet already recorded. The EC2 instance is not in state because it failed.
What to do:
$ terraform apply
Simply run apply again. Terraform sees the VPC and subnet already exist (from state), skips them, and only creates the EC2 instance.
Chapter Summary
In this chapter, you learned:
- init: Downloads providers, modules, configures backend
- validate: Checks syntax without API calls
- fmt: Enforces consistent formatting
- plan: Previews changes with
+,~,-symbols - apply: Executes changes, updates state
- destroy: Removes all managed resources
- Key flags:
-auto-approve,-out,-target,-input=false,-detailed-exitcode - CI/CD pattern: init → validate → fmt check → plan (save) → approve → apply (saved plan)
Next up: Data Sources — reading existing infrastructure.