Initial import with GitLab CI/CD and registry deploy flow
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
|
||||
|
||||
preflight = importlib.import_module("scripts.postgres_dev_preflight")
|
||||
|
||||
|
||||
def test_run_preflight_rejects_non_postgres_database_url(monkeypatch):
|
||||
monkeypatch.setenv("SCHEMA_MANAGEMENT_MODE", "migrations")
|
||||
|
||||
results = preflight.run_preflight(
|
||||
database_url="sqlite:///./mvp_cc.db",
|
||||
base_url=None,
|
||||
require_rabbitmq=False,
|
||||
)
|
||||
|
||||
assert len(results) == 1
|
||||
assert results[0].name == "database_url"
|
||||
assert results[0].ok is False
|
||||
|
||||
|
||||
def test_run_preflight_requires_migrations_mode(monkeypatch):
|
||||
monkeypatch.setenv("SCHEMA_MANAGEMENT_MODE", "legacy")
|
||||
|
||||
results = preflight.run_preflight(
|
||||
database_url="postgresql://mvp:mvp@localhost:5432/mvpcc",
|
||||
base_url=None,
|
||||
require_rabbitmq=False,
|
||||
)
|
||||
|
||||
assert [item.name for item in results] == ["database_url", "schema_management_mode"]
|
||||
assert results[-1].ok is False
|
||||
|
||||
|
||||
def test_run_preflight_passes_with_http_and_rabbitmq(monkeypatch):
|
||||
monkeypatch.setenv("SCHEMA_MANAGEMENT_MODE", "migrations")
|
||||
monkeypatch.setenv("EVENT_BUS_ENABLED", "1")
|
||||
monkeypatch.setenv("EVENT_BUS_URL", "amqp://guest:guest@localhost:5672/")
|
||||
|
||||
monkeypatch.setattr(
|
||||
preflight,
|
||||
"_check_tcp_endpoint",
|
||||
lambda name, url, default_port: preflight.CheckResult(name, True, f"{default_port} ok"),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
preflight,
|
||||
"_check_database_connection",
|
||||
lambda database_url: preflight.CheckResult("database_connection", True, "SELECT 1 succeeded"),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
preflight,
|
||||
"_check_schema_migrations",
|
||||
lambda database_url: preflight.CheckResult("schema_migrations", True, "applied=18/18"),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
preflight,
|
||||
"_http_preflight_checks",
|
||||
lambda base_url: [
|
||||
preflight.CheckResult("gateway_health", True, "status=200"),
|
||||
preflight.CheckResult("auth_health", True, "status=200"),
|
||||
],
|
||||
)
|
||||
|
||||
results = preflight.run_preflight(
|
||||
database_url="postgresql://mvp:mvp@localhost:5432/mvpcc",
|
||||
base_url="http://127.0.0.1:8080",
|
||||
require_rabbitmq=False,
|
||||
)
|
||||
|
||||
assert all(item.ok for item in results)
|
||||
assert any(item.name == "rabbitmq_tcp" for item in results)
|
||||
assert any(item.name == "gateway_health" for item in results)
|
||||
|
||||
|
||||
def test_main_returns_nonzero_when_preflight_fails(monkeypatch, capsys):
|
||||
monkeypatch.setattr(
|
||||
preflight,
|
||||
"run_preflight",
|
||||
lambda **kwargs: [preflight.CheckResult("database_connection", False, "boom")],
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
preflight.argparse.ArgumentParser,
|
||||
"parse_args",
|
||||
lambda self: type(
|
||||
"Args",
|
||||
(),
|
||||
{
|
||||
"env_file": [],
|
||||
"database_url": "postgresql://mvp:mvp@localhost:5432/mvpcc",
|
||||
"base_url": "",
|
||||
"require_rabbitmq": False,
|
||||
"json": False,
|
||||
},
|
||||
)(),
|
||||
)
|
||||
|
||||
exit_code = preflight.main()
|
||||
output = capsys.readouterr().out
|
||||
|
||||
assert exit_code == 1
|
||||
assert "[FAIL] PostgreSQL dev preflight failed" in output
|
||||
|
||||
|
||||
def test_http_preflight_uses_admin_login_token_for_read_checks(monkeypatch):
|
||||
monkeypatch.setenv("ALLOW_LEGACY_HEADER_AUTH", "0")
|
||||
monkeypatch.setenv("EVENT_BUS_ENABLED", "0")
|
||||
monkeypatch.setenv("ASTERISK_BRIDGE_ENABLED", "0")
|
||||
monkeypatch.setattr(preflight, "issue_app_token", lambda **kwargs: "ops-token")
|
||||
|
||||
recorded_headers = {}
|
||||
|
||||
class FakeResponse:
|
||||
def __init__(self, status_code, payload):
|
||||
self.status_code = status_code
|
||||
self._payload = payload
|
||||
|
||||
def json(self):
|
||||
return self._payload
|
||||
|
||||
class FakeClient:
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc, tb):
|
||||
return False
|
||||
|
||||
def get(self, path, headers=None):
|
||||
if path == "/health":
|
||||
return FakeResponse(200, {"status": "ok"})
|
||||
if path == "/registry":
|
||||
return FakeResponse(200, {"services": {name: {} for name in preflight.REQUIRED_PROXY_HEALTH_SERVICES}})
|
||||
if path.startswith("/proxy/") and path.endswith("/health"):
|
||||
return FakeResponse(200, {"status": "ok"})
|
||||
if path in {
|
||||
"/proxy/routing/queues",
|
||||
"/proxy/voice/integrations/voice/events?limit=1",
|
||||
"/proxy/whatsapp/integrations/whatsapp/threads",
|
||||
}:
|
||||
recorded_headers[path] = dict(headers or {})
|
||||
return FakeResponse(200, [])
|
||||
raise AssertionError(f"Unexpected GET path: {path}")
|
||||
|
||||
def post(self, path, json=None):
|
||||
if path == "/proxy/auth/auth/login":
|
||||
return FakeResponse(200, {"access_token": "login-token"})
|
||||
raise AssertionError(f"Unexpected POST path: {path}")
|
||||
|
||||
monkeypatch.setattr(preflight.httpx, "Client", FakeClient)
|
||||
|
||||
results = preflight._http_preflight_checks("http://127.0.0.1:18080")
|
||||
|
||||
assert all(item.ok for item in results)
|
||||
assert recorded_headers["/proxy/routing/queues"] == {"Authorization": "Bearer login-token"}
|
||||
assert recorded_headers["/proxy/voice/integrations/voice/events?limit=1"] == {"Authorization": "Bearer login-token"}
|
||||
assert recorded_headers["/proxy/whatsapp/integrations/whatsapp/threads"] == {"Authorization": "Bearer login-token"}
|
||||
Reference in New Issue
Block a user