summaryrefslogtreecommitdiffstats
path: root/keystone/openstack
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-06-05 17:55:58 +0000
committerGerrit Code Review <review@openstack.org>2012-06-05 17:55:58 +0000
commit2ec3e232dc1e112886ceff350aa85e86a298b28e (patch)
treed7cdaba98db35db2d5cf9b46d5c980f8402ca193 /keystone/openstack
parent17723a6b6dc047e6341bcfcda29120580f352b46 (diff)
parentdd14b16c5cd181d27b1b1848533e67c1f1fb42be (diff)
downloadkeystone-2ec3e232dc1e112886ceff350aa85e86a298b28e.tar.gz
keystone-2ec3e232dc1e112886ceff350aa85e86a298b28e.tar.xz
keystone-2ec3e232dc1e112886ceff350aa85e86a298b28e.zip
Merge "Sync with latest version of openstack.common.cfg"
Diffstat (limited to 'keystone/openstack')
-rw-r--r--keystone/openstack/common/cfg.py101
1 files changed, 86 insertions, 15 deletions
diff --git a/keystone/openstack/common/cfg.py b/keystone/openstack/common/cfg.py
index 844ee326..03c9b703 100644
--- a/keystone/openstack/common/cfg.py
+++ b/keystone/openstack/common/cfg.py
@@ -149,6 +149,14 @@ Options can be registered as belonging to a group::
conf.register_opt(rabbit_host_opt, group=rabbit_group)
conf.register_opt(rabbit_port_opt, group='rabbit')
+If it no group attributes are required other than the group name, the group
+need not be explicitly registered e.g.
+
+ def register_rabbit_opts(conf):
+ # The group will automatically be created, equivalent calling::
+ # conf.register_group(OptGroup(name='rabbit'))
+ conf.register_opt(rabbit_port_opt, group='rabbit')
+
If no group is specified, options belong to the 'DEFAULT' section of config
files::
@@ -213,6 +221,9 @@ as the leftover arguments, but will instead return::
i.e. argument parsing is stopped at the first non-option argument.
+Options may be declared as required so that an error is raised if the user
+does not supply a value for the option.
+
Options may be declared as secret so that their values are not leaked into
log files:
@@ -291,6 +302,21 @@ class DuplicateOptError(Error):
return "duplicate option: %s" % self.opt_name
+class RequiredOptError(Error):
+ """Raised if an option is required but no value is supplied by the user."""
+
+ def __init__(self, opt_name, group=None):
+ self.opt_name = opt_name
+ self.group = group
+
+ def __str__(self):
+ if self.group is None:
+ return "value required for option: %s" % self.opt_name
+ else:
+ return "value required for option: %s.%s" % (self.group.name,
+ self.opt_name)
+
+
class TemplateSubstitutionError(Error):
"""Raised if an error occurs substituting a variable in an opt value."""
@@ -452,7 +478,7 @@ class Opt(object):
multi = False
def __init__(self, name, dest=None, short=None, default=None,
- metavar=None, help=None, secret=False):
+ metavar=None, help=None, secret=False, required=False):
"""Construct an Opt object.
The only required parameter is the option's name. However, it is
@@ -465,6 +491,7 @@ class Opt(object):
:param metavar: the option argument to show in --help
:param help: an explanation of how the option is used
:param secret: true iff the value should be obfuscated in log output
+ :param required: true iff a value must be supplied for this option
"""
self.name = name
if dest is None:
@@ -476,6 +503,7 @@ class Opt(object):
self.metavar = metavar
self.help = help
self.secret = secret
+ self.required = required
def _get_from_config_parser(self, cparser, section):
"""Retrieves the option value from a MultiConfigParser object.
@@ -909,9 +937,10 @@ class ConfigOpts(collections.Mapping):
:params args: command line arguments (defaults to sys.argv[1:])
:returns: the list of arguments left over after parsing options
- :raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError
+ :raises: SystemExit, ConfigFilesNotFoundError, ConfigFileParseError,
+ RequiredOptError
"""
- self.reset()
+ self.clear()
self._args = args
@@ -928,6 +957,8 @@ class ConfigOpts(collections.Mapping):
self._parse_config_files(from_file + from_dir)
+ self._check_required_opts()
+
return args
def __getattr__(self, name):
@@ -956,11 +987,16 @@ class ConfigOpts(collections.Mapping):
"""Return the number of options and option groups."""
return len(self._opts) + len(self._groups)
- @__clear_cache
def reset(self):
- """Reset the state of the object to before it was called."""
+ """Clear the object state and unset overrides and defaults."""
+ self._unset_defaults_and_overrides()
+ self.clear()
+
+ @__clear_cache
+ def clear(self):
+ """Clear the state of the object to before it was called."""
self._args = None
- self._cli_values = None
+ self._cli_values = {}
self._cparser = None
@__clear_cache
@@ -977,7 +1013,7 @@ class ConfigOpts(collections.Mapping):
:raises: DuplicateOptError
"""
if group is not None:
- return self._get_group(group)._register_opt(opt)
+ return self._get_group(group, autocreate=True)._register_opt(opt)
if _is_opt_registered(self._opts, opt):
return False
@@ -1012,7 +1048,7 @@ class ConfigOpts(collections.Mapping):
return False
if group is not None:
- group = self._get_group(group)
+ group = self._get_group(group, autocreate=True)
opt._add_to_cli(self._oparser, group)
@@ -1067,6 +1103,17 @@ class ConfigOpts(collections.Mapping):
opt_info = self._get_opt_info(name, group)
opt_info['default'] = default
+ def _unset_defaults_and_overrides(self):
+ """Unset any default or override on all options."""
+ def unset(opts):
+ for info in opts.values():
+ info['default'] = None
+ info['override'] = None
+
+ unset(self._opts)
+ for group in self._groups.values():
+ unset(group._opts)
+
def disable_interspersed_args(self):
"""Set parsing to stop on the first non-option.
@@ -1188,7 +1235,7 @@ class ConfigOpts(collections.Mapping):
return self.GroupAttr(self, self._get_group(name))
info = self._get_opt_info(name, group)
- default, opt, override = map(lambda k: info[k], sorted(info.keys()))
+ default, opt, override = [info[k] for k in sorted(info.keys())]
if override is not None:
return override
@@ -1241,7 +1288,7 @@ class ConfigOpts(collections.Mapping):
else:
return value
- def _get_group(self, group_or_name):
+ def _get_group(self, group_or_name, autocreate=False):
"""Looks up a OptGroup object.
Helper function to return an OptGroup given a parameter which can
@@ -1252,15 +1299,17 @@ class ConfigOpts(collections.Mapping):
the API have access to.
:param group_or_name: the group's name or the OptGroup object itself
+ :param autocreate: whether to auto-create the group if it's not found
:raises: NoSuchGroupError
"""
- if isinstance(group_or_name, OptGroup):
- group_name = group_or_name.name
- else:
- group_name = group_or_name
+ group = group_or_name if isinstance(group_or_name, OptGroup) else None
+ group_name = group.name if group else group_or_name
if not group_name in self._groups:
- raise NoSuchGroupError(group_name)
+ if not group is None or not autocreate:
+ raise NoSuchGroupError(group_name)
+
+ self.register_group(OptGroup(name=group_name))
return self._groups[group_name]
@@ -1298,6 +1347,28 @@ class ConfigOpts(collections.Mapping):
not_read_ok = filter(lambda f: f not in read_ok, config_files)
raise ConfigFilesNotFoundError(not_read_ok)
+ def _do_check_required_opts(self, opts, group=None):
+ for info in opts.values():
+ default, opt, override = [info[k] for k in sorted(info.keys())]
+
+ if opt.required:
+ if (default is not None or
+ override is not None):
+ continue
+
+ if self._get(opt.name, group) is None:
+ raise RequiredOptError(opt.name, group)
+
+ def _check_required_opts(self):
+ """Check that all opts marked as required have values specified.
+
+ :raises: RequiredOptError
+ """
+ self._do_check_required_opts(self._opts)
+
+ for group in self._groups.values():
+ self._do_check_required_opts(group._opts, group)
+
class GroupAttr(collections.Mapping):
"""