Ravindra BagaleCourses & study guides मराठी

Chapter 38: Terraform CLI Commands fmt validate plan apply state and more

38.2 plan, show and saved plan files

Story. On a Netflix-style release, the plan reviewed at 10 AM must be the plan applied at 11 AM, not whatever the code says by then. Saving the plan with -out freezes it. terraform show reads it back as text or JSON, which scanners and approvers can inspect. -detailed-exitcode tells scripts whether anything would change.

plan -out tfplan show tfplan show -json review / scan apply tfplan
Save the plan, inspect it, then apply exactly that file.
terraform plan -out=tfplan -var-file=dev.tfvars
terraform show tfplan
terraform show -json tfplan > tfplan.json
terraform plan -detailed-exitcode
echo $?

What each line does

  • terraform plan -out=tfplan -var-file=dev.tfvars — Computes the change for dev and saves it to a binary file.
  • terraform show tfplan — Prints the saved plan in readable form.
  • terraform show -json tfplan > tfplan.json — Exports the plan as JSON for tools such as Checkov.
  • terraform plan -detailed-exitcode — Exits 0 for no changes, 2 for changes, 1 for errors.
  • echo $? — Shows that exit code.

When it is green.

Plan: 3 to add, 0 to change, 0 to destroy.
Saved the plan to: tfplan
To perform exactly these actions, run: terraform apply "tfplan"
2

When it is red.

Error: Saved plan is stale
The given plan file can no longer be applied because the state was changed by another operation
after the plan was created.

Fix. Someone applied in between. Plan again, review the new plan, and apply that.

What: every term in plain English

  • plan — Terraform compares code, state and real AWS, then lists what it will add, change or destroy.
  • + create, ~ update, - destroy, -/+ replace — The symbols in a plan. Replace means delete and create again.
  • -out=tfplan — Saves the plan to a file, so you can apply exactly that plan later.
  • terraform show — Prints a saved plan or the current state in readable form.
  • show -json — The same plan as JSON, for scanners and scripts.
  • -detailed-exitcode — Exit 0 means no changes, 2 means changes, 1 means error.
  • stale plan — A saved plan that no longer matches state because someone applied after it was made.

Example 1: Read a plan for one security group

Before any apply, you must read the plan like a bill before paying.

  1. Save versions.tf and sg.tf below.
  2. Run init and plan.
  3. Read the + lines and the summary line.
terraform {
  required_version = ">= 1.6"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-south-1"
}
data "aws_vpc" "default" {
  default = true
}

