2633dc1654
gates / gates (push) Successful in 26s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
55 lines
2.4 KiB
Python
55 lines
2.4 KiB
Python
"""fg_b4_lib.py — the demo-box helpers fg_b4_member.py uses (deploy, the Család card, remove), product endpoints only."""
|
|
import json, os, secrets, subprocess, sys, time
|
|
os.environ.setdefault("GUEST", "9201"); os.environ.setdefault("BASE", "https://192.168.0.155")
|
|
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts")
|
|
import box_walk as w
|
|
w.HP = "hp"
|
|
DOM = w.DOMAIN; CTL = f"felhom.{DOM}"; DRIVE = "/mnt/felhom-drives/hdd_1"
|
|
|
|
|
|
def _card(action, name):
|
|
sess = open(f"{w.SC}/sess{os.getpid()}.txt").read().strip(); csrf = open(f"{w.SC}/csrf{os.getpid()}.txt").read().strip()
|
|
r = subprocess.run(["curl", "-sk", "-H", f"Host: {CTL}", "-H", f"Cookie: {sess}", "-H", f"X-CSRF-Token: {csrf}", "-X", "POST",
|
|
"--data", f"name={name}", f"{w.BASE}/family/members/{action}"], capture_output=True, text=True)
|
|
return json.loads(r.stdout)
|
|
|
|
|
|
def add_member(name, say):
|
|
d = _card("add", name)
|
|
say(f"Család card: add {name} -> ok={d['ok']} (password returned once, not printed)")
|
|
return d["data"]["password"]
|
|
|
|
|
|
def remove_member(name, say):
|
|
d = _card("remove", name)
|
|
say(f"Család card: remove {name} -> ok={d['ok']} members now {d['data'].get('members')}")
|
|
|
|
|
|
def deploy(app, sub, say):
|
|
code, d = w.ctl("GET", f"/api/stacks/{app}/deploy-fields")
|
|
fields = (((d.get("data") or {}).get("metadata") or {}).get("deploy_fields")) or []
|
|
values = {"DOMAIN": DOM, "SUBDOMAIN": sub}
|
|
for f in fields:
|
|
ev, ty = f.get("env_var"), f.get("type")
|
|
if ev in values or (not f.get("required") and ty != "password"):
|
|
continue
|
|
values[ev] = DRIVE if ty == "path" else ("Demo-" + secrets.token_hex(12) if ty in ("secret", "password") else (f.get("default") or app))
|
|
code, d = w.ctl("POST", f"/api/stacks/{app}/deploy", {"values": values})
|
|
say(f"deploy {app} -> {code}")
|
|
for _ in range(120):
|
|
time.sleep(5)
|
|
st = w.stack(app)
|
|
if st.get("deployed") and (st.get("app_config") or {}).get("pinned_images") and st.get("state") == "running":
|
|
break
|
|
say(f" state={st.get('state')}")
|
|
|
|
|
|
def remove(app, say):
|
|
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": True, "remove_backups": True})
|
|
say(f"remove {app} WITH data and backups -> {code} {str(d)[:200]}")
|