tfautomv
(Terraform auto-move) is a refactoring helper that automatically generates moved
blocks and terraform state mv
commands when you restructure your Terraform code. It helps make structural changes to your Terraform codebase without losing track of resource state.
When you move or rename resources in your Terraform code, Terraform loses track of the resource’s state. The next time you run terraform plan
, it will plan to delete the old resource and create a “new” one - even though they’re the same resource with a different name or location.
tfautomv
solves this by:
terraform plan
to see what Terraform wants to create and deletemoved
blocks or terraform state mv
commands to preserve statebrew install busser/tap/tfautomv
Security Note: Always review remote installation scripts before executing them to ensure they are safe.
curl -sSfL https://raw.githubusercontent.com/busser/tfautomv/main/install.sh -o install.sh
less install.sh # Review the script contents
sh install.sh
Download the appropriate binary from the GitHub releases page and place it in your PATH.
asdf plugin add tfautomv https://github.com/busser/asdf-tfautomv.git
asdf install tfautomv latest
asdf global tfautomv latest
moved
blocks or shell commandsRun in any directory where you would normally run terraform plan
:
tfautomv
This will:
terraform init
, terraform refresh
, and terraform plan
moved
blocks in a moves.tf
filetfautomv ./production
tfautomv --output=commands
# or short form
tfautomv -o commands
tfautomv -o commands | sh
Move resources across different Terraform modules:
tfautomv ./production/main ./production/backup -o commands
Note: Cross-module moves only work with --output=commands
, not with moved
blocks.
--output=blocks
(default): Generate moved
blocks--output=commands
: Generate terraform state mv
commandsSkip expensive operations when iterating:
# Skip initialization
tfautomv --skip-init
# Skip refresh
tfautomv --skip-refresh
# Skip both (short form)
tfautomv -sS
Perfect for CI/CD or when you already have plan files:
# Generate plan first
terraform plan -out=tfplan.bin
# Use existing plan
tfautomv --preplanned
# Custom plan file name
terraform plan -out=my-plan.bin
tfautomv --preplanned --preplanned-file=my-plan.bin
# JSON plans work too
terraform show -json tfplan.bin > tfplan.json
tfautomv --preplanned --preplanned-file=tfplan.json
tfautomv --terraform-bin=terragrunt
tfautomv --terraform-bin=tofu
Add to your .pre-commit-config.yaml
:
repos:
- repo: https://github.com/busser/tfautomv
rev: v0.7.0 # Use the latest version
hooks:
- id: tfautomv
args: ["--output=blocks"]
Use --ignore
when providers transform attribute values in ways that prevent tfautomv from matching resources:
Ignore any difference in an attribute:
tfautomv --ignore="everything:aws_s3_bucket:arn"
Ignore whitespace differences (useful for JSON/XML):
tfautomv --ignore="whitespace:azurerm_api_management_policy:xml_content"
Ignore specific prefixes:
tfautomv --ignore="prefix:google_storage_bucket_iam_member:bucket:b/"
Reference nested attributes with dots:
tfautomv --ignore="everything:aws_instance:tags.Environment"
✅ Good Examples:
# Provider normalizes JSON formatting
tfautomv --ignore="whitespace:aws_iam_policy:policy"
# Provider adds computed ARN field
tfautomv --ignore="everything:aws_s3_bucket:arn"
# Provider normalizes bucket path
tfautomv --ignore="prefix:google_storage_bucket:name:projects/my-project/buckets/"
❌ Avoid These:
# DON'T ignore intentional changes
tfautomv --ignore="everything:aws_instance:tags" # You changed tags!
# DON'T mix refactoring with infrastructure changes
aws_instance.web
→ aws_instance.web_server
aws_instance.web
→ module.ec2.aws_instance.web
for_each
loopsIncrease verbosity to understand what tfautomv is doing:
# Show attribute paths and comparison details
tfautomv -vvv
# See exactly which attributes differ
tfautomv --verbosity=3
Use pre-generated plans in CI/CD pipelines:
# In CI pipeline
terraform plan -out=tfplan.bin -no-color > plan.txt
terraform show -json tfplan.bin > tfplan.json
# Later stage or local
tfautomv --preplanned --preplanned-file=tfplan.json
For complex enterprise setups with remote state:
# Use environment variables for Terraform configuration
TF_CLI_ARGS_plan="-var-file=production.tfvars" tfautomv
# Skip expensive operations in large environments
tfautomv -sS --preplanned
Issue: “No moves found” despite obvious renames
-vvv
, use --ignore
if neededIssue: tfautomv suggests moves that would change infrastructure
Issue: Cross-module moves not working
--output=commands
instead of moved
blocksIssue: Slow performance with large state
--skip-init --skip-refresh
or --preplanned
Issue: Provider transforms attributes
--ignore
rules for provider-specific transformationsFor more detailed information and examples, visit the official tfautomv repository.