Core Workflow and Advanced Features¶
Overview¶
This document covers the Terraform core workflow (init, plan, apply, destroy), workspaces, provisioners, debugging, and other advanced features. The core workflow accounts for 15% of the exam (Domain 6), and advanced features outside the core workflow account for 10% (Domain 4).
π Core Workflow - Write, Plan, Apply workflow
Core Terraform Commands¶
terraform init¶
Initializes the working directory for Terraform operations.
terraform init # Standard initialization
terraform init -upgrade # Upgrade providers and modules
terraform init -reconfigure # Reconfigure backend, discard state
terraform init -migrate-state # Migrate state to new backend
terraform init -backend=false # Skip backend initialization
terraform init -input=false # Disable interactive input
What init does: - Downloads and installs providers into .terraform/providers/ - Downloads modules into .terraform/modules/ - Initializes the backend for state storage - Creates .terraform.lock.hcl (dependency lock file)
When to re-run init: - Adding or changing providers - Adding or changing modules - Changing backend configuration - After terraform init -upgrade to get newer versions
π terraform init - Init command reference
terraform validate¶
Checks configuration syntax and internal consistency.
terraform validate # Validate configuration
terraform validate -json # Output in JSON format
What validate checks: - HCL syntax errors - Attribute names and types - Required arguments - Module references
What validate does NOT check: - Provider credentials or API access - Remote state accessibility - Actual cloud resource availability - Provider-specific validation
π terraform validate - Validate command reference
terraform plan¶
Creates an execution plan showing what changes will be made.
terraform plan # Standard plan
terraform plan -out=plan.tfplan # Save plan to file
terraform plan -destroy # Plan a destroy operation
terraform plan -target=aws_instance.web # Plan for specific resource
terraform plan -var="key=value" # Pass variable
terraform plan -var-file=prod.tfvars # Use variable file
terraform plan -refresh-only # Only refresh state (no changes)
terraform plan -refresh=false # Skip state refresh
terraform plan -parallelism=5 # Limit concurrent operations
terraform plan -generate-config-out=gen.tf # Generate config for imports
Plan output symbols: - + Create - - Destroy - ~ Update in-place - -/+ Destroy and recreate - <= Read (data source)
π terraform plan - Plan command reference
terraform apply¶
Executes the changes defined in the plan.
terraform apply # Apply with interactive approval
terraform apply -auto-approve # Skip approval prompt
terraform apply plan.tfplan # Apply a saved plan file
terraform apply -target=aws_instance.web # Apply specific resource
terraform apply -var="key=value" # Pass variable
terraform apply -parallelism=10 # Concurrent operations limit
terraform apply -replace=aws_instance.web # Force replacement
Key behaviors: - Generates a new plan if no saved plan file is provided - Prompts for approval by default (unless -auto-approve) - Updates state file after each resource operation - Partially applied states are saved (operations are not transactional)
π terraform apply - Apply command reference
terraform destroy¶
Destroys all resources managed by the current configuration.
terraform destroy # Destroy with interactive approval
terraform destroy -auto-approve # Skip approval prompt
terraform destroy -target=aws_instance.web # Destroy specific resource
- Equivalent to
terraform apply -destroy - Destroys resources in reverse dependency order
- Updates state file to reflect destroyed resources
- Only destroys resources tracked in the current state
π terraform destroy - Destroy command reference
terraform fmt¶
Formats configuration files to canonical style.
terraform fmt # Format current directory
terraform fmt -recursive # Format subdirectories too
terraform fmt -check # Check formatting (exit code 0 if formatted)
terraform fmt -diff # Show formatting differences
π terraform fmt - Format command reference
terraform show¶
Displays the current state or a saved plan.
terraform show # Show current state
terraform show plan.tfplan # Show saved plan
terraform show -json # Output in JSON format
terraform output¶
Displays output values from state.
terraform output # Show all outputs
terraform output instance_id # Show specific output
terraform output -json # JSON format
terraform output -raw instance_id # Raw value (no quotes)
terraform graph¶
Generates a visual representation of the dependency graph.
terraform graph # Output DOT format
terraform graph | dot -Tpng > graph.png # Generate image (requires graphviz)
Workspaces¶
Concept¶
- Workspaces provide separate state files for the same configuration
- Each workspace has its own state, enabling environment isolation
- Default workspace is named "default" and cannot be deleted
Commands¶
terraform workspace list # List all workspaces
terraform workspace new dev # Create new workspace
terraform workspace select dev # Switch to workspace
terraform workspace delete dev # Delete workspace
terraform workspace show # Show current workspace
Using Workspaces in Configuration¶
resource "aws_instance" "web" {
instance_type = terraform.workspace == "prod" ? "t3.large" : "t3.micro"
tags = {
Environment = terraform.workspace
}
}
State File Location¶
- Default workspace:
terraform.tfstate - Named workspaces:
terraform.tfstate.d/<workspace>/terraform.tfstate
CLI Workspaces vs Terraform Cloud Workspaces¶
| Feature | CLI Workspaces | Cloud Workspaces |
|---|---|---|
| State isolation | Yes | Yes |
| Variable sets | No (use terraform.workspace) | Yes (per-workspace variables) |
| Access control | No | Yes (team permissions) |
| Remote execution | No | Yes |
| VCS integration | No | Yes |
π Workspaces - Workspace management
Workspace Limitations¶
- Not ideal for entirely different infrastructure sets
- Better suited for same config with different parameters
- No built-in variable management per workspace (use conditionals)
- For complex multi-environment setups, consider separate directories or Terraform Cloud
Provisioners¶
What Are Provisioners?¶
- Execute scripts or commands on local or remote machines
- Used for bootstrapping, configuration, or cleanup
- Considered a last resort by HashiCorp
local-exec¶
resource "aws_instance" "web" {
# ...
provisioner "local-exec" {
command = "echo ${self.public_ip} >> ip_addresses.txt"
}
}
self for resource attributes - Common use: trigger scripts, update files, call APIs remote-exec¶
resource "aws_instance" "web" {
# ...
connection {
type = "ssh"
user = "ubuntu"
private_key = file("~/.ssh/id_rsa")
host = self.public_ip
}
provisioner "remote-exec" {
inline = [
"sudo apt-get update",
"sudo apt-get install -y nginx"
]
}
}
connection block (SSH or WinRM) - Supports inline, script, and scripts arguments file Provisioner¶
provisioner "file" {
source = "conf/app.conf"
destination = "/etc/app.conf"
}
connection block π Provisioners - Provisioner reference
Provisioner Behavior¶
- Run only during resource creation by default
when = destroyruns during resource destructionon_failure = continueallows Terraform to continue on failureon_failure = fail(default) stops execution on failure- Not stored in state - cannot be re-run without recreation
- HashiCorp recommends using cloud-init, user_data, or configuration management tools instead
Why Provisioners Are a Last Resort¶
- Not captured in the plan
- Cannot be previewed
- Make configurations less predictable
- Break the declarative model
- Prefer:
user_data, cloud-init, Packer, Ansible, Chef, Puppet
Debugging and Troubleshooting¶
TF_LOG Environment Variable¶
export TF_LOG=TRACE # Most verbose
export TF_LOG=DEBUG # Debug level
export TF_LOG=INFO # Informational
export TF_LOG=WARN # Warnings only
export TF_LOG=ERROR # Errors only
Log Output¶
export TF_LOG_PATH=./terraform.log # Write logs to file
export TF_LOG_CORE=TRACE # Core-specific logging
export TF_LOG_PROVIDER=DEBUG # Provider-specific logging
- Set
TF_LOGto empty string to disable logging TF_LOG_COREandTF_LOG_PROVIDERoverrideTF_LOGfor their scope- Log files are useful for debugging provider issues and plan failures
π Debugging - Debugging Terraform
Common Errors and Solutions¶
| Error | Cause | Solution |
|---|---|---|
| Provider not found | Missing required_providers | Add provider to terraform block |
| Backend initialization required | Changed backend config | Run terraform init |
| State lock error | Concurrent operation | Wait or force-unlock |
| Resource not found | Resource deleted externally | Run terraform plan -refresh-only |
| Cycle detected | Circular dependencies | Remove circular depends_on |
Terraform Replace (formerly taint)¶
terraform taint (Deprecated)¶
# Legacy approach
terraform taint aws_instance.web
terraform apply # Will destroy and recreate
terraform apply -replace (Recommended)¶
# Modern approach
terraform apply -replace=aws_instance.web
- Forces recreation of a specific resource
-replaceis preferred overtaint(taint is deprecated)- Useful when a resource is in a bad state but attributes have not changed
terraform untaint¶
terraform untaint aws_instance.web
Key Exam Points¶
Core Workflow¶
terraform initmust run before any other commandterraform validatedoes not check provider credentialsterraform plan -outsaves plan for exact apply laterterraform applywith saved plan does not prompt for approvalterraform destroyonly affects resources in current state- Plan symbols:
+create,-destroy,~update,-/+replace
Advanced Features¶
- Workspaces share configuration but have separate state
- Default workspace cannot be deleted
- CLI workspaces differ from Terraform Cloud workspaces
- Provisioners are a last resort - always prefer native alternatives
TF_LOG=TRACEis the most verbose logging levelterraform apply -replacereplacesterraform taintterraform plan -refresh-onlyreplacesterraform refresh