feat(api): мок-контрол-плейн по контракту + единый формат ошибок (Refs #19)
- app.py: create_app() собирает мок-сервер и отдаёт /openapi.json из спецификации. - errors.py: ApiError + хендлеры, приводящие 4xx/5xx/422 к схеме Error. - deps.py: Bearer-токен и cookie-сессия (ADR-008). - schemas.py: pydantic-модели запросов, зеркалящие схемы контракта (extra=forbid, writeOnly для секретов).
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
"""Сборка FastAPI-приложения мок-контрол-плейна (контракт ``docs/openapi.yaml``)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
from awg_api import __version__
|
||||
from awg_api.contract import load_spec
|
||||
from awg_api.errors import install_error_handlers
|
||||
from awg_api.routers import auth, config, devices, ops, routing, status
|
||||
from awg_api.state import DEV_TOKEN, MockState
|
||||
from awg_api.ws import metrics
|
||||
|
||||
TOKEN_ENV_VAR = "AWG_API_TOKEN" # noqa: S105 — имя переменной окружения, не секрет
|
||||
|
||||
|
||||
class ContractFastAPI(FastAPI):
|
||||
"""FastAPI, отдающий ``/openapi.json`` из контрактной спецификации, не из кода."""
|
||||
|
||||
def openapi(self) -> dict[str, Any]:
|
||||
return load_spec()
|
||||
|
||||
|
||||
def create_app(state: MockState | None = None, token: str | None = None) -> FastAPI:
|
||||
"""Создаёт приложение мок-сервера; ``state``/``token`` подменяются в тестах."""
|
||||
resolved_token = token or os.environ.get(TOKEN_ENV_VAR) or DEV_TOKEN
|
||||
mock_state = state if state is not None else MockState()
|
||||
mock_state.token = resolved_token
|
||||
app = ContractFastAPI(
|
||||
title="awg-dash API",
|
||||
version=__version__,
|
||||
description="Мок-контрол-плейн по контракту docs/openapi.yaml (задача #19)",
|
||||
)
|
||||
app.state.mock_state = mock_state
|
||||
app.state.api_token = resolved_token
|
||||
install_error_handlers(app)
|
||||
app.include_router(ops.router)
|
||||
app.include_router(auth.router)
|
||||
app.include_router(status.router)
|
||||
app.include_router(config.router)
|
||||
app.include_router(routing.router)
|
||||
app.include_router(devices.router)
|
||||
app.include_router(metrics.router)
|
||||
return app
|
||||
Reference in New Issue
Block a user