v0.335.0: no app stop for a tier the agent will refuse because its host is busy (host_busy pre-check, R-921)
gates / gates (push) Successful in 53s

This commit is contained in:
2026-10-19 20:05:52 +02:00
parent db980ff2cc
commit 15ea002458
9 changed files with 282 additions and 13 deletions
@@ -73,3 +73,35 @@ func TestBackupJobsInFlight_StatusErrorIsReturned(t *testing.T) {
t.Fatal("a failed status read was swallowed — the caller could not tell it from 'nothing in flight'")
}
}
// R-921 part 2: HostBusy reads the agent's real wire shape (untargeted GET /backup/status, `host_busy`); an agent
// without the field is „not known" — never „free".
func TestHostBusy_ReadsTheAgentsGate(t *testing.T) {
for _, tc := range []struct {
name, body string
busy, known bool
what string
}{
{"held", `{"ok":true,"data":{"vmid":9201,"phase":"idle","host_busy":{"busy":true,"what":"os-pve-step"}}}`, true, true, "os-pve-step"},
{"free", `{"ok":true,"data":{"vmid":9201,"phase":"idle","host_busy":{"busy":false}}}`, false, true, ""},
{"older agent", `{"ok":true,"data":{"vmid":9201,"phase":"idle"}}`, false, false, ""},
} {
t.Run(tc.name, func(t *testing.T) {
mux := http.NewServeMux()
mux.HandleFunc("GET /backup/status", func(w http.ResponseWriter, r *http.Request) {
if r.URL.RawQuery != "" {
http.Error(w, "want the untargeted status", http.StatusBadRequest)
return
}
_, _ = w.Write([]byte(tc.body))
})
s := httptest.NewTLSServer(mux)
defer s.Close()
c := clientFor(t, s, strings.TrimPrefix(s.URL, "https://"))
busy, what, known, err := c.HostBusy(context.Background())
if err != nil || busy != tc.busy || known != tc.known || what != tc.what {
t.Fatalf("HostBusy = %v %q known=%v err=%v, want %v %q known=%v", busy, what, known, err, tc.busy, tc.what, tc.known)
}
})
}
}