From 83524ed1bfb7c8cef307d7c21c3452cbe7a16c4b Mon Sep 17 00:00:00 2001 From: Volker Theile Date: Wed, 30 Mar 2022 13:38:33 +0200 Subject: [PATCH] mgr/dashboard: Imrove error message of '/api/grafana/validation' API endpoint In case the validation of the Grafana URL fails, e.g. because of an invalid SSL certificate, a useless and not helping default error message is displayed in the UI. This PR will re-raise the exception as a DashboardException which includes the detailed description of what happened. This will help to identify SSL cert issues much easier for example. Fixes: https://tracker.ceph.com/issues/55133 Signed-off-by: Volker Theile --- src/pybind/mgr/dashboard/controllers/grafana.py | 13 ++++--------- src/pybind/mgr/dashboard/services/exception.py | 8 ++++++++ src/pybind/mgr/dashboard/tests/test_grafana.py | 8 ++++++++ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/pybind/mgr/dashboard/controllers/grafana.py b/src/pybind/mgr/dashboard/controllers/grafana.py index d5c9b19f80878..79a6806715fd7 100644 --- a/src/pybind/mgr/dashboard/controllers/grafana.py +++ b/src/pybind/mgr/dashboard/controllers/grafana.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- from .. import mgr -from ..exceptions import DashboardException from ..grafana import GrafanaRestClient, push_local_dashboards from ..security import Scope +from ..services.exception import handle_error from ..settings import Settings from . import APIDoc, APIRouter, BaseController, Endpoint, EndpointDoc, \ ReadPermission, UpdatePermission @@ -31,6 +31,7 @@ class Grafana(BaseController): @Endpoint() @ReadPermission + @handle_error('grafana') def validation(self, params): grafana = GrafanaRestClient() method = 'GET' @@ -41,14 +42,8 @@ class Grafana(BaseController): @Endpoint(method='POST') @UpdatePermission + @handle_error('grafana', 500) def dashboards(self): response = dict() - try: - response['success'] = push_local_dashboards() - except Exception as e: # pylint: disable=broad-except - raise DashboardException( - msg=str(e), - component='grafana', - http_status_code=500, - ) + response['success'] = push_local_dashboards() return response diff --git a/src/pybind/mgr/dashboard/services/exception.py b/src/pybind/mgr/dashboard/services/exception.py index 68db4ce57ce14..80c4b372afa35 100644 --- a/src/pybind/mgr/dashboard/services/exception.py +++ b/src/pybind/mgr/dashboard/services/exception.py @@ -115,3 +115,11 @@ def handle_request_error(component): raise DashboardException( msg=content_message, component=component) raise DashboardException(e=e, component=component) + + +@contextmanager +def handle_error(component, http_status_code=None): + try: + yield + except Exception as e: # pylint: disable=broad-except + raise DashboardException(e, component=component, http_status_code=http_status_code) diff --git a/src/pybind/mgr/dashboard/tests/test_grafana.py b/src/pybind/mgr/dashboard/tests/test_grafana.py index f54219c9f132c..b822020d8ac9a 100644 --- a/src/pybind/mgr/dashboard/tests/test_grafana.py +++ b/src/pybind/mgr/dashboard/tests/test_grafana.py @@ -53,6 +53,14 @@ class GrafanaTest(ControllerTestCase, KVStoreMockMixin): self.assertStatus(200) self.assertBody(b'"404"') + @patch('dashboard.controllers.grafana.GrafanaRestClient.url_validation') + def test_validation_endpoint_fails(self, url_validation): + url_validation.side_effect = RequestException + self.server_settings() + self._get('/api/grafana/validation/bar') + self.assertStatus(400) + self.assertJsonBody({'detail': '', 'code': 'Error', 'component': 'grafana'}) + def test_dashboards_unavailable_no_url(self): self.server_settings(url="") self._post('/api/grafana/dashboards') -- 2.39.5