Add reload_config_files function
Add reload_config_files function for ConfigOpts instance to reload all configuration files. Implements blueprint cfg-reload-config-files Change-Id: Ia4d96be170d1ddfaa70b8e467b9a19ed45dc4060
This commit is contained in:
@@ -266,6 +266,7 @@ import copy
|
||||
import functools
|
||||
import glob
|
||||
import itertools
|
||||
import logging
|
||||
import os
|
||||
import six
|
||||
import string
|
||||
@@ -274,6 +275,8 @@ import sys
|
||||
from oslo.config import iniparser
|
||||
from six import moves
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
"""Base class for cfg exceptions."""
|
||||
@@ -1913,23 +1916,28 @@ class ConfigOpts(collections.Mapping):
|
||||
"""Print the help message for the current program."""
|
||||
self._oparser.print_help(file)
|
||||
|
||||
def _get(self, name, group=None):
|
||||
def _get(self, name, group=None, namespace=None):
|
||||
if isinstance(group, OptGroup):
|
||||
key = (group.name, name)
|
||||
else:
|
||||
key = (group, name)
|
||||
try:
|
||||
if namespace is not None:
|
||||
raise KeyError
|
||||
|
||||
return self.__cache[key]
|
||||
except KeyError:
|
||||
value = self._substitute(self._do_get(name, group))
|
||||
value = self._substitute(self._do_get(name, group, namespace))
|
||||
self.__cache[key] = value
|
||||
return value
|
||||
|
||||
def _do_get(self, name, group=None):
|
||||
def _do_get(self, name, group=None, namespace=None):
|
||||
"""Look up an option value.
|
||||
|
||||
:param name: the opt name (or 'dest', more precisely)
|
||||
:param group: an OptGroup
|
||||
:param namespace: the namespace object that retrieves the option
|
||||
value from
|
||||
:returns: the option value, or a GroupAttr object
|
||||
:raises: NoSuchOptError, NoSuchGroupError, ConfigFileValueError,
|
||||
TemplateSubstitutionError
|
||||
@@ -1946,10 +1954,12 @@ class ConfigOpts(collections.Mapping):
|
||||
if 'override' in info:
|
||||
return info['override']
|
||||
|
||||
if self._namespace is not None:
|
||||
if namespace is None:
|
||||
namespace = self._namespace
|
||||
if namespace is not None:
|
||||
group_name = group.name if group is not None else None
|
||||
try:
|
||||
return opt._get_from_namespace(self._namespace, group_name)
|
||||
return opt._get_from_namespace(namespace, group_name)
|
||||
except KeyError:
|
||||
pass
|
||||
except ValueError as ve:
|
||||
@@ -2020,9 +2030,10 @@ class ConfigOpts(collections.Mapping):
|
||||
|
||||
return opts[opt_name]
|
||||
|
||||
def _check_required_opts(self):
|
||||
def _check_required_opts(self, namespace=None):
|
||||
"""Check that all opts marked as required have values specified.
|
||||
|
||||
:param namespace: the namespace object be checked the required options
|
||||
:raises: RequiredOptError
|
||||
"""
|
||||
for info, group in self._all_opt_infos():
|
||||
@@ -2032,7 +2043,7 @@ class ConfigOpts(collections.Mapping):
|
||||
if 'default' in info or 'override' in info:
|
||||
continue
|
||||
|
||||
if self._get(opt.dest, group) is None:
|
||||
if self._get(opt.dest, group, namespace) is None:
|
||||
raise RequiredOptError(opt.name, group)
|
||||
|
||||
def _parse_cli_opts(self, args):
|
||||
@@ -2053,16 +2064,46 @@ class ConfigOpts(collections.Mapping):
|
||||
key=lambda x: x[0].name):
|
||||
opt._add_to_cli(self._oparser, group)
|
||||
|
||||
namespace = _Namespace(self)
|
||||
return self._parse_config_files()
|
||||
|
||||
for arg in args:
|
||||
def _parse_config_files(self):
|
||||
"""Parse configure files options.
|
||||
|
||||
:raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError,
|
||||
RequiredOptError, DuplicateOptError
|
||||
"""
|
||||
namespace = _Namespace(self)
|
||||
for arg in self._args:
|
||||
if arg == '--config-file' or arg.startswith('--config-file='):
|
||||
break
|
||||
else:
|
||||
for config_file in self.default_config_files:
|
||||
ConfigParser._parse_file(config_file, namespace)
|
||||
return self._oparser.parse_args(self._args, namespace)
|
||||
|
||||
return self._oparser.parse_args(args, namespace)
|
||||
@__clear_cache
|
||||
def reload_config_files(self):
|
||||
"""Reload configure files and parse all options
|
||||
|
||||
:return False if reload configure files failed or else return True
|
||||
"""
|
||||
try:
|
||||
namespace = self._parse_config_files()
|
||||
if namespace.files_not_found:
|
||||
raise ConfigFilesNotFoundError(namespace.files_not_found)
|
||||
self._check_required_opts(namespace)
|
||||
|
||||
except SystemExit as exc:
|
||||
LOG.warn("Caught SystemExit while reloading configure files \
|
||||
with exit code: %d" % exc.code)
|
||||
return False
|
||||
except Error as err:
|
||||
LOG.warn("Caught Error while reloading configure files: %s"
|
||||
% err.__str__())
|
||||
return False
|
||||
else:
|
||||
self._namespace = namespace
|
||||
return True
|
||||
|
||||
class GroupAttr(collections.Mapping):
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
@@ -1234,6 +1235,104 @@ class ConfigFileOptsTestCase(BaseTestCase):
|
||||
self.assertEquals(self.conf.foo, 'bar-%08x')
|
||||
|
||||
|
||||
class ConfigFileReloadTestCase(BaseTestCase):
|
||||
|
||||
def test_conf_files_reload(self):
|
||||
self.conf.register_cli_opt(cfg.StrOpt('foo'))
|
||||
|
||||
paths = self.create_tempfiles([('1',
|
||||
'[DEFAULT]\n'
|
||||
'foo = baar\n'),
|
||||
('2',
|
||||
'[DEFAULT]\n'
|
||||
'foo = baaar\n')])
|
||||
|
||||
self.conf(['--config-file', paths[0]])
|
||||
self.assertTrue(hasattr(self.conf, 'foo'))
|
||||
self.assertEquals(self.conf.foo, 'baar')
|
||||
|
||||
shutil.copy(paths[1], paths[0])
|
||||
|
||||
self.conf.reload_config_files()
|
||||
self.assertTrue(hasattr(self.conf, 'foo'))
|
||||
self.assertEquals(self.conf.foo, 'baaar')
|
||||
|
||||
def test_conf_files_reload_default(self):
|
||||
self.conf.register_cli_opt(cfg.StrOpt('foo1'))
|
||||
self.conf.register_cli_opt(cfg.StrOpt('foo2'))
|
||||
|
||||
paths = self.create_tempfiles([('1',
|
||||
'[DEFAULT]\n'
|
||||
'foo1 = default1\n'),
|
||||
('2',
|
||||
'[DEFAULT]\n'
|
||||
'foo2 = default2\n')])
|
||||
|
||||
paths_change = self.create_tempfiles([('1',
|
||||
'[DEFAULT]\n'
|
||||
'foo1 = change_default1\n'),
|
||||
('2',
|
||||
'[DEFAULT]\n'
|
||||
'foo2 = change_default2\n')])
|
||||
|
||||
self.conf(args=[], default_config_files=paths)
|
||||
self.assertTrue(hasattr(self.conf, 'foo1'))
|
||||
self.assertEquals(self.conf.foo1, 'default1')
|
||||
self.assertTrue(hasattr(self.conf, 'foo2'))
|
||||
self.assertEquals(self.conf.foo2, 'default2')
|
||||
|
||||
shutil.copy(paths_change[0], paths[0])
|
||||
shutil.copy(paths_change[1], paths[1])
|
||||
|
||||
self.conf.reload_config_files()
|
||||
self.assertTrue(hasattr(self.conf, 'foo1'))
|
||||
self.assertEquals(self.conf.foo1, 'change_default1')
|
||||
self.assertTrue(hasattr(self.conf, 'foo2'))
|
||||
self.assertEquals(self.conf.foo2, 'change_default2')
|
||||
|
||||
def test_conf_files_reload_file_not_found(self):
|
||||
self.conf.register_cli_opt(cfg.StrOpt('foo', required=True))
|
||||
paths = self.create_tempfiles([('1',
|
||||
'[DEFAULT]\n'
|
||||
'foo = baar\n')])
|
||||
|
||||
self.conf(['--config-file', paths[0]])
|
||||
self.assertTrue(hasattr(self.conf, 'foo'))
|
||||
self.assertEquals(self.conf.foo, 'baar')
|
||||
|
||||
os.remove(paths[0])
|
||||
|
||||
self.conf.reload_config_files()
|
||||
self.assertTrue(hasattr(self.conf, 'foo'))
|
||||
self.assertEquals(self.conf.foo, 'baar')
|
||||
|
||||
def test_conf_files_reload_error(self):
|
||||
self.conf.register_cli_opt(cfg.StrOpt('foo', required=True))
|
||||
self.conf.register_cli_opt(cfg.StrOpt('foo1', required=True))
|
||||
paths = self.create_tempfiles([('1',
|
||||
'[DEFAULT]\n'
|
||||
'foo = test1\n'
|
||||
'foo1 = test11\n'),
|
||||
('2',
|
||||
'[DEFAULT]\n'
|
||||
'foo2 = test2\n'
|
||||
'foo3 = test22\n')])
|
||||
|
||||
self.conf(['--config-file', paths[0]])
|
||||
self.assertTrue(hasattr(self.conf, 'foo'))
|
||||
self.assertEquals(self.conf.foo, 'test1')
|
||||
self.assertTrue(hasattr(self.conf, 'foo1'))
|
||||
self.assertEquals(self.conf.foo1, 'test11')
|
||||
|
||||
shutil.copy(paths[1], paths[0])
|
||||
|
||||
self.conf.reload_config_files()
|
||||
self.assertTrue(hasattr(self.conf, 'foo'))
|
||||
self.assertEquals(self.conf.foo, 'test1')
|
||||
self.assertTrue(hasattr(self.conf, 'foo1'))
|
||||
self.assertEquals(self.conf.foo1, 'test11')
|
||||
|
||||
|
||||
class OptGroupsTestCase(BaseTestCase):
|
||||
|
||||
def test_arg_group(self):
|
||||
|
Reference in New Issue
Block a user