From d532d68878e143c207027aea3efff2d43cef2706 Mon Sep 17 00:00:00 2001 From: Volker Theile Date: Tue, 4 Feb 2020 15:04:08 +0100 Subject: [PATCH] mgr/dashboard: RGW port autodetection does not support "Beast" RGW frontend * Improve regular expressions to support more configuration variations. * Modify error message. It includes the config line to be parsed. This should help to debug errors much easier. * If there are multiple (ssl_)ports/(ssl_)endpoints options, then the first found option will be returned. Fixes: https://tracker.ceph.com/issues/39252 Signed-off-by: Volker Theile --- .../mgr/dashboard/services/rgw_client.py | 73 +++++++--------- .../mgr/dashboard/tests/test_rgw_client.py | 86 ++++++++++++++++++- 2 files changed, 118 insertions(+), 41 deletions(-) diff --git a/src/pybind/mgr/dashboard/services/rgw_client.py b/src/pybind/mgr/dashboard/services/rgw_client.py index a3c7b6edc63..5ec4269ee19 100644 --- a/src/pybind/mgr/dashboard/services/rgw_client.py +++ b/src/pybind/mgr/dashboard/services/rgw_client.py @@ -150,44 +150,13 @@ def _parse_frontend_config(config): Get the port the RGW is running on. Due the complexity of the syntax not all variations are supported. + If there are multiple (ssl_)ports/(ssl_)endpoints options, then + the first found option will be returned. + Get more details about the configuration syntax here: http://docs.ceph.com/docs/master/radosgw/frontends/ https://civetweb.github.io/civetweb/UserManual.html - >>> _parse_frontend_config('beast port=8000') - (8000, False) - - >>> _parse_frontend_config('civetweb port=8000s') - (8000, True) - - >>> _parse_frontend_config('beast port=192.0.2.3:80') - (80, False) - - >>> _parse_frontend_config('civetweb port=172.5.2.51:8080s') - (8080, True) - - >>> _parse_frontend_config('civetweb port=[::]:8080') - (8080, False) - - >>> _parse_frontend_config('civetweb port=ip6-localhost:80s') - (80, True) - - >>> _parse_frontend_config('civetweb port=[2001:0db8::1234]:80') - (80, False) - - >>> _parse_frontend_config('civetweb port=[::1]:8443s') - (8443, True) - - >>> _parse_frontend_config('civetweb port=xyz') - Traceback (most recent call last): - ... - LookupError: Failed to determine RGW port - - >>> _parse_frontend_config('civetweb') - Traceback (most recent call last): - ... - LookupError: Failed to determine RGW port - :param config: The configuration string to parse. :type config: str :raises LookupError if parsing fails to determine the port. @@ -195,12 +164,36 @@ def _parse_frontend_config(config): whether SSL is used. :rtype: (int, boolean) """ - match = re.search(r'port=(.*:)?(\d+)(s)?', config) + match = re.search(r'^(beast|civetweb)\s+.+$', config) if match: - port = int(match.group(2)) - ssl = match.group(3) == 's' - return port, ssl - raise LookupError('Failed to determine RGW port') + if match.group(1) == 'beast': + match = re.search(r'(port|ssl_port|endpoint|ssl_endpoint)=(.+)', + config) + if match: + option_name = match.group(1) + if option_name in ['port', 'ssl_port']: + match = re.search(r'(\d+)', match.group(2)) + if match: + port = int(match.group(1)) + ssl = option_name == 'ssl_port' + return port, ssl + if option_name in ['endpoint', 'ssl_endpoint']: + match = re.search(r'([\d.]+|\[.+\])(:(\d+))?', + match.group(2)) + if match: + port = int(match.group(3)) if \ + match.group(2) is not None else 443 if \ + option_name == 'ssl_endpoint' else \ + 80 + ssl = option_name == 'ssl_endpoint' + return port, ssl + if match.group(1) == 'civetweb': + match = re.search(r'port=(.*:)?(\d+)(s)?', config) + if match: + port = int(match.group(2)) + ssl = match.group(3) == 's' + return port, ssl + raise LookupError('Failed to determine RGW port from "{}"'.format(config)) class RgwClient(RestClient): @@ -256,7 +249,7 @@ class RgwClient(RestClient): return [partial_dict( zonegroup['val'], ['api_name', 'zones'] - ) for zonegroup in zonegroups['zonegroups']] + ) for zonegroup in zonegroups['zonegroups']] @staticmethod def _rgw_settings(): diff --git a/src/pybind/mgr/dashboard/tests/test_rgw_client.py b/src/pybind/mgr/dashboard/tests/test_rgw_client.py index 8d5241cd4a2..7e153a2eefc 100644 --- a/src/pybind/mgr/dashboard/tests/test_rgw_client.py +++ b/src/pybind/mgr/dashboard/tests/test_rgw_client.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# pylint: disable=too-many-public-methods import unittest try: @@ -6,7 +7,7 @@ try: except ImportError: from unittest.mock import patch -from ..services.rgw_client import RgwClient +from ..services.rgw_client import RgwClient, _parse_frontend_config from ..settings import Settings from . import KVStoreMockMixin @@ -122,3 +123,86 @@ class RgwClientTest(unittest.TestCase, KVStoreMockMixin): ] } self.assertEqual(expected_result, instance.get_placement_targets()) + + +class RgwClientHelperTest(unittest.TestCase): + def test_parse_frontend_config_1(self): + self.assertEqual(_parse_frontend_config('beast port=8000'), (8000, False)) + + def test_parse_frontend_config_2(self): + self.assertEqual(_parse_frontend_config('beast port=80 port=8000'), (80, False)) + + def test_parse_frontend_config_3(self): + self.assertEqual(_parse_frontend_config('beast ssl_port=443 port=8000'), (443, True)) + + def test_parse_frontend_config_4(self): + self.assertEqual(_parse_frontend_config('beast endpoint=192.168.0.100:8000'), (8000, False)) + + def test_parse_frontend_config_5(self): + self.assertEqual(_parse_frontend_config('beast endpoint=[::1]'), (80, False)) + + def test_parse_frontend_config_6(self): + self.assertEqual(_parse_frontend_config( + 'beast ssl_endpoint=192.168.0.100:8443'), (8443, True)) + + def test_parse_frontend_config_7(self): + self.assertEqual(_parse_frontend_config('beast ssl_endpoint=192.168.0.100'), (443, True)) + + def test_parse_frontend_config_8(self): + self.assertEqual(_parse_frontend_config( + 'beast ssl_endpoint=[::1]:8443 endpoint=192.0.2.3:80'), (8443, True)) + + def test_parse_frontend_config_9(self): + self.assertEqual(_parse_frontend_config( + 'beast port=8080 endpoint=192.0.2.3:80'), (8080, False)) + + def test_parse_frontend_config_10(self): + self.assertEqual(_parse_frontend_config( + 'beast ssl_endpoint=192.0.2.3:8443 port=8080'), (8443, True)) + + def test_parse_frontend_config_11(self): + self.assertEqual(_parse_frontend_config('civetweb port=8000s'), (8000, True)) + + def test_parse_frontend_config_12(self): + self.assertEqual(_parse_frontend_config('civetweb port=443s port=8000'), (443, True)) + + def test_parse_frontend_config_13(self): + self.assertEqual(_parse_frontend_config('civetweb port=192.0.2.3:80'), (80, False)) + + def test_parse_frontend_config_14(self): + self.assertEqual(_parse_frontend_config('civetweb port=172.5.2.51:8080s'), (8080, True)) + + def test_parse_frontend_config_15(self): + self.assertEqual(_parse_frontend_config('civetweb port=[::]:8080'), (8080, False)) + + def test_parse_frontend_config_16(self): + self.assertEqual(_parse_frontend_config('civetweb port=ip6-localhost:80s'), (80, True)) + + def test_parse_frontend_config_17(self): + self.assertEqual(_parse_frontend_config('civetweb port=[2001:0db8::1234]:80'), (80, False)) + + def test_parse_frontend_config_18(self): + self.assertEqual(_parse_frontend_config('civetweb port=[::1]:8443s'), (8443, True)) + + def test_parse_frontend_config_19(self): + self.assertEqual(_parse_frontend_config('civetweb port=127.0.0.1:8443s+8000'), (8443, True)) + + def test_parse_frontend_config_20(self): + self.assertEqual(_parse_frontend_config('civetweb port=127.0.0.1:8080+443s'), (8080, False)) + + def test_parse_frontend_config_21(self): + with self.assertRaises(LookupError) as ctx: + _parse_frontend_config('civetweb port=xyz') + self.assertEqual(str(ctx.exception), + 'Failed to determine RGW port from "civetweb port=xyz"') + + def test_parse_frontend_config_22(self): + with self.assertRaises(LookupError) as ctx: + _parse_frontend_config('civetweb') + self.assertEqual(str(ctx.exception), 'Failed to determine RGW port from "civetweb"') + + def test_parse_frontend_config_23(self): + with self.assertRaises(LookupError) as ctx: + _parse_frontend_config('mongoose port=8080') + self.assertEqual(str(ctx.exception), + 'Failed to determine RGW port from "mongoose port=8080"') -- 2.47.3