Add source status API and enhance dashboard with data source checks

- Introduced a new API endpoint `/api/source-status/` to return the status of Prometheus and OpenStack data sources.
- Implemented lightweight health check functions for both Prometheus and OpenStack.
- Updated the dashboard template to display the status of data sources dynamically.
- Added tests for the new API endpoint to ensure correct functionality and response handling.
- Configured a cache timeout for source status checks to improve performance.
This commit is contained in:
2026-02-07 17:12:25 +03:00
parent 917a7758bc
commit fd03c22042
7 changed files with 207 additions and 3 deletions

View File

@@ -12,6 +12,7 @@ from dashboard.views import (
collect_audits,
api_stats,
api_audits,
api_source_status,
)
@@ -259,3 +260,102 @@ class ApiAuditsTest(TestCase):
data = json.loads(response.content)
self.assertEqual(data["audits"][0]["name"], "Cached Audit")
self.assertEqual(data["current_cluster"], cached_cluster)
class ApiSourceStatusTest(TestCase):
"""Tests for api_source_status view."""
def setUp(self):
self.factory = RequestFactory()
@patch("dashboard.views.settings")
def test_api_source_status_mock_returns_mock_status(self, mock_settings):
mock_settings.USE_MOCK_DATA = True
mock_settings.SOURCE_STATUS_CACHE_TTL = 30
request = self.factory.get("/api/source-status/")
response = api_source_status(request)
self.assertEqual(response.status_code, 200)
self.assertEqual(response["Content-Type"], "application/json")
data = json.loads(response.content)
self.assertEqual(data["prometheus"]["status"], "mock")
self.assertEqual(data["openstack"]["status"], "mock")
@patch("dashboard.views.check_openstack")
@patch("dashboard.views.check_prometheus")
@patch("dashboard.views.settings")
def test_api_source_status_both_ok_returns_ok(
self, mock_settings, mock_check_prometheus, mock_check_openstack
):
mock_settings.USE_MOCK_DATA = False
mock_settings.SOURCE_STATUS_CACHE_TTL = 30
mock_check_prometheus.return_value = {"status": "ok"}
mock_check_openstack.return_value = {"status": "ok"}
cache.clear()
request = self.factory.get("/api/source-status/")
response = api_source_status(request)
self.assertEqual(response.status_code, 200)
data = json.loads(response.content)
self.assertEqual(data["prometheus"]["status"], "ok")
self.assertEqual(data["openstack"]["status"], "ok")
mock_check_prometheus.assert_called_once()
mock_check_openstack.assert_called_once()
@patch("dashboard.views.check_openstack")
@patch("dashboard.views.check_prometheus")
@patch("dashboard.views.settings")
def test_api_source_status_prometheus_error_returns_error_message(
self, mock_settings, mock_check_prometheus, mock_check_openstack
):
mock_settings.USE_MOCK_DATA = False
mock_settings.SOURCE_STATUS_CACHE_TTL = 30
mock_check_prometheus.return_value = {"status": "error", "message": "Connection refused"}
mock_check_openstack.return_value = {"status": "ok"}
cache.clear()
request = self.factory.get("/api/source-status/")
response = api_source_status(request)
self.assertEqual(response.status_code, 200)
data = json.loads(response.content)
self.assertEqual(data["prometheus"]["status"], "error")
self.assertEqual(data["prometheus"]["message"], "Connection refused")
self.assertEqual(data["openstack"]["status"], "ok")
@patch("dashboard.views.check_openstack")
@patch("dashboard.views.check_prometheus")
@patch("dashboard.views.settings")
def test_api_source_status_openstack_error_returns_error_message(
self, mock_settings, mock_check_prometheus, mock_check_openstack
):
mock_settings.USE_MOCK_DATA = False
mock_settings.SOURCE_STATUS_CACHE_TTL = 30
mock_check_prometheus.return_value = {"status": "ok"}
mock_check_openstack.return_value = {"status": "error", "message": "Auth failed"}
cache.clear()
request = self.factory.get("/api/source-status/")
response = api_source_status(request)
self.assertEqual(response.status_code, 200)
data = json.loads(response.content)
self.assertEqual(data["prometheus"]["status"], "ok")
self.assertEqual(data["openstack"]["status"], "error")
self.assertEqual(data["openstack"]["message"], "Auth failed")
@patch("dashboard.views.check_openstack")
@patch("dashboard.views.check_prometheus")
@patch("dashboard.views.settings")
def test_api_source_status_uses_cache(
self, mock_settings, mock_check_prometheus, mock_check_openstack
):
mock_settings.USE_MOCK_DATA = False
mock_settings.SOURCE_STATUS_CACHE_TTL = 30
cache.clear()
cached = {
"prometheus": {"status": "ok"},
"openstack": {"status": "ok"},
}
cache.set("dashboard_source_status", cached, timeout=30)
request = self.factory.get("/api/source-status/")
response = api_source_status(request)
mock_check_prometheus.assert_not_called()
mock_check_openstack.assert_not_called()
data = json.loads(response.content)
self.assertEqual(data["prometheus"]["status"], "ok")
self.assertEqual(data["openstack"]["status"], "ok")