Files
felhom.eu/documentation/audits/new-apps-2026-10-01/tools/restorecase.py
T
2026-10-01 18:01:40 +02:00

30 lines
1.8 KiB
Python

"""restorecase.py <app> <sub> — checklist 2.5 on 9202: the per-app backup the guarded Update took (R-648: the only per-app
backup press), then REMOVE keeping the backups, the household's restore button (`POST /backup/restore`), and the seed
read back through the app's own front door. Evidence: box/<app>/restore.txt."""
import json, os, sys, time
import walk as w
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts")
import upgrade_fixtures_box as fixtures, upgrade_fixtures_box28 as _f28
FX = dict(_f28.FIXTURES28); FX.update(fixtures.FIXTURES)
app, sub = sys.argv[1:3]
EVD = f"{w.EV}/box/{app}"; os.makedirs(EVD, exist_ok=True)
log = open(f"{EVD}/restore.txt", "a", buffering=1)
def say(*a):
w.say(*a); log.write(" ".join(map(str, a)) + "\n")
w.login()
toks = json.load(open(w.SC + "/seed-tokens-box.json"))
if toks[app].get("__generated"): w.GENERATED[app] = toks[app]["__generated"]
say("restore points offered BEFORE the remove:", [(s.get("id") or s.get("snapshot_id"), s.get("time") or s.get("created")) for s in w.snapshots(app)][:5])
w.ctl("POST", f"/api/stacks/{app}/stop")
for _ in range(24):
time.sleep(5)
if w.stack(app).get("state") != "running": break
code, d = w.ctl("POST", f"/api/stacks/{app}/remove", {"remove_hdd_data": False, "remove_backups": False})
say(f"remove KEEPING backups -> {code} {str(d)[:240]}")
time.sleep(6)
say("left after remove:", w.guest(f"docker ps -a --format '{{{{.Names}}}}' | grep -E '^{app}'; docker volume ls -q | grep -i {app}").strip() or "nothing (containers and volumes gone)")
r = w.restore(app)
say("restore:", {k: r.get(k) for k in ("ok", "snapshot_id", "http", "seconds", "state_after", "hold_after", "why")})
time.sleep(10)
say(f"2.5 the seed reads back after remove + restore: {FX[app].verify(w, sub, toks[app], say)}")