fix(opentofu): drop the last Proxmox VM and forget it from state #621

Merged
k.renner merged 1 commits from tofu-drop-proxmox-vm into master 2026-08-26 05:19:34 +00:00
Member

The infrastructure pipeline has been failing since neptune was wiped, and it is not related to #612. module.k8s_3 still declared a Proxmox VM, so the provider tried to reach a hypervisor that no longer exists.

From pipeline 6649, the plan step:

Error: failed to get resources list of type ("vm") for cluster:
dial tcp 10.2.40.201:8006: connect: no route to host
  with module.k8s_3.proxmox_virtual_environment_vm.this,
  on modules/proxmox_vm/main.tf line 26

Everything else in that plan was fine — Plan: 0 to add, 60 to change, 0 to destroy for the UniFi resources — then it died on Proxmox.

Why deleting the file is not enough

Removing a resource from configuration makes OpenTofu plan a destroy, and planning a destroy refreshes the resource through the same unreachable provider. The plan would keep failing, just at a different point.

A removed block with lifecycle { destroy = false } forgets the state entry without contacting Proxmox:

removed {
  from = module.k8s_3
  lifecycle {
    destroy = false
  }
}

Nothing is orphaned by this. The guest, its disks and the hypervisor underneath were all destroyed during the conversion — there is no resource left for state to be tracking.

This is deliberately the declarative form rather than a tofu state rm run by hand against production state: it is reviewable here, and it goes through the normal pipeline instead of an out-of-band operation.

The block is one-shot. Delete it once a plan has run cleanly with it.

Also removed

talos_image.tf — locals naming the nocloud image for VM import, with no consumer other than the VM module.

Deliberately left for a follow-up

The proxmox provider block, the proxmox_vm / proxmox_lxc / bpg_proxmox_container modules, and sync_state_from_pve.py. A provider with no resources is never contacted, so leaving it declared costs nothing — and removing it should wait until one clean plan proves state holds no other Proxmox resources.

I could not verify that from here: the S3 credentials used for local runs have been revoked, so I cannot read state. Worth doing that check before the follow-up rather than guessing.

Verified

tofu validate → Success! The configuration is valid. and tofu fmt -check clean, both offline.

One caveat worth a glance: removed blocks need OpenTofu ≥ 1.7. Local is v1.12.1; the CI image is ci-tofu:2026-04-29, comfortably past that, but if the plan fails to parse that is the first thing to check.

**The infrastructure pipeline has been failing since neptune was wiped**, and it is not related to #612. `module.k8s_3` still declared a Proxmox VM, so the provider tried to reach a hypervisor that no longer exists. From pipeline 6649, the `plan` step: ``` Error: failed to get resources list of type ("vm") for cluster: dial tcp 10.2.40.201:8006: connect: no route to host with module.k8s_3.proxmox_virtual_environment_vm.this, on modules/proxmox_vm/main.tf line 26 ``` Everything else in that plan was fine — `Plan: 0 to add, 60 to change, 0 to destroy` for the UniFi resources — then it died on Proxmox. ## Why deleting the file is not enough Removing a resource from configuration makes OpenTofu plan a **destroy**, and planning a destroy refreshes the resource through the same unreachable provider. The plan would keep failing, just at a different point. A `removed` block with `lifecycle { destroy = false }` forgets the state entry without contacting Proxmox: ```hcl removed { from = module.k8s_3 lifecycle { destroy = false } } ``` Nothing is orphaned by this. The guest, its disks and the hypervisor underneath were all destroyed during the conversion — there is no resource left for state to be tracking. This is deliberately the declarative form rather than a `tofu state rm` run by hand against production state: it is reviewable here, and it goes through the normal pipeline instead of an out-of-band operation. The block is one-shot. Delete it once a plan has run cleanly with it. ## Also removed `talos_image.tf` — locals naming the nocloud image for VM import, with no consumer other than the VM module. ## Deliberately left for a follow-up The `proxmox` provider block, the `proxmox_vm` / `proxmox_lxc` / `bpg_proxmox_container` modules, and `sync_state_from_pve.py`. A provider with no resources is never contacted, so leaving it declared costs nothing — and removing it should wait until one clean plan proves state holds no other Proxmox resources. I could not verify that from here: the S3 credentials used for local runs have been revoked, so I cannot read state. Worth doing that check before the follow-up rather than guessing. ## Verified `tofu validate` → `Success! The configuration is valid.` and `tofu fmt -check` clean, both offline. One caveat worth a glance: `removed` blocks need OpenTofu ≥ 1.7. Local is v1.12.1; the CI image is `ci-tofu:2026-04-29`, comfortably past that, but if the plan fails to parse that is the first thing to check.
claude-bot added 1 commit 2026-08-26 05:05:48 +00:00
fix(opentofu): drop the last Proxmox VM and forget it from state
ci/woodpecker/pr/pr-review Pipeline was successful
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
c1a6a2c6ca
Every infrastructure plan has failed since neptune was wiped. module.k8s_3 still
declared a Proxmox VM, so the bpg/proxmox provider tried to reach a hypervisor
that no longer exists:

  Error: failed to get resources list of type ("vm") for cluster:
  dial tcp 10.2.40.201:8006: connect: no route to host
    with module.k8s_3.proxmox_virtual_environment_vm.this

Deleting vm_152_k8s_3.tf alone does not fix that. Removing a resource from
configuration makes OpenTofu plan a destroy, and planning a destroy refreshes
the resource through the same unreachable provider.

