controller v0.265.0: R-634 cause fixed, held apps say so, OOM storm alarm, R-647 leftovers
gates / gates (push) Successful in 27s
gates / gates (push) Successful in 27s
R-634: a whole-box backup no longer stops/restarts a DEPLOYING app (the measured cause of containers running under 'not deployed'); StopStack and StartStack refuse a deploying stack for every caller. R-625: held badge 'Stopped - restore needed', no Update button. R-636: kernel oom_kill counter; 20+ in 30 min -> one app_oom_storm. R-647: held error per reader, copy_holds key, two log wordings. 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:
@@ -53,3 +53,46 @@ func TestScanOOMKilled_SeesKilledWorkerInRunningContainer(t *testing.T) {
|
||||
t.Fatalf("cache not cleared after a clean scan: %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
// R-636 — the kernel's kill counter, the limit and the peak are read from `cat memory.events
|
||||
// memory.max memory.peak` inside the container; an unreadable one is -1, never 0.
|
||||
func TestR636_ParseCgroupMemory(t *testing.T) {
|
||||
out := "low 0\nhigh 0\nmax 4521\noom 4530\noom_kill 4530\noom_group_kill 0\n1342177280\n1341128704\n"
|
||||
k, lim, peak := parseCgroupMemory(out)
|
||||
if k != 4530 || lim != "1280M" || peak != "1279M" {
|
||||
t.Fatalf("got kills=%d limit=%q peak=%q", k, lim, peak)
|
||||
}
|
||||
if k, lim, _ := parseCgroupMemory("oom_kill 3\nmax\n"); k != 3 || lim != "max" {
|
||||
t.Fatalf("no memory.peak (older kernel), unlimited: got %d %q", k, lim)
|
||||
}
|
||||
if k, _, _ := parseCgroupMemory("OCI runtime exec failed: exec: \"cat\": executable file not found"); k != -1 {
|
||||
t.Fatalf("an image without cat must read -1 (unknown), got %d", k)
|
||||
}
|
||||
}
|
||||
|
||||
// R-636 — the scan asks the kill counter of the FLAGGED containers only (one exec each; none on a
|
||||
// healthy box). COMPANION RED-PROOF (REPORT.md): drop the exec loop — Kills stays -1 and this fails.
|
||||
func TestR636_ScanReadsTheCounterOfFlaggedContainersOnly(t *testing.T) {
|
||||
var execd []string
|
||||
m := &Manager{logger: log.New(io.Discard, "", 0), stacks: map[string]*Stack{
|
||||
"romm": {Name: "romm", Deployed: true, Containers: []ContainerInfo{{Name: "romm", State: StateRunning}}},
|
||||
"bookstack": {Name: "bookstack", Deployed: true, Containers: []ContainerInfo{{Name: "bookstack", State: StateRunning}}},
|
||||
}}
|
||||
m.execFn = func(name string, args ...string) (string, error) {
|
||||
if args[0] == "exec" {
|
||||
execd = append(execd, args[1])
|
||||
return "oom_kill 377\n1342177280\n1341128704\n", nil
|
||||
}
|
||||
return "/bookstack|false|t0\n/romm|true|2026-09-22T09:08:00Z\n", nil
|
||||
}
|
||||
ooms, err := m.ScanOOMKilled()
|
||||
if err != nil || len(ooms) != 1 {
|
||||
t.Fatalf("ooms=%+v err=%v", ooms, err)
|
||||
}
|
||||
if ooms[0].Kills != 377 || ooms[0].MemLimit != "1280M" || ooms[0].Peak != "1279M" {
|
||||
t.Errorf("the counter must be read for the flagged container: %+v", ooms[0])
|
||||
}
|
||||
if len(execd) != 1 || execd[0] != "romm" {
|
||||
t.Errorf("exec must reach the flagged container only, got %v", execd)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user