hub v0.133.0 (R-859 test approvals end with the test; R-840 bundle on the System page, manifest, alarm); installer 1.31.0 (root files from the config bundle); bundle bootstrap script; golden 0.293.0 evidence; rulings 96–99; drill-r50 removed (evidence)
gates / gates (push) Successful in 29s
gates / gates (push) Successful in 29s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -31,9 +31,10 @@ type systemRow struct {
|
||||
FactsNote string
|
||||
// host
|
||||
PVE, KernelRunning, KernelNextBoot, HostDebian cell
|
||||
HostRelease, HostPending, HostNotCovered cell
|
||||
Held, RebootSince, KernelPanic, Oops cell
|
||||
CrashRestarts24h, Guard cell
|
||||
HostRelease, HostPending, HostNotCovered cell
|
||||
Held, RebootSince, KernelPanic, Oops cell
|
||||
CrashRestarts24h, Guard cell
|
||||
Bundle cell // R-840: the root-owned config bundle
|
||||
// guest
|
||||
GuestDebian, GuestRelease, GuestPending, GuestRestart cell
|
||||
// docker
|
||||
@@ -46,13 +47,43 @@ type systemRow struct {
|
||||
type OSSystemView interface {
|
||||
Fleet() ([]osupdates.FleetLine, error)
|
||||
Releases() []osupdates.ReleaseInfo
|
||||
CancelledReleases() []osupdates.ReleaseInfo
|
||||
Candidates() []osupdates.Status
|
||||
Thresholds() (stale, reboot, notCovered time.Duration)
|
||||
BundleThreshold() time.Duration
|
||||
ApproveDocker() (string, error)
|
||||
}
|
||||
|
||||
func plain(s string) cell { return cell{Text: s} }
|
||||
|
||||
// bundleCell is the "Root files" cell (R-840): the box's config bundle against the vouched agent's. Amber while behind,
|
||||
// red from the alarm's wait on, amber when a file was changed by hand (drift); "unknown" is never coloured as a fact.
|
||||
func bundleCell(f sysfacts.System, vouchedAgent, vouchedSHA string, since time.Time, after time.Duration, now time.Time) cell {
|
||||
b := f.Bundle
|
||||
if !f.Present || b.Version == "" || b.Version == sysfacts.Unknown {
|
||||
return unknownCell("")
|
||||
}
|
||||
c := cell{Text: b.Version}
|
||||
switch {
|
||||
case vouchedSHA == "":
|
||||
c.Title = "no vouched bundle to compare with (the vouched agent carries none)"
|
||||
case b.BundleSHA256 != vouchedSHA:
|
||||
c.Class, c.Title = "warn", "behind the vouched agent "+vouchedAgent+"'s bundle — send it with a signed agent_config_update"
|
||||
if !since.IsZero() {
|
||||
c.Title += " (behind since " + since.UTC().Format("2006-01-02 15:04") + " UTC)"
|
||||
if now.Sub(since) >= after {
|
||||
c.Class = "bad"
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(b.Drift) > 0 {
|
||||
c.Text += " (changed by hand)"
|
||||
c.Class = "warn"
|
||||
c.Title = "files differ from the installed bundle: " + strings.Join(b.Drift, ", ")
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func unknownCell(s string) cell {
|
||||
if s == "" || s == sysfacts.Unknown {
|
||||
return cell{Text: "unknown", Class: "warn", Title: "the box could not read it (agent older than v0.142.0, or the guest is down)"}
|
||||
@@ -207,9 +238,16 @@ func (s *Server) handleSystem(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
stale, reboot, notCov := view.Thresholds()
|
||||
rows := buildSystemRows(lines, facts, names, stale, reboot, notCov, time.Now())
|
||||
man := s.store.GetArtifactManifest()
|
||||
for i := range rows {
|
||||
rows[i].Bundle = bundleCell(facts[rows[i].HostID], man.AgentVersion, man.BundleSHA256,
|
||||
s.store.BundleBehindSince(rows[i].HostID), view.BundleThreshold(), time.Now())
|
||||
}
|
||||
data := map[string]interface{}{
|
||||
"Rows": buildSystemRows(lines, facts, names, stale, reboot, notCov, time.Now()),
|
||||
"Rows": rows,
|
||||
"Releases": view.Releases(),
|
||||
"Cancelled": view.CancelledReleases(),
|
||||
"Candidates": view.Candidates(),
|
||||
"Flash": r.URL.Query().Get("flash"),
|
||||
"FlashErr": r.URL.Query().Get("err"),
|
||||
|
||||
Reference in New Issue
Block a user