83d5a23406
- 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 для секретов).
48 lines
1.8 KiB
Python
48 lines
1.8 KiB
Python
"""Сборка 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
|