From c2b4985abe05934716c736e80bb7c4b17c809a7e Mon Sep 17 00:00:00 2001 From: Ilker Manap Date: Mon, 5 Oct 2026 02:29:00 +0200 Subject: [PATCH] The floating address is read each time the summary is asked server add records it after restarting the new control plane, which then never named it. Co-Authored-By: Claude Opus 5.5 (1M context) --- internal/cli/controlplanes.go | 13 ++++++++----- internal/cli/controlplanes_test.go | 6 +++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/internal/cli/controlplanes.go b/internal/cli/controlplanes.go index 95209836..6d959b64 100644 --- a/internal/cli/controlplanes.go +++ b/internal/cli/controlplanes.go @@ -25,8 +25,9 @@ const floatingPath = "/etc/llmgw/floating" // held it last and says nothing about a standby that has stopped — and a // standby that is not there is the thing worth seeing before it is needed. type controlPlaneProbe struct { - st *store.DB - self string + st *store.DB + self string + // floating is the file the floating address is recorded in. floating string client *http.Client // leaderURL is where a host is asked; tests point it elsewhere. @@ -65,7 +66,9 @@ func (p *controlPlaneProbe) Status() adminapi.ControlPlanes { p.at, p.last = time.Now(), adminapi.ControlPlanes{} return p.last } - out := adminapi.ControlPlanes{Members: make([]adminapi.ControlPlane, len(cps)), Floating: p.floating} + // Read each time: server add writes it after this process may have + // started. + out := adminapi.ControlPlanes{Members: make([]adminapi.ControlPlane, len(cps)), Floating: floatingAddress(p.floating)} var wg sync.WaitGroup for i, cp := range cps { host := cp.URL @@ -75,8 +78,8 @@ func (p *controlPlaneProbe) Status() adminapi.ControlPlanes { out.Members[i] = adminapi.ControlPlane{Name: cp.Name, Address: host, This: cp.Name == p.self} wg.Go(func() { out.Members[i].State = p.ask(ctx, host) }) } - if p.floating != "" { - wg.Go(func() { out.FloatingUp = p.ask(ctx, p.floating) == "leading" }) + if out.Floating != "" { + wg.Go(func() { out.FloatingUp = p.ask(ctx, out.Floating) == "leading" }) } wg.Wait() p.at, p.last = time.Now(), out diff --git a/internal/cli/controlplanes_test.go b/internal/cli/controlplanes_test.go index 7fde4e61..bd0cb2ca 100644 --- a/internal/cli/controlplanes_test.go +++ b/internal/cli/controlplanes_test.go @@ -76,7 +76,11 @@ func TestTheProbeAsksEachControlPlaneWhetherItLeads(t *testing.T) { } at := map[string]string{"10.0.0.1": leading.URL, "10.0.0.2": standby.URL, "10.0.0.3": gone.URL, "10.0.0.161": leading.URL} p := newControlPlaneProbe(st, ":8080") - p.self, p.floating = "two", "10.0.0.161" + floating := filepath.Join(t.TempDir(), "floating") + if err := os.WriteFile(floating, []byte("10.0.0.161/24\n"), 0o644); err != nil { + t.Fatal(err) + } + p.self, p.floating = "two", floating p.leaderURL = func(host string) string { return at[host] + "/leader" } s := p.Status()