8cdeadd6dd
PR 1 of 4 for the runtime service registry change. - Add Fernet encryption helper (services/secrets.py) with a required MANAGE_ENCRYPTION_KEY; validate it on startup. - Add closed integrations/ registry with Pydantic config + widget-config definitions for grafana, prometheus, jellyfin, nextcloud, and ssh_tasks. - Add services + service_task_runs tables and SettingsStore CRUD with cascade-delete (defensive until widgets carry service_id). - Add /api/services/types and /api/services/instances CRUD (encrypted secrets, secrets_set flags only; never plaintext). - Declare cryptography as a direct dependency. - Require MANAGE_ENCRYPTION_KEY in compose + .env.example + README. - Add 25 backend tests (registry, encryption, CRUD, cascade, task-run history). Verification: ruff clean; pytest 225 passed; frontend lint/build green.
47 lines
1.1 KiB
Python
47 lines
1.1 KiB
Python
"""Grafana service definition."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from media_library_viewer_api.integrations.base import (
|
|
SecretField,
|
|
ServiceConfigBase,
|
|
ServiceDefinition,
|
|
WidgetConfigBase,
|
|
widget_kind,
|
|
)
|
|
|
|
|
|
class GrafanaConfig(ServiceConfigBase):
|
|
"""Non-secret Grafana connection config."""
|
|
|
|
base_url: str
|
|
timeout_seconds: int = 5
|
|
|
|
|
|
class GrafanaLinkWidgetConfig(WidgetConfigBase):
|
|
"""Deep-link to a Grafana dashboard or panel."""
|
|
|
|
dashboard_uid: str
|
|
panel_id: int | None = None
|
|
|
|
|
|
DEFINITION = ServiceDefinition(
|
|
service_type="grafana",
|
|
name="Grafana",
|
|
description="Dashboards, metrics, and logs.",
|
|
config_model=GrafanaConfig,
|
|
secret_fields=[
|
|
SecretField(key="api_key", label="API key", helper="Service account token (optional)"),
|
|
],
|
|
widget_kinds=[
|
|
widget_kind(
|
|
kind="link",
|
|
name="Dashboard link",
|
|
description="Deep-link to a Grafana dashboard or panel.",
|
|
model_cls=GrafanaLinkWidgetConfig,
|
|
default_config={"dashboard_uid": ""},
|
|
refresh_interval_ms=0,
|
|
),
|
|
],
|
|
)
|