Add cfgfilter.ConfigFilter
Add a new class designed to wrap cfg.ConfigOpts, with the following use cases in mind: 1. Help enforce that a given module does not access options registered by another module, without first declaring those cross-module dependencies using import_opt(). 2. Prevent private configuration opts from being visible to modules other than the one which registered it. blueprint: oslo-config-cfgfilter Change-Id: I477f7027806d7630ce91159fb274f41c0c203770
This commit is contained in:
parent
dcef87a282
commit
bcb8b7b8f6
5
doc/source/cfgfilter.rst
Normal file
5
doc/source/cfgfilter.rst
Normal file
@ -0,0 +1,5 @@
|
||||
--------------------
|
||||
The cfgfilter Module
|
||||
--------------------
|
||||
|
||||
.. automodule:: oslo.config.cfgfilter
|
@ -14,6 +14,7 @@ Contents
|
||||
opts
|
||||
types
|
||||
configopts
|
||||
cfgfilter
|
||||
helpers
|
||||
parser
|
||||
exceptions
|
||||
|
318
oslo/config/cfgfilter.py
Normal file
318
oslo/config/cfgfilter.py
Normal file
@ -0,0 +1,318 @@
|
||||
# Copyright 2014 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
r"""
|
||||
There are two use cases for the ConfigFilter class:
|
||||
|
||||
1. Help enforce that a given module does not access options registered
|
||||
by another module, without first declaring those cross-module
|
||||
dependencies using import_opt().
|
||||
|
||||
2. Prevent private configuration opts from being visible to modules
|
||||
other than the one which registered it.
|
||||
|
||||
Cross-Module Option Dependencies
|
||||
--------------------------------
|
||||
|
||||
When using the global cfg.CONF object, it is quite common for a module
|
||||
to require the existence of configuration options registered by other
|
||||
modules.
|
||||
|
||||
For example, if module 'foo' registers the 'blaa' option and the module
|
||||
'bar' uses the 'blaa' option then 'bar' might do::
|
||||
|
||||
import foo
|
||||
|
||||
print(CONF.blaa)
|
||||
|
||||
However, it's completely non-obvious why foo is being imported (is it
|
||||
unused, can we remove the import) and where the 'blaa' option comes from.
|
||||
|
||||
The CONF.import_opt() method allows such a dependency to be explicitly
|
||||
declared::
|
||||
|
||||
CONF.import_opt('blaa', 'foo')
|
||||
print(CONF.blaa)
|
||||
|
||||
However, import_opt() has a weakness - if 'bar' imports 'foo' using the
|
||||
import builtin and doesn't use import_opt() to import 'blaa', then 'blaa'
|
||||
can still be used without problems. Similarly, where multiple options
|
||||
are registered a module imported via importopt(), a lazy programmer can
|
||||
get away with only declaring a dependency on a single option.
|
||||
|
||||
The ConfigFilter class provides a way to ensure that options are not
|
||||
available unless they have been registered in the module or imported using
|
||||
import_opt() e.g. with::
|
||||
|
||||
CONF = ConfigFilter(cfg.CONF)
|
||||
CONF.import_opt('blaa', 'foo')
|
||||
print(CONF.blaa)
|
||||
|
||||
no other options other than 'blaa' are available via CONF.
|
||||
|
||||
Private Configuration Options
|
||||
-----------------------------
|
||||
|
||||
Libraries which register configuration options typically do not want
|
||||
users of the library API to access those configuration options. If
|
||||
API users do access private configuration options, those users will
|
||||
be disrupted if and when a configuration option is renamed. In other
|
||||
words, one does not typically wish for the name of the private config
|
||||
options to be part of the public API.
|
||||
|
||||
The ConfigFilter class provides a way for a library to register
|
||||
options such that they are not visible via the ConfigOpts instance
|
||||
which the API user supplies to the library. For example::
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
from oslo.config.cfg import *
|
||||
from oslo.config.cfgfilter import *
|
||||
|
||||
class Widget(object):
|
||||
|
||||
def __init__(self, conf):
|
||||
self.conf = conf
|
||||
self._private_conf = ConfigFilter(self.conf)
|
||||
self._private_conf.register_opt(StrOpt('foo'))
|
||||
|
||||
@property
|
||||
def foo(self):
|
||||
return self._private_conf.foo
|
||||
|
||||
conf = ConfigOpts()
|
||||
widget = Widget(conf)
|
||||
print(widget.foo)
|
||||
print(conf.foo) # raises NoSuchOptError
|
||||
|
||||
"""
|
||||
|
||||
import collections
|
||||
import itertools
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
|
||||
class ConfigFilter(collections.Mapping):
|
||||
|
||||
"""A helper class which wraps a ConfigOpts object.
|
||||
|
||||
ConfigFilter enforces the explicit declaration of dependencies on external
|
||||
options and allows private options which are not registered with the
|
||||
wrapped Configopts object.
|
||||
"""
|
||||
|
||||
def __init__(self, conf):
|
||||
"""Construct a ConfigFilter object.
|
||||
|
||||
:param conf: a ConfigOpts object
|
||||
"""
|
||||
self._conf = conf
|
||||
self._fconf = cfg.ConfigOpts()
|
||||
self._sync()
|
||||
|
||||
self._imported_opts = set()
|
||||
self._imported_groups = dict()
|
||||
|
||||
def _sync(self):
|
||||
if self._fconf._namespace is not self._conf._namespace:
|
||||
self._fconf.clear()
|
||||
self._fconf._namespace = self._conf._namespace
|
||||
self._fconf._args = self._conf._args
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Look up an option value.
|
||||
|
||||
:param name: the opt name (or 'dest', more precisely)
|
||||
:returns: the option value (after string subsititution) or a GroupAttr
|
||||
:raises: NoSuchOptError,ConfigFileValueError,TemplateSubstitutionError
|
||||
"""
|
||||
if name in self._imported_groups:
|
||||
return self._imported_groups[name]
|
||||
elif name in self._imported_opts:
|
||||
return getattr(self._conf, name)
|
||||
else:
|
||||
self._sync()
|
||||
return getattr(self._fconf, name)
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Look up an option value."""
|
||||
return getattr(self, key)
|
||||
|
||||
def __contains__(self, key):
|
||||
"""Return True if key is the name of a registered opt or group."""
|
||||
return (key in self._fconf or
|
||||
key in self._imported_opts or
|
||||
key in self._imported_groups)
|
||||
|
||||
def __iter__(self):
|
||||
"""Iterate over all registered opt and group names."""
|
||||
return itertools.chain(self._fconf.keys(),
|
||||
self._imported_opts,
|
||||
self._imported_groups.keys())
|
||||
|
||||
def __len__(self):
|
||||
"""Return the number of options and option groups."""
|
||||
return (len(self._fconf) +
|
||||
len(self._imported_opts) +
|
||||
len(self._imported_groups))
|
||||
|
||||
@staticmethod
|
||||
def _already_registered(conf, opt, group=None):
|
||||
group_name = group.name if isinstance(group, cfg.OptGroup) else group
|
||||
return ((group_name is None and
|
||||
opt.dest in conf) or
|
||||
(group_name is not None and
|
||||
group_name in conf and
|
||||
opt.dest in conf[group_name]))
|
||||
|
||||
def register_opt(self, opt, group=None):
|
||||
"""Register an option schema.
|
||||
|
||||
:param opt: an instance of an Opt sub-class
|
||||
:param group: an optional OptGroup object or group name
|
||||
:return: False if the opt was already registered, True otherwise
|
||||
:raises: DuplicateOptError
|
||||
"""
|
||||
if self._already_registered(self._conf, opt, group):
|
||||
# Raises DuplicateError if there is another opt with the same name
|
||||
ret = self._conf.register_opt(opt, group)
|
||||
self._import_opt(opt.dest, group)
|
||||
return ret
|
||||
else:
|
||||
return self._fconf.register_opt(opt, group)
|
||||
|
||||
def register_opts(self, opts, group=None):
|
||||
"""Register multiple option schemas at once."""
|
||||
for opt in opts:
|
||||
self.register_opt(opt, group)
|
||||
|
||||
def register_cli_opt(self, opt, group=None):
|
||||
"""Register a CLI option schema.
|
||||
|
||||
:param opt: an instance of an Opt sub-class
|
||||
:param group: an optional OptGroup object or group name
|
||||
:return: False if the opt was already register, True otherwise
|
||||
:raises: DuplicateOptError, ArgsAlreadyParsedError
|
||||
"""
|
||||
if self._already_registered(self._conf, opt, group):
|
||||
# Raises DuplicateError if there is another opt with the same name
|
||||
ret = self._conf.register_cli_opt(opt, group)
|
||||
self._import_opt(opt.dest, group)
|
||||
return ret
|
||||
else:
|
||||
return self._fconf.register_cli_opt(opt, group)
|
||||
|
||||
def register_cli_opts(self, opts, group=None):
|
||||
"""Register multiple CLI option schemas at once."""
|
||||
for opt in opts:
|
||||
self.register_cli_opt(opt, group)
|
||||
|
||||
def register_group(self, group):
|
||||
"""Register an option group.
|
||||
|
||||
:param group: an OptGroup object
|
||||
"""
|
||||
self._fconf.register_group(group)
|
||||
|
||||
def import_opt(self, opt_name, module_str, group=None):
|
||||
"""Import an option definition from a module.
|
||||
|
||||
:param name: the name/dest of the opt
|
||||
:param module_str: the name of a module to import
|
||||
:param group: an option OptGroup object or group name
|
||||
:raises: NoSuchOptError, NoSuchGroupError
|
||||
"""
|
||||
self._conf.import_opt(opt_name, module_str, group)
|
||||
self._import_opt(opt_name, group)
|
||||
|
||||
def import_group(self, group, module_str):
|
||||
"""Import an option group from a module.
|
||||
|
||||
Note that this allows access to all options registered with
|
||||
the group whether or not those options were registered by
|
||||
the given module.
|
||||
|
||||
:param group: an option OptGroup object or group name
|
||||
:param module_str: the name of a module to import
|
||||
:raises: ImportError, NoSuchGroupError
|
||||
"""
|
||||
self._conf.import_group(group, module_str)
|
||||
group = self._import_group(group)
|
||||
group._all_opts = True
|
||||
|
||||
def _import_opt(self, opt_name, group):
|
||||
if group is None:
|
||||
self._imported_opts.add(opt_name)
|
||||
return True
|
||||
else:
|
||||
group = self._import_group(group)
|
||||
return group._import_opt(opt_name)
|
||||
|
||||
def _import_group(self, group_or_name):
|
||||
if isinstance(group_or_name, cfg.OptGroup):
|
||||
group_name = group_or_name.name
|
||||
else:
|
||||
group_name = group_or_name
|
||||
|
||||
if group_name in self._imported_groups:
|
||||
return self._imported_groups[group_name]
|
||||
else:
|
||||
group = self.GroupAttr(self._conf, group_name)
|
||||
self._imported_groups[group_name] = group
|
||||
return group
|
||||
|
||||
class GroupAttr(collections.Mapping):
|
||||
|
||||
"""Helper class to wrap a group object.
|
||||
|
||||
Represents the option values of a group as a mapping and attributes.
|
||||
"""
|
||||
|
||||
def __init__(self, conf, group):
|
||||
"""Construct a GroupAttr object.
|
||||
|
||||
:param conf: a ConfigOpts object
|
||||
:param group: an OptGroup object
|
||||
"""
|
||||
self._conf = conf
|
||||
self._group = group
|
||||
self._imported_opts = set()
|
||||
self._all_opts = False
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Look up an option value."""
|
||||
if not self._all_opts and name not in self._imported_opts:
|
||||
raise cfg.NoSuchOptError(name)
|
||||
return getattr(self._conf[self._group], name)
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Look up an option value."""
|
||||
return getattr(self, key)
|
||||
|
||||
def __contains__(self, key):
|
||||
"""Return True if key is the name of a registered opt or group."""
|
||||
return key in self._imported_opts
|
||||
|
||||
def __iter__(self):
|
||||
"""Iterate over all registered opt and group names."""
|
||||
for key in self._imported_opts:
|
||||
yield key
|
||||
|
||||
def __len__(self):
|
||||
"""Return the number of options and option groups."""
|
||||
return len(self._imported_opts)
|
||||
|
||||
def _import_opt(self, opt_name):
|
||||
self._imported_opts.add(opt_name)
|
280
tests/test_cfgfilter.py
Normal file
280
tests/test_cfgfilter.py
Normal file
@ -0,0 +1,280 @@
|
||||
# Copyright 2014 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslotest import base as test_base
|
||||
|
||||
from oslo.config import cfg
|
||||
from oslo.config import cfgfilter
|
||||
|
||||
|
||||
class BaseTestCase(test_base.BaseTestCase):
|
||||
|
||||
def setUp(self, conf=None):
|
||||
super(BaseTestCase, self).setUp()
|
||||
if conf is None:
|
||||
self.conf = cfg.ConfigOpts()
|
||||
else:
|
||||
self.conf = conf
|
||||
self.fconf = cfgfilter.ConfigFilter(self.conf)
|
||||
|
||||
|
||||
class RegisterTestCase(BaseTestCase):
|
||||
|
||||
def test_register_opt_default(self):
|
||||
self.fconf.register_opt(cfg.StrOpt('foo', default='bar'))
|
||||
|
||||
self.assertEqual('bar', self.fconf.foo)
|
||||
self.assertEqual('bar', self.fconf['foo'])
|
||||
self.assertIn('foo', self.fconf)
|
||||
self.assertEqual(['foo'], list(self.fconf))
|
||||
self.assertEqual(1, len(self.fconf))
|
||||
|
||||
self.assertNotIn('foo', self.conf)
|
||||
self.assertEqual(0, len(self.conf))
|
||||
self.assertRaises(cfg.NoSuchOptError, getattr, self.conf, 'foo')
|
||||
|
||||
def test_register_opt_none_default(self):
|
||||
self.fconf.register_opt(cfg.StrOpt('foo'))
|
||||
|
||||
self.assertIsNone(self.fconf.foo)
|
||||
self.assertIsNone(self.fconf['foo'])
|
||||
self.assertIn('foo', self.fconf)
|
||||
self.assertEqual(['foo'], list(self.fconf))
|
||||
self.assertEqual(1, len(self.fconf))
|
||||
|
||||
self.assertNotIn('foo', self.conf)
|
||||
self.assertEqual(0, len(self.conf))
|
||||
self.assertRaises(cfg.NoSuchOptError, getattr, self.conf, 'foo')
|
||||
|
||||
def test_register_grouped_opt_default(self):
|
||||
self.fconf.register_opt(cfg.StrOpt('foo', default='bar'),
|
||||
group='blaa')
|
||||
|
||||
self.assertEqual('bar', self.fconf.blaa.foo)
|
||||
self.assertEqual('bar', self.fconf['blaa']['foo'])
|
||||
self.assertIn('blaa', self.fconf)
|
||||
self.assertIn('foo', self.fconf.blaa)
|
||||
self.assertEqual(['blaa'], list(self.fconf))
|
||||
self.assertEqual(['foo'], list(self.fconf.blaa))
|
||||
self.assertEqual(1, len(self.fconf))
|
||||
self.assertEqual(1, len(self.fconf.blaa))
|
||||
|
||||
self.assertNotIn('blaa', self.conf)
|
||||
self.assertEqual(0, len(self.conf))
|
||||
self.assertRaises(cfg.NoSuchOptError, getattr, self.conf, 'blaa')
|
||||
|
||||
def test_register_grouped_opt_none_default(self):
|
||||
self.fconf.register_opt(cfg.StrOpt('foo'), group='blaa')
|
||||
|
||||
self.assertIsNone(self.fconf.blaa.foo)
|
||||
self.assertIsNone(self.fconf['blaa']['foo'])
|
||||
self.assertIn('blaa', self.fconf)
|
||||
self.assertIn('foo', self.fconf.blaa)
|
||||
self.assertEqual(['blaa'], list(self.fconf))
|
||||
self.assertEqual(['foo'], list(self.fconf.blaa))
|
||||
self.assertEqual(1, len(self.fconf))
|
||||
self.assertEqual(1, len(self.fconf.blaa))
|
||||
|
||||
self.assertNotIn('blaa', self.conf)
|
||||
self.assertEqual(0, len(self.conf))
|
||||
self.assertRaises(cfg.NoSuchOptError, getattr, self.conf, 'blaa')
|
||||
|
||||
def test_register_group(self):
|
||||
group = cfg.OptGroup('blaa')
|
||||
self.fconf.register_group(group)
|
||||
self.fconf.register_opt(cfg.StrOpt('foo'), group=group)
|
||||
|
||||
self.assertIsNone(self.fconf.blaa.foo)
|
||||
self.assertIsNone(self.fconf['blaa']['foo'])
|
||||
self.assertIn('blaa', self.fconf)
|
||||
self.assertIn('foo', self.fconf.blaa)
|
||||
self.assertEqual(['blaa'], list(self.fconf))
|
||||
self.assertEqual(['foo'], list(self.fconf.blaa))
|
||||
self.assertEqual(1, len(self.fconf))
|
||||
self.assertEqual(1, len(self.fconf.blaa))
|
||||
|
||||
self.assertNotIn('blaa', self.conf)
|
||||
self.assertEqual(0, len(self.conf))
|
||||
self.assertRaises(cfg.NoSuchOptError, getattr, self.conf, 'blaa')
|
||||
|
||||
def test_register_opts(self):
|
||||
self.fconf.register_opts([cfg.StrOpt('foo'),
|
||||
cfg.StrOpt('bar')])
|
||||
self.assertIn('foo', self.fconf)
|
||||
self.assertIn('bar', self.fconf)
|
||||
self.assertNotIn('foo', self.conf)
|
||||
self.assertNotIn('bar', self.conf)
|
||||
|
||||
def test_register_cli_opt(self):
|
||||
self.fconf.register_cli_opt(cfg.StrOpt('foo'))
|
||||
self.assertIn('foo', self.fconf)
|
||||
self.assertNotIn('foo', self.conf)
|
||||
|
||||
def test_register_cli_opts(self):
|
||||
self.fconf.register_cli_opts([cfg.StrOpt('foo'), cfg.StrOpt('bar')])
|
||||
self.assertIn('foo', self.fconf)
|
||||
self.assertIn('bar', self.fconf)
|
||||
self.assertNotIn('foo', self.conf)
|
||||
self.assertNotIn('bar', self.conf)
|
||||
|
||||
def test_register_opts_grouped(self):
|
||||
self.fconf.register_opts([cfg.StrOpt('foo'), cfg.StrOpt('bar')],
|
||||
group='blaa')
|
||||
self.assertIn('foo', self.fconf.blaa)
|
||||
self.assertIn('bar', self.fconf.blaa)
|
||||
self.assertNotIn('blaa', self.conf)
|
||||
|
||||
def test_register_cli_opt_grouped(self):
|
||||
self.fconf.register_cli_opt(cfg.StrOpt('foo'), group='blaa')
|
||||
self.assertIn('foo', self.fconf.blaa)
|
||||
self.assertNotIn('blaa', self.conf)
|
||||
|
||||
def test_register_cli_opts_grouped(self):
|
||||
self.fconf.register_cli_opts([cfg.StrOpt('foo'), cfg.StrOpt('bar')],
|
||||
group='blaa')
|
||||
self.assertIn('foo', self.fconf.blaa)
|
||||
self.assertIn('bar', self.fconf.blaa)
|
||||
self.assertNotIn('blaa', self.conf)
|
||||
|
||||
def test_unknown_opt(self):
|
||||
self.assertNotIn('foo', self.fconf)
|
||||
self.assertEqual(0, len(self.fconf))
|
||||
self.assertRaises(cfg.NoSuchOptError, getattr, self.fconf, 'foo')
|
||||
self.assertNotIn('blaa', self.conf)
|
||||
|
||||
def test_blocked_opt(self):
|
||||
self.conf.register_opt(cfg.StrOpt('foo'))
|
||||
|
||||
self.assertIn('foo', self.conf)
|
||||
self.assertEqual(1, len(self.conf))
|
||||
self.assertIsNone(self.conf.foo)
|
||||
self.assertNotIn('foo', self.fconf)
|
||||
self.assertEqual(0, len(self.fconf))
|
||||
self.assertRaises(cfg.NoSuchOptError, getattr, self.fconf, 'foo')
|
||||
|
||||
def test_already_registered_opt(self):
|
||||
self.conf.register_opt(cfg.StrOpt('foo'))
|
||||
self.fconf.register_opt(cfg.StrOpt('foo'))
|
||||
|
||||
self.assertIn('foo', self.conf)
|
||||
self.assertEqual(1, len(self.conf))
|
||||
self.assertIsNone(self.conf.foo)
|
||||
self.assertIn('foo', self.fconf)
|
||||
self.assertEqual(1, len(self.fconf))
|
||||
self.assertIsNone(self.fconf.foo)
|
||||
|
||||
self.conf.set_override('foo', 'bar')
|
||||
|
||||
self.assertEqual('bar', self.conf.foo)
|
||||
self.assertEqual('bar', self.fconf.foo)
|
||||
|
||||
def test_already_registered_opts(self):
|
||||
self.conf.register_opts([cfg.StrOpt('foo'),
|
||||
cfg.StrOpt('fu')])
|
||||
self.fconf.register_opts([cfg.StrOpt('foo'),
|
||||
cfg.StrOpt('bu')])
|
||||
|
||||
self.assertIn('foo', self.conf)
|
||||
self.assertIn('fu', self.conf)
|
||||
self.assertNotIn('bu', self.conf)
|
||||
self.assertEqual(2, len(self.conf))
|
||||
self.assertIsNone(self.conf.foo)
|
||||
self.assertIsNone(self.conf.fu)
|
||||
self.assertIn('foo', self.fconf)
|
||||
self.assertIn('bu', self.fconf)
|
||||
self.assertNotIn('fu', self.fconf)
|
||||
self.assertEqual(2, len(self.fconf))
|
||||
self.assertIsNone(self.fconf.foo)
|
||||
self.assertIsNone(self.fconf.bu)
|
||||
|
||||
self.conf.set_override('foo', 'bar')
|
||||
|
||||
self.assertEqual('bar', self.conf.foo)
|
||||
self.assertEqual('bar', self.fconf.foo)
|
||||
|
||||
def test_already_registered_cli_opt(self):
|
||||
self.conf.register_cli_opt(cfg.StrOpt('foo'))
|
||||
self.fconf.register_cli_opt(cfg.StrOpt('foo'))
|
||||
|
||||
self.assertIn('foo', self.conf)
|
||||
self.assertEqual(1, len(self.conf))
|
||||
self.assertIsNone(self.conf.foo)
|
||||
self.assertIn('foo', self.fconf)
|
||||
self.assertEqual(1, len(self.fconf))
|
||||
self.assertIsNone(self.fconf.foo)
|
||||
|
||||
self.conf.set_override('foo', 'bar')
|
||||
|
||||
self.assertEqual('bar', self.conf.foo)
|
||||
self.assertEqual('bar', self.fconf.foo)
|
||||
|
||||
def test_already_registered_cli_opts(self):
|
||||
self.conf.register_cli_opts([cfg.StrOpt('foo'),
|
||||
cfg.StrOpt('fu')])
|
||||
self.fconf.register_cli_opts([cfg.StrOpt('foo'),
|
||||
cfg.StrOpt('bu')])
|
||||
|
||||
self.assertIn('foo', self.conf)
|
||||
self.assertIn('fu', self.conf)
|
||||
self.assertNotIn('bu', self.conf)
|
||||
self.assertEqual(2, len(self.conf))
|
||||
self.assertIsNone(self.conf.foo)
|
||||
self.assertIsNone(self.conf.fu)
|
||||
self.assertIn('foo', self.fconf)
|
||||
self.assertIn('bu', self.fconf)
|
||||
self.assertNotIn('fu', self.fconf)
|
||||
self.assertEqual(2, len(self.fconf))
|
||||
self.assertIsNone(self.fconf.foo)
|
||||
self.assertIsNone(self.fconf.bu)
|
||||
|
||||
self.conf.set_override('foo', 'bar')
|
||||
|
||||
self.assertEqual('bar', self.conf.foo)
|
||||
self.assertEqual('bar', self.fconf.foo)
|
||||
|
||||
|
||||
class ImportTestCase(BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ImportTestCase, self).setUp(cfg.CONF)
|
||||
|
||||
def test_import_opt(self):
|
||||
self.assertFalse(hasattr(self.conf, 'fblaa'))
|
||||
self.conf.import_opt('fblaa', 'tests.testmods.fblaa_opt')
|
||||
self.assertTrue(hasattr(self.conf, 'fblaa'))
|
||||
self.assertFalse(hasattr(self.fconf, 'fblaa'))
|
||||
self.fconf.import_opt('fblaa', 'tests.testmods.fblaa_opt')
|
||||
self.assertTrue(hasattr(self.fconf, 'fblaa'))
|
||||
|
||||
def test_import_opt_in_group(self):
|
||||
self.assertFalse(hasattr(self.conf, 'fbar'))
|
||||
self.conf.import_opt('foo', 'tests.testmods.fbar_foo_opt',
|
||||
group='fbar')
|
||||
self.assertTrue(hasattr(self.conf, 'fbar'))
|
||||
self.assertTrue(hasattr(self.conf.fbar, 'foo'))
|
||||
self.assertFalse(hasattr(self.fconf, 'fbar'))
|
||||
self.fconf.import_opt('foo', 'tests.testmods.fbar_foo_opt',
|
||||
group='fbar')
|
||||
self.assertTrue(hasattr(self.fconf, 'fbar'))
|
||||
self.assertTrue(hasattr(self.fconf.fbar, 'foo'))
|
||||
|
||||
def test_import_group(self):
|
||||
self.assertFalse(hasattr(self.conf, 'fbaar'))
|
||||
self.conf.import_group('fbaar', 'tests.testmods.fbaar_baa_opt')
|
||||
self.assertTrue(hasattr(self.conf, 'fbaar'))
|
||||
self.assertTrue(hasattr(self.conf.fbaar, 'baa'))
|
||||
self.assertFalse(hasattr(self.fconf, 'fbaar'))
|
||||
self.fconf.import_group('fbaar', 'tests.testmods.fbaar_baa_opt')
|
||||
self.assertTrue(hasattr(self.fconf, 'fbaar'))
|
||||
self.assertTrue(hasattr(self.fconf.fbaar, 'baa'))
|
21
tests/testmods/fbaar_baa_opt.py
Normal file
21
tests/testmods/fbaar_baa_opt.py
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright 2012 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
opt = cfg.StrOpt('baa')
|
||||
|
||||
CONF.register_opt(opt, group='fbaar')
|
21
tests/testmods/fbar_foo_opt.py
Normal file
21
tests/testmods/fbar_foo_opt.py
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright 2013 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
opt = cfg.StrOpt('foo')
|
||||
|
||||
CONF.register_opt(opt, group='fbar')
|
21
tests/testmods/fblaa_opt.py
Normal file
21
tests/testmods/fblaa_opt.py
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright 2012 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
opt = cfg.StrOpt('fblaa')
|
||||
|
||||
CONF.register_opt(opt)
|
Loading…
x
Reference in New Issue
Block a user