Configs overrides for custom services

"configs" section added to "services" group.

services:
  some_service:
    service_def: ads
    configs:
      asd: dsa

If you are mapping some service to some another service,
configs will be inherited as well.

Change-Id: Id64c0bf816a639c0b3dee96e5a72fcf964f9f731
This commit is contained in:
Andrey Pavlov 2017-02-17 16:14:19 +04:00
parent 9942c0e978
commit ccaadd5e0b
7 changed files with 46 additions and 49 deletions

View File

@ -1,3 +1,4 @@
import copy
import itertools
import logging
import os
@ -181,9 +182,17 @@ def process_dependencies(service, deps_map, services_map):
cmd['dependencies'] = new_deps
def get_deploy_components_info(rendering_context=None):
if rendering_context is None:
rendering_context = CONF.configs._dict
def extend_with_service_configs(service_name, config):
service = CONF.services.get(service_name, {})
config._merge(service.get('configs', {}))
service_mapping = service.get('mapping')
if service_mapping:
for _, target_service in service_mapping._items():
extend_with_service_configs(target_service, config)
def get_deploy_components_info():
rendering_context = CONF.configs
service_definitions_map = get_service_definitions_map()
services_map = {}
custom_services_map = {}
@ -215,8 +224,8 @@ def get_deploy_components_info(rendering_context=None):
if service_file.endswith('.yaml'):
LOG.debug("Rendering service definition: %s", service_file)
content = jinja_utils.jinja_render(
os.path.join(service_dir, service_file), rendering_context,
functions=[address]
os.path.join(service_dir, service_file),
rendering_context._dict, functions=[address]
)
LOG.debug("Parse service definition: %s", service_file)
service_definition = yaml.load(content)
@ -230,11 +239,12 @@ def get_deploy_components_info(rendering_context=None):
for svc in service_definitions_map.get(service_name, ()):
LOG.debug("Rendering service definition: %s for '%s' "
"service", service_file, svc)
context = rendering_context.copy()
context = copy.deepcopy(rendering_context)
context['_current_service'] = svc
extend_with_service_configs(svc, context)
content = jinja_utils.jinja_render(
os.path.join(service_dir, service_file),
context, functions=[address]
context._dict, functions=[address]
)
LOG.debug("Parse service definition: %s for '%s' "
"service", service_file, svc)

View File

@ -19,7 +19,7 @@ class AttrDict(object):
def __getattr__(self, name):
try:
return self._dict[name]
return object.__getattribute__(self, '_dict')[name]
except KeyError:
raise AttributeError(name)

View File

@ -8,6 +8,7 @@ SCHEMA = {
"properties": {
"service_def": {"type": "string"},
"mapping": {"type": "object"},
"configs": {"type": "object"},
}
}
}

View File

@ -109,6 +109,7 @@ def parse_role(component, topology, configmaps):
process_files(files, service_dir)
files_cm = _create_files_configmap(service_name, files, files_header)
meta_cm = _create_meta_configmap(service)
_create_service_configmap(service_name)
yield _process_secrets(role.get("secrets"))
@ -354,6 +355,15 @@ def _create_nodes_configmap(nodes):
return kubernetes.process_object(cm)
def _create_service_configmap(service_name):
configmap_name = "%s-%s" % (service_name, templates.SERVICE_CONFIG)
config = _yaml.AttrDict()
utils.extend_with_service_configs(service_name, config)
data = {templates.SERVICE_CONFIG: config._json()}
template = templates.serialize_configmap(configmap_name, data)
return kubernetes.process_object(template)
def get_start_script():
start_scr_path = os.path.join(CONF.repositories.path,
CONF.repositories.entrypoint_repo_name,

View File

@ -10,6 +10,7 @@ CONF = config.CONF
GLOBAL_CONFIG = "globals"
NODES_CONFIG = "nodes-config"
SERVICE_CONFIG = "service-config"
SCRIPT_CONFIG = "start-script"
FILES_CONFIG = "files"
META_CONFIG = "meta"
@ -83,6 +84,10 @@ def serialize_volume_mounts(container, for_job=None):
{
"name": NODES_CONFIG,
"mountPath": "/etc/ccp/%s" % NODES_CONFIG
},
{
"name": SERVICE_CONFIG,
"mountPath": "/etc/ccp/%s" % SERVICE_CONFIG
}
]
for v in itertools.chain(container.get("volumes", ()),
@ -319,10 +324,18 @@ def serialize_volumes(service, for_job=None):
"items": [{"key": NODES_CONFIG,
"path": "nodes-config.json"}]
}
},
{
"name": SERVICE_CONFIG,
"configMap": {
"name": "%s-%s" % (service["name"], SERVICE_CONFIG),
"items": [{"key": SERVICE_CONFIG,
"path": "%s.json" % SERVICE_CONFIG}]
}
}
]
volume_names = [GLOBAL_CONFIG, META_CONFIG, ROLE_CONFIG, SCRIPT_CONFIG,
FILES_CONFIG, EXPORTS_CONFIG, NODES_CONFIG]
FILES_CONFIG, EXPORTS_CONFIG, NODES_CONFIG, SERVICE_CONFIG]
for cont in itertools.chain(service["containers"], [for_job]):
for v in cont.get("volumes", ()):
if v["name"] in volume_names:

View File

@ -49,45 +49,6 @@ class TestUtils(base.TestCase):
self.assertDictEqual(expected, res)
def test_get_deploy_components_info_with_custom_context(self):
custom_params = {
"configs": {
"service_name": "keystone",
"db_root_password": "db_root_password_custom",
"keystone_db_name": "keystone_db_name_custom",
"keystone_db_username": "keystone_db_username_custom",
"keystone_db_password": "keystone_db_password_custom",
"openstack_user_password": "os_user_password_custom",
"openstack_user_name": "os_user_name_custom",
"openstack_project_name": "os_project_name_custom",
"openstack_role_name": "os_role_name_custom",
"keystone_admin_port": "keystone_admin_port_custom",
"keystone_public_port": "keystone_public_port_custom"
}
}
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")
self.conf.repositories.repos = [{"name": "component"}]
config.load_component_defaults()
res = utils.get_deploy_components_info(
rendering_context=custom_params["configs"]
)["keystone"]["service_content"]
with open(os.path.join(base_dir,
"service-rendered-example-custom.yaml")) as f:
expected = yaml.load(f)
self.assertDictEqual(expected, res)
def test_get_deploy_components_info_with_not_enough_context(self):
default_params = {

View File

@ -51,7 +51,9 @@ class TestDeploy(base.TestCase):
'name': 'start-script'},
{'mountPath': '/etc/ccp/exports', 'name': 'exports'},
{'mountPath': '/etc/ccp/files', 'name': 'files'},
{'mountPath': '/etc/ccp/nodes-config', 'name': 'nodes-config'}
{'mountPath': '/etc/ccp/nodes-config', 'name': 'nodes-config'},
{'mountPath': '/etc/ccp/service-config',
'name': 'service-config'}
],
"readinessProbe": {
"exec": {