feat(per-instance-hook-scoping): scope observability + backup hooks by instance

This commit is contained in:
Developer
2026-07-09 23:54:31 +00:00
parent ad61d92b32
commit 3bc7ce5269
12 changed files with 268 additions and 73 deletions
+83
View File
@@ -1,6 +1,7 @@
import tempfile
from pathlib import Path
import pytest
from fastapi.testclient import TestClient
from media_library_viewer_api.main import app
@@ -33,6 +34,88 @@ def test_dashboard_backups():
auth_module._API_KEY = None
# ---------------------------------------------------------------------------
# Per-instance service scoping (PI-110, PI-111, PI-119)
# ---------------------------------------------------------------------------
@pytest.fixture
def store(tmp_path):
"""Fresh SettingsStore with schema initialized."""
db_path = tmp_path / "test_settings.sqlite"
s = SettingsStore(db_path)
s.init_schema()
return s
class TestBackupServiceScoping:
"""Verify service_id filtering on list_backup_jobs/runs/alerts."""
def test_list_backup_jobs_filtered_by_service(self, store: SettingsStore):
store.upsert_backup_job({"name": "job-a", "service_id": "svc-a"})
store.upsert_backup_job({"name": "job-b", "service_id": "svc-b"})
assert len(store.list_backup_jobs(service_id="svc-a")) == 1
assert len(store.list_backup_jobs(service_id="svc-b")) == 1
def test_list_backup_jobs_unfiltered_returns_all(self, store: SettingsStore):
store.upsert_backup_job({"name": "job-a", "service_id": "svc-a"})
store.upsert_backup_job({"name": "job-b", "service_id": "svc-b"})
assert len(store.list_backup_jobs()) == 2
assert len(store.list_backup_jobs(service_id="")) == 2
def test_list_backup_runs_filtered_by_service(self, store: SettingsStore):
job_a = store.upsert_backup_job({"name": "job-a", "service_id": "svc-a"})
job_b = store.upsert_backup_job({"name": "job-b", "service_id": "svc-b"})
store.create_backup_run({"job_id": job_a["id"], "started_at": 1700000000, "status": "success"})
store.create_backup_run({"job_id": job_b["id"], "started_at": 1700000000, "status": "success"})
assert len(store.list_backup_runs(service_id="svc-a")) == 1
assert len(store.list_backup_runs(service_id="svc-b")) == 1
def test_list_backup_alerts_filtered_by_service(self, store: SettingsStore):
job_a = store.upsert_backup_job({"name": "job-a", "service_id": "svc-a"})
job_b = store.upsert_backup_job({"name": "job-b", "service_id": "svc-b"})
store.create_backup_run({"job_id": job_a["id"], "started_at": 1700000000, "status": "success"})
store.create_backup_run({"job_id": job_b["id"], "started_at": 1700000000, "status": "success"})
store.create_backup_alert(
{"job_id": job_a["id"], "alert_type": "test", "severity": "warning"}
)
store.create_backup_alert(
{"job_id": job_b["id"], "alert_type": "test", "severity": "warning"}
)
assert len(store.list_backup_alerts(service_id="svc-a")) == 1
assert len(store.list_backup_alerts(service_id="svc-b")) == 1
def test_list_backup_runs_unfiltered_returns_all(self, store: SettingsStore):
job_a = store.upsert_backup_job({"name": "job-a", "service_id": "svc-a"})
job_b = store.upsert_backup_job({"name": "job-b", "service_id": "svc-b"})
store.create_backup_run({"job_id": job_a["id"], "started_at": 1700000000, "status": "success"})
store.create_backup_run({"job_id": job_b["id"], "started_at": 1700000000, "status": "success"})
assert len(store.list_backup_runs()) == 2
def test_endpoint_threads_service_id_to_store(self, store: SettingsStore):
"""GET /api/backups/jobs?service_id=svc-a filters via the endpoint."""
import media_library_viewer_api.auth as auth_module
from media_library_viewer_api.services import settings_store
store.upsert_backup_job({"name": "job-a", "service_id": "svc-a"})
store.upsert_backup_job({"name": "job-b", "service_id": "svc-b"})
original_store = settings_store._store
settings_store._store = store
auth_module._API_KEY = None
try:
client = TestClient(app)
resp = client.get("/api/backups/jobs", params={"service_id": "svc-a"})
assert resp.status_code == 200
data = resp.json()
assert len(data) == 1
assert data[0]["name"] == "job-a"
finally:
settings_store._store = original_store
auth_module._API_KEY = None
def test_post_backup_report():
with tempfile.TemporaryDirectory() as tmpdir:
db_path = Path(tmpdir) / "test_settings.sqlite"