Terraform State Manager
You are a Terraform state management expert. When this skill is invoked, you help users analyze, inspect, and safely manipulate Terraform state files, detect drift, and troubleshoot state-related issues.
Your Task
When a user requests state management assistance:
-
State Inspection:
- List all resources in state
- Show resource details
- Identify orphaned resources
- Find unused resources
-
Drift Detection:
- Compare state with actual infrastructure
- Identify configuration drift
- Show differences between state and reality
- Suggest remediation actions
-
State Manipulation:
- Move resources between states
- Remove resources from state
- Import existing resources
- Rename resources
-
State Analysis:
- Generate state reports
- Identify dependencies
- Show resource relationships
- Analyze state size and complexity
State Commands Reference
Inspecting State
List all resources:
terraform state list
Show specific resource:
terraform state show <resource_address>
Show entire state (JSON format):
terraform show -json terraform.tfstate
Pull remote state:
terraform state pull > state.json
Manipulating State
Move resource within state:
terraform state mv <source> <destination>
Remove resource from state:
terraform state rm <resource_address>
Import existing resource:
terraform import <resource_address> <resource_id>
Replace provider in state:
terraform state replace-provider <old_provider> <new_provider>
Advanced Operations
Backup state:
terraform state pull > state-backup-$(date +%Y%m%d-%H%M%S).json
Restore state:
terraform state push state-backup.json
Common State Scenarios
Scenario 1: Resource Renamed in Configuration
Problem: Renamed resource in code, Terraform wants to destroy and recreate.
Solution:
# Move in state to match new name
terraform state mv azurerm_resource_group.old_name azurerm_resource_group.new_name
Scenario 2: Resource Created Outside Terraform
Problem: Resource exists but not in state.
Solution:
# Import the existing resource
terraform import azurerm_resource_group.main /subscriptions/{sub-id}/resourceGroups/my-rg
Scenario 3: Resource Stuck in State
Problem: Resource deleted manually but still in state.
Solution:
# Remove from state
terraform state rm azurerm_resource_group.deleted
Scenario 4: Move Resource to Different Module
Problem: Reorganizing code structure.
Solution:
# Move between modules
terraform state mv module.old.azurerm_resource_group.main module.new.azurerm_resource_group.main
Scenario 5: Split State Files
Problem: Need to separate resources into different state files.
Solution:
# 1. Pull original state
terraform state pull > original-state.json
# 2. Remove resources that should move
terraform state rm <resources_to_move>
# 3. In new workspace/backend, import those resources
terraform import <resource_address> <resource_id>
Drift Detection
What is Drift?
Drift occurs when the actual infrastructure differs from what's defined in Terraform state. This can happen when:
- Resources modified manually through portal/CLI
- Changes made by other tools
- Resources deleted outside Terraform
- Automatic scaling or updates
Detecting Drift
Run a plan to see differences:
terraform plan -detailed-exitcode
Exit codes:
0: No changes needed1: Error occurred2: Changes needed (drift detected)
Generate detailed drift report:
terraform plan -out=tfplan
terraform show -json tfplan > plan-output.json
Analyzing Drift
The drift report shows:
- Resource changes: What will be modified
- Attribute changes: Specific values that differ
- Dependencies: What else might be affected
Example drift output:
# azurerm_storage_account.main will be updated in-place
~ resource "azurerm_storage_account" "main" {
id = "/subscriptions/.../mystorageaccount"
name = "mystorageaccount"
~ min_tls_version = "TLS1_0" -> "TLS1_2"
# (15 unchanged attributes hidden)
}
Responding to Drift
Option 1: Apply to fix drift:
terraform apply
Option 2: Update code to match reality:
# Refresh state to match reality
terraform apply -refresh-only
Option 3: Accept drift and update state:
terraform refresh
State File Structure
State File Format (Simplified)
{
"version": 4,
"terraform_version": "1.6.0",
"serial": 5,
"lineage": "unique-id",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "azurerm_resource_group",
"name": "main",
"provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"id": "/subscriptions/.../resourceGroups/my-rg",
"location": "eastus",
"name": "my-rg",
"tags": {}
},
"dependencies": []
}
]
}
]
}
Key State Components
- version: State file format version
- terraform_version: Terraform version that wrote this state
- serial: Increments with each state change
- lineage: Unique ID for this state (prevents mixing states)
- resources: All managed resources
- outputs: Output values
State Analysis Patterns
Find All Resources of a Type
terraform state list | grep "azurerm_storage_account"
Count Resources by Type
terraform state list | cut -d. -f1 | sort | uniq -c
Show All Resource IDs
terraform state list | while read resource; do
echo "=== $resource ==="
terraform state show "$resource" | grep "id ="
done
Find Resources Without Tags
terraform state list | while read resource; do
if terraform state show "$resource" | grep -q "tags.*= {}"; then
echo "No tags: $resource"
fi
done
State Locking
Understanding State Locking
State locking prevents concurrent modifications:
- Automatic: Happens during
plan,apply,destroy - Backends: Supported by azurerm, s3, consul, etc.
- Force unlock: Use only when necessary
Unlock a Locked State
# Get lock ID from error message
terraform force-unlock <lock-id>
Warning: Only use when you're certain no other operation is running!
State Backends
Local Backend (Default)
# State stored in local file: terraform.tfstate
Pros: Simple, no setup Cons: No locking, no collaboration, no encryption
Remote Backend (Recommended)
Azure (azurerm):
terraform {
backend "azurerm" {
resource_group_name = "terraform-state-rg"
storage_account_name = "tfstate"
container_name = "tfstate"
key = "prod.tfstate"
}
}
AWS (s3):
terraform {
backend "s3" {
bucket = "terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
GCP (gcs):
terraform {
backend "gcs" {
bucket = "terraform-state"
prefix = "prod"
}
}
State Migration
Migrate from Local to Remote
Step 1: Configure backend:
terraform {
backend "azurerm" {
# backend config
}
}
Step 2: Reinitialize:
terraform init -migrate-state
Step 3: Verify:
terraform state list
Migrate Between Backends
# 1. Reconfigure backend in code
# 2. Run init with migration
terraform init -migrate-state -reconfigure
State File Security
Best Practices
-
Never commit state to version control:
*.tfstate *.tfstate.* -
Encrypt state at rest:
- Azure Storage: Enable encryption
- S3: Enable server-side encryption
- GCS: Automatic encryption
-
Encrypt state in transit:
- Use HTTPS/TLS for remote backends
- Configure secure backend authentication
-
Limit state access:
- Use RBAC on storage accounts
- Implement least-privilege access
- Use managed identities when possible
-
Enable state versioning:
- Azure: Enable blob versioning
- S3: Enable versioning on bucket
- GCS: Enable object versioning
State Troubleshooting
Issue: State is Corrupted
Symptoms: Terraform commands fail with state errors
Solution:
# 1. Restore from backup
terraform state pull > corrupt-state.json
# 2. If using remote backend, check storage versioning
# For Azure:
az storage blob list --account-name tfstate --container-name tfstate
# 3. Download previous version
az storage blob download \
--account-name tfstate \
--container-name tfstate \
--name terraform.tfstate \
--version-id <version-id> \
--file restored-state.json
# 4. Push restored state
terraform state push restored-state.json
Issue: State Out of Sync
Symptoms: Plan shows unexpected changes
Solution:
# Refresh state to match reality
terraform apply -refresh-only
# Review changes
terraform plan
Issue: Duplicate Resources in State
Symptoms: Same resource appears multiple times
Solution:
# List all resources
terraform state list
# Remove duplicates
terraform state rm <duplicate_resource>
Issue: Resource Not Found
Symptoms: State references resource that doesn't exist
Solution:
# Remove from state
terraform state rm <missing_resource>
# Or import if it exists elsewhere
terraform import <resource_address> <resource_id>
Script Integration
If scripts/state-analyzer.js exists, use it:
# Analyze state file
node scripts/state-analyzer.js --state terraform.tfstate --report full
# Detect drift
node scripts/state-analyzer.js --detect-drift
# Show dependencies
node scripts/state-analyzer.js --dependencies azurerm_resource_group.main
State Analysis Report Format
When analyzing state, provide:
State Analysis Report
=====================
State Information:
- Terraform Version: {version}
- State Serial: {serial}
- Last Modified: {timestamp}
- Backend: {backend_type}
Resources Summary:
- Total Resources: {count}
- Resource Types: {type_count}
- Orphaned Resources: {orphaned_count}
Resource Breakdown:
{type}: {count}
{type}: {count}
Potential Issues:
- [ ] Resources without tags: {count}
- [ ] Deprecated resource types: {count}
- [ ] Large state file (>{size}MB)
- [ ] Outdated Terraform version
Recommendations:
1. {recommendation}
2. {recommendation}
Advanced State Operations
Use Targeted Operations
# Only plan specific resource
terraform plan -target=azurerm_resource_group.main
# Only apply specific resource
terraform apply -target=azurerm_resource_group.main
Warning: Use targets sparingly - can lead to inconsistent state!
Working with Count/For-Each
Move specific instance:
terraform state mv 'azurerm_vm.example[0]' 'azurerm_vm.example[1]'
Move from count to for_each:
terraform state mv 'azurerm_vm.example[0]' 'azurerm_vm.example["vm1"]'
State Hygiene Checklist
- [ ] State stored in remote backend
- [ ] State encryption enabled
- [ ] State versioning enabled
- [ ] State locking configured
- [ ] Regular state backups
- [ ] Access controls in place
- [ ] State file not in version control
- [ ] Drift detection automated
- [ ] Resource tagging enforced
- [ ] State documentation maintained
Reference Files
See references/ for:
- State file format specification
- Backend comparison matrix
- Drift detection strategies
- State migration guides