Files
felhom.eu/documentation/audits/night-2026-10-28/bench/tools/meili_bench.py
T

71 lines
3.8 KiB
Python

#!/usr/bin/env python3
"""meili_bench.py <template-dir-under-/opt/upg/templates> <label> [collect_s=600] — runs ON THE BENCH (/opt/upg).
R-1338: a FRESH Wanderer from <template> (like 9202's fresh install, not a swap), through upgrade-test.py's own render /
compose / settle / build_env, the box walk's own Wanderer fixture (upgrade_boxport) for the seed, and the harness's own
memory_watch (its load + its anon/peak record) — while meili_collect.sh samples wanderer-search every 10 s from the
moment of `up -d`. Evidence in /opt/upg/evidence/R1338-<label>/; the stack is removed (down -v) and its .env shredded."""
import importlib.util, json, subprocess, sys, time
from pathlib import Path
sys.path.insert(0, "/opt/upg")
s = importlib.util.spec_from_file_location("ut", "/opt/upg/upgrade-test.py")
ut = importlib.util.module_from_spec(s); s.loader.exec_module(ut)
tdir, label = sys.argv[1], sys.argv[2]
collect_s = int(sys.argv[3]) if len(sys.argv) > 3 else 600
app, project = "wanderer", "r1338" + label.replace("-", "")
ev = Path("/opt/upg/evidence/R1338-" + label); ev.mkdir(parents=True, exist_ok=True)
work = Path("/opt/upg/work/R1338-" + label)
felhom = (ut.TEMPLATES / tdir / ".felhom.yml").read_text(encoding="utf-8")
ctext = (ut.TEMPLATES / tdir / "docker-compose.yml").read_text(encoding="utf-8")
env = ut.cvp.build_env(app, felhom, ctext)
secrets_ = ut.secret_values(felhom, env)
log = []
def say(m):
line = ut.redact("[%s] %s" % (time.strftime("%H:%M:%S", time.gmtime()), m), secrets_)
print(line, flush=True); log.append(line)
rec = {"template": tdir, "label": label, "images": ut.template_images(tdir, ut.TEMPLATES)}
coll = None
try:
ut.clear_scratch_folders(ctext, env, say)
ut.render(app, {}, work, env, tdir)
say("up -d %s from templates/%s" % (rec["images"], tdir))
up = ut.compose(work, project, "up", "-d")
say("up rc=%s %s" % (up.returncode, up.stderr.strip()[-300:]))
coll = subprocess.Popen(["bash", "/opt/upg/meili_collect.sh", "wanderer-search", "10", str(collect_s)],
stdout=open(ev / "meili-collect.csv", "w"), stderr=subprocess.STDOUT)
t_up = time.time()
ok, secs, states = ut.settle(project, work)
say("settled=%s in %ss %s" % (ok, secs, json.dumps(states)))
fixture = ut.boxport.get(app, ctext, env)
seeded = fixture.seed(ut.container_ip, say)
secrets_[:] = sorted(set(secrets_) | set(ut.secret_values(felhom, env, seeded)), key=len, reverse=True)
rec["seeded"] = seeded is not None
rec["read_back_before"] = bool(seeded) and bool(fixture.verify(ut.container_ip, seeded, say))
left = int(collect_s - (time.time() - t_up)) - 20
mem, killed, marks = ut.memory_watch(app, project, work, max(left, 360), say, ev)
rec["memory_watch"], rec["killed"], rec["marks"] = mem, killed, marks
rec["read_back_after"] = bool(seeded) and bool(fixture.verify(ut.container_ip, seeded, say))
finally:
if coll:
try:
coll.wait(timeout=collect_s + 120)
except subprocess.TimeoutExpired:
coll.kill()
lg = subprocess.run(["docker", "logs", "wanderer-search"], capture_output=True, text=True)
(ev / "meili-docker-logs.txt").write_text((lg.stdout + lg.stderr)[-200000:], encoding="utf-8")
fm = subprocess.run(["free", "-m"], capture_output=True, text=True).stdout
(ev / "bench-free-m.txt").write_text(fm + "\n" + open("/proc/meminfo").read(), encoding="utf-8")
(ev / "run.log").write_text("\n".join(log), encoding="utf-8")
(ev / "record.json").write_text(json.dumps(rec, indent=1, default=str), encoding="utf-8")
ut.compose(work, project, "down", "-v", "--remove-orphans", timeout=900)
held = ut.redact_tree(ev, secrets_)
if held:
print("[redact] secret removed from %d evidence file(s)" % len(held))
ut.shred_file(work / ".env")
print(json.dumps({k: v for k, v in rec.items() if k != "memory_watch"}, default=str))