Skip to content

antoniocali/terafrom

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

terafrom

A drop-in replacement for terraform plan and terraform apply that replaces Terraform's verbose output with a clean, readable diff.

Summary table — every changed resource at a glance:

  Changes to be applied
  ──────────────────────────────────────────────────────────────────────────
       Type                      Name          Action
  ──────────────────────────────────────────────────────────────────────────
  +  aws_s3_bucket             my_bucket     create
  ~  aws_instance              web           update
  ±  aws_db_instance           postgres      replace
  -  aws_security_group        old           destroy
  ──────────────────────────────────────────────────────────────────────────
  2 to add  ·  1 to change  ·  1 to replace  ·  1 to destroy

Per-resource panels — only the attributes that actually changed, with old → new values. Nested objects and arrays are flattened to dot-paths. JSON-encoded strings are decoded and diffed internally:

  ┌─ update  aws_scheduler_schedule.my_job ──────────────────────────────
  │  schedule_expression              "rate(1 hour)"  →  "rate(2 hours)"
  │  target.0.ecs_parameters.0.task_definition_arn
  │                                   "...task:4"  →  "...task:5"
  │  target.0.input.containerOverrides.0.command
  │                                   [..., "100000000"]  →  [..., "1000"]
  │  (10 unchanged attribute(s) hidden)
  └───────────────────────────────────────────────────────────────────────

  ┌─ replace  aws_db_instance.postgres ─────────────────────────────────
  │  engine_version                   "13.4"  →  "15.2"
  │  instance_class                   "db.t3.micro"  →  "db.t3.medium"
  │  (2 unchanged attribute(s) hidden)
  └───────────────────────────────────────────────────────────────────────

Requirements

  • terraform binary available in $PATH

Installation

Homebrew (macOS / Linux)

brew install antoniocali/tap/terafrom

go install

go install github.com/antoniodavide/terafrom@latest

Pre-built binaries

Download the latest release for your platform from the GitHub Releases page, extract the archive, and place the terafrom binary somewhere on your $PATH.

Usage

Plan

Show the diff for the current directory — runs terraform init automatically if needed:

terafrom
# Specific directory
terafrom --dir ./infra

# Show unchanged attributes too
terafrom --show-all

# Only the summary table, no per-resource panels
terafrom --compact

# Load an existing plan file instead of running terraform plan
terafrom --plan-file ./my.tfplan

# Pass extra arguments through to terraform plan
terafrom -- -var-file=prod.tfvars -target=aws_s3_bucket.data

Apply

Plan, show the diff, then apply in one step. Terraform's own stdout is suppressed to avoid duplicate output — only errors and real progress come through:

terafrom apply
terafrom apply --dir ./infra
terafrom apply -- -var-file=prod.tfvars

Remote / cloud backends

terafrom works transparently with any backend that stores state remotely (S3, GCS, Azure Blob Storage, HTTP, Consul, PostgreSQL, …). Terraform fetches the remote state itself during plan — no extra configuration needed.

If .terraform/ is absent, terafrom runs terraform init automatically before planning. Use --init to force a re-init (e.g. after changing the backend config or provider versions), or --no-init to skip it entirely.

Environment variable credentials

Set the relevant environment variables before running terafrom — they are inherited by the terraform subprocess:

# AWS (S3 backend)
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=us-east-1
terafrom --dir ./infra

# GCP (GCS backend)
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json
terafrom --dir ./infra

# Azure (azurerm backend)
export ARM_CLIENT_ID=... ARM_CLIENT_SECRET=... ARM_TENANT_ID=... ARM_SUBSCRIPTION_ID=...
terafrom --dir ./infra

Partial backend config

If your .tf files use a partial backend configuration, pass the missing values via --backend-config — forwarded to terraform init -backend-config=...:

terafrom \
  --backend-config bucket=my-tfstate-bucket \
  --backend-config region=eu-west-1 \
  --backend-config dynamodb_table=tf-locks \
  --dir ./infra

# Switch state key per environment without touching .tf files
terafrom --init --backend-config "key=envs/prod/terraform.tfstate" --dir ./infra

Flags

terafrom (plan)

Flag Default Description
--plan-file Load an existing .tfplan or JSON plan file
--dir . Terraform working directory
--init false Force terraform init before planning
--no-init false Never run terraform init automatically
--init-arg Extra argument forwarded to terraform init (repeatable)
--backend-config Backend config key=value forwarded to terraform init (repeatable)
--show-all false Show unchanged attributes inside resource panels
--compact false Summary table only, no per-resource panels
--no-color false Disable ANSI colour output
--verbose false Also print the raw terraform plan output before the terafrom diff
--terraform-args Extra argument forwarded to terraform plan (repeatable)

terafrom apply

Flag Default Description
--dir . Terraform working directory
--init false Force terraform init before applying
--no-init false Never run terraform init automatically
--init-arg Extra argument forwarded to terraform init (repeatable)
--backend-config Backend config key=value forwarded to terraform init (repeatable)
--show-all false Show unchanged attributes in the diff output
--no-color false Disable ANSI colour output
--terraform-args Extra argument forwarded to terraform plan/apply (repeatable)

Legend

Symbol Colour Meaning
+ Green Resource/attribute added
- Red Resource/attribute destroyed
~ Yellow Resource/attribute modified
± Magenta Resource replaced (destroy + create)
> Cyan Data source read

Contributing

Requirements: Go 1.21+, terraform in $PATH.

git clone https://github.com/antoniodavide/terafrom
cd terafrom
Command Description
make build Compile the binary to ./terafrom
make install Install to $GOPATH/bin
make test Run all tests
make test-verbose Run tests with verbose output
make lint Run go vet
make fmt Format source with go fmt
make tidy Tidy and verify go.mod / go.sum
make clean Remove build artefacts

Project layout

terafrom/
├── main.go                      # Entry point
├── cmd/terafrom/
│   ├── root.go                  # terafrom (plan) command and flags
│   └── apply.go                 # terafrom apply subcommand
└── internal/
    ├── backend/
    │   └── backend.go           # Backend type detection (.terraform/terraform.tfstate)
    ├── plan/
    │   ├── types.go             # Plan JSON structs + ActionType helpers
    │   └── loader.go            # File loader, auto-init, terraform runner
    ├── diff/
    │   └── diff.go              # Attribute diff engine (flattening, JSON decoding)
    ├── render/
    │   └── render.go            # Summary table + per-resource panel renderer
    └── version/
        └── version.go           # Build-time version, commit, and date (set via ldflags)

About

Prettier output for terraform plan and terraform apply

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors