From 037dee19ed9ab8023b0da0e2734bb54e88cb4cdb Mon Sep 17 00:00:00 2001 From: Mehdi Abaakouk <sileht@redhat.com> Date: Thu, 23 Feb 2017 09:37:16 +0100 Subject: [PATCH] Validate the transport url query string When driver load we allow to override option unrelated to the driver and to set option useless for the driver. This change validates the query string when the driver load to report as soon as possible invalid options. And allow to override only option of the driver option group (ie: [oslo_messaging_<driver_name>]. Related-bug: #1666903 Change-Id: Iaf23f773279c10bf37d545883ada7c2f6a9ffbbf --- oslo_messaging/_drivers/common.py | 12 ++++++-- oslo_messaging/_drivers/impl_amqp1.py | 2 +- oslo_messaging/_drivers/impl_pika.py | 2 +- oslo_messaging/_drivers/impl_rabbit.py | 2 +- oslo_messaging/_drivers/kafka_options.py | 2 +- .../_drivers/zmq_driver/zmq_options.py | 2 +- .../tests/test_config_opts_proxy.py | 30 ++++++++++++------- 7 files changed, 35 insertions(+), 17 deletions(-) diff --git a/oslo_messaging/_drivers/common.py b/oslo_messaging/_drivers/common.py index 7b0e4028b..9b35c5dd9 100644 --- a/oslo_messaging/_drivers/common.py +++ b/oslo_messaging/_drivers/common.py @@ -460,13 +460,21 @@ class ConfigOptsProxy(collections.Mapping): and valid) override corresponding values from the configuration. """ - def __init__(self, conf, url): + def __init__(self, conf, url, group): self._conf = conf self._url = url + self._group = group + self._validate_query() + + def _validate_query(self): + for name in self._url.query: + self.GroupAttrProxy(self._conf, self._group, + self._conf[self._group], + self._url)[name] def __getattr__(self, name): value = getattr(self._conf, name) - if isinstance(value, self._conf.GroupAttr): + if isinstance(value, self._conf.GroupAttr) and name == self._group: return self.GroupAttrProxy(self._conf, name, value, self._url) return value diff --git a/oslo_messaging/_drivers/impl_amqp1.py b/oslo_messaging/_drivers/impl_amqp1.py index 8c17a9827..e5eb03669 100644 --- a/oslo_messaging/_drivers/impl_amqp1.py +++ b/oslo_messaging/_drivers/impl_amqp1.py @@ -200,7 +200,7 @@ class ProtonDriver(base.BaseDriver): title='AMQP 1.0 driver options') conf.register_group(opt_group) conf.register_opts(opts.amqp1_opts, group=opt_group) - conf = common.ConfigOptsProxy(conf, url) + conf = common.ConfigOptsProxy(conf, url, opt_group.name) self._hosts = url.hosts self._conf = conf diff --git a/oslo_messaging/_drivers/impl_pika.py b/oslo_messaging/_drivers/impl_pika.py index 2fe1b870a..0d413b41a 100644 --- a/oslo_messaging/_drivers/impl_pika.py +++ b/oslo_messaging/_drivers/impl_pika.py @@ -144,7 +144,7 @@ class PikaDriver(base.BaseDriver): conf.register_opts(message_opts, group=opt_group) conf.register_opts(rpc_opts, group=opt_group) conf.register_opts(notification_opts, group=opt_group) - conf = common.ConfigOptsProxy(conf, url) + conf = common.ConfigOptsProxy(conf, url, opt_group.name) self._pika_engine = pika_drv_engine.PikaEngine( conf, url, default_exchange, allowed_remote_exmods diff --git a/oslo_messaging/_drivers/impl_rabbit.py b/oslo_messaging/_drivers/impl_rabbit.py index 6f7afd529..a32c5ccac 100644 --- a/oslo_messaging/_drivers/impl_rabbit.py +++ b/oslo_messaging/_drivers/impl_rabbit.py @@ -1335,7 +1335,7 @@ class RabbitDriver(amqpdriver.AMQPDriverBase): conf.register_opts(rabbit_opts, group=opt_group) conf.register_opts(rpc_amqp.amqp_opts, group=opt_group) conf.register_opts(base.base_opts, group=opt_group) - conf = rpc_common.ConfigOptsProxy(conf, url) + conf = rpc_common.ConfigOptsProxy(conf, url, opt_group.name) self.missing_destination_retry_timeout = ( conf.oslo_messaging_rabbit.kombu_missing_consumer_retry_timeout) diff --git a/oslo_messaging/_drivers/kafka_options.py b/oslo_messaging/_drivers/kafka_options.py index fa3b06aef..0bdcde532 100644 --- a/oslo_messaging/_drivers/kafka_options.py +++ b/oslo_messaging/_drivers/kafka_options.py @@ -59,4 +59,4 @@ def register_opts(conf, url): title='Kafka driver options') conf.register_group(opt_group) conf.register_opts(KAFKA_OPTS, group=opt_group) - return common.ConfigOptsProxy(conf, url) + return common.ConfigOptsProxy(conf, url, opt_group.name) diff --git a/oslo_messaging/_drivers/zmq_driver/zmq_options.py b/oslo_messaging/_drivers/zmq_driver/zmq_options.py index 529ec94d4..426570409 100644 --- a/oslo_messaging/_drivers/zmq_driver/zmq_options.py +++ b/oslo_messaging/_drivers/zmq_driver/zmq_options.py @@ -210,4 +210,4 @@ def register_opts(conf, url): conf.register_opts(zmq_opts, group=opt_group) conf.register_opts(server._pool_opts) conf.register_opts(base.base_opts) - return common.ConfigOptsProxy(conf, url) + return common.ConfigOptsProxy(conf, url, opt_group.name) diff --git a/oslo_messaging/tests/test_config_opts_proxy.py b/oslo_messaging/tests/test_config_opts_proxy.py index 0733c5363..0dee66970 100644 --- a/oslo_messaging/tests/test_config_opts_proxy.py +++ b/oslo_messaging/tests/test_config_opts_proxy.py @@ -27,7 +27,6 @@ class TestConfigOptsProxy(test_utils.BaseTestCase): self.config(rabbit_retry_interval=1, rabbit_qos_prefetch_count=0, rabbit_max_retries=3, - kombu_reconnect_delay=5.0, group=group) dummy_opts = [cfg.ListOpt('list_str', item_type=types.String(), default=[]), @@ -40,14 +39,12 @@ class TestConfigOptsProxy(test_utils.BaseTestCase): url = transport.TransportURL.parse( self.conf, "rabbit:///" "?rabbit_qos_prefetch_count=2" - "&unknown_opt=4" - "&kombu_reconnect_delay=invalid_value" "&list_str=1&list_str=2&list_str=3" "&list_int=1&list_int=2&list_int=3" "&dict=x:1&dict=y:2&dict=z:3" "&bool=True" ) - conf = drv_cmn.ConfigOptsProxy(self.conf, url) + conf = drv_cmn.ConfigOptsProxy(self.conf, url, group) self.assertRaises(cfg.NoSuchOptError, conf.__getattr__, 'unknown_group') @@ -57,15 +54,28 @@ class TestConfigOptsProxy(test_utils.BaseTestCase): self.assertEqual(2, conf.oslo_messaging_rabbit.rabbit_qos_prefetch_count) self.assertEqual(3, conf.oslo_messaging_rabbit.rabbit_max_retries) - self.assertRaises(cfg.NoSuchOptError, - conf.oslo_messaging_rabbit.__getattr__, - 'unknown_opt') - self.assertRaises(ValueError, - conf.oslo_messaging_rabbit.__getattr__, - 'kombu_reconnect_delay') self.assertEqual(['1', '2', '3'], conf.oslo_messaging_rabbit.list_str) self.assertEqual([1, 2, 3], conf.oslo_messaging_rabbit.list_int) self.assertEqual({'x': '1', 'y': '2', 'z': '3'}, conf.oslo_messaging_rabbit.dict) self.assertEqual(True, conf.oslo_messaging_rabbit.bool) self.assertEqual('default', conf.oslo_messaging_rabbit.str) + + def test_not_in_group(self): + group = 'oslo_messaging_rabbit' + url = transport.TransportURL.parse( + self.conf, "rabbit:///?unknown_opt=4" + ) + self.assertRaises(cfg.NoSuchOptError, + drv_cmn.ConfigOptsProxy, + self.conf, url, group) + + def test_invalid_value(self): + group = 'oslo_messaging_rabbit' + self.config(kombu_reconnect_delay=5.0, + group=group) + url = transport.TransportURL.parse( + self.conf, "rabbit:///?kombu_reconnect_delay=invalid_value" + ) + self.assertRaises(ValueError, drv_cmn.ConfigOptsProxy, self.conf, + url, group)