terraform apply -target can still plan to destroy something you never named
Targeting one VM pulled an orphaned image download in through a local value and planned its destroy. A temporary edit keeps it out, and applying a saved, inspected plan beats an auto-approved one, because a saved plan goes stale after any other apply.
I only wanted to change a network tag on three VMs. terraform plan -target=<vm>
planned the change I expected and one I didn’t: the destroy of a downloaded image
that no VM used any more.
The target pulls in everything the VM’s boot logic refers to, and my boot source
is computed in a local that also touches the image downloads. Resources that are
orphaned (in state, no longer produced by the configuration) get destroyed along
the way. My Terraform version has no -exclude.
Keeping it out
A temporary edit that keeps the orphan’s key in the for_each, then apply, then
revert:
needed_images = distinct(concat(
[{ node = "pve2", image = "debian-13" }], # temporary: keeps the orphan out of the plan
[for vm in var.vms : { node = vm.node, image = vm.image } if ...],
))After the apply, git checkout the file.
Apply a plan you’ve read
Save the plan, inspect it as data, and apply the file:
terraform plan -out=vm.tfplan -target='proxmox_virtual_environment_vm.vms["905"]'
terraform show -json vm.tfplan | python3 -c '...' # assert: one update, only the field I meant
terraform apply vm.tfplanI asserted in the script that the plan had exactly one resource change and that
only the intended attribute differed. Two practical notes: the resources here are
keyed by VM id, so the address is vms["905"] and not the VM’s name; and a saved
plan goes stale after any other apply to the same state (“Saved plan is stale”),
so with several VMs, plan again before each one. A long apply can also be cut off
by a tool’s timeout in the middle: run it in the background and plan again to see where it
stopped.