spec(grafana-metric-gateway): verify + close GM-115 + reconcile tracking

Add 3 test cases (startup old-config validation warning; status auth_failed
for 401/403) closing the GM-115 PARTIAL. Write apply-progress.md, tick all 33
tasks, add verify-report.md (15/16 PASS, 1 PARTIAL->PASS). Gates green: 331+
pytest, ruff clean, npm build+lint 0 errors, 151 vitest.
This commit is contained in:
Developer
2026-07-09 21:53:18 +00:00
parent 7e91e7f931
commit c886fcdf09
5 changed files with 408 additions and 34 deletions
+58
View File
@@ -5,10 +5,12 @@ without requiring real remote connections.
"""
import json
import logging
from types import SimpleNamespace
from unittest.mock import MagicMock, patch
import pytest
import requests
from fastapi.testclient import TestClient
from media_library_viewer_api.clients.ssh import CommandResult
@@ -787,3 +789,59 @@ class TestPrometheusStatus:
assert data["up"] is True
assert data["version"] == "ok"
assert data["service_id"] == "p1"
@pytest.mark.parametrize("status_code", [401, 403])
def test_prometheus_status_returns_auth_failure_message(self, test_client, status_code):
# GM-110: a 401/403 from the Grafana gateway must surface as an
# auth-related error, not a crash and not a generic gateway error.
service = ServiceRecord(
id="p1",
service_type="prometheus",
name="Prometheus",
config={"grafana_url": "http://grafana:3000", "datasource_uid": "prometheus"},
secrets={"grafana_api_key": "bad-key"},
)
auth_error = requests.HTTPError(
f"{status_code} Client Error",
response=MagicMock(status_code=status_code),
)
with (
patch(f"{_MON}.resolve_service_record", return_value=service),
patch(f"{_MON}.requests.post", side_effect=auth_error),
):
response = test_client.get("/api/monitoring/prometheus-status")
assert response.status_code == 200
data = response.json()
assert not data["up"]
assert data["error"] == "auth_failed"
assert data["service_id"] == "p1"
class TestPrometheusStartupValidation:
"""GM-113: startup warns (never crashes) about old-shape prometheus services."""
def test_old_shape_prometheus_service_logs_migration_warning(self, tmp_path, caplog):
from media_library_viewer_api.main import _validate_prometheus_gateway_config
# Seed a prometheus service persisted with the OLD config shape: a
# ``base_url`` and no ``grafana_url`` (pre-gateway migration).
store = SettingsStore(tmp_path / "settings.sqlite")
store.upsert_service(
{
"service_type": "prometheus",
"name": "Legacy Prometheus",
"config": {"base_url": "https://prometheus.example.com"},
"enabled": True,
}
)
with (
patch("media_library_viewer_api.main.get_settings_store", return_value=store),
caplog.at_level(logging.WARNING, logger="media_library_viewer_api.main"),
):
# Must not raise even though the service uses the deprecated shape.
_validate_prometheus_gateway_config()
# Best-effort validator logs a migration hint referencing grafana_url.
assert "grafana_url" in caplog.text
assert any(record.levelno == logging.WARNING for record in caplog.records)