firegex/tests/mcp_restart_probe.py
av0idd4rk 863422f202 Add authenticated MCP server and agent guide
Expose 28 tools with shared REST operations, role-scoped bearer authentication, revisions, durable retries, snapshots, jobs and timed rollback. Add Docker verification harnesses and setup/workflow documentation in docs/mcp.md and inst.md. Validated with 330 unit tests, two consecutive 25-case MCP/import runs, and restart recovery; the full upstream regression run remains incomplete.
2026-10-23 09:46:44 +03:00

61 lines
2.5 KiB
Python

"""Two-phase probe driven by the Docker runner around a real backend restart."""
import asyncio
import json
import os
from pathlib import Path
import sys
import time
import uuid
sys.path.insert(0, "/test/backend")
sys.path.insert(0, "/test/tests")
from integration.test_mcp import connect, call, options, read_service
from mcp_api.store import Store
STATE = Path("/tmp/firegex-mcp-restart.json")
URL = "http://127.0.0.1:4444/"
async def prepare():
store = Store(os.environ["FIREGEX_MCP_TEST_DB"])
store.open()
credential = store.token_create("restart-probe", "admin", 1)
store.close()
async with connect(URL, credential) as client:
name = "restart-" + uuid.uuid4().hex[:12]
spec = {"name": name, "addresses": [{"ip_int": "127.0.0.1", "port": 23456}]}
opts = options()
service = await call(client, "fgx_service_apply", spec=spec, options=opts)
before = (await call(client, "fgx_firewall_get"))["data"]
change = await call(client, "fgx_firewall_apply",
patch={"settings": {"allow_icmp": not before["settings"]["allow_icmp"]}},
options=options(before["revision"], confirm_within_seconds=5))
STATE.write_text(json.dumps({"credential": credential, "service": service, "spec": spec,
"options": opts, "revision": before["revision"], "change_id": change["change"]["id"]}))
STATE.chmod(0o600)
print("Prepared an unconfirmed change and a retry receipt", flush=True)
async def verify():
saved = json.loads(STATE.read_text())
async with connect(URL, saved["credential"]) as client:
change = await call(client, "fgx_change_get", change_id=saved["change_id"])
assert change["data"]["status"] == "rolled_back", change
current = (await call(client, "fgx_firewall_get"))["data"]
assert current["revision"] == saved["revision"]
replay = await call(client, "fgx_service_apply", spec=saved["spec"], options=saved["options"])
assert replay["change"]["id"] == saved["service"]["change"]["id"]
sid = replay["data"]["service_id"]
current = await read_service(client, sid)
await call(client, "fgx_service_delete", service=sid, options=options(current["revision"]))
store = Store(os.environ["FIREGEX_MCP_TEST_DB"])
store.open()
store.token_revoke(saved["credential"]["id"])
store.close()
STATE.unlink()
print("PASS: expired lease recovered and identical request replayed after restart", flush=True)
if __name__ == "__main__":
asyncio.run(prepare() if sys.argv[1] == "prepare" else verify())