"""RunPod client modes, email parsing, ticket composition and Jira scoping.""" import os import sys import tempfile sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) os.environ.setdefault("CX_DATABASE_URL", f"sqlite:///{tempfile.mkdtemp()}/rp.db") FAILS = [] def expect(label, cond, got=""): print((" PASS " if cond else " FAIL ") + label + ("" if cond else f" <- {got}")) if not cond: FAILS.append(label) print("\nCLIENT MODES") from app.runpod.client import RunPodClient, RunPodError expect("api key wins over console credentials", RunPodClient(api_key="k", email="e", password="p").mode == "api_key") expect("falls back to console login", RunPodClient(email="e", password="p").mode == "console_login") expect("reports unconfigured", RunPodClient().mode == "unconfigured") try: RunPodClient()._console_jwt() expect("unconfigured client refuses to call out", False) except RunPodError as exc: expect("unconfigured client refuses to call out", "not configured" in str(exc).lower()) code = RunPodClient(totp_secret="JBSWY3DPEHPK3PXP")._totp_code() expect("TOTP generator returns a 6-digit code", code.isdigit() and len(code) == 6, code) print("\nEMAIL PARSING") from app.runpod.email_parse import classify, parse SAMPLE = """Your machine ca1-esc8-106 (x0gn8v2rthk4) hit a critical error and was automatically unlisted. Error detected: dcgm-xid-check: potential XID issue detected gpu health check failed: metric gpu_cuda_ok: expected 1, got 0 error indicator present: gpu_failed{reason=memory_remap,uuid=GPU-d29f} Impact: 8 GPU(s) currently rented on this machine. Common causes and where to look: """ r = parse(SAMPLE, subject="ca1-esc8-106 Unlisted - CRITICAL ERROR") expect("host extracted", r["host"] == "ca1-esc8-106", r["host"]) expect("machine id extracted", r["machine_id"] == "x0gn8v2rthk4", r["machine_id"]) expect("rented GPUs extracted", r["gpus_rented"] == 8, r["gpus_rented"]) expect("marked critical", r["is_critical"]) expect("error block captured, boilerplate excluded", "dcgm-xid-check" in r["error_text"] and "Common causes" not in r["error_text"]) expect("memory remap recognised as hardware", r["signature"] == "GPU memory remapping failure", r["signature"]) expect("quoted-printable is decoded", "=3D" not in parse("Error detected:\ngpu_failed{a=3Db}\nImpact: 1 GPU(s)")["error_text"]) expect("subject-only still yields a host", parse("no machine line here", subject="no1-os1-5090-050 Unlisted")["host"] == "no1-os1-5090-050") for text, want in [("nvidia-smi: too many failures", "nvidia-smi failing repeatedly"), ("pod sync failed 16 times", "Pod sync failing"), ("container stuck: docker service unresponsive", "Docker daemon unresponsive"), ("total gibberish", "Unrecognised error")]: expect(f"classify: {text[:34]}", classify(text)["signature"] == want, classify(text)["signature"]) print("\nTICKET COMPOSITION") from app.models import RunpodHost from app.runpod.delivery import unlisting_ticket host = RunpodHost(machine_id="x0gn8v2rthk4", name="ca1-esc8-106", gpu_reserved=8, gpu_total=8, unlist_count=7, data_center="CA1", last_error="dcgm-xid-check: potential XID issue detected\nreason=memory_remap") t = unlisting_ticket(host) expect("subject names the host and the fault", "ca1-esc8-106" in t["subject"] and "memory" in t["subject"].lower(), t["subject"]) expect("body carries the error text", "dcgm-xid-check" in t["body"]) expect("body states the rented impact", "8 GPU(s) currently rented" in t["body"]) expect("body carries the repeat count", "7 time(s)" in t["body"]) drained = RunpodHost(machine_id="m", name="h", gpu_reserved=0, gpu_total=8, unlist_count=1) expect("a drained machine says so", "drained" in unlisting_ticket(drained)["body"]) print("\nJIRA SCOPING") from app.config import Settings os.environ.update({"CX_JIRA_BASE": "https://oie.atlassian.net", "CX_JIRA_EMAIL": "oie@x", "CX_JIRA_TOKEN": "t1", "CX_JIRA_PROJECT": "OIE"}) s = Settings() expect("default scope uses the OIE instance", s.jira_for("default")["base"] == "https://oie.atlassian.net") expect("runpod inherits when unset", s.jira_for("runpod")["base"] == "https://oie.atlassian.net") expect("runpod keeps its own project", s.jira_for("runpod")["project"] == "RMA") os.environ.update({"CX_RUNPOD_JIRA_BASE": "https://rma.atlassian.net", "CX_RUNPOD_JIRA_EMAIL": "rma@x", "CX_RUNPOD_JIRA_TOKEN": "t2"}) s = Settings() expect("runpod uses its own instance when given one", s.jira_for("runpod")["base"] == "https://rma.atlassian.net") expect("the two scopes stay separate", s.jira_for("runpod")["token"] != s.jira_for("default")["token"]) expect("default is untouched by the runpod values", s.jira_for("default")["base"] == "https://oie.atlassian.net") print("\n" + ("ALL CHECKS PASSED" if not FAILS else f"{len(FAILS)} FAILED: {FAILS}")) sys.exit(1 if FAILS else 0)