resource "aws_security_group" "web" {
  name   = "plan-lab-web"
  vpc_id = data.aws_vpc.default.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
terraform init
terraform plan

Output

data.aws_vpc.default: Reading...
data.aws_vpc.default: Read complete after 1s [id=vpc-0a1b2c3d4e5f60789]

Terraform will perform the following actions:

  # aws_security_group.web will be created
  + resource "aws_security_group" "web" {
      + arn    = (known after apply)
      + id     = (known after apply)
      + name   = "plan-lab-web"
      + vpc_id = "vpc-0a1b2c3d4e5f60789"
      ...
    }

Plan: 1 to add, 0 to change, 0 to destroy.

What it shows: known after apply means AWS decides that value. The last line is the summary to read first.

Example 2: Save, show and apply the exact plan

At Swiggy-scale teams, the reviewed plan must be the applied plan.

  1. Save the plan with -out.
  2. Show it in text and as JSON.
  3. Count changes with jq.
  4. Apply the file.
terraform plan -out=tfplan
terraform show tfplan | tail -3
terraform show -json tfplan > tfplan.json
jq '[.resource_changes[] | .change.actions[]] | group_by(.) | map({(.[0]): length}) | add' tfplan.json
terraform apply tfplan

Output

Saved the plan to: tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "tfplan"
Plan: 1 to add, 0 to change, 0 to destroy.
{
  "create": 1
}
aws_security_group.web: Creating...
aws_security_group.web: Creation complete after 2s [id=sg-0f1e2d3c4b5a69788]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

What it shows: apply did not ask yes. A saved plan was already reviewed, so it runs directly.

Example 3: Spot a replace before it hurts

Some edits delete and recreate a resource. On a database that means data loss. Learn to see -/+ fast.

  1. Change name to plan-lab-web-v2. Security group names cannot change in place.
  2. Run plan.
  3. Look for -/+ and forces replacement.
sed -i 's/plan-lab-web"/plan-lab-web-v2"/' sg.tf
terraform plan

Output

  # aws_security_group.web must be replaced
-/+ resource "aws_security_group" "web" {
      ~ id   = "sg-0f1e2d3c4b5a69788" -> (known after apply)
      ~ name = "plan-lab-web" -> "plan-lab-web-v2" # forces replacement
    }

Plan: 1 to add, 0 to change, 1 to destroy.

What it shows: forces replacement names the exact argument. On RDS or a bucket, stop and think before apply.

Example 4: Drift check with -detailed-exitcode

A nightly job can tell you if anything changed outside Terraform.

  1. Run plan with -detailed-exitcode in a small script.
  2. Act on the exit code.
terraform plan -detailed-exitcode -input=false -no-color > plan.txt
rc=$?
if [ "$rc" -eq 0 ]; then echo "No drift"; fi
if [ "$rc" -eq 2 ]; then echo "Changes found"; grep 'Plan:' plan.txt; fi
if [ "$rc" -eq 1 ]; then echo "Plan failed"; fi

Output

Changes found
Plan: 1 to add, 0 to change, 1 to destroy.

What it shows: Exit 2 is not an error. It means work to do. Your script decides what to do next.

Command cheat sheet

Command What it does When to use it
terraform plan Shows the change Before every apply
terraform plan -​out=​tfplan Saves the change Pipelines and reviews
terraform show tfplan Reads a saved plan Approval step
terraform show -​json tfplan Plan as JSON Checkov, tfsec, scripts
terraform plan -​var-​file=​prod.​tfvars Plan with prod values Per environment
terraform plan -​detailed-​exitcode Exit 0, 1 or 2 Drift checks and gates
terraform plan -​destroy Previews deletes Before destroy

Verify: did it work?

  1. A saved plan exists

    ls -l tfplan
    

    Output

    -rw-r--r-- 1 ravi ravi 4120 Oct 25 10:12 tfplan
    
  2. Nothing left to do after apply

    terraform plan -detailed-exitcode; echo $?
    

    Output

    No changes. Your infrastructure matches the configuration.
    0
    

When it is red 1

Error: Saved plan is stale
The given plan file can no longer be applied because the state was changed by another operation after the plan was created.

Cause. Someone applied between your plan and your apply.

Fix, step by step

  1. Delete the old tfplan.
  2. Run plan -out=tfplan again and review it.
  3. Apply the new file.

When it is red 2

Error: No valid credential sources found
Please see https://registry.terraform.io/providers/hashicorp/aws for more information about providing credentials.

Cause. plan must call AWS and found no login.

Fix, step by step

  1. Run aws sts get-caller-identity to test.
  2. Run aws configure or use an IAM role.
  3. Plan again.

When it is red 3

Error: Failed to load "tfplan" as a plan file
plan file was created by Terraform 1.9.5, but this is 1.8.2

Cause. The plan was saved by a different Terraform version.

Fix, step by step

  1. Use the same Terraform version for plan and apply.
  2. Pin it in CI with required_version.

Cleanup

terraform destroy -auto-approve
rm -f tfplan tfplan.json plan.txt

Practice tasks

Easy Read three summaries

Why: The summary line is read first.

What to do: Run plan for three small changes and write each summary line.

How:
  1. Add a tag.
  2. Change a port.
  3. Rename the group.

Check: You can say which one replaces.

Medium Plan for prod values

Why: One code, many inputs.

What to do: Run plan with -var-file=dev.tfvars and prod.tfvars.

How:
  1. Create both files with a different name.
  2. Compare the plans.

Check: Only the values differ.

Medium Count changes with jq

Why: Robots read JSON.

What to do: Export show -json and count delete actions.

How:
  1. Use the jq line from Example 2.

Check: Your script prints the delete count.

Hard Make a stale plan

Why: Know the error by face.

What to do: Save a plan, apply a change from another terminal, then apply the old plan.

How:
  1. Use two terminals in the same folder.

Check: You see Saved plan is stale.

Easy Say it in two lines

Why: If you can say it simply, you understand it.

What to do: Write two short lines about this lesson for a fresher.

How:
  1. Write the problem it solves.
  2. Write the one command or file you use.
  3. Read it aloud.

Check: A fresher understands it without a question.

Easy Start a safe lab folder

Why: Practice needs a throwaway place.

What to do: Make a new folder with versions.tf and a random_pet resource, so no AWS cost.

How:
  1. mkdir tf-lab and cd into it.
  2. Add the hashicorp/random provider and one random_pet.
  3. Run terraform init and terraform apply.

Check: Apply complete! with 1 added.

Medium Break it on purpose

Why: You must know the red output by face.

What to do: Cause one error from the red part of this lesson and fix it.

How:
  1. Follow one red section.
  2. Copy the exact message to your notes.
  3. Write the fix in one line.

Check: You fixed it without searching the web.

Medium Run it twice

Why: A second run must be quiet.

What to do: Run the same plan two times with no edits.

How:
  1. Run terraform plan.
  2. Run it again.
  3. Explain any change it still shows.

Check: The second plan says No changes, or you can explain each line.

Medium Write a runbook page

Why: At 2 a.m. nobody remembers flags.

What to do: Write a one-page runbook for this lesson.

How:
  1. Title, when to use, exact commands, how to check, how to undo.

Check: A teammate can follow it alone.

Medium Run it from a pipeline

Why: Real teams run Terraform from CI, not from laptops.

What to do: Run the main command of this lesson inside a GitHub Actions or Jenkins job.

How:
  1. Add a job with hashicorp/setup-terraform or a Terraform Docker image.
  2. Give it AWS access through an IAM role, never a key in the file.
  3. Run init, then the command from this lesson.

Check: The job log shows the same output you saw on your laptop.

Medium Check the cost

Why: Labs left running cost real money.

What to do: Find what this lesson would cost per day if you forgot to destroy it.

How:
  1. Open the AWS Pricing Calculator.
  2. Add each resource from your plan.
  3. Write the daily cost in your notes.

Check: You know the daily cost and you ran terraform destroy.

Hard Draw the flow top to bottom

Why: A drawing shows the order of work.

What to do: Draw this lesson as boxes from top to bottom.

How:
  1. Start at your code, go through plan and state, end at AWS.
  2. Mark where each command reads or writes.

Check: Each box matches a real step you ran.

Hard Explain it like an interview

Why: Interviewers want real stories.

What to do: Record a 60 second answer about this lesson.

How:
  1. Say the problem, the command, and one error you hit.

Check: Your answer has a real command and a real error message.

Homework: try at home

Try at home

Save a plan for any small lab. Open it with terraform show and write in your own words what each + and ~ line means.

Recap

  • plan is a preview. Read the summary line first.
  • -out saves the plan. apply tfplan runs exactly that, with no prompt.
  • show and show -json read a saved plan.
  • -/+ and forces replacement mean delete then create.
  • -detailed-exitcode gives 0, 2 or 1 for scripts.

FAQ

Is the plan file safe to share?

No. It can hold secret values. Treat it like the state file.

Can I edit a saved plan?

No. Change the code and plan again.

Why does plan say known after apply?

AWS creates that value, such as an id, only during apply.

Does plan change anything?

No. It only reads and compares.

Why does plan take long?

It refreshes every resource. Large states take longer. Split big stacks.

Interview questions

  1. Why use plan -out in pipelines?

    So the approved plan is exactly what applies. Without it, code could change between review and apply.

  2. What does -/+ mean?

    Replace. Terraform deletes and creates the resource because an argument cannot change in place.

  3. What is -detailed-exitcode used for?

    Drift checks and gates. 0 no changes, 2 changes, 1 error.

  4. How do security scanners read a plan?

    From terraform show -json tfplan.

  5. What is a stale plan?

    A saved plan made before another apply changed state. Terraform refuses it.

Quick quiz

Q1. Which flag saves a plan?

-out.

Q2. What does exit code 2 mean with -detailed-exitcode?

There are changes.

Q3. Does apply tfplan ask for yes?

No.

Q4. What does forces replacement mean?

The resource will be deleted and created again.

Q5. Which command exports plan JSON?

terraform show -json tfplan.

Samajla ka?

Ravi Sir's Cards for this lesson

मराठी cards