hub v0.176.1: Restart controller for every guest of a customer host (0.176.0 gated it on a controller version the agent does not report — found live); R-1345 filed (token scopes cannot be edited) — test red first
gates / gates (push) Successful in 1m46s

This commit is contained in:
admin committed 2026-10-29 12:57:14 +01:00
1 parent 682015db86
commit d0dbc6f1cd
5 files changed
+29 -5

No files matched your search

+17
View File
@@ -92,3 +92,20 @@ func TestHostPage_RestartAndClearHoldPosts(t *testing.T) {
t.Fatalf("rows = %d, want the two accepted presses only", len(rows))
}
}
// Live 2026-10-29 (hub 0.176.0, Tester 1): the agent reports guests WITHOUT a controller version (the column reads „—"),
// so a button gated on the version never rendered. Every guest of a customer host gets it; the agent refuses a guest it
// did not provision. RED-PROOF: seen failing on 0.176.0's template (gated on .ControllerVersion).
func TestHostPage_RestartRendersForAGuestWithNoReportedVersion(t *testing.T) {
s, st := newTestServer(t)
if err := st.UpsertHost(&store.Host{HostID: "h1", CustomerID: "c1", APIKey: "k"}); err != nil {
t.Fatal(err)
}
now := time.Now()
if err := st.UpsertGuestFromReport(&store.Guest{GuestID: "h1-9201", CustomerID: "c1", HostID: "h1", VMID: 9201, Status: "running", LastSeenAt: &now}); err != nil {
t.Fatal(err)
}
if body := renderHost(t, s, "h1"); !strings.Contains(body, `data-restart-controller="9201"`) {
t.Fatal("no Restart controller for a guest whose controller version the agent does not report")
}
}
+3 -3
View File
@@ -174,8 +174,8 @@ func TestHandleHostDetail(t *testing.T) {
// Decision 185 (2026-10-08): plus the four operator-action buttons — a closed list, none of which
// deletes or mutates the host (TestOperatorActions_* pin what they may do). Every OTHER button
// remains absent: 2 log requests + 4 operator actions, and the 4 all post to /operator-action.
// 2026-10-29 (operator brief, Part 1): plus ONE „Restart controller" per guest that runs a controller (the AGENT's
// closed list, behind a confirm step; this fixture has one such guest). „Clear hold" appears only per held app (none
// 2026-10-29 (operator brief, Part 1): plus ONE „Restart controller" per guest of a customer host (the AGENT's closed
// list, behind a confirm step; this fixture has one guest). „Clear hold" appears only per held app (none
// here). No other button.
if got := strings.Count(strings.ToLower(body), "<button"); got != 7 {
t.Errorf("host detail has %d buttons, want exactly the 2 log-request + 4 operator-action + 1 restart-controller buttons", got)
@@ -184,7 +184,7 @@ func TestHandleHostDetail(t *testing.T) {
t.Errorf("operator-action forms = %d, want 5", got)
}
if got := strings.Count(body, `value="restart_controller"`); got != 1 {
t.Errorf("restart_controller forms = %d, want 1 (one guest with a controller)", got)
t.Errorf("restart_controller forms = %d, want 1 (one guest)", got)
}
if strings.Count(body, `action="/hosts/demo-felhom-01/request-logs"`) != 2 {
t.Error("the request-logs forms are missing — every button must be a log-bundle request")
@@ -134,7 +134,7 @@
<td>{{if .DisplayName}}{{.DisplayName}}{{else}}—{{end}}</td>
<td>{{if eq .Status "running"}}<span style="color: var(--green)">{{.Status}}</span>{{else if eq .Status "stopped"}}<span style="color: var(--red)">{{.Status}}</span>{{else}}{{.Status}}{{end}}</td>
<td>{{if .ControllerVersion}}<code>{{.ControllerVersion}}</code>{{else}}—{{end}}
{{if and .ControllerVersion $.CustomerID}}{{/* 2026-10-29: the AGENT restarts it (the supervisor's act and guards; 3 in 15 min, then refused for 30) — works with the controller stopped */}}
{{if $.CustomerID}}{{/* 2026-10-29: the AGENT restarts it (every guest: the agent reports no controller version, and it refuses a guest it did not provision) (the supervisor's act and guards; 3 in 15 min, then refused for 30) — works with the controller stopped */}}
<details class="op-confirm" data-restart-controller="{{.VMID}}">
<summary class="btn btn-sm btn-outline">Restart controller</summary>
<form method="POST" action="/hosts/{{$.HostID}}/operator-action">