Add deep merging when loading component configs

Change-Id: I05428668fefcb62462eccef945e2acc8efa784ff
This commit is contained in:
Yuriy Taraday 2016-10-05 16:22:30 +03:00
parent 5a9f70b83f
commit 7d818d2827
6 changed files with 50 additions and 47 deletions

View File

@ -24,8 +24,7 @@ def get_resource_path(path):
return pkg_resources.resource_filename(fuel_ccp.version_info.package, path)
def get_global_parameters(*config_groups):
cfg = {}
def get_config_paths():
components = list(CONF.repositories.names)
paths = []
# Order does matter. At first we add global defaults.
@ -37,30 +36,7 @@ def get_global_parameters(*config_groups):
paths.append(os.path.join(CONF.repositories.path, component,
"service/files/defaults.yaml"))
for path in paths:
if os.path.isfile(path):
LOG.debug("Adding parameters from \"%s\"", path)
with open(path, "r") as f:
data = yaml.load(f)
for group in config_groups:
cfg.setdefault(group, {})
cfg[group].update(data.get(group, {}))
else:
LOG.debug("\"%s\" not found, skipping", path)
for group in config_groups:
cfg.setdefault(group, {})
try:
config_group = CONF[group]
except KeyError:
continue
else:
cfg[group].update(config_group._items())
if 'configs' in cfg:
cfg['configs']['namespace'] = CONF.kubernetes.namespace
return cfg
return paths
def address(service):

View File

@ -100,10 +100,20 @@ def load_component_defaults():
from fuel_ccp.common import utils
sections = ['versions', 'sources', 'configs', 'nodes', 'roles', 'replicas']
gp = utils.get_global_parameters(*sections)
new_config = _yaml.AttrDict()
new_config._merge(gp)
new_config = _yaml.AttrDict((k, _yaml.AttrDict()) for k in sections)
for path in utils.get_config_paths():
if not os.path.exists(path):
LOG.debug("\"%s\" not found, skipping", path)
continue
LOG.debug("Adding parameters from \"%s\"", path)
with open(path) as f:
data = _yaml.load(f)
for section in sections:
if section in data:
new_config[section]._merge(data[section])
global _REAL_CONF
new_config['configs']['namespace'] = _REAL_CONF.kubernetes.namespace
new_config._merge(_REAL_CONF)
_REAL_CONF = new_config

View File

@ -1,4 +1,5 @@
import collections
import json
import os
import six
@ -67,6 +68,16 @@ class AttrDict(object):
other_value = AttrDict(other_value)
self._dict[key] = other_value
def _json(self, **kwargs):
return JSONEncoder(**kwargs).encode(self)
class JSONEncoder(json.JSONEncoder):
def default(self, obj):
if not isinstance(obj, AttrDict):
return super(self, JSONEncoder).default(obj)
return obj._dict
class Loader(yaml.SafeLoader):
pass

View File

@ -258,9 +258,7 @@ def _push_files_to_workflow(workflow, files):
def _create_globals_configmap(config):
data = {
templates.GLOBAL_CONFIG: json.dumps(config, sort_keys=True)
}
data = {templates.GLOBAL_CONFIG: config._json(sort_keys=True)}
cm = templates.serialize_configmap(templates.GLOBAL_CONFIG, data)
return kubernetes.process_object(cm)
@ -407,7 +405,7 @@ def deploy_components(components_map, components):
_create_namespace(CONF.configs)
_create_globals_configmap(CONF.configs._dict)
_create_globals_configmap(CONF.configs)
start_script_cm = _create_start_script_configmap()
configmaps = (start_script_cm,)

View File

@ -1,7 +1,6 @@
import os
from jinja2 import exceptions as jinja_exceptions
from mock import mock
import yaml
from fuel_ccp.common import utils
@ -11,9 +10,7 @@ from fuel_ccp.tests import base
class TestUtils(base.TestCase):
@mock.patch("fuel_ccp.common.utils.get_global_parameters")
def test_get_deploy_components_info_with_default_context(
self, get_global_parameters_mock):
def test_get_deploy_components_info_with_default_context(self):
default_params = {
"configs": {
@ -31,15 +28,16 @@ class TestUtils(base.TestCase):
}
}
get_global_parameters_mock.return_value = default_params
conf = config._yaml.AttrDict()
conf._merge(default_params)
conf._merge(config._REAL_CONF)
config._REAL_CONF = conf
base_dir = os.path.dirname(__file__)
self.conf.repositories.path = os.path.join(base_dir, "test_repo_dir")
self.conf.repositories.names = ["component"]
config.load_component_defaults()
res = (
utils.get_deploy_components_info()["keystone"]["service_content"]
)
@ -50,9 +48,7 @@ class TestUtils(base.TestCase):
self.assertDictEqual(expected, res)
@mock.patch("fuel_ccp.common.utils.get_global_parameters")
def test_get_deploy_components_info_with_custom_context(
self, get_global_parameters_mock):
def test_get_deploy_components_info_with_custom_context(self):
custom_params = {
"configs": {
@ -70,6 +66,10 @@ class TestUtils(base.TestCase):
}
}
conf = config._yaml.AttrDict()
conf._merge(custom_params)
conf._merge(config._REAL_CONF)
config._REAL_CONF = conf
base_dir = os.path.dirname(__file__)
self.conf.repositories.path = os.path.join(base_dir, "test_repo_dir")
@ -87,9 +87,7 @@ class TestUtils(base.TestCase):
self.assertDictEqual(expected, res)
@mock.patch("fuel_ccp.common.utils.get_global_parameters")
def test_get_deploy_components_info_with_not_enough_context(
self, get_global_parameters_mock):
def test_get_deploy_components_info_with_not_enough_context(self):
default_params = {
"configs": {
@ -105,7 +103,10 @@ class TestUtils(base.TestCase):
}
}
get_global_parameters_mock.return_value = default_params
conf = config._yaml.AttrDict()
conf._merge(default_params)
conf._merge(config._REAL_CONF)
config._REAL_CONF = conf
base_dir = os.path.dirname(__file__)

View File

@ -130,3 +130,10 @@ class TestLoadDump(testscenarios.WithScenarios, base.TestCase):
stream = io.StringIO()
_yaml.dump(obj, stream)
self.assertEqual(self.yaml, stream.getvalue())
class TestAttrDict(base.TestCase):
def test_json(self):
source = _yaml.AttrDict({'a': 1, 'b': _yaml.AttrDict({'c': 2})})
res = source._json(sort_keys=True)
self.assertEqual(res, '{"a": 1, "b": {"c": 2}}')