"""POST /config/notify — the hive's push, on the instance side."""
import asyncio
import pytest
from fastapi import FastAPI
from httpx import ASGITransport, AsyncClient
from navi.api.routes import config_overlay
from navi.overlay.state import get_state, reset_state
from navi.settings_model import Settings
@pytest.fixture(autouse=True)
def _state():
reset_state()
state = get_state()
state.enabled = True
state.base_settings = Settings(_env_file=None)
yield
reset_state()
@pytest.fixture()
def app(monkeypatch):
monkeypatch.setattr("navi.swarm.verify_swarm_key", lambda key: key == "swarm-secret")
app = FastAPI()
app.include_router(config_overlay.router)
return app
async def _post(app, **kwargs):
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://navi") as client:
return await client.post("/config/notify", **kwargs)
async def test_notify_requires_the_swarm_key(app):
assert (await _post(app)).status_code == 401
assert (await _post(app, headers={"X-Swarm-Key": "nope"})).status_code == 403
async def test_notify_schedules_a_refresh(app, monkeypatch):
calls = []
def fake_refresh(trigger):
calls.append(trigger)
return {"status": "applied"}
monkeypatch.setattr(config_overlay, "refresh", fake_refresh)
resp = await _post(
app,
json={"version": 3, "hash": "sha256:x"},
headers={"X-Swarm-Key": "swarm-secret"},
)
assert resp.status_code == 202
assert resp.json()["status"] == "scheduled"
for _ in range(100):
if calls:
break
await asyncio.sleep(0.01)
assert calls == ["notify"]
async def test_notify_on_a_disabled_instance_does_nothing(app):
get_state().enabled = False
resp = await _post(
app, json={"version": 3}, headers={"X-Swarm-Key": "swarm-secret"}
)
assert resp.status_code == 202
assert "disabled" in resp.json()["detail"]
async def test_status_requires_the_key_and_returns_the_state(app):
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://navi") as client:
assert (await client.get("/config/status")).status_code == 401
body = (
await client.get(
"/config/status", headers={"X-Swarm-Key": "swarm-secret"}
)
).json()
assert "status" in body
assert "hash" in body