58 lines
3.1 KiB
Python
58 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""ADVERSARY WC3 restore round-trip + recover custom-html canonical to known-good idle.
|
|
State on entry (left by adv_check_wc2 crash): app UP (warm), known-good marker file deleted, my
|
|
marker adv_own.txt present. This driver: restore the known-good snapshot -> known-good marker BACK,
|
|
my marker GONE (restore = exact known-good) -> leave idle. Also diagnoses HTTPS serving."""
|
|
import os, subprocess, sys
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
from harness import canonical, lifecycle, warmsnap
|
|
|
|
R = "custom-html"; D = "warm-custom-html.ci.commoninternet.net"; HTML = "/usr/share/nginx/html"
|
|
KG_FILE = "wc2-marker.txt"; KG_STR = "WC2-DATA-MARKER-7f3a9c"; A_FILE = "adv_own.txt"
|
|
fails = []
|
|
def sh(*c): return lifecycle.exec_in_app(D, list(c), service="app")
|
|
def ls(): return sh("ls", HTML).split()
|
|
def has_service():
|
|
out = subprocess.run(["docker","service","ls","--format","{{.Name}}"],capture_output=True,text=True).stdout
|
|
return any("custom-html" in n for n in out.split())
|
|
def has_volume():
|
|
out = subprocess.run(["docker","volume","ls","--format","{{.Name}}"],capture_output=True,text=True).stdout
|
|
return any("warm-custom-html" in n and n.endswith("_content") for n in out.split())
|
|
def code(path):
|
|
return subprocess.run(["curl","-sk","--resolve",f"{D}:443:127.0.0.1","-o","/dev/null","-w","%{http_code}",
|
|
"--max-time","10",f"https://{D}{path}"],capture_output=True,text=True).stdout.strip()
|
|
|
|
# ensure app is up to inspect entry state (it should be, from the crash)
|
|
if not has_service():
|
|
canonical.deploy_canonical(R)
|
|
entry = ls()
|
|
print(f"ENTRY html={entry} (expect adv_own.txt present, {KG_FILE} deleted)")
|
|
# serving diagnosis
|
|
print(f"SERVING: /={code('/')} /index.html={code('/index.html')} /{KG_FILE}={code('/'+KG_FILE)} /{A_FILE}={code('/'+A_FILE)}")
|
|
|
|
# WC3 restore round-trip
|
|
canonical.undeploy_keep_volume(R)
|
|
warmsnap.restore(R, D)
|
|
canonical.deploy_canonical(R)
|
|
after = ls()
|
|
kg_back = KG_FILE in after
|
|
a_gone = A_FILE not in after
|
|
kg_content = sh("cat", f"{HTML}/{KG_FILE}").strip() if kg_back else ""
|
|
print(f"AFTER RESTORE html={after} kg_back={kg_back} kg_content={kg_content!r} my_marker_gone={a_gone}")
|
|
if not kg_back: fails.append("WC3: known-good marker NOT restored")
|
|
if KG_STR not in kg_content: fails.append(f"WC3: restored marker content wrong: {kg_content!r}")
|
|
if not a_gone: fails.append("WC3: my marker still present — restore not exact known-good")
|
|
|
|
# leave idle as found
|
|
canonical.undeploy_keep_volume(R)
|
|
fin = canonical.read_registry(R)
|
|
print(f"END registry_status={fin.get('status')} version={fin.get('version')} service={has_service()} "
|
|
f"volume={has_volume()} snapshot={warmsnap.has_snapshot(R)}")
|
|
if has_service(): fails.append("END: service still running (should be idle)")
|
|
if not has_volume(): fails.append("END: volume not retained")
|
|
if fin.get("status") != "idle": fails.append(f"END: status={fin.get('status')} (want idle)")
|
|
|
|
print("\nRESULT:", "FAIL: "+"; ".join(fails) if fails else
|
|
"PASS — WC3 restore round-trips the EXACT known-good (marker back, content correct, my mutation gone); canonical left idle+retained")
|
|
sys.exit(1 if fails else 0)
|