A `removed` block with `lifecycle { destroy = false }` forgets the state entry
without contacting Proxmox. Nothing is orphaned: the guest, its disks and the
hypervisor underneath were all destroyed during the conversion. This is the
declarative equivalent of a state removal, reviewable in git rather than run by
hand against production state.

talos_image.tf goes with it. Its locals named the nocloud image for VM import
and had no consumer other than the VM module.

Deliberately kept for a follow-up: the proxmox provider block, the
proxmox_vm/proxmox_lxc/bpg_proxmox_container modules and sync_state_from_pve.py.
A provider with no resources is never contacted, so leaving it costs nothing,
and removing it should wait until a clean plan proves state holds no other
Proxmox resources. That check cannot be made from here — the S3 credentials
used for local runs have been revoked.

Verified with `tofu validate` and `tofu fmt -check` offline.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
review-bot left a comment
Member

🤖 Automated review — model CLI default (complexity: complex), commit c1a6a2c6ca259602cd6c4397ff14951f500a9de9.

Advisory review by the review-bot pipeline. It never approves; a human merges. Push new commits to get a fresh review.


Summary

This PR fixes the failing infrastructure pipeline by replacing the last Proxmox-VM module call (module.k8s_3, in vm_152_k8s_3.tf) with a removed block (opentofu/removed_k8s_3.tf) that forgets the state entry without contacting the now-unreachable Proxmox host, and drops the now-unused talos_image.tf locals. I verified the removed block targets the correct module address, that no other .tf file references module.k8s_3, its outputs, or the deleted talos_image locals, and that module.k8s_3's nested dns_records submodule never received cnames/ingress_cnames (both default to []), so there's nothing orphaned in that nested module either. No blocking issues found.

🟡 Suggestions

  • kubernetes/RUNBOOK-cold-rebuild.md:79-83 — the cold-rebuild runbook still says Step 1 (tofu apply) provisions k8s-2 (saturn) and k8s-3 (neptune) as Proxmox VMs, and that only k8s-1 (jupiter) is bare metal needing the separate bare-metal ISO boot flow described just below. After this PR, k8s-3/neptune is bare metal too and OpenTofu no longer creates it, so a rebuild following this doc as written would wait forever for a VM that OpenTofu will never provision. Worth a follow-up updating this section to treat neptune like jupiter (bare-metal boot before Step 2). Not introduced by this diff — the drift dates to the earlier neptune conversion — but this PR is the natural place to catch it since it's finishing that conversion in code.
  • PR body notes the removed block is "one-shot" and should be deleted once a plan runs cleanly; consider linking a tracking issue so that cleanup isn't only remembered via the merged PR description.

Tests

No automated tests apply here — this is IaC config verified via tofu validate/tofu fmt -check per the PR description (not independently re-run in this review, but the change is a syntactically standard removed block plus two file deletions with no remaining references anywhere in the repo, so I have no reason to doubt those results). The author's caveat about removed requiring OpenTofu ≥ 1.7 (CI image is well past that) is reasonable and already called out.

Recommendation

Looks reasonable — no blocking issues; comments above are optional.

🤖 **Automated review** — model `CLI default` (complexity: complex), commit `c1a6a2c6ca259602cd6c4397ff14951f500a9de9`. > Advisory review by the `review-bot` pipeline. It never approves; a human merges. Push new commits to get a fresh review. --- ## Summary This PR fixes the failing infrastructure pipeline by replacing the last Proxmox-VM module call (`module.k8s_3`, in `vm_152_k8s_3.tf`) with a `removed` block (`opentofu/removed_k8s_3.tf`) that forgets the state entry without contacting the now-unreachable Proxmox host, and drops the now-unused `talos_image.tf` locals. I verified the `removed` block targets the correct module address, that no other `.tf` file references `module.k8s_3`, its outputs, or the deleted `talos_image` locals, and that `module.k8s_3`'s nested `dns_records` submodule never received `cnames`/`ingress_cnames` (both default to `[]`), so there's nothing orphaned in that nested module either. No blocking issues found. ## 🟡 Suggestions - `kubernetes/RUNBOOK-cold-rebuild.md:79-83` — the cold-rebuild runbook still says Step 1 (`tofu apply`) provisions `k8s-2 (saturn) and k8s-3 (neptune)` as Proxmox VMs, and that only `k8s-1` (jupiter) is bare metal needing the separate bare-metal ISO boot flow described just below. After this PR, `k8s-3`/neptune is bare metal too and OpenTofu no longer creates it, so a rebuild following this doc as written would wait forever for a VM that OpenTofu will never provision. Worth a follow-up updating this section to treat neptune like jupiter (bare-metal boot before Step 2). Not introduced by this diff — the drift dates to the earlier neptune conversion — but this PR is the natural place to catch it since it's finishing that conversion in code. - PR body notes the `removed` block is "one-shot" and should be deleted once a plan runs cleanly; consider linking a tracking issue so that cleanup isn't only remembered via the merged PR description. ## Tests No automated tests apply here — this is IaC config verified via `tofu validate`/`tofu fmt -check` per the PR description (not independently re-run in this review, but the change is a syntactically standard `removed` block plus two file deletions with no remaining references anywhere in the repo, so I have no reason to doubt those results). The author's caveat about `removed` requiring OpenTofu ≥ 1.7 (CI image is well past that) is reasonable and already called out. ## Recommendation Looks reasonable — no blocking issues; comments above are optional. <!-- pr-review:sha=c1a6a2c6ca259602cd6c4397ff14951f500a9de9 -->
k.renner merged commit 7b2900e594 into master 2026-08-26 05:19:34 +00:00
Sign in to join this conversation.