Fixes ordering of environment files in a deployment plan
Sometimes making changes in basic deployment breaks the order of passed env files and leads to a failed deployment. This patch orders the environment files according to the rules defined in the capabilities-map.yaml file. Change-Id: Idbb6f0f3adebebd429bcb3447e559838180f4b1c
This commit is contained in:
parent
527b32534a
commit
bae4296502
|
@ -193,6 +193,23 @@ class UpdateCapabilitiesAction(base.TripleOAction):
|
||||||
|
|
||||||
self.cache_delete(context, self.container, "tripleo.parameters.get")
|
self.cache_delete(context, self.container, "tripleo.parameters.get")
|
||||||
|
|
||||||
|
# get the capabilities-map content to perform the environment ordering
|
||||||
|
try:
|
||||||
|
swift = self.get_object_client(context)
|
||||||
|
map_file = swift.get_object(
|
||||||
|
self.container, 'capabilities-map.yaml')
|
||||||
|
capabilities = yaml.safe_load(map_file[1])
|
||||||
|
except swiftexceptions.ClientException as err:
|
||||||
|
err_msg = ("Error retrieving capabilities-map.yaml for "
|
||||||
|
"plan %s: %s" % (self.container, err))
|
||||||
|
LOG.exception(err_msg)
|
||||||
|
return actions.Result(error=err_msg)
|
||||||
|
|
||||||
|
ordered_env = plan_utils.apply_environments_order(
|
||||||
|
capabilities, env.get('environments', []))
|
||||||
|
|
||||||
|
env['environments'] = ordered_env
|
||||||
|
|
||||||
try:
|
try:
|
||||||
plan_utils.put_env(swift, env)
|
plan_utils.put_env(swift, env)
|
||||||
except swiftexceptions.ClientException as err:
|
except swiftexceptions.ClientException as err:
|
||||||
|
|
|
@ -246,7 +246,9 @@ class UpdateCapabilitiesActionTest(base.TestCase):
|
||||||
- path: /path/to/overcloud-default-env.yaml
|
- path: /path/to/overcloud-default-env.yaml
|
||||||
- path: /path/to/ceph-storage-env.yaml
|
- path: /path/to/ceph-storage-env.yaml
|
||||||
"""
|
"""
|
||||||
swift.get_object.return_value = ({}, mocked_env)
|
swift.get_object.side_effect = (
|
||||||
|
({}, mocked_env),
|
||||||
|
({}, MAPPING_YAML_CONTENTS))
|
||||||
get_object_client_mock.return_value = swift
|
get_object_client_mock.return_value = swift
|
||||||
|
|
||||||
environments = {
|
environments = {
|
||||||
|
@ -287,7 +289,9 @@ class UpdateCapabilitiesActionTest(base.TestCase):
|
||||||
- path: /path/to/overcloud-default-env.yaml
|
- path: /path/to/overcloud-default-env.yaml
|
||||||
- path: /path/to/ceph-storage-env.yaml
|
- path: /path/to/ceph-storage-env.yaml
|
||||||
"""
|
"""
|
||||||
swift.get_object.return_value = ({}, mocked_env)
|
swift.get_object.side_effect = (
|
||||||
|
({}, mocked_env),
|
||||||
|
({}, MAPPING_YAML_CONTENTS))
|
||||||
get_object_client_mock.return_value = swift
|
get_object_client_mock.return_value = swift
|
||||||
|
|
||||||
environments = {
|
environments = {
|
||||||
|
|
|
@ -44,6 +44,36 @@ resource_registry:
|
||||||
OS::TripleO::Foo: bar.yaml
|
OS::TripleO::Foo: bar.yaml
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
UNORDERED_PLAN_ENV_LIST = [
|
||||||
|
{'path': 'overcloud-resource-registry-puppet.yaml'},
|
||||||
|
{'path': 'environments/docker-ha.yaml'},
|
||||||
|
{'path': 'environments/containers-default-parameters.yaml'},
|
||||||
|
{'path': 'environments/docker.yaml'}
|
||||||
|
]
|
||||||
|
|
||||||
|
CAPABILITIES_DICT = {
|
||||||
|
'topics': [{
|
||||||
|
'environment_groups': [{
|
||||||
|
'environments': [{
|
||||||
|
'file': 'overcloud-resource-registry-puppet.yaml'}
|
||||||
|
]}, {
|
||||||
|
'environments': [{
|
||||||
|
'file': 'environments/docker.yaml',
|
||||||
|
'requires': ['overcloud-resource-registry-puppet.yaml']
|
||||||
|
}, {
|
||||||
|
'file': 'environments/containers-default-parameters.yaml',
|
||||||
|
'requires': ['overcloud-resource-registry-puppet.yaml',
|
||||||
|
'environments/docker.yaml']
|
||||||
|
}]}, {
|
||||||
|
'environments': [{
|
||||||
|
'file': 'environments/docker-ha.yaml',
|
||||||
|
'requires': ['overcloud-resource-registry-puppet.yaml',
|
||||||
|
'environments/docker.yaml']
|
||||||
|
}]}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class PlanTest(base.TestCase):
|
class PlanTest(base.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -247,3 +277,15 @@ class PlanTest(base.TestCase):
|
||||||
|
|
||||||
for path in temp_env_paths:
|
for path in temp_env_paths:
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
|
|
||||||
|
def test_apply_env_order(self):
|
||||||
|
ordered_plan_env_list = [
|
||||||
|
{'path': 'overcloud-resource-registry-puppet.yaml'},
|
||||||
|
{'path': 'environments/docker.yaml'},
|
||||||
|
{'path': 'environments/docker-ha.yaml'},
|
||||||
|
{'path': 'environments/containers-default-parameters.yaml'}
|
||||||
|
]
|
||||||
|
|
||||||
|
ordered_env = plan_utils.apply_environments_order(
|
||||||
|
CAPABILITIES_DICT, UNORDERED_PLAN_ENV_LIST)
|
||||||
|
self.assertEqual(ordered_env, ordered_plan_env_list)
|
||||||
|
|
|
@ -160,3 +160,42 @@ def build_env_paths(swift, container, plan_env):
|
||||||
|
|
||||||
env_paths.extend(temp_env_paths)
|
env_paths.extend(temp_env_paths)
|
||||||
return env_paths, temp_env_paths
|
return env_paths, temp_env_paths
|
||||||
|
|
||||||
|
|
||||||
|
def apply_environments_order(capabilities, environments):
|
||||||
|
"""traverses the capabilities and orders the environment files
|
||||||
|
|
||||||
|
by dependency rules defined in capabilities-map, so that parent
|
||||||
|
environments are first and children environments override these
|
||||||
|
parents
|
||||||
|
|
||||||
|
:param capabilities: dict representing capabilities-map.yaml file
|
||||||
|
:param environments: list representing the environments section of the
|
||||||
|
plan-environments.yaml file
|
||||||
|
:return: list containing ordered environments
|
||||||
|
|
||||||
|
"""
|
||||||
|
# get ordering rules from capabilities-map file
|
||||||
|
order_rules = {}
|
||||||
|
for topic in capabilities.get('topics', []):
|
||||||
|
for group in topic.get('environment_groups', []):
|
||||||
|
for environment in group.get('environments', []):
|
||||||
|
order_rules[environment['file']] = []
|
||||||
|
if 'requires' in environment:
|
||||||
|
order_rules[environment['file']] \
|
||||||
|
= environment.get('requires', [])
|
||||||
|
|
||||||
|
# apply ordering rules
|
||||||
|
for e in environments:
|
||||||
|
path = e.get('path', '')
|
||||||
|
if path not in order_rules:
|
||||||
|
continue
|
||||||
|
path_pos = environments.index(e)
|
||||||
|
for requirement in order_rules[path]:
|
||||||
|
if {'path': requirement} in environments:
|
||||||
|
requirement_pos = environments.index({'path': requirement})
|
||||||
|
if requirement_pos > path_pos:
|
||||||
|
item = environments.pop(requirement_pos)
|
||||||
|
environments.insert(path_pos, item)
|
||||||
|
|
||||||
|
return environments
|
||||||
|
|
Loading…
Reference in New Issue