Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

How to read an OpenTofu plan

After this lesson: I can read a plan after a change and say what is created, changed or destroyed.

60 min lesson10 commandsOpenTofu lab: infrastructure as code with plan, apply and state on one VM

A plan lists changes before they happen

An OpenTofu plan is the list of changes the tool would make, with a symbol in front of each. Reading it before you apply is the main safety check of infrastructure as code. A small edit can destroy a resource and build it again.

The skill is quick: find the symbol, find the name, read the total on the last line.

By the end of this lesson

Note

I can read a plan after a change and say what is created, changed or destroyed.

Key words

WordWhat it meansExample
Update in placea resource changes and stays the same resource~
Destroya resource will be removed-
Replacedestroy a resource, then create it again-/+
Known after applya value that is only decided during the apply
Triggera value whose change forces a replacement

The cells students fill in are left blank in this preview.

Every plan line starts with a symbol

A plan marks every resource it will touch. + means create. - means destroy. ~ means update in place.

A fourth symbol, -/+, means replace: OpenTofu destroys the old resource, then creates a new one. The last line adds it all up. A replacement counts once as an add and once as a destroy.

The plan symbols and what they mean

SymbolWords in the planCounted as
+will be created1 to add
~will be updated in-place1 to change
-will be destroyed1 to destroy
-/+must be replaced1 to add and 1 to destroy

The cells students fill in are left blank in this preview.

Make a folder for the signs

Command
mkdir -p ~/iac-demo/signs

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Go into it

Command
cd ~/iac-demo/signs

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Write a project with three resources

Command
printf '%s\n' 'variable "shop" {' '  type    = string' '  default = "Corner Shop"' '}' '' 'variable "sign_version" {' '  type    = number' '  default = 1' '}' '' 'resource "terraform_data" "door" {' '  input = format("%s: open", var.shop)' '}' '' 'resource "terraform_data" "sign" {' '  input            = "Open today"' '  triggers_replace = [var.sign_version]' '}' '' 'resource "terraform_data" "window" {' '  input = "Sale"' '}' > main.tf

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Prepare the folder

Command
tofu init -no-color | grep successfully

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Apply, so the state holds all three

Command
tofu apply -auto-approve -no-color | grep "Apply complete"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

An edit may change or replace a resource

Only the resources an edit reaches appear in the plan. The door reads the variable shop, so changing the shop touches the door and nothing else.

The sign has triggers_replace, a list of values. When any of them changes, OpenTofu will not edit the sign: it replaces it. The Runs below pass different values with -var. They only plan, so nothing is applied.

Change the shop name: one update in place

Command
tofu plan -no-color -var shop="Hill Shop" | grep -E "will be|^Plan|known after apply"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Change the sign version: one replacement

Command
tofu plan -no-color -var sign_version=2 | grep -E "will be|must be|^Plan"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A common mistake

Warning

Many people think a replacement is a gentle change. It is not. The old resource is destroyed and a new one is made, so anything stored in the old one is gone. Before you apply, look for -/+ and the words must be replaced.

Both changes at once

Command
tofu plan -no-color -var shop="Hill Shop" -var sign_version=2 | grep -E "will be|must be|^Plan"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Worked example: adding up the last line

ResourceSymbolTo addTo changeTo destroy
door~010
sign-/+101
windownone000
Total111

The cells students fill in are left blank in this preview.

Delete the window block from the file

Command
sed -i '/"window"/,/^}/d' main.tf

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Show the symbol for each change

Command
tofu plan -no-color -var shop="Hill Shop" -var sign_version=2 | grep resource

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A plan worked out in Python

Code: python
# Work out a plan between a state and a wish.
state = {
    "door": {"input": "open", "trigger": 1},
    "sign": {"input": "Open today", "trigger": 1},
    "window": {"input": "Sale", "trigger": 1},
}
wish = {
    "door": {"input": "open", "trigger": 1},
    "sign": {"input": "Open today", "trigger": 2},
    "gate": {"input": "Locked", "trigger": 1},
}
add = 0
destroy = 0
for name in wish:
    if name not in state:
        print("+", name)
        add = add + 1
    elif wish[name]["trigger"] != state[name]["trigger"]:
        print("-/+", name)
        add = add + 1
        destroy = destroy + 1
for name in state:
    if name not in wish:
        print("-", name)
        destroy = destroy + 1
print("Plan:", add, "to add,", destroy, "to destroy.")
# Change window's trigger in the wish and look again.

About this lab and its source: OpenTofu lab: infrastructure as code with plan, apply and state on one VM

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.