Handle nodes configs and merge them with globals

Get nodes configs map, check for existing configs for
current node, and if it is, merge it with globals config - variables
for further using in jinja and so on.

Change-Id: I379f4840e6093b7910b5d7dd612de62b1fe0ac2e
Depends-on: I4de6a0fad94d5f83ca486c952d80d1c87c880c0e
Related-bug: #1653077
This commit is contained in:
Peter Razumovsky 2017-01-23 15:52:27 +04:00
parent ff6efca2c8
commit 0feaf3e1c2
2 changed files with 101 additions and 3 deletions

View File

@ -6,6 +6,7 @@ import functools
import logging
import os
import pwd
import re
import signal
import socket
import subprocess
@ -23,6 +24,7 @@ import six
VARIABLES = {}
GLOBALS_PATH = '/etc/ccp/globals/globals.json'
NODES_CONFIG_PATH = '/etc/ccp/nodes-config/nodes-config.json'
META_FILE = "/etc/ccp/meta/meta.json"
WORKFLOW_PATH_TEMPLATE = '/etc/ccp/role/%s.json'
FILES_DIR = '/etc/ccp/files'
@ -446,10 +448,43 @@ def get_workflow(role_name):
return workflow
def find_node_config_keys(nodes_config):
current_node = os.environ['CCP_NODE_NAME']
config_keys = []
for node in sorted(nodes_config):
if re.match(node, current_node):
config_keys.append(node)
return config_keys
def merge_nodes_configs(variables, node_config):
for k, v in node_config.items():
if k not in variables:
variables[k] = v
continue
if isinstance(v, dict) and isinstance(variables[k], dict):
merge_nodes_configs(variables[k], v)
else:
variables[k] = v
def get_variables(role_name):
LOG.info("Getting global variables from %s", GLOBALS_PATH)
with open(GLOBALS_PATH) as f:
variables = json.load(f)
LOG.info("Getting nodes variables from %s", NODES_CONFIG_PATH)
with open(NODES_CONFIG_PATH) as f:
nodes_config = json.load(f)
config_keys = find_node_config_keys(nodes_config)
if config_keys:
# merge configs for all keys and get final node_configs for this node.
# Note that if there several override configs, variables will be
# override with order of list this configs.
node_config = nodes_config[config_keys.pop(0)]
for key in config_keys:
merge_nodes_configs(node_config, nodes_config[key])
# and then merge variables with final node_config.
merge_nodes_configs(variables, node_config)
if os.path.exists(META_FILE):
LOG.info("Getting meta information from %s", META_FILE)
with open(META_FILE) as f:

View File

@ -85,9 +85,7 @@ class TestGetVariables(base.TestCase):
@mock.patch('json.load')
@mock.patch('fuel_ccp_entrypoint.start_script.create_network_topology')
def test_get_variables(self, m_create_network_topology, m_json_load):
def side_effect(file_name):
return {'glob': 'glob_val'}
m_json_load.return_value = {'glob': 'glob_val'}
m_json_load.side_effect = [{'glob': 'glob_val'}, {}]
m_create_network_topology.return_value = 'network_topology'
r_value = start_script.get_variables('role')
e_value = {
@ -99,6 +97,71 @@ class TestGetVariables(base.TestCase):
}
self.assertEqual(r_value, e_value)
@mock.patch('six.moves.builtins.open', mock.mock_open())
@mock.patch('json.load')
@mock.patch('fuel_ccp_entrypoint.start_script.create_network_topology')
def test_get_variables_with_node_config(self, m_create_network_topology,
m_json_load):
m_json_load.side_effect = [
# globals
{
'a': {
'b': {
'c': ['d', 'e', 'f'],
'g': 'h',
},
'i': ['j', 'k'],
'l': 'm'
},
'n': ['o', 'p', 'q'],
'r': 's'
},
# nodes configs
{
'node[1-3]': {
'a': {
'b': {
'c': ['e', 'f', 't'],
'u': 'v'
},
'w': {
'x': 'y'
}
},
'n': ['o', 'p'],
'z': 'NaN'
},
'node[1-2]': {
'aa': {'ab': 'ac'},
'r': {'ad': ['ae', 'af', 'ag']}
}
}
]
m_create_network_topology.return_value = 'network_topology'
actual = start_script.get_variables('fake_role')
expected = {
'role_name': 'fake_role',
'network_topology': 'network_topology',
'node_name': 'node1',
'pod_name': 'pod1',
'a': {
'b': {
'c': ['e', 'f', 't'],
'g': 'h',
'u': 'v'
},
'w': {'x': 'y'},
'i': ['j', 'k'],
'l': 'm'
},
'n': ['o', 'p'],
'r': {'ad': ['ae', 'af', 'ag']},
'z': 'NaN',
'aa': {'ab': 'ac'},
}
self.assertEqual(expected, actual)
class TestRetry(base.TestCase):
def setUp(self):