73 lines
3.0 KiB
Python
73 lines
3.0 KiB
Python
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
from datetime import UTC, datetime, timedelta
|
|
|
|
from fastapi.testclient import TestClient
|
|
from pydantic import SecretStr
|
|
|
|
from modelforge_api.domain.release import PRODUCT_VERSION, TARGET_SCHEMA_REVISION
|
|
from modelforge_api.main import app
|
|
from modelforge_api.settings import Settings, get_settings
|
|
|
|
ADMIN_TOKEN = "update-preflight-admin-test-token-long-enough" # noqa: S105 - synthetic test credential
|
|
VIEWER_TOKEN = "mfop_" + "v" * 43
|
|
OPERATOR_TOKEN = "mfop_" + "o" * 43
|
|
|
|
|
|
def test_update_preflight_is_read_only_admin_only_and_marks_missing_approval_unknown() -> None:
|
|
identities = [
|
|
{
|
|
"credential_id": role,
|
|
"subject": role,
|
|
"role": role,
|
|
"token_sha256": hashlib.sha256(token.encode()).hexdigest(),
|
|
"expires_at": (datetime.now(UTC) + timedelta(days=1)).isoformat(),
|
|
}
|
|
for role, token in (("viewer", VIEWER_TOKEN), ("operator", OPERATOR_TOKEN))
|
|
]
|
|
settings = Settings(
|
|
_env_file=None,
|
|
operator_api_key=SecretStr(ADMIN_TOKEN),
|
|
operator_identities=SecretStr(json.dumps(identities)),
|
|
)
|
|
app.dependency_overrides[get_settings] = lambda: settings
|
|
client = TestClient(app)
|
|
try:
|
|
path = "/api/v1/admin/updates/preflight"
|
|
assert client.get(path).status_code == 401
|
|
for token in (VIEWER_TOKEN, OPERATOR_TOKEN):
|
|
denied = client.get(path, headers={"X-ModelForge-Admin-Token": token})
|
|
assert denied.status_code == 403
|
|
|
|
response = client.get(path, headers={"X-ModelForge-Admin-Token": ADMIN_TOKEN})
|
|
assert response.status_code == 200
|
|
payload = response.json()
|
|
|
|
assert payload["read_only"] is True
|
|
assert payload["status"] == "INCOMPLETE"
|
|
assert payload["current"]["version"] == PRODUCT_VERSION
|
|
assert payload["current"]["schema_revision"] == TARGET_SCHEMA_REVISION
|
|
assert payload["approved"]["version"] is None
|
|
assert payload["approved"]["status"] == "UNKNOWN"
|
|
assert payload["approved"]["notes"]["status"] == "UNKNOWN"
|
|
assert payload["approved"]["notes"]["value"] is None
|
|
assert payload["impact"]["schema"]["status"] == "UNKNOWN"
|
|
assert payload["impact"]["schema"]["value"] is None
|
|
assert payload["impact"]["breaking"]["status"] == "UNKNOWN"
|
|
assert payload["impact"]["breaking"]["value"] is None
|
|
assert payload["backup"]["required"]["status"] == "UNKNOWN"
|
|
assert payload["backup"]["required"]["value"] is None
|
|
assert payload["provenance"]["current"]["status"] == "UNKNOWN"
|
|
assert payload["provenance"]["approved"]["status"] == "UNKNOWN"
|
|
assert payload["execution"] == {
|
|
"available": False,
|
|
"control": "HUMAN_CONTROLLED",
|
|
}
|
|
|
|
assert client.post(path, headers={"X-ModelForge-Admin-Token": ADMIN_TOKEN}).status_code == 405
|
|
finally:
|
|
client.close()
|
|
app.dependency_overrides.clear()
|