cf6fec8d87
gates / gates (push) Successful in 6m17s
Needs attention, Waiting for you (one card per kernel/Docker/Proxmox set the button may approve), a 7-column Boxes table whose rows open to every old value, and a closed Details (release ids, cancelled approvals, ring-0 counts, floors, crash guard and root files, Approve now - which now asks first). Same data, buttons, routes and CSRF field. No deploy. Screenshots in audits/hub-system-page-2026-10-10/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
82 lines
4.3 KiB
Go
82 lines
4.3 KiB
Go
package web
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-hub/internal/store"
|
|
"gitea.dooplex.hu/admin/felhom-hub/internal/sysfacts"
|
|
)
|
|
|
|
// R-444 (`09` §3 decision 139): the System page's "Last disk trim" cell — one case per branch. Staleness is judged on
|
|
// last_ok_at, never on the attempt time ("presence is not success").
|
|
func TestTrimCell(t *testing.T) {
|
|
now := time.Date(2026, 10, 6, 12, 0, 0, 0, time.UTC)
|
|
at := func(d time.Duration) string { return now.Add(-d).Format(time.RFC3339) }
|
|
day := 24 * time.Hour
|
|
dt := func(gs ...sysfacts.GuestTrim) *sysfacts.DiskTrim {
|
|
return &sysfacts.DiskTrim{Schedule: "weekly", Guests: gs}
|
|
}
|
|
cases := []struct {
|
|
name string
|
|
dt *sysfacts.DiskTrim
|
|
text string
|
|
class string
|
|
titleHas string
|
|
}{
|
|
{"agent sends nothing", nil, "—", "", "reports no disk trim"},
|
|
{"stanza, no guest yet", dt(), "none yet", "", "has not trimmed a guest yet"},
|
|
{"recent ok", dt(sysfacts.GuestTrim{VMID: 9201, LastAttemptAt: at(2 * day), LastOKAt: at(2 * day), OK: true, BytesTrimmed: 32427003904}),
|
|
"2 days ago · 30.2 GiB", "", "schedule: weekly"},
|
|
{"ok but older than 14 days", dt(sysfacts.GuestTrim{VMID: 9201, LastAttemptAt: at(15 * day), LastOKAt: at(15 * day), OK: true, BytesTrimmed: 1 << 30}),
|
|
"15 days ago · 1.0 GiB", "warn", "older than 14 days"},
|
|
{"exactly 14 days is not stale", dt(sysfacts.GuestTrim{VMID: 9201, LastAttemptAt: at(14 * day), LastOKAt: at(14 * day), OK: true}),
|
|
"14 days ago · 0.0 GiB", "", ""},
|
|
{"newest failed, recent success before it", dt(sysfacts.GuestTrim{VMID: 9201, LastAttemptAt: at(1 * day), LastOKAt: at(8 * day), OK: false, Error: "pct fstrim: exit 255"}),
|
|
"FAILED 24 h ago: pct fstrim: exit 255 (last ok 8 days ago)", "warn", "the newest trim failed"},
|
|
{"failed and never ok", dt(sysfacts.GuestTrim{VMID: 9201, LastAttemptAt: at(1 * day), OK: false}),
|
|
"FAILED 24 h ago: no error text (never ok)", "warn", "the newest trim failed"},
|
|
{"a recent ATTEMPT does not hide a 20-day-old success", dt(sysfacts.GuestTrim{VMID: 9201, LastAttemptAt: at(1 * day), LastOKAt: at(20 * day), OK: false, Error: "busy"}),
|
|
"FAILED 24 h ago: busy (last ok 20 days ago)", "warn", "older than 14 days"},
|
|
{"two guests, one amber", dt(
|
|
sysfacts.GuestTrim{VMID: 9201, LastAttemptAt: at(2 * day), LastOKAt: at(2 * day), OK: true, BytesTrimmed: 2 << 30},
|
|
sysfacts.GuestTrim{VMID: 9202, LastAttemptAt: at(1 * day), OK: false, Error: "x"}),
|
|
"9201: 2 days ago · 2.0 GiB / 9202: FAILED 24 h ago: x (never ok)", "warn", "guest 9202"},
|
|
{"unreadable time", dt(sysfacts.GuestTrim{VMID: 9201, LastAttemptAt: "yesterday", OK: true}), "unknown", "warn", "unreadable last_attempt_at"},
|
|
}
|
|
for _, c := range cases {
|
|
got := trimCell(c.dt, now)
|
|
if got.Text != c.text || got.Class != c.class || !strings.Contains(got.Title, c.titleHas) {
|
|
t.Errorf("%s: got %+v, want text %q class %q title containing %q", c.name, got, c.text, c.class, c.titleHas)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The cell reaches the rendered page, read from the stored host report (the endpoint the operator's browser calls).
|
|
func TestSystemPage_LastDiskTrim(t *testing.T) {
|
|
s, st, _ := systemServer(t)
|
|
when := time.Now().Add(-20 * 24 * time.Hour).UTC().Format(time.RFC3339)
|
|
body := fmt.Sprintf(`{"host":{"cpu_percent":1},"guest_disk_trim":{"schedule":"weekly","guests":[{"vmid":9201,"last_attempt_at":%q,"ok":true,"bytes_trimmed":32427003904,"mounts":2,"duration_seconds":24.4,"last_ok_at":%q}]}}`, when, when)
|
|
if err := st.UpsertHost(&store.Host{HostID: "trim-1", CustomerID: "c-trim", APIKey: "k-trim"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := st.SaveHostReport("trim-1", "c-trim", []byte(body), store.HostReportDenorm{AgentVersion: "0.150.0", CloudflaredStatus: "running"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
b := getSystem(t, s)
|
|
if !strings.Contains(b, ">Last disk trim</dt>") {
|
|
t.Error("the System page lacks the Last disk trim column")
|
|
}
|
|
if !strings.Contains(b, "20 days ago · 30.2 GiB") {
|
|
t.Errorf("the trim-1 box's trim is not on the page")
|
|
}
|
|
if !strings.Contains(b, `class="c-warn" title="guest 9201: the last successful trim is older than 14 days`) {
|
|
t.Error("a 20-day-old trim must be amber, with its reason")
|
|
}
|
|
if !strings.Contains(b, `title="the agent reports no disk trim`) {
|
|
t.Error("a box whose agent sends no trim must read — with its reason")
|
|
}
|
|
}
|