Files
felhom.eu/documentation/audits/os-docker-crash-2026-10-04/partA/hub_rp2.py
T

55 lines
3.3 KiB
Python

import subprocess, shutil, sys
M = [
("unknown, never empty (parser)", "internal/sysfacts/sysfacts.go",
"out.Guest.Containerd, out.Guest.LiveRestore = orUnknown(out.Guest.Containerd), orUnknown(out.Guest.LiveRestore)",
"out.Guest.Containerd, out.Guest.LiveRestore = out.Guest.Containerd, out.Guest.LiveRestore",
"./internal/sysfacts/", "TestParse_AbsentAndPartialAreUnknown"),
("Docker never auto-approved", "internal/osupdates/service.go",
"var Layers = []string{LayerGuest, LayerHost}", "var Layers = []string{LayerGuest, LayerHost, LayerDocker}",
"./internal/osupdates/", "TestDocker_NeverAutoApproved"),
("Docker button needs 2 nights", "internal/osupdates/service.go",
"\tcase need == 0:\n\t\tneed = 2", "\tcase need == 0:\n\t\tneed = 1",
"./internal/osupdates/", "TestDocker_ApproveNeedsTwoHealthyNightsOnEveryRing0Box"),
("a Docker approval nudges no box", "internal/osupdates/service.go",
"if s.Bump != nil && layer != LayerDocker {", "if s.Bump != nil {",
"./internal/osupdates/", "TestDocker_ApproveNeedsTwoHealthyNightsOnEveryRing0Box"),
("crash event once per boot", "internal/api/crash.go",
"\t\tif known[b] {\n\t\t\tcontinue\n\t\t}", "\t\tif false {\n\t\t\tcontinue\n\t\t}",
"./internal/api/", "TestCheckCrash_EventsOncePerFact"),
("first sighting is quiet", "internal/api/crash.go",
"\t\tif first {\n\t\t\treturn\n\t\t}\n\t\td := map", "\t\td := map",
"./internal/api/", "TestCheckCrash_EventsOncePerFact"),
("page: unknown cell", "internal/web/system.go",
'if s == "" || s == sysfacts.Unknown {', 'if false {',
"./internal/web/", "TestSystemPage_FullPartialUnknown"),
("page: Docker button gate", "internal/web/templates/system.html",
'(not .Approved) (eq .Waiting "")}}', '(not .Approved)}}',
"./internal/web/", "TestSystemPage_DockerButtonOnlyWhenReady"),
("buttons need the operator login", "internal/web/server.go",
'if r.URL.Path == "/login" || isPublicBindPath(r.URL.Path) {', 'if r.URL.Path == "/login" || isPublicBindPath(r.URL.Path) || strings.HasPrefix(r.URL.Path, "/os/") {',
"./internal/web/", "TestSystemButtons_NeedTheOperatorLogin"),
("Hosts column", "internal/web/templates/hosts.html",
"<th>Proxmox / kernel</th>", "<th>Proxmox</th>",
"./internal/web/", "TestHostsPage_ProxmoxKernelColumn"),
]
ok = True
for name, f, old, new, pkg, test in M:
src = open(f).read()
assert src.count(old) == 1, (name, src.count(old))
shutil.copy(f, f + ".bak")
open(f, "w").write(src.replace(old, new))
r = subprocess.run(["go", "test", pkg, "-run", "^" + test + "$", "-v", "-count=1"], capture_output=True, text=True)
shutil.move(f + ".bak", f)
out = r.stdout + r.stderr
ran = ("=== RUN " + test) in out
failed = ("--- FAIL: " + test) in out
v = "CAUGHT" if ran and failed else "NOT CAUGHT"
ok &= v == "CAUGHT"
print(f"[{v}] {name}: {f} mutated; {test} ran={ran} failed={failed}")
for l in out.splitlines():
if "_test.go:" in l or "build failed" in l or l.startswith("#"):
print(" " + l.strip()[:200])
r = subprocess.run(["go", "test", "./internal/sysfacts/", "./internal/osupdates/", "./internal/api/", "./internal/web/", "-count=1"], capture_output=True, text=True)
print("after restore:", r.stdout.strip().replace("\n", " | "), "rc=", r.returncode)
sys.exit(0 if ok and r.returncode == 0 else 1)