70c5b67df3
Move the public API out of oslo.config to oslo_config. Retain the ability to import from the old namespace package for backwards compatibility for this release cycle. bp/drop-namespace-packages Change-Id: I56274336802036de050efc62eb2ee6b5d4ede77b
540 lines
14 KiB
Python
540 lines
14 KiB
Python
# 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.
|
|
|
|
import sys
|
|
|
|
import fixtures
|
|
import mock
|
|
from oslotest import base
|
|
from six import moves
|
|
import testscenarios
|
|
|
|
from oslo.config import cfg
|
|
from oslo.config import fixture as config_fixture
|
|
from oslo.config import generator
|
|
|
|
load_tests = testscenarios.load_tests_apply_scenarios
|
|
|
|
|
|
class GeneratorTestCase(base.BaseTestCase):
|
|
|
|
opts = {
|
|
'foo': cfg.StrOpt('foo', help='foo option'),
|
|
'bar': cfg.StrOpt('bar', help='bar option'),
|
|
'foo-bar': cfg.StrOpt('foo-bar', help='foobar'),
|
|
'no_help': cfg.StrOpt('no_help'),
|
|
'long_help': cfg.StrOpt('long_help',
|
|
help='Lorem ipsum dolor sit amet, consectetur '
|
|
'adipisicing elit, sed do eiusmod tempor '
|
|
'incididunt ut labore et dolore magna '
|
|
'aliqua. Ut enim ad minim veniam, quis '
|
|
'nostrud exercitation ullamco laboris '
|
|
'nisi ut aliquip ex ea commodo '
|
|
'consequat. Duis aute irure dolor in '
|
|
'reprehenderit in voluptate velit esse '
|
|
'cillum dolore eu fugiat nulla '
|
|
'pariatur. Excepteur sint occaecat '
|
|
'cupidatat non proident, sunt in culpa '
|
|
'qui officia deserunt mollit anim id est '
|
|
'laborum.'),
|
|
'deprecated_opt': cfg.StrOpt('bar',
|
|
deprecated_name='foobar',
|
|
help='deprecated'),
|
|
'deprecated_group': cfg.StrOpt('bar',
|
|
deprecated_group='group1',
|
|
deprecated_name='foobar',
|
|
help='deprecated'),
|
|
# Unknown Opt default must be a string
|
|
'unknown_type': cfg.Opt('unknown_opt',
|
|
default='123',
|
|
help='unknown'),
|
|
'str_opt': cfg.StrOpt('str_opt',
|
|
default='foo bar',
|
|
help='a string'),
|
|
'str_opt_sample_default': cfg.StrOpt('str_opt',
|
|
default='fooishbar',
|
|
help='a string'),
|
|
'str_opt_with_space': cfg.StrOpt('str_opt',
|
|
default=' foo bar ',
|
|
help='a string with spaces'),
|
|
'bool_opt': cfg.BoolOpt('bool_opt',
|
|
default=False,
|
|
help='a boolean'),
|
|
'int_opt': cfg.IntOpt('int_opt',
|
|
default=10,
|
|
help='an integer'),
|
|
'float_opt': cfg.FloatOpt('float_opt',
|
|
default=0.1,
|
|
help='a float'),
|
|
'list_opt': cfg.ListOpt('list_opt',
|
|
default=['1', '2', '3'],
|
|
help='a list'),
|
|
'dict_opt': cfg.DictOpt('dict_opt',
|
|
default={'1': 'yes', '2': 'no'},
|
|
help='a dict'),
|
|
'multi_opt': cfg.MultiStrOpt('multi_opt',
|
|
default=['1', '2', '3'],
|
|
help='multiple strings'),
|
|
'multi_opt_none': cfg.MultiStrOpt('multi_opt_none',
|
|
help='multiple strings'),
|
|
'multi_opt_empty': cfg.MultiStrOpt('multi_opt_empty',
|
|
default=[],
|
|
help='multiple strings'),
|
|
'multi_opt_sample_default': cfg.MultiStrOpt('multi_opt',
|
|
default=['1', '2', '3'],
|
|
sample_default=['5', '6'],
|
|
help='multiple strings'),
|
|
}
|
|
|
|
content_scenarios = [
|
|
('empty',
|
|
dict(opts=[], expected='''[DEFAULT]
|
|
''')),
|
|
('single_namespace',
|
|
dict(opts=[('test', [(None, [opts['foo']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# foo option (string value)
|
|
#foo = <None>
|
|
''')),
|
|
('multiple_namespaces',
|
|
dict(opts=[('test', [(None, [opts['foo']])]),
|
|
('other', [(None, [opts['bar']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From other
|
|
#
|
|
|
|
# bar option (string value)
|
|
#bar = <None>
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# foo option (string value)
|
|
#foo = <None>
|
|
''')),
|
|
('group',
|
|
dict(opts=[('test', [('group1', [opts['foo']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
|
|
[group1]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# foo option (string value)
|
|
#foo = <None>
|
|
''')),
|
|
('empty_group',
|
|
dict(opts=[('test', [('group1', [])])],
|
|
expected='''[DEFAULT]
|
|
''')),
|
|
('multiple_groups',
|
|
dict(opts=[('test', [('group1', [opts['foo']]),
|
|
('group2', [opts['bar']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
|
|
[group1]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# foo option (string value)
|
|
#foo = <None>
|
|
|
|
|
|
[group2]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# bar option (string value)
|
|
#bar = <None>
|
|
''')),
|
|
('group_in_multiple_namespaces',
|
|
dict(opts=[('test', [('group1', [opts['foo']])]),
|
|
('other', [('group1', [opts['bar']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
|
|
[group1]
|
|
|
|
#
|
|
# From other
|
|
#
|
|
|
|
# bar option (string value)
|
|
#bar = <None>
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# foo option (string value)
|
|
#foo = <None>
|
|
''')),
|
|
('hyphenated_name',
|
|
dict(opts=[('test', [(None, [opts['foo-bar']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# foobar (string value)
|
|
#foo_bar = <None>
|
|
''')),
|
|
('no_help',
|
|
dict(opts=[('test', [(None, [opts['no_help']])])],
|
|
log_warning=('"%s" is missing a help string', 'no_help'),
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# (string value)
|
|
#no_help = <None>
|
|
''')),
|
|
('long_help',
|
|
dict(opts=[('test', [(None, [opts['long_help']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
|
|
# eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
|
|
# ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
|
|
# aliquip ex ea commodo consequat. Duis aute irure dolor in
|
|
# reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
|
|
# pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
|
|
# culpa qui officia deserunt mollit anim id est laborum. (string
|
|
# value)
|
|
#long_help = <None>
|
|
''')),
|
|
('long_help_wrap_at_40',
|
|
dict(opts=[('test', [(None, [opts['long_help']])])],
|
|
wrap_width=40,
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# Lorem ipsum dolor sit amet,
|
|
# consectetur adipisicing elit, sed do
|
|
# eiusmod tempor incididunt ut labore et
|
|
# dolore magna aliqua. Ut enim ad minim
|
|
# veniam, quis nostrud exercitation
|
|
# ullamco laboris nisi ut aliquip ex ea
|
|
# commodo consequat. Duis aute irure
|
|
# dolor in reprehenderit in voluptate
|
|
# velit esse cillum dolore eu fugiat
|
|
# nulla pariatur. Excepteur sint
|
|
# occaecat cupidatat non proident, sunt
|
|
# in culpa qui officia deserunt mollit
|
|
# anim id est laborum. (string value)
|
|
#long_help = <None>
|
|
''')),
|
|
('long_help_no_wrapping',
|
|
dict(opts=[('test', [(None, [opts['long_help']])])],
|
|
wrap_width=0,
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
''' # noqa
|
|
'# Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod '
|
|
'tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, '
|
|
'quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo '
|
|
'consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse '
|
|
'cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat '
|
|
'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. '
|
|
'(string value)'
|
|
'''
|
|
#long_help = <None>
|
|
''')),
|
|
('deprecated',
|
|
dict(opts=[('test', [('foo', [opts['deprecated_opt']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
|
|
[foo]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# deprecated (string value)
|
|
# Deprecated group/name - [DEFAULT]/foobar
|
|
#bar = <None>
|
|
''')),
|
|
('deprecated_group',
|
|
dict(opts=[('test', [('foo', [opts['deprecated_group']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
|
|
[foo]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# deprecated (string value)
|
|
# Deprecated group/name - [group1]/foobar
|
|
#bar = <None>
|
|
''')),
|
|
('unknown_type',
|
|
dict(opts=[('test', [(None, [opts['unknown_type']])])],
|
|
log_warning=('Unknown option type: %s',
|
|
repr(opts['unknown_type'])),
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# unknown (unknown type)
|
|
#unknown_opt = 123
|
|
''')),
|
|
('str_opt',
|
|
dict(opts=[('test', [(None, [opts['str_opt']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# a string (string value)
|
|
#str_opt = foo bar
|
|
''')),
|
|
('str_opt_with_space',
|
|
dict(opts=[('test', [(None, [opts['str_opt_with_space']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# a string with spaces (string value)
|
|
#str_opt = " foo bar "
|
|
''')),
|
|
('bool_opt',
|
|
dict(opts=[('test', [(None, [opts['bool_opt']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# a boolean (boolean value)
|
|
#bool_opt = false
|
|
''')),
|
|
('int_opt',
|
|
dict(opts=[('test', [(None, [opts['int_opt']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# an integer (integer value)
|
|
#int_opt = 10
|
|
''')),
|
|
('float_opt',
|
|
dict(opts=[('test', [(None, [opts['float_opt']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# a float (floating point value)
|
|
#float_opt = 0.1
|
|
''')),
|
|
('list_opt',
|
|
dict(opts=[('test', [(None, [opts['list_opt']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# a list (list value)
|
|
#list_opt = 1,2,3
|
|
''')),
|
|
('dict_opt',
|
|
dict(opts=[('test', [(None, [opts['dict_opt']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# a dict (dict value)
|
|
#dict_opt = 1:yes,2:no
|
|
''')),
|
|
('multi_opt',
|
|
dict(opts=[('test', [(None, [opts['multi_opt']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# multiple strings (multi valued)
|
|
#multi_opt = 1
|
|
#multi_opt = 2
|
|
#multi_opt = 3
|
|
''')),
|
|
('multi_opt_none',
|
|
dict(opts=[('test', [(None, [opts['multi_opt_none']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# multiple strings (multi valued)
|
|
#multi_opt_none =
|
|
''')),
|
|
('multi_opt_empty',
|
|
dict(opts=[('test', [(None, [opts['multi_opt_empty']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# multiple strings (multi valued)
|
|
#multi_opt_empty =
|
|
''')),
|
|
('str_opt_sample_default',
|
|
dict(opts=[('test', [(None, [opts['str_opt_sample_default']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# a string (string value)
|
|
#str_opt = fooishbar
|
|
''')),
|
|
('multi_opt_sample_default',
|
|
dict(opts=[('test', [(None, [opts['multi_opt_sample_default']])])],
|
|
expected='''[DEFAULT]
|
|
|
|
#
|
|
# From test
|
|
#
|
|
|
|
# multiple strings (multi valued)
|
|
#multi_opt = 5
|
|
#multi_opt = 6
|
|
''')),
|
|
]
|
|
|
|
output_file_scenarios = [
|
|
('stdout',
|
|
dict(stdout=True, output_file=None)),
|
|
('output_file',
|
|
dict(output_file='sample.conf', stdout=False)),
|
|
]
|
|
|
|
@classmethod
|
|
def generate_scenarios(cls):
|
|
cls.scenarios = testscenarios.multiply_scenarios(
|
|
cls.content_scenarios,
|
|
cls.output_file_scenarios)
|
|
|
|
def setUp(self):
|
|
super(GeneratorTestCase, self).setUp()
|
|
|
|
self.conf = cfg.ConfigOpts()
|
|
self.config_fixture = config_fixture.Config(self.conf)
|
|
self.config = self.config_fixture.config
|
|
self.useFixture(self.config_fixture)
|
|
|
|
self.tempdir = self.useFixture(fixtures.TempDir())
|
|
|
|
def _capture_stream(self, stream_name):
|
|
self.useFixture(fixtures.MonkeyPatch("sys.%s" % stream_name,
|
|
moves.StringIO()))
|
|
return getattr(sys, stream_name)
|
|
|
|
def _capture_stdout(self):
|
|
return self._capture_stream('stdout')
|
|
|
|
@mock.patch('stevedore.named.NamedExtensionManager')
|
|
@mock.patch('oslo_config.generator.LOG')
|
|
def test_generate(self, mock_log, named_mgr):
|
|
generator.register_cli_opts(self.conf)
|
|
|
|
namespaces = [i[0] for i in self.opts]
|
|
self.config(namespace=namespaces)
|
|
|
|
wrap_width = getattr(self, 'wrap_width', None)
|
|
if wrap_width is not None:
|
|
self.config(wrap_width=wrap_width)
|
|
|
|
if self.stdout:
|
|
stdout = self._capture_stdout()
|
|
else:
|
|
output_file = self.tempdir.join(self.output_file)
|
|
self.config(output_file=output_file)
|
|
|
|
mock_eps = []
|
|
for name, opts in self.opts:
|
|
mock_ep = mock.Mock()
|
|
mock_ep.configure_mock(name=name, obj=opts)
|
|
mock_eps.append(mock_ep)
|
|
named_mgr.return_value = mock_eps
|
|
|
|
generator.generate(self.conf)
|
|
|
|
if self.stdout:
|
|
self.assertEqual(self.expected, stdout.getvalue())
|
|
else:
|
|
content = open(output_file).read()
|
|
self.assertEqual(self.expected, content)
|
|
|
|
named_mgr.assert_called_once_with('oslo.config.opts',
|
|
names=namespaces,
|
|
invoke_on_load=True)
|
|
|
|
log_warning = getattr(self, 'log_warning', None)
|
|
if log_warning is not None:
|
|
mock_log.warning.assert_called_once_with(*log_warning)
|
|
else:
|
|
self.assertFalse(mock_log.warning.called)
|
|
|
|
|
|
GeneratorTestCase.generate_scenarios()
|