From c1a6a2c6ca259602cd6c4397ff14951f500a9de9 Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Wed, 26 Aug 2026 07:05:16 +0200 Subject: [PATCH] fix(opentofu): drop the last Proxmox VM and forget it from state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- opentofu/removed_k8s_3.tf | 27 +++++++++++++++++++++ opentofu/talos_image.tf | 13 ---------- opentofu/vm_152_k8s_3.tf | 50 --------------------------------------- 3 files changed, 27 insertions(+), 63 deletions(-) create mode 100644 opentofu/removed_k8s_3.tf delete mode 100644 opentofu/talos_image.tf delete mode 100644 opentofu/vm_152_k8s_3.tf diff --git a/opentofu/removed_k8s_3.tf b/opentofu/removed_k8s_3.tf new file mode 100644 index 00000000..598ad52e --- /dev/null +++ b/opentofu/removed_k8s_3.tf @@ -0,0 +1,27 @@ +# k8s-3 was the last Proxmox VM. neptune now runs Talos on bare metal, and its +# disks were wiped during the conversion, so the VM this module described does +# not exist in any form. +# +# `removed` rather than simply deleting vm_152_k8s_3.tf: dropping the resource +# from configuration alone makes OpenTofu plan a DESTROY, and planning a destroy +# refreshes the resource through the bpg/proxmox provider — which now has no +# endpoint to reach. That is exactly what has been failing every infrastructure +# plan since the conversion: +# +# 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 +# +# `lifecycle { destroy = false }` forgets the state entry without attempting to +# contact Proxmox. Nothing is orphaned by doing so: the guest, its disks and the +# hypervisor underneath it are all already gone. +# +# This block can be deleted once one plan has run cleanly with it — it is a +# one-shot instruction, not standing configuration. +removed { + from = module.k8s_3 + + lifecycle { + destroy = false + } +} diff --git a/opentofu/talos_image.tf b/opentofu/talos_image.tf deleted file mode 100644 index 45a8c653..00000000 --- a/opentofu/talos_image.tf +++ /dev/null @@ -1,13 +0,0 @@ -locals { - talos_version = "v1.12.6" - # Image Factory schematic (predictable naming: net.ifnames=1). Keep in - # sync with TALOS_SCHEMATIC in .woodpecker/deploy-infrastructure.yml — - # that pipeline downloads the image, this local names it for VM import, - # and both MUST agree on the filename. The schematic hash is embedded in - # the filename so a schematic bump changes the name, forcing a fresh - # download instead of silently reusing a stale cached image (which would - # reintroduce net.ifnames=0 on the next VM (re)provision). - talos_schematic = "88e3752db032a08082972bd0adf16a80849e3870c3f95cf5b669936c5699e5ad" - talos_filename = "talos-${local.talos_version}-${substr(local.talos_schematic, 0, 12)}-nocloud-amd64.raw" - talos_image = "local:import/${local.talos_filename}" -} diff --git a/opentofu/vm_152_k8s_3.tf b/opentofu/vm_152_k8s_3.tf deleted file mode 100644 index 69e9fb99..00000000 --- a/opentofu/vm_152_k8s_3.tf +++ /dev/null @@ -1,50 +0,0 @@ -module "k8s_3" { - source = "./modules/proxmox_vm" - - name = "k8s-3.srv.renner.uno" - target_node = "neptune" - vmid = 152 - memory = 49152 - cores = 8 - - template_name = null - cloud_init = false - full_clone = false - bios = "ovmf" - machine = "q35" - boot = "order=virtio0" - agent_enabled = true - - # Second NIC on v30iot so Cilium L2 announce can win ARP on the IoT - # VLAN from this node (previously only k8s-edge had v30iot, so any - # IoT-pool LB lease landing here was unreachable from devices). - extra_network_bridges = ["v30iot"] - - disks = [ - { - storage = "local-zfs" - size = "64G" - format = "raw" - slot = "virtio0" - file_id = local.talos_image - } - ] - - hostpci = [ - { - mapping = "osd-ssd" - }, - { - mapping = "x710-port1" - } - ] - - tags = "kubernetes;talos;controlplane" - ssh_public_keys = local.common_ssh_keys - - vm_state = "running" - - # Rebuild pipeline issues `-replace`; skip graceful shutdown so a - # non-responsive Talos guest can't hang the destroy for 30 minutes. - stop_on_destroy = true -} -- 2.54.0