Agent Skills: Terraform State Manager

Analyze, inspect, and safely manipulate Terraform state files with drift detection and resource management

UncategorizedID: GuicedEE/ai-rules/terraform-state-manager

Install this agent skill to your local

pnpm dlx add-skill https://github.com/GuicedEE/ai-rules/tree/HEAD/skills/.curated/terraform-state-manager

Skill Files

Browse the full folder contents for terraform-state-manager.

Download Skill

Loading file tree…

skills/.curated/terraform-state-manager/SKILL.md

Skill Metadata

Name
terraform-state-manager
Description
Analyze, inspect, and safely manipulate Terraform state files with drift detection and resource management

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:

  1. State Inspection:

    • List all resources in state
    • Show resource details
    • Identify orphaned resources
    • Find unused resources
  2. Drift Detection:

    • Compare state with actual infrastructure
    • Identify configuration drift
    • Show differences between state and reality
    • Suggest remediation actions
  3. State Manipulation:

    • Move resources between states
    • Remove resources from state
    • Import existing resources
    • Rename resources
  4. 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 needed
  • 1: Error occurred
  • 2: 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

  1. Never commit state to version control:

    *.tfstate
    *.tfstate.*
    
  2. Encrypt state at rest:

    • Azure Storage: Enable encryption
    • S3: Enable server-side encryption
    • GCS: Automatic encryption
  3. Encrypt state in transit:

    • Use HTTPS/TLS for remote backends
    • Configure secure backend authentication
  4. Limit state access:

    • Use RBAC on storage accounts
    • Implement least-privilege access
    • Use managed identities when possible
  5. 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