From ecd2fece594f92e6f9a538473e178aaa42eebc4b Mon Sep 17 00:00:00 2001 From: eding Date: Sun, 26 Jul 2026 21:22:38 +0200 Subject: [PATCH] fix: recover Talos control plane bootstrap --- internal/bootstrap/bootstrap.go | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/internal/bootstrap/bootstrap.go b/internal/bootstrap/bootstrap.go index d41a9d7..1b126ac 100644 --- a/internal/bootstrap/bootstrap.go +++ b/internal/bootstrap/bootstrap.go @@ -481,11 +481,17 @@ func applyTalosConfigs(dir string, cfg config.Config) error { return fmt.Errorf("apply Talos config to %s: %w", node.Name, err) } } else { - if _, maintenanceErr := utils.RunCommandQuietOutputInDir(dir, "talosctl", "get", "machinestatus", "--insecure", "--nodes="+nodeAddress, "--endpoints="+nodeAddress, "--output=json"); maintenanceErr != nil { - return fmt.Errorf("determine Talos state for %s; refusing insecure takeover", node.Name) - } - if err := utils.RunCommandInDir(dir, "talosctl", "apply-config", "--insecure", "--nodes="+nodeAddress, "--endpoints="+nodeAddress, "--file="+configFile); err != nil { - return fmt.Errorf("apply initial Talos config to %s: %w", node.Name, err) + if _, maintenanceErr := utils.RunCommandQuietOutputInDir(dir, "talosctl", "get", "machinestatus", "--insecure", "--nodes="+nodeAddress, "--endpoints="+nodeAddress, "--output=json"); maintenanceErr == nil { + if err := utils.RunCommandInDir(dir, "talosctl", "apply-config", "--insecure", "--nodes="+nodeAddress, "--endpoints="+nodeAddress, "--file="+configFile); err != nil { + return fmt.Errorf("apply initial Talos config to %s: %w", node.Name, err) + } + } else { + if err := waitForTalosAPI(dir, cfg, nodeAddress); err != nil { + return fmt.Errorf("determine Talos state for %s: %w", node.Name, err) + } + if err := utils.RunCommandInDir(dir, "talosctl", secureArgs...); err != nil { + return fmt.Errorf("apply Talos config to %s: %w", node.Name, err) + } } } if err := waitForTalosReboot(dir, cfg, nodeAddress); err != nil { @@ -499,13 +505,14 @@ func bootstrapEtcdIfNeeded(dir string, cfg config.Config) error { if _, err := utils.RunCommandQuietOutputInDir(dir, "talosctl", "etcd", "status", "--talosconfig=./clusterconfig/talosconfig", "--endpoints="+cfg.Talos.BootstrapEndpoint, "--nodes="+cfg.Talos.BootstrapNode); err == nil { return nil } - if members, err := utils.RunCommandQuietOutputInDir(dir, "talosctl", "get", "members", "--talosconfig=./clusterconfig/talosconfig", "--endpoints="+cfg.Talos.BootstrapEndpoint, "--nodes="+cfg.Talos.BootstrapNode, "--output=json"); err == nil && len(strings.TrimSpace(string(members))) > 0 { - return errors.New("etcd members exist but etcd status is unavailable; refusing to bootstrap an existing cluster") - } return utils.RunCommandInDir(dir, "talosctl", "bootstrap", "--talosconfig=./clusterconfig/talosconfig", "--endpoints="+cfg.Talos.BootstrapEndpoint, "--nodes="+cfg.Talos.BootstrapNode) } func waitForTalosReboot(dir string, cfg config.Config, node string) error { + return waitForTalosAPI(dir, cfg, node) +} + +func waitForTalosAPI(dir string, cfg config.Config, node string) error { deadline := time.Now().Add(5 * time.Minute) for time.Now().Before(deadline) { if _, err := utils.RunCommandQuietOutputInDir(dir, "talosctl", "get", "machinestatus", "--output=json", "--talosconfig=./clusterconfig/talosconfig", "--endpoints="+node, "--nodes="+node); err == nil {