§ Reference · Commands

pravo destroy

Destroy every resource recorded in the state, dependents first, after a plan and a confirmation.

View as Markdown

On this page

Quick reference

Synopsis pravo destroy [flags]
Changes infrastructure Yes. It deletes every object in the state.
Scope Every node in the state, whether or not the specification still declares it.
Refused when A resource that the specification still declares has $lifecycle: prevent_destroy: true. Nothing is changed.
Order Dependents first. A resource is deleted once every resource that depends on it is gone, and independent resources are deleted at the same time. The plan reads the records at the same time as well.
Confirmation Do you really want to destroy all resources? Only yes is accepted.
Preview pravo plan --destroy prints the same plan and changes nothing.
Taught in Quick start, step 9, and B3, Apply, outputs, state.

Flags

Flag Default Meaning
--auto-approve off Destroy without asking.
--refresh=age|expired|false|all age When to read real state before the plan. See pravo plan.
--policy FILE none A CUE file the plan of deletions must satisfy. Repeatable.
-t, --tag key=value, -T none Tags, as for pravo plan.

destroy takes no --out, --only or --replace. To destroy in parts, save the plan with pravo plan --destroy --out FILE and apply it with pravo apply FILE --only ADDR,.... Outputs of a partial destroy says which outputs a part removes. The global flags apply.

Exit codes

Code Meaning
0 Everything in the state was destroyed, or the state was empty.
1 An error: the prompt was answered with anything but yes, a provider failed, --json without --auto-approve, a resource has prevent_destroy.
4 Rejected: a node is locked or reserved by another actor.
5 A policy refused the plan, or a --policy file cannot be used.
6 The specification does not load or evaluate.

Examples

Work in an empty directory named demo. port reads base.

main.cue
package demo

import rnd "pravo.dev/providers/hashicorp/random"

$random: rnd.#Provider

base: $random.#Resource.random_integer & {min: 1, max: 9, seed: "base"}

port: $random.#Resource.random_integer & {
	min:  20000 + base.result
	max:  20100
	seed: "port"
}
terminal
$pravo init > /dev/null
$pravo apply -auto-approve > /dev/null
$pravo state list
base
port

Preview

terminal
$pravo plan --destroy
base: Refreshing state... [id=9]
port: Refreshing state... [id=20093]

pravo will perform the following actions:

  # port (random_integer) will be destroyed
  - port: {
  -     id:     "20093"
  -     max:    20100
  -     min:    20009
  -     result: 20093
  -     seed:   "port"
    }

  # base (random_integer) will be destroyed
  - base: {
  -     id:     "9"
  -     max:    9
  -     min:    1
  -     result: 9
  -     seed:   "base"
    }

Plan: 0 to add, 0 to change, 2 to destroy.
Graph: 2 resources in state, 2 refreshed.

The Graph: line counts the nodes in the state. port comes first, because it depends on base.

Refuse deletions with a policy

A plan policy that allows no destroy action refuses the command before anything is deleted. The state is untouched.

policy/keep.cue
summary: destroy: 0
terminalexit 5
$pravo destroy --policy policy/keep.cue
base: Refreshing state... [id=9]
port: Refreshing state... [id=20093]
...
Plan: 0 to add, 0 to change, 2 to destroy.
Graph: 2 resources in state, 2 refreshed.

Error: the plan violates the policy policy/keep.cue (sha256:238d99a0ac31):
summary.destroy: conflicting values 2 and 0:
    plan:1:<col>
    policy/keep.cue:1:19

The plan is printed first and judged second. The prompt never appears. Both nodes are still in the state:

terminal
$pravo state list
base
port

See Policies.

Destroy

terminal
$pravo destroy -auto-approve
base: Refreshing state... [id=9]
port: Refreshing state... [id=20093]
...
Plan: 0 to add, 0 to change, 2 to destroy.
Graph: 2 resources in state, 2 refreshed.
port: Destroying... [id=20093]
port: Destruction complete after 0s
base: Destroying... [id=9]
base: Destruction complete after 0s

Destroy complete! Resources: 0 added, 0 changed, 2 destroyed. [txn <txn>]

The state is empty afterwards. The specification and the lock file stay.

terminal
$pravo state list

Protect a resource

$lifecycle: prevent_destroy: true on a resource that the specification declares refuses pravo destroy and pravo plan --destroy while the resource is in the state. Add it to port:

main.cue
package demo

import rnd "pravo.dev/providers/hashicorp/random"

$random: rnd.#Provider

base: $random.#Resource.random_integer & {min: 1, max: 9, seed: "base"}

port: $random.#Resource.random_integer & {
	$lifecycle: prevent_destroy: true
	min:        20000 + base.result
	max:        20100
	seed:       "port"
}
terminalexit 1
$pravo apply -auto-approve > /dev/null
$pravo destroy -auto-approve
Error: destroy refused: $lifecycle.prevent_destroy is set on port; remove the setting from the specification to destroy the resource

The refusal names each resource that has the setting. It comes before the plan, so nothing is deleted, not even the resources without the setting:

terminal
$pravo state list
base
port

The setting also refuses a replacement of the resource, because a replacement deletes it:

terminalexit 1
$pravo plan --replace port
port: Refreshing state... [id=20093]

Error: port: replacement requires destroying the resource, but $lifecycle.prevent_destroy is set

A resource that the specification does not declare has no $lifecycle to read. Remove port from the specification and pravo destroy deletes it with base:

main.cue
package demo

import rnd "pravo.dev/providers/hashicorp/random"

$random: rnd.#Provider

base: $random.#Resource.random_integer & {min: 1, max: 9, seed: "base"}
terminal
$pravo destroy -auto-approve | grep '^Destroy complete'
Destroy complete! Resources: 0 added, 0 changed, 2 destroyed. [txn <txn>]

To refuse deletions of every kind, name a plan policy with --policy, as above.

See also