New /api/v1/infra/stack/status probes all stack apps/APIs/SW; Infra UI groups proc-cards by VM; wire vm123 router; menu INFRA COD and Serviços IaaS · Infra as Code labels. Co-authored-by: Cursor <cursoragent@cursor.com>
210 lines
7.1 KiB
Python
210 lines
7.1 KiB
Python
"""Teste de confirmação — OpenPanel API multidomínio (Spec 028)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import random
|
|
import re
|
|
import string
|
|
import time
|
|
from typing import Any
|
|
|
|
from app.vm123 import openpanel_client
|
|
|
|
TEST_PASSWORD = "LbOpenTest805353"
|
|
DEFAULT_PLAN = "ligbox-site-cms"
|
|
USER_RE = re.compile(r"^[a-z][a-z0-9]{2,15}$")
|
|
|
|
|
|
def _step(name: str, ok: bool, detail: str = "", extra: dict | None = None) -> dict[str, Any]:
|
|
return {"name": name, "ok": ok, "detail": detail, **(extra or {})}
|
|
|
|
|
|
def _default_accounts() -> list[tuple[str, str]]:
|
|
suffix = "".join(random.choices(string.digits, k=5))
|
|
user1 = f"apitest{suffix}"
|
|
user2 = f"apitestb{suffix}"
|
|
return [
|
|
(user1, f"apitest{suffix}.ligbox.com.br"),
|
|
(user2, f"apitestb{suffix}.ligbox.com.br"),
|
|
]
|
|
|
|
|
|
def _normalize_accounts(
|
|
accounts: list[dict[str, str]] | None,
|
|
*,
|
|
auto_names: bool = True,
|
|
) -> list[tuple[str, str]]:
|
|
out: list[tuple[str, str]] = []
|
|
if accounts:
|
|
for row in accounts:
|
|
username = (row.get("username") or "").strip().lower()
|
|
domain = (row.get("domain") or "").strip().lower()
|
|
if not username and not domain:
|
|
continue
|
|
if not username and domain:
|
|
username = re.sub(r"[^a-z0-9]", "", domain.split(".")[0])[:15]
|
|
if not domain and username:
|
|
domain = f"{username}.ligbox.com.br" if "." not in username else username
|
|
if not USER_RE.fullmatch(username):
|
|
raise ValueError(f"username inválido: {username!r} (a-z, 3-16 chars)")
|
|
out.append((username, domain))
|
|
if not out and auto_names:
|
|
return _default_accounts()
|
|
if not out:
|
|
raise ValueError("informe pelo menos uma conta/domínio ou active auto_names")
|
|
return out[:5]
|
|
|
|
|
|
def run_confirmation_test(
|
|
*,
|
|
triggered_by: str = "api",
|
|
accounts: list[dict[str, str]] | None = None,
|
|
password: str = TEST_PASSWORD,
|
|
cleanup: bool = True,
|
|
auto_names: bool = True,
|
|
check_reference: bool = True,
|
|
) -> dict[str, Any]:
|
|
"""Suite E2E: health → list → N contas/domínios → cleanup opcional."""
|
|
started = time.time()
|
|
steps: list[dict[str, Any]] = []
|
|
try:
|
|
pairs = _normalize_accounts(accounts, auto_names=auto_names)
|
|
except ValueError as exc:
|
|
return {
|
|
"ok": False,
|
|
"suite": "openpanel-multidomain-api-confirm",
|
|
"message": str(exc),
|
|
"steps": [_step("validate_input", False, str(exc))],
|
|
"steps_passed": 0,
|
|
"steps_total": 1,
|
|
"triggered_by": triggered_by,
|
|
}
|
|
|
|
health = openpanel_client.health()
|
|
steps.append(
|
|
_step(
|
|
"bridge_health",
|
|
health.get("ok") is True,
|
|
f"bridge={health.get('bridge')} url={health.get('bridge_url')}",
|
|
{"response": health},
|
|
)
|
|
)
|
|
if not health.get("ok"):
|
|
return _result(False, steps, pairs[0][0], triggered_by, started, pairs=pairs)
|
|
|
|
try:
|
|
listed = openpanel_client.list_users()
|
|
users = (listed.get("users") or {}).get("data") or []
|
|
steps.append(_step("list_users", True, f"{len(users)} contas", {"count": len(users)}))
|
|
except openpanel_client.OpenPanelBridgeError as exc:
|
|
steps.append(_step("list_users", False, str(exc)))
|
|
return _result(False, steps, pairs[0][0], triggered_by, started, pairs=pairs)
|
|
|
|
if check_reference:
|
|
try:
|
|
ref = openpanel_client.get_user("diarissima")
|
|
steps.append(
|
|
_step(
|
|
"get_reference_user",
|
|
ref.get("success") is True,
|
|
(ref.get("domains") or "")[:80],
|
|
)
|
|
)
|
|
except openpanel_client.OpenPanelBridgeError as exc:
|
|
steps.append(_step("get_reference_user", False, str(exc)))
|
|
|
|
created: list[str] = []
|
|
for idx, (username, domain) in enumerate(pairs, start=1):
|
|
label = f"provision_{username}"
|
|
try:
|
|
prov = openpanel_client.provision_user(
|
|
username=username,
|
|
password=password,
|
|
email=f"hosting@{domain}",
|
|
domain=domain,
|
|
plan_name=DEFAULT_PLAN,
|
|
)
|
|
ok = prov.get("success") is True
|
|
if ok:
|
|
created.append(username)
|
|
steps.append(
|
|
_step(
|
|
label,
|
|
ok,
|
|
prov.get("response", {}).get("message", "")[:120],
|
|
{"username": username, "domain": domain, "index": idx},
|
|
)
|
|
)
|
|
except openpanel_client.OpenPanelBridgeError as exc:
|
|
steps.append(_step(label, False, str(exc), {"username": username, "domain": domain}))
|
|
|
|
try:
|
|
listed2 = openpanel_client.list_users()
|
|
names = {u.get("username") for u in (listed2.get("users") or {}).get("data") or []}
|
|
expected = {u for u, _ in pairs}
|
|
found = expected & names
|
|
steps.append(
|
|
_step(
|
|
"verify_multidomain_platform",
|
|
found == expected,
|
|
f"encontrados {len(found)}/{len(expected)}: {', '.join(sorted(found))}",
|
|
{"users_found": sorted(found), "users_expected": sorted(expected)},
|
|
)
|
|
)
|
|
except openpanel_client.OpenPanelBridgeError as exc:
|
|
steps.append(_step("verify_multidomain_platform", False, str(exc)))
|
|
|
|
deleted = 0
|
|
if cleanup:
|
|
for username in created:
|
|
try:
|
|
openpanel_client.delete_user(username)
|
|
deleted += 1
|
|
steps.append(_step(f"cleanup_{username}", True, "removido"))
|
|
except openpanel_client.OpenPanelBridgeError as exc:
|
|
steps.append(_step(f"cleanup_{username}", False, str(exc)))
|
|
else:
|
|
steps.append(_step("cleanup_skipped", True, f"mantidas: {', '.join(created)}"))
|
|
|
|
all_ok = all(s["ok"] for s in steps)
|
|
cleanup_ok = (not cleanup) or (deleted == len(created))
|
|
return _result(
|
|
all_ok and cleanup_ok,
|
|
steps,
|
|
pairs[0][0],
|
|
triggered_by,
|
|
started,
|
|
pairs=pairs,
|
|
cleanup=cleanup_ok,
|
|
)
|
|
|
|
|
|
def _result(
|
|
ok: bool,
|
|
steps: list[dict[str, Any]],
|
|
username: str,
|
|
triggered_by: str,
|
|
started: float,
|
|
*,
|
|
pairs: list[tuple[str, str]] | None = None,
|
|
cleanup: bool = True,
|
|
) -> dict[str, Any]:
|
|
passed = sum(1 for s in steps if s["ok"])
|
|
return {
|
|
"ok": ok,
|
|
"suite": "openpanel-multidomain-api-confirm",
|
|
"spec": "028-openpanel-ce-ligbox-reengineering",
|
|
"triggered_by": triggered_by,
|
|
"test_user": username,
|
|
"accounts_tested": [{"username": u, "domain": d} for u, d in (pairs or [])],
|
|
"cleanup_done": cleanup,
|
|
"steps_passed": passed,
|
|
"steps_total": len(steps),
|
|
"steps": steps,
|
|
"duration_sec": round(time.time() - started, 2),
|
|
"message": (
|
|
"OpenPanel via API multidomínio Ligbox Re-engenharia — CONFIRMADO"
|
|
if ok
|
|
else "Falha em um ou mais passos — ver steps"
|
|
),
|
|
}
|