Files
GTI_GERENCIADOR_FISCAL/scripts/e2e_local_hub.py
T

103 lines
3.8 KiB
Python

"""Local E2E hub for Phase D — Windows installer against a real HTTP Hub.
Boots the control plane against a scratch SQLite DB, seeds a tenant + admin,
publishes the real built EXE as release 1.1.1, creates a PENDING enrollment,
generates an install code, then serves uvicorn on 127.0.0.1:PORT.
The operator/Setup CLI then runs against this local Hub. Usage:
python scripts/e2e_local_hub.py --port 8901 --exe dist/installer/GTIFiscalAgent-Setup-1.1.1.exe
"""
from __future__ import annotations
import argparse
import dataclasses
import os
import sys
import tempfile
import uuid
from datetime import datetime, timedelta, timezone
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT))
sys.path.insert(0, str(ROOT / "central"))
from central.app import config, enrollment # noqa: E402
from central.app.models import AgentEnrollment, Tenant # noqa: E402
from central.scripts.publish_agent_release import publish # noqa: E402
from central.tests.test_control_plane import create_admin, seed # noqa: E402
from sqlalchemy import select
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--port", type=int, default=8765)
parser.add_argument("--exe", default=str(ROOT / "dist/installer/GTIFiscalAgent-Setup-1.1.1.exe"))
args = parser.parse_args()
workdir = Path(tempfile.mkdtemp(prefix="gti_e2e_hub_"))
print(f"[e2e] workdir={workdir}")
replaced = dataclasses.replace(
config.settings,
agent_release_storage_path=str(workdir / "releases"),
base_url=f"http://127.0.0.1:{args.port}",
web_cookie_secure=False,
)
config.settings = replaced
if "app.config" in sys.modules:
sys.modules["app.config"].settings = replaced
url = f"sqlite:///{workdir / 'e2e_hub.db'}"
os.environ["DATABASE_URL"] = url
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import StaticPool
from central.app.models import Base
engine = create_engine(url, connect_args={"check_same_thread": False}, poolclass=StaticPool)
Base.metadata.create_all(engine)
factory = sessionmaker(bind=engine, expire_on_commit=False)
seed(factory)
with factory() as session:
data = Path(args.exe)
if not data.exists():
print(f"[e2e] EXE artefact not found: {data}", file=sys.stderr)
return 2
release, _created = publish(session, data, version="1.1.1")
release_id = release.id
print(f"[e2e] published release {release.version} id={release_id}")
tenant = session.scalars(select(Tenant).limit(1)).first()
enr = AgentEnrollment(enrollment_uuid=str(uuid.uuid4()), tenant_id=tenant.id,
display_name="Servidor E2E LOCAL", release_id=release_id, status="PENDING")
session.add(enr)
session.flush()
code = enrollment.generate_install_code()
enr.install_code_hash = enrollment.install_code_digest(code)
enr.install_code_expires_at = datetime.now(timezone.utc) + timedelta(seconds=86400)
enr.install_code_created_at = datetime.now(timezone.utc)
session.commit()
print(f"[e2e] enrollment_uuid={enr.enrollment_uuid}", flush=True)
print(f"[e2e] INSTALL_CODE={code}", flush=True)
(workdir / "install_code.txt").write_text(code)
(workdir / "enrollment_uuid.txt").write_text(enr.enrollment_uuid)
print(f"[e2e] workdir={workdir}", flush=True)
import uvicorn
from central.app.main import create_app
app = create_app(database_probe=lambda: True, session_factory=factory, bootstrap_token=None)
print(f"[e2e] serving hub on http://127.0.0.1:{args.port}")
uvicorn.run(app, host="127.0.0.1", port=args.port, log_level="info")
return 0
if __name__ == "__main__":
sys.exit(main())