118 lines
3.9 KiB
Python
118 lines
3.9 KiB
Python
"""Единая точка регистрации модулей: API, веб-UI и подписки на события.
|
|
|
|
Новый модуль: файл в `onguard24/modules/`, запись в `MODULE_MOUNTS` — см. docs/MODULES.md.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncpg
|
|
from collections.abc import Awaitable, Callable
|
|
from dataclasses import dataclass
|
|
|
|
from fastapi import APIRouter
|
|
from starlette.requests import Request
|
|
|
|
from onguard24.domain.events import EventBus
|
|
from onguard24.modules import (
|
|
contacts,
|
|
escalations,
|
|
grafana_catalog,
|
|
incidents,
|
|
schedules,
|
|
statusboard,
|
|
tasks,
|
|
)
|
|
|
|
# async (Request) -> str — фрагмент HTML для главной страницы (опционально)
|
|
HomeFragment = Callable[[Request], Awaitable[str]]
|
|
RegisterEvents = Callable[[EventBus, asyncpg.Pool | None], None]
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ModuleMount:
|
|
"""Один модуль: API под url_prefix, UI под /ui/modules/{slug}."""
|
|
|
|
router: APIRouter
|
|
url_prefix: str
|
|
register_events: RegisterEvents
|
|
slug: str
|
|
title: str
|
|
ui_router: APIRouter | None = None
|
|
render_home_fragment: HomeFragment | None = None
|
|
|
|
|
|
def _mounts() -> list[ModuleMount]:
|
|
return [
|
|
ModuleMount(
|
|
router=grafana_catalog.router,
|
|
url_prefix="/api/v1/modules/grafana-catalog",
|
|
register_events=grafana_catalog.register_events,
|
|
slug="grafana-catalog",
|
|
title="Каталог Grafana",
|
|
ui_router=grafana_catalog.ui_router,
|
|
render_home_fragment=grafana_catalog.render_home_fragment,
|
|
),
|
|
ModuleMount(
|
|
router=incidents.router,
|
|
url_prefix="/api/v1/modules/incidents",
|
|
register_events=incidents.register_events,
|
|
slug="incidents",
|
|
title="Инциденты",
|
|
ui_router=incidents.ui_router,
|
|
render_home_fragment=incidents.render_home_fragment,
|
|
),
|
|
ModuleMount(
|
|
router=tasks.router,
|
|
url_prefix="/api/v1/modules/tasks",
|
|
register_events=tasks.register_events,
|
|
slug="tasks",
|
|
title="Задачи",
|
|
ui_router=tasks.ui_router,
|
|
render_home_fragment=tasks.render_home_fragment,
|
|
),
|
|
ModuleMount(
|
|
router=escalations.router,
|
|
url_prefix="/api/v1/modules/escalations",
|
|
register_events=escalations.register_events,
|
|
slug="escalations",
|
|
title="Эскалации",
|
|
ui_router=escalations.ui_router,
|
|
render_home_fragment=escalations.render_home_fragment,
|
|
),
|
|
ModuleMount(
|
|
router=schedules.router,
|
|
url_prefix="/api/v1/modules/schedules",
|
|
register_events=schedules.register_events,
|
|
slug="schedules",
|
|
title="Календарь дежурств",
|
|
ui_router=schedules.ui_router,
|
|
render_home_fragment=schedules.render_home_fragment,
|
|
),
|
|
ModuleMount(
|
|
router=contacts.router,
|
|
url_prefix="/api/v1/modules/contacts",
|
|
register_events=contacts.register_events,
|
|
slug="contacts",
|
|
title="Контакты",
|
|
ui_router=contacts.ui_router,
|
|
render_home_fragment=contacts.render_home_fragment,
|
|
),
|
|
ModuleMount(
|
|
router=statusboard.router,
|
|
url_prefix="/api/v1/modules/statusboard",
|
|
register_events=statusboard.register_events,
|
|
slug="statusboard",
|
|
title="Светофор",
|
|
ui_router=statusboard.ui_router,
|
|
render_home_fragment=statusboard.render_home_fragment,
|
|
),
|
|
]
|
|
|
|
|
|
MODULE_MOUNTS: list[ModuleMount] = _mounts()
|
|
|
|
|
|
def register_module_events(bus: EventBus, pool: asyncpg.Pool | None = None) -> None:
|
|
for m in MODULE_MOUNTS:
|
|
m.register_events(bus, pool)
|