diff --git a/charms_openstack/adapters.py b/charms_openstack/adapters.py index 082a680..88ea2c4 100644 --- a/charms_openstack/adapters.py +++ b/charms_openstack/adapters.py @@ -84,6 +84,31 @@ def config_property(f): _custom_config_properties[property_name] = f return f + +@config_property +def config_flags(cls): + """Decorator to add a custom configuration property with + config-flags to add extra options. + + :param cls: Configuration Adapter class + :type cls: charms_openstack.adapters.DefaultConfigurationAdapter + """ + cf_config = {} + config = hookenv.config + if config and 'config-flags' in config: + # match 0 or multiple time any pair of character a=b divide by a coma + # zero or one spaces are allows between tokens + parsing_regex = r"^(?:\s{0,1}[^=]\s{0,1}=\s{0,1}[^,]\s{0,1}(?:,|$))*$" + if re.match(parsing_regex, config['config-flags']): + cf_config = dict(map(lambda x: [s.strip() for s in x.split('=')], + config['config-flags'] + .split(','))) + else: + raise RuntimeError("config-flags string error: {}".format(config)) + + return cf_config + + ## diff --git a/unit_tests/test_charms_openstack_adapters.py b/unit_tests/test_charms_openstack_adapters.py index 589f0f1..2d468cf 100644 --- a/unit_tests/test_charms_openstack_adapters.py +++ b/unit_tests/test_charms_openstack_adapters.py @@ -51,6 +51,66 @@ class TestCustomProperties(unittest.TestCase): self.assertTrue(adapters._custom_config_properties['test_func'], test_func) + def test_user_config_flags(self): + cfg = { + 'config-flags': "a = b,c=d, e= f", + } + cls_mock = mock.MagicMock() + with mock.patch.object(adapters.hookenv, + 'config', + new=cfg): + + conf = adapters.config_flags(cls_mock) + self.assertEqual(conf['a'], 'b') + self.assertEqual(conf['c'], 'd') + self.assertEqual(conf['e'], 'f') + + def test_user_config_flags_parsing_error_1(self): + cfg = { + 'config-flags': "a = b, c = d e= f", + } + cls_mock = mock.MagicMock() + with mock.patch.object(adapters.hookenv, + 'config', + new=cfg): + + with self.assertRaises(RuntimeError): + adapters.config_flags(cls_mock) + + def test_user_config_flags_parsing_error_2(self): + cfg = { + 'config-flags': "a = b, c d, e= f", + } + cls_mock = mock.MagicMock() + with mock.patch.object(adapters.hookenv, + 'config', + new=cfg): + + with self.assertRaises(RuntimeError): + adapters.config_flags(cls_mock) + + def test_user_config_flags_missing(self): + cfg = { + 'other-flags': 1 + } + cls_mock = mock.MagicMock() + with mock.patch.object(adapters.hookenv, + 'config', + new=cfg): + + conf = adapters.config_flags(cls_mock) + self.assertEqual(conf, {}) + + def test_user_config_none(self): + cfg = None + cls_mock = mock.MagicMock() + with mock.patch.object(adapters.hookenv, + 'config', + new=cfg): + + conf = adapters.config_flags(cls_mock) + self.assertEqual(conf, {}) + class MyRelation(object):