From 54a2ae283877e6d6f97d4c1e0158acf7bc5a55f0 Mon Sep 17 00:00:00 2001 From: eding Date: Sun, 6 Sep 2026 09:35:05 +0200 Subject: [PATCH] fix: recover externally removed Talos VMs --- internal/bootstrap/bootstrap.go | 4 +++ internal/bootstrap/bootstrap_test.go | 44 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/internal/bootstrap/bootstrap.go b/internal/bootstrap/bootstrap.go index ce06890..6afab1d 100644 --- a/internal/bootstrap/bootstrap.go +++ b/internal/bootstrap/bootstrap.go @@ -1406,6 +1406,10 @@ func terraformReconcileTargets(cfg config.Config) []string { func (r Runner) rebuildTalosVMs(terraformDir string, environment []string) error { if err := r.importConfiguredTalosVMs(terraformDir, environment); err != nil { + var apiErr proxmox.APIError + if errors.As(err, &apiErr) && apiErr.StatusCode == 404 { + return nil + } return err } return destroyTalosVMs(terraformDir, environment) diff --git a/internal/bootstrap/bootstrap_test.go b/internal/bootstrap/bootstrap_test.go index 688f4eb..2d33897 100644 --- a/internal/bootstrap/bootstrap_test.go +++ b/internal/bootstrap/bootstrap_test.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "encoding/json" "errors" + "fmt" "net/http" "net/http/httptest" "os" @@ -17,6 +18,7 @@ import ( "github.com/Pingu-Studio/MaidnCLI/internal/config" "github.com/Pingu-Studio/MaidnCLI/internal/forgejo" "github.com/Pingu-Studio/MaidnCLI/internal/openbao" + "github.com/Pingu-Studio/MaidnCLI/internal/proxmox" "gopkg.in/yaml.v3" ) @@ -1278,6 +1280,48 @@ func TestRebuildTerraformRetainsFullTalosVMLifecycle(t *testing.T) { } } +func TestRebuildTerraformSkipsAlreadyAbsentTalosVM(t *testing.T) { + originalVerify := verifyTalosVMs + originalRun := runTerraform + originalDestroy := destroyTalosVMs + t.Cleanup(func() { + verifyTalosVMs = originalVerify + runTerraform = originalRun + destroyTalosVMs = originalDestroy + }) + + cfg := config.Config{ClusterID: "test-cluster", Talos: config.TalosConfig{ + Nodes: []config.TalosNode{{Name: "cp-01", ProxmoxNode: "pve", VMID: 100, Role: "controlplane"}}, + }} + var events []string + verifyTalosVMs = func(config.Config) error { + return fmt.Errorf("inspect configured Talos VM: %w", proxmox.APIError{StatusCode: 404}) + } + destroyTalosVMs = func(string, []string) error { + t.Fatal("destroy ran for an already-absent VM") + return nil + } + runTerraform = func(_ string, _ []string, name string, args ...string) error { + if name != "terraform" { + t.Fatalf("unexpected command %q", name) + } + switch args[0] { + case "init", "plan", "apply": + events = append(events, args[0]) + default: + t.Fatalf("unexpected Terraform operation %q", args[0]) + } + return nil + } + + if err := (Runner{Config: cfg, Mode: Rebuild}).reconcileTerraform(t.TempDir()); err != nil { + t.Fatal(err) + } + if strings.Join(events, ",") != "init,plan,apply" { + t.Fatalf("Terraform phase order = %q", events) + } +} + func TestEnsureLifecycleIdentityStoresMetadataUnderGeneratedDirectory(t *testing.T) { repo := t.TempDir() terraformDir := filepath.Join(repo, "terraform")