From: Volker Theile Date: Tue, 31 Jul 2018 08:43:06 +0000 (+0200) Subject: mgr/dashboard: RestClient can't handle ProtocolError exceptions X-Git-Tag: v14.0.1~667^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F23347%2Fhead;p=ceph.git mgr/dashboard: RestClient can't handle ProtocolError exceptions Fixes: https://tracker.ceph.com/issues/25190 Signed-off-by: Volker Theile --- diff --git a/src/pybind/mgr/dashboard/rest_client.py b/src/pybind/mgr/dashboard/rest_client.py index 6099fe945254f..a8ac9f8ea6f8c 100644 --- a/src/pybind/mgr/dashboard/rest_client.py +++ b/src/pybind/mgr/dashboard/rest_client.py @@ -439,8 +439,11 @@ class RestClient(object): logger.error("%s REST API failed %s, SSL error.", self.client_name, method.upper()) else: - match = re.match(r'.*: \[Errno (-?\d+)\] (.+)', - ex.args[0].reason.args[0]) + try: + match = re.match(r'.*: \[Errno (-?\d+)\] (.+)', + ex.args[0].reason.args[0]) + except AttributeError: + match = False if match: errno = match.group(1) strerror = match.group(2) diff --git a/src/pybind/mgr/dashboard/tests/test_rest_client.py b/src/pybind/mgr/dashboard/tests/test_rest_client.py index 7a15319ff9ece..f1f0267abd545 100644 --- a/src/pybind/mgr/dashboard/tests/test_rest_client.py +++ b/src/pybind/mgr/dashboard/tests/test_rest_client.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- import unittest +import requests.exceptions from mock import patch +from urllib3.exceptions import MaxRetryError, ProtocolError from .. import mgr -from ..rest_client import RestClient +from ..rest_client import RequestException, RestClient class RestClientTest(unittest.TestCase): @@ -42,3 +44,51 @@ class RestClientTest(unittest.TestCase): mock_request.assert_called_with( 'GET', '/test', None, None, None, None, None, None, 40) + + +class RestClientDoRequestTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.mock_requests = patch('requests.Session').start() + cls.rest_client = RestClient('localhost', 8000, 'UnitTest') + + def test_do_request_exception_no_args(self): + self.mock_requests().get.side_effect = requests.exceptions.ConnectionError() + with self.assertRaises(RequestException) as context: + self.rest_client.do_request('GET', '/test') + self.assertEqual('UnitTest REST API cannot be reached. Please ' + 'check your configuration and that the API ' + 'endpoint is accessible', + context.exception.message) + + def test_do_request_exception_args_1(self): + self.mock_requests().post.side_effect = requests.exceptions.ConnectionError( + MaxRetryError('Abc', 'http://xxx.yyy', 'too many redirects')) + with self.assertRaises(RequestException) as context: + self.rest_client.do_request('POST', '/test') + self.assertEqual('UnitTest REST API cannot be reached. Please ' + 'check your configuration and that the API ' + 'endpoint is accessible', + context.exception.message) + + def test_do_request_exception_args_2(self): + self.mock_requests().put.side_effect = requests.exceptions.ConnectionError( + ProtocolError('Connection broken: xyz')) + with self.assertRaises(RequestException) as context: + self.rest_client.do_request('PUT', '/test') + self.assertEqual('UnitTest REST API cannot be reached. Please ' + 'check your configuration and that the API ' + 'endpoint is accessible', + context.exception.message) + + def test_do_request_exception_nested_args(self): + self.mock_requests().delete.side_effect = requests.exceptions.ConnectionError( + MaxRetryError('Xyz', 'https://foo.bar', + Exception('Foo: [Errno -42] bla bla bla'))) + with self.assertRaises(RequestException) as context: + self.rest_client.do_request('DELETE', '/test') + self.assertEqual('UnitTest REST API cannot be reached: bla ' + 'bla bla [errno -42]. Please check your ' + 'configuration and that the API endpoint ' + 'is accessible', + context.exception.message)