From 1ab3eabd4f17ffa3cb47315893a27331a2722a05 Mon Sep 17 00:00:00 2001 From: Hieu LE Date: Wed, 17 Aug 2016 10:14:34 +0700 Subject: [PATCH] Init magnum centralize config Initialize magnum centralize config folder and test cases. Change-Id: Ib68e54701e127546fbaa91e3633f50d149a5b878 Implements: blueprint centralize-config-magnum --- etc/magnum/magnum-config-generator.conf | 1 + magnum/conf/__init__.py | 52 ++++++++++++++++ magnum/conf/opts.py | 79 +++++++++++++++++++++++++ magnum/tests/unit/conf/__init__.py | 0 magnum/tests/unit/conf/test_conf.py | 66 +++++++++++++++++++++ setup.cfg | 1 + 6 files changed, 199 insertions(+) create mode 100644 magnum/conf/__init__.py create mode 100644 magnum/conf/opts.py create mode 100644 magnum/tests/unit/conf/__init__.py create mode 100644 magnum/tests/unit/conf/test_conf.py diff --git a/etc/magnum/magnum-config-generator.conf b/etc/magnum/magnum-config-generator.conf index 59165b2463..a2514810a5 100644 --- a/etc/magnum/magnum-config-generator.conf +++ b/etc/magnum/magnum-config-generator.conf @@ -3,6 +3,7 @@ output_file = etc/magnum/magnum.conf.sample wrap_width = 79 namespace = magnum +namespace = magnum.conf namespace = oslo.concurrency namespace = oslo.db namespace = oslo.log diff --git a/magnum/conf/__init__.py b/magnum/conf/__init__.py new file mode 100644 index 0000000000..07a831e803 --- /dev/null +++ b/magnum/conf/__init__.py @@ -0,0 +1,52 @@ +# Copyright 2016 Fujitsu Ltd. +# All Rights Reserved. +# +# 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 + +# from magnum.conf import api +# from magnum.conf import barbican +# from magnum.conf import certificates +# from magnum.conf import cinder +# from magnum.conf import cluster +# from magnum.conf import cluster_templates +# from magnum.conf import conductor +# from magnum.conf import database +# from magnum.conf import docker +# from magnum.conf import glance +# from magnum.conf import heat +# from magnum.conf import keystone +# from magnum.conf import magnum_client +# from magnum.conf import neutron +# from magnum.conf import nova +# from magnum.conf import x509 + +CONF = cfg.CONF + +# api.register_opts(CONF) +# barbican.register_opts(CONF) +# cluster.register_opts(CONF) +# cluster_templates.register_opts(CONF) +# certificates.register_opts(CONF) +# cinder.register_opts(CONF) +# conductor.register_opts(CONF) +# database.register_opts(CONF) +# docker.register_opts(CONF) +# glance.register_opts(CONF) +# heat.register_opts(CONF) +# keystone.register_opts(CONF) +# magnum_client.register_opts(CONF) +# neutron.register_opts(CONF) +# nova.register_opts(CONF) +# x509.register_opts(CONF) diff --git a/magnum/conf/opts.py b/magnum/conf/opts.py new file mode 100644 index 0000000000..64e6da1549 --- /dev/null +++ b/magnum/conf/opts.py @@ -0,0 +1,79 @@ +# Copyright 2015 OpenStack Foundation +# All Rights Reserved. +# +# 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. + +""" +This is the single point of entry to generate the sample configuration +file for Magnum. It collects all the necessary info from the other modules +in this package. It is assumed that: + +* every other module in this package has a 'list_opts' function which + return a dict where + * the keys are strings which are the group names + * the value of each key is a list of config options for that group +* the magnum.conf package doesn't have further packages with config options +* this module is only used in the context of sample file generation +""" + +import collections +import importlib +import os +import pkgutil + +LIST_OPTS_FUNC_NAME = "list_opts" + + +def _tupleize(dct): + """Take the dict of options and convert to the 2-tuple format.""" + return [(key, val) for key, val in dct.items()] + + +def list_opts(): + opts = collections.defaultdict(list) + module_names = _list_module_names() + imported_modules = _import_modules(module_names) + _append_config_options(imported_modules, opts) + return _tupleize(opts) + + +def _list_module_names(): + module_names = [] + package_path = os.path.dirname(os.path.abspath(__file__)) + for _, modname, ispkg in pkgutil.iter_modules(path=[package_path]): + if modname == "opts" or ispkg: + continue + else: + module_names.append(modname) + return module_names + + +def _import_modules(module_names): + imported_modules = [] + for modname in module_names: + mod = importlib.import_module("magnum.conf." + modname) + if not hasattr(mod, LIST_OPTS_FUNC_NAME): + msg = "The module 'magnum.conf.%s' should have a '%s' "\ + "function which returns the config options." % \ + (modname, LIST_OPTS_FUNC_NAME) + raise AttributeError(msg) + else: + imported_modules.append(mod) + return imported_modules + + +def _append_config_options(imported_modules, config_options): + for mod in imported_modules: + configs = mod.list_opts() + for key, val in configs.items(): + config_options[key].extend(val) diff --git a/magnum/tests/unit/conf/__init__.py b/magnum/tests/unit/conf/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/magnum/tests/unit/conf/test_conf.py b/magnum/tests/unit/conf/test_conf.py new file mode 100644 index 0000000000..bfe64e518c --- /dev/null +++ b/magnum/tests/unit/conf/test_conf.py @@ -0,0 +1,66 @@ +# Copyright 2016 Fujitsu Ltd. +# +# 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 collections +import mock +from oslo_config import cfg + +from magnum.conf import opts +from magnum.tests import base + + +class ConfTestCase(base.TestCase): + + def test_list_opts(self): + for group, opt_list in opts.list_opts(): + self.assertIsInstance(group, cfg.OptGroup) + for opt in opt_list: + self.assertIsInstance(opt, cfg.Opt) + + def test_list_module_name_invalid_mods(self): + with mock.patch('pkgutil.iter_modules') as mock_mods: + mock_mods.return_value = [(None, 'foo', True), + (None, 'opts', False)] + self.assertEqual([], opts._list_module_names()) + + def test_list_module_name_valid_mods(self): + with mock.patch('pkgutil.iter_modules') as mock_mods: + mock_mods.return_value = [(None, 'foo', False)] + self.assertEqual(['foo'], opts._list_module_names()) + + def test_import_mods_no_func(self): + modules = ['foo', 'bar'] + with mock.patch('importlib.import_module') as mock_import: + mock_import.return_value = mock.sentinel.mods + self.assertRaises(AttributeError, opts._import_modules, modules) + mock_import.assert_called_once_with('magnum.conf.foo') + + def test_import_mods_valid_func(self): + modules = ['foo', 'bar'] + with mock.patch('importlib.import_module') as mock_import: + mock_mod = mock.MagicMock() + mock_import.return_value = mock_mod + self.assertEqual([mock_mod, mock_mod], + opts._import_modules(modules)) + mock_import.assert_has_calls([mock.call('magnum.conf.foo'), + mock.call('magnum.conf.bar')]) + + def test_append_config(self): + opt = collections.defaultdict(list) + mock_module = mock.MagicMock() + mock_conf = mock.MagicMock() + mock_module.list_opts.return_value = mock_conf + mock_conf.items.return_value = [('foo', 'bar')] + opts._append_config_options([mock_module], opt) + self.assertEqual({'foo': ['b', 'a', 'r']}, opt) diff --git a/setup.cfg b/setup.cfg index 0ccf500617..84132e8470 100644 --- a/setup.cfg +++ b/setup.cfg @@ -53,6 +53,7 @@ console_scripts = oslo.config.opts = magnum = magnum.opts:list_opts + magnum.conf = magnum.conf.opts:list_opts oslo.config.opts.defaults = magnum = magnum.common.config:set_cors_middleware_defaults