#!/usr/bin/env python3 """A3 live, part 2: Start on the box-stopped gokapi lifts the hold and gives ONE more try; the loop comes back, the box stops it again (trip 2 within 24 h) and the page says support is informed. hu + en. No app_start_failed.""" import html as H, json, re, sys, time sys.path.insert(0, ".") import walk as w APP = "gokapi" out = {"controller": w.guest("cat /etc/felhom-controller-image").strip()} w.login() t0 = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) st = w.stack(APP) out["before"] = {k: st.get(k) for k in ("state", "hold_kind", "hold_reason")} w.say("before " + json.dumps(out["before"], ensure_ascii=False)) code, d = w.ctl("POST", f"/api/stacks/{APP}/start") w.say(f"Start -> {code} {json.dumps(d, ensure_ascii=False)[:200]}") time.sleep(5) st = w.stack(APP) out["after_start"] = {k: st.get(k) for k in ("state", "hold_kind", "hold_reason")} w.say("after start " + json.dumps(out["after_start"], ensure_ascii=False)) tp, last = time.time(), None while time.time() - tp < 1800: st = w.stack(APP) cur = (st.get("state"), st.get("hold_kind")) if cur != last: rc = w.guest("docker inspect -f '{{.Name}} {{.RestartCount}}' $(docker ps -aq --filter label=com.docker.compose.project=gokapi)").strip() w.say(f" +{time.time()-tp:6.0f}s state={cur[0]} hold={cur[1]} restarts: {rc}") last = cur if cur[1] == "unhealthy_stop": break time.sleep(15) out["tripped_after_s"] = round(time.time() - tp) for lang in ("hu", "en"): page = H.unescape(w.page(f"/apps/{APP}?lang={lang}")) m = re.search(r'data-unhealthy-stop[^>]*>(.*?)', page, re.S) txt = re.sub(r"<[^>]+>", " ", m.group(1)).strip() if m else None out[f"page_{lang}"] = re.sub(r"\s+", " ", txt) if txt else None w.say(f"[{lang}] {out[f'page_{lang}']!r}") out["log"] = w.guest(f"docker logs --since {t0} felhom-controller 2>&1 | grep -E 'deadapp|STOPPED by the box|hold (SET|CLEARED|lifted)|unhealthy|app_start_failed|app_stopped' | tail -15") w.say("log:\n" + out["log"]) out["start_failed_lines"] = w.guest(f"docker logs --since {t0} felhom-controller 2>&1 | grep -c app_start_failed || true").strip() w.say("app_start_failed lines: " + out["start_failed_lines"]) json.dump(out, open("../A3/30-start-then-trip2.json", "w"), indent=2, ensure_ascii=False, default=str) open("../A3/30-start-then-trip2.log", "w").write("\n".join(w.LOG) + "\n")