86c4b9a0d8
gates / gates (push) Successful in 27s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
30 lines
1.7 KiB
Python
30 lines
1.7 KiB
Python
#!/usr/bin/env python3
|
|
"""R-660 positive control: a throwaway app (actualbudget) stopped OUT OF BAND must raise app_start_failed
|
|
while the held nextcloud (held since 06:27:40Z) must not. Then the throwaway is removed through the product."""
|
|
import json, sys, time
|
|
sys.path.insert(0, ".")
|
|
import walk as w
|
|
w.login()
|
|
t0 = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
|
ok = w.deploy("actualbudget", "budget-c660")
|
|
w.wait_app("budget-c660", "/", tries=40, delay=3)
|
|
w.say("stopping the throwaway's container out of band (not through the product): " + w.guest("docker stop actualbudget 2>&1").strip())
|
|
found = None
|
|
for i in range(24):
|
|
time.sleep(10)
|
|
c, d = w.ctl("GET", "/api/debug/logs?level=DEBUG&lines=6000")
|
|
ents = ((d.get("data") or {}).get("entries") or []) if isinstance(d, dict) else []
|
|
evs = [e["timestamp"] + " " + e["message"] for e in ents if e.get("timestamp", "") >= t0 and
|
|
("app_start_failed" in e.get("message", "") or "currently down" in e.get("message", ""))]
|
|
if any("app_start_failed" in x for x in evs):
|
|
found = evs
|
|
break
|
|
w.say("events/heartbeats since the control started:\n " + "\n ".join(found or evs))
|
|
names = w.guest(f"docker logs --since {t0} felhom-controller 2>&1 | grep -iE 'app_start_failed|not running|DeadApp|nem fut' | tail -8")
|
|
w.say("controller log lines:\n" + names)
|
|
st = w.stack("nextcloud")
|
|
w.say(f"nextcloud meanwhile: state={st.get('state')} held={bool(st.get('hold_reason'))}")
|
|
w.remove("actualbudget")
|
|
json.dump({"events": found or evs, "log": names, "nextcloud_state": st.get("state")}, open("../partB/03-r660-control.json", "w"), indent=2)
|
|
open("../partB/03-r660-control.log", "w").write("\n".join(w.LOG) + "\n")
|