chore(observability): externalize stack from root compose files
Manage now connects to existing Grafana/Prometheus/Alertmanager instances and never deploys its own stack. - docker-compose.yml / docker-compose.dev.yml: removed prometheus, loki, alloy, grafana, alertmanager, node-exporter services, the monitoring network, and observability named volumes; they now ship only backend + frontend. Dev frontend now joins the web network so the Vite dev proxy can reach the backend. - backend: alertmanager_url default is now empty; /api/monitoring/alerts and /alertmanager-status return graceful "not configured" responses when ALERTMANAGER_URL is unset. Added not-configured tests. - docker-compose.observability.yml: kept as the optional standalone example; header clarifies Manage does not deploy it. - Removed orphaned combined monitoring/prometheus/prometheus.yml (standalone stack uses prometheus.standalone.yml). - Docs (README, REQUIREMENTS decision log, monitoring-logging-design, observability-runbooks, context.md, MIGRATION_PLAN, frontend/README, CHANGELOG) updated to the connect-to-existing model. VITE_GRAFANA_URL / VITE_PROMETHEUS_URL remain as optional frontend deep-link overrides. .env.example still needs a manual update (safety policy blocks assistant edits): set ALERTMANAGER_URL empty/optional and move standalone-only vars out of the root file.
This commit is contained in:
@@ -677,6 +677,17 @@ class TestAlertmanager:
|
||||
assert data["total"] == 0
|
||||
assert data["error"] == "alertmanager_unreachable"
|
||||
|
||||
def test_alerts_endpoint_when_not_configured(self, test_client):
|
||||
with patch("media_library_viewer_api.routers.monitoring._alertmanager_client") as mock_client:
|
||||
session = MagicMock()
|
||||
mock_client.return_value = (session, "")
|
||||
response = test_client.get("/api/monitoring/alerts")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["total"] == 0
|
||||
assert data["error"] == "alertmanager_not_configured"
|
||||
session.get.assert_not_called()
|
||||
|
||||
def test_alerts_endpoint_returns_summary(self, test_client):
|
||||
with patch("media_library_viewer_api.routers.monitoring._alertmanager_client") as mock_client:
|
||||
session = MagicMock()
|
||||
@@ -700,6 +711,16 @@ class TestAlertmanager:
|
||||
assert data["by_severity"]["critical"] == 1
|
||||
assert data["alerts"][0]["name"] == "BackupJobFailed"
|
||||
|
||||
def test_alertmanager_status_endpoint_when_not_configured(self, test_client):
|
||||
with patch("media_library_viewer_api.routers.monitoring._alertmanager_client") as mock_client:
|
||||
session = MagicMock()
|
||||
mock_client.return_value = (session, "")
|
||||
response = test_client.get("/api/monitoring/alertmanager-status")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["up"] is False
|
||||
session.get.assert_not_called()
|
||||
|
||||
def test_alertmanager_status_endpoint_when_unreachable(self, test_client):
|
||||
with patch("media_library_viewer_api.routers.monitoring._alertmanager_client") as mock_client:
|
||||
session = MagicMock()
|
||||
|
||||
@@ -369,7 +369,6 @@ async def test_ssh_task_adapter_records_history_on_run(client):
|
||||
fake_result = SimpleNamespace(exit_status=0, stdout="hi\n", stderr="")
|
||||
fake_client = SimpleNamespace(run=lambda *a, **k: fake_result)
|
||||
|
||||
from media_library_viewer_api.services.task_runner import build_ssh_client
|
||||
from media_library_viewer_api.widgets.sources import SshTaskWidgetSource
|
||||
|
||||
adapter = SshTaskWidgetSource()
|
||||
|
||||
Reference in New Issue
Block a user