From 85f2a9aa2758570950edab415d7ef6043e5a76cf 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 (cherry picked from commit 83524ed1bfb7c8cef307d7c21c3452cbe7a16c4b) Conflicts: src/pybind/mgr/dashboard/services/exception.py --- 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 e200984ea4abb..1f222a6635e54 100644 --- a/src/pybind/mgr/dashboard/controllers/grafana.py +++ b/src/pybind/mgr/dashboard/controllers/grafana.py @@ -2,9 +2,9 @@ from __future__ import absolute_import 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 @@ -33,6 +33,7 @@ class Grafana(BaseController): @Endpoint() @ReadPermission + @handle_error('grafana') def validation(self, params): grafana = GrafanaRestClient() method = 'GET' @@ -43,14 +44,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 64fa6dc1c0f15..4ec9ffce2ee22 100644 --- a/src/pybind/mgr/dashboard/services/exception.py +++ b/src/pybind/mgr/dashboard/services/exception.py @@ -98,3 +98,11 @@ def handle_orchestrator_error(component): yield except OrchestratorError as e: raise DashboardException(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