diff options
author | Jenkins <jenkins@review.openstack.org> | 2015-02-23 02:46:12 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2015-02-23 02:46:12 +0000 |
commit | 0abac4881355a395a14a5d68e3347805a480cff9 (patch) | |
tree | a27a976de2c7dc4b45354e7b711067acd525a047 | |
parent | a98dc254d31cd29fce6795a67b01246641a73dad (diff) | |
parent | dc1d2340d552796ad66165bc0ff88e10fe0b6f06 (diff) | |
download | oslo-config-0abac4881355a395a14a5d68e3347805a480cff9.tar.gz |
Merge "Log a warning when deprecated opts are used"1.7.0
-rw-r--r-- | oslo_config/cfg.py | 32 | ||||
-rw-r--r-- | oslo_config/tests/test_cfg.py | 97 |
2 files changed, 129 insertions, 0 deletions
diff --git a/oslo_config/cfg.py b/oslo_config/cfg.py index 48a5482..b51b4ec 100644 --- a/oslo_config/cfg.py +++ b/oslo_config/cfg.py @@ -1416,9 +1416,13 @@ class ConfigParser(iniparser.BaseParser): class MultiConfigParser(object): + _deprecated_opt_message = ('Option "%s" from group "%s" is deprecated. ' + 'Use option "%s" from group "%s".') + def __init__(self): self.parsed = [] self._normalized = [] + self._emitted_deprecations = set() def read(self, config_files): read_ok = [] @@ -1470,6 +1474,8 @@ class MultiConfigParser(object): if section not in sections: continue if name in sections[section]: + self._check_deprecated((section, name), names[0], + names[1:]) val = sections[section][name] if multi: rvalue = val + rvalue @@ -1479,6 +1485,32 @@ class MultiConfigParser(object): return rvalue raise KeyError + def _check_deprecated(self, name, current, deprecated): + """Check for usage of deprecated names. + + :param name: A tuple of the form (group, name) representing the group + and name where an opt value was found. + :param current: A tuple of the form (group, name) representing the + current name for an option. + :param deprecated: A list of tuples with the same format as the name + param which represent any deprecated names for an option. + If the name param matches any entries in this list a + deprecation warning will be logged. + """ + # Opts in the DEFAULT group may come in with a group name of either + # 'DEFAULT' or None. Force them all to 'DEFAULT' since that's a more + # user-friendly form. + deprecated_names = set((g or 'DEFAULT', n) for (g, n) in deprecated) + name = (name[0] or 'DEFAULT', name[1]) + if name in deprecated_names and name not in self._emitted_deprecations: + self._emitted_deprecations.add(name) + current = (current[0] or 'DEFAULT', current[1]) + # NOTE(bnemec): Not using versionutils for this to avoid a + # circular dependency between oslo.config and whatever library + # versionutils ends up in. + LOG.warning(self._deprecated_opt_message, name[1], + name[0], current[1], current[0]) + class _Namespace(argparse.Namespace): diff --git a/oslo_config/tests/test_cfg.py b/oslo_config/tests/test_cfg.py index f8e600f..eb5ddd1 100644 --- a/oslo_config/tests/test_cfg.py +++ b/oslo_config/tests/test_cfg.py @@ -3563,3 +3563,100 @@ class SectionsTestCase(base.BaseTestCase): config(args=[], default_config_files=[paths[0]]) sections = set(config.list_all_sections()) self.assertEqual(sections, set(['DEFAULT', 'BLAA'])) + + +class DeprecationWarningTestBase(BaseTestCase): + def setUp(self): + super(DeprecationWarningTestBase, self).setUp() + self.log_fixture = self.useFixture(fixtures.FakeLogger()) + self._parser_class = cfg.MultiConfigParser + + +class DeprecationWarningTestScenarios(DeprecationWarningTestBase): + scenarios = [('default-deprecated', dict(deprecated=True, + group='DEFAULT')), + ('default-not-deprecated', dict(deprecated=False, + group='DEFAULT')), + ('other-deprecated', dict(deprecated=True, + group='other')), + ('other-not-deprecated', dict(deprecated=False, + group='other')), + ] + + def test_deprecated_logging(self): + self.conf.register_opt(cfg.StrOpt('foo', deprecated_name='bar')) + self.conf.register_group(cfg.OptGroup('other')) + self.conf.register_opt(cfg.StrOpt('foo', deprecated_name='bar'), + group='other') + if self.deprecated: + content = 'bar=baz' + else: + content = 'foo=baz' + paths = self.create_tempfiles([('test', + '[' + self.group + ']\n' + + content + '\n')]) + + self.conf(['--config-file', paths[0]]) + # Reference these twice to verify they only get logged once + if self.group == 'DEFAULT': + self.assertEqual('baz', self.conf.foo) + self.assertEqual('baz', self.conf.foo) + else: + self.assertEqual('baz', self.conf.other.foo) + self.assertEqual('baz', self.conf.other.foo) + if self.deprecated: + expected = (self._parser_class._deprecated_opt_message % + ('bar', self.group, 'foo', self.group) + '\n') + else: + expected = '' + self.assertEqual(expected, self.log_fixture.output) + + +class DeprecationWarningTests(DeprecationWarningTestBase): + def test_DeprecatedOpt(self): + default_deprecated = [cfg.DeprecatedOpt('bar')] + other_deprecated = [cfg.DeprecatedOpt('baz', group='other')] + self.conf.register_group(cfg.OptGroup('other')) + self.conf.register_opt(cfg.StrOpt('foo', + deprecated_opts=default_deprecated)) + self.conf.register_opt(cfg.StrOpt('foo', + deprecated_opts=other_deprecated), + group='other') + paths = self.create_tempfiles([('test', + '[DEFAULT]\n' + + 'bar=baz\n' + + '[other]\n' + + 'baz=baz\n')]) + self.conf(['--config-file', paths[0]]) + self.assertEqual('baz', self.conf.foo) + self.assertEqual('baz', self.conf.other.foo) + self.assertIn('Option "bar" from group "DEFAULT"', + self.log_fixture.output) + self.assertIn('Option "baz" from group "other"', + self.log_fixture.output) + + def test_check_deprecated_default_none(self): + parser = self._parser_class() + deprecated_list = [(None, 'bar')] + parser._check_deprecated(('DEFAULT', 'bar'), (None, 'foo'), + deprecated_list) + self.assert_message_logged('bar', 'DEFAULT', 'foo', 'DEFAULT') + # Make sure check_deprecated didn't modify the list passed in + self.assertEqual([(None, 'bar')], deprecated_list) + + def test_check_deprecated_none_default(self): + parser = self._parser_class() + deprecated_list = [('DEFAULT', 'bar')] + parser._check_deprecated((None, 'bar'), ('DEFAULT', 'foo'), + deprecated_list) + self.assert_message_logged('bar', 'DEFAULT', 'foo', 'DEFAULT') + # Make sure check_deprecated didn't modify the list passed in + self.assertEqual([('DEFAULT', 'bar')], deprecated_list) + + def assert_message_logged(self, deprecated_name, deprecated_group, + current_name, current_group): + expected = (self._parser_class._deprecated_opt_message % + (deprecated_name, deprecated_group, + current_name, current_group) + ) + self.assertEqual(expected + '\n', self.log_fixture.output) |