Use Swift to store Plan environment
Start using the plan environment file in Swift for plan environment storage instead of Mistral. Add util functions to get/update environment data. Remove CreatePlanAction and UpdatePlanAction as all they did was sync between Mistral and Swift environments. Amend the corresponding workflows to account for removal of these actions. Implements: blueprint stop-using-mistral-env Co-Authored-By: Julie Pichon <jpichon@redhat.com> Depends-On: I3bcef27413e685c498165b43a8b59c8c9cc5cf5e Change-Id: Ieedecf92113142e43925131dcbccc4c0cd5b1a18
This commit is contained in:
parent
1c162d61e2
commit
bd4e26e823
|
@ -0,0 +1,6 @@
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
The environment configuration for deployments is now stored in a
|
||||||
|
file called ``plan-environment.yaml`` and stored in Swift with the
|
||||||
|
templates; Mistral is no longer used to store this data. Migration
|
||||||
|
of the existing plans is handled automatically.
|
|
@ -87,8 +87,6 @@ mistral.actions =
|
||||||
tripleo.parameters.generate_passwords = tripleo_common.actions.parameters:GeneratePasswordsAction
|
tripleo.parameters.generate_passwords = tripleo_common.actions.parameters:GeneratePasswordsAction
|
||||||
tripleo.parameters.get_passwords = tripleo_common.actions.parameters:GetPasswordsAction
|
tripleo.parameters.get_passwords = tripleo_common.actions.parameters:GetPasswordsAction
|
||||||
tripleo.parameters.generate_fencing = tripleo_common.actions.parameters:GenerateFencingParametersAction
|
tripleo.parameters.generate_fencing = tripleo_common.actions.parameters:GenerateFencingParametersAction
|
||||||
tripleo.plan.create = tripleo_common.actions.plan:CreatePlanAction
|
|
||||||
tripleo.plan.update = tripleo_common.actions.plan:UpdatePlanAction
|
|
||||||
tripleo.plan.create_container = tripleo_common.actions.plan:CreateContainerAction
|
tripleo.plan.create_container = tripleo_common.actions.plan:CreateContainerAction
|
||||||
tripleo.plan.delete = tripleo_common.actions.plan:DeletePlanAction
|
tripleo.plan.delete = tripleo_common.actions.plan:DeletePlanAction
|
||||||
tripleo.plan.list = tripleo_common.actions.plan:ListPlansAction
|
tripleo.plan.list = tripleo_common.actions.plan:ListPlansAction
|
||||||
|
@ -111,3 +109,4 @@ mistral.actions =
|
||||||
tripleo.validations.verify_profiles = tripleo_common.actions.validations:VerifyProfilesAction
|
tripleo.validations.verify_profiles = tripleo_common.actions.validations:VerifyProfilesAction
|
||||||
# deprecated for pike release, will be removed in queens
|
# deprecated for pike release, will be removed in queens
|
||||||
tripleo.templates.upload_default = tripleo_common.actions.templates:UploadTemplatesAction
|
tripleo.templates.upload_default = tripleo_common.actions.templates:UploadTemplatesAction
|
||||||
|
tripleo.plan.migrate = tripleo_common.actions.plan:MigratePlanAction
|
||||||
|
|
|
@ -19,13 +19,13 @@ import time
|
||||||
from heatclient.common import deployment_utils
|
from heatclient.common import deployment_utils
|
||||||
from heatclient import exc as heat_exc
|
from heatclient import exc as heat_exc
|
||||||
from mistral.workflow import utils as mistral_workflow_utils
|
from mistral.workflow import utils as mistral_workflow_utils
|
||||||
from mistralclient.api import base as mistralclient_exc
|
|
||||||
from swiftclient import exceptions as swiftexceptions
|
from swiftclient import exceptions as swiftexceptions
|
||||||
|
|
||||||
from tripleo_common.actions import base
|
from tripleo_common.actions import base
|
||||||
from tripleo_common.actions import templates
|
from tripleo_common.actions import templates
|
||||||
from tripleo_common import constants
|
from tripleo_common import constants
|
||||||
from tripleo_common.utils import overcloudrc
|
from tripleo_common.utils import overcloudrc
|
||||||
|
from tripleo_common.utils import plan as plan_utils
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -145,8 +145,7 @@ class DeployStackAction(templates.ProcessTemplatesAction):
|
||||||
stack_is_new = stack is None
|
stack_is_new = stack is None
|
||||||
|
|
||||||
# update StackAction, DeployIdentifier and UpdateIdentifier
|
# update StackAction, DeployIdentifier and UpdateIdentifier
|
||||||
wc = self.get_workflow_client(context)
|
swift = self.get_object_client(context)
|
||||||
wf_env = wc.environments.get(self.container)
|
|
||||||
|
|
||||||
parameters = dict()
|
parameters = dict()
|
||||||
if not self.skip_deploy_identifier:
|
if not self.skip_deploy_identifier:
|
||||||
|
@ -154,15 +153,22 @@ class DeployStackAction(templates.ProcessTemplatesAction):
|
||||||
parameters['UpdateIdentifier'] = ''
|
parameters['UpdateIdentifier'] = ''
|
||||||
parameters['StackAction'] = 'CREATE' if stack_is_new else 'UPDATE'
|
parameters['StackAction'] = 'CREATE' if stack_is_new else 'UPDATE'
|
||||||
|
|
||||||
if 'parameter_defaults' not in wf_env.variables:
|
try:
|
||||||
wf_env.variables['parameter_defaults'] = {}
|
env = plan_utils.get_env(swift, self.container)
|
||||||
wf_env.variables['parameter_defaults'].update(parameters)
|
except swiftexceptions.ClientException as err:
|
||||||
env_kwargs = {
|
err_msg = ("Error retrieving environment for plan %s: %s" % (
|
||||||
'name': wf_env.name,
|
self.container, err))
|
||||||
'variables': wf_env.variables,
|
LOG.exception(err_msg)
|
||||||
}
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
# store params changes back to db before call to process templates
|
|
||||||
wc.environments.update(**env_kwargs)
|
try:
|
||||||
|
plan_utils.update_in_env(swift, env, 'parameter_defaults',
|
||||||
|
parameters)
|
||||||
|
except swiftexceptions.ClientException as err:
|
||||||
|
err_msg = ("Error updating environment for plan %s: %s" % (
|
||||||
|
self.container, err))
|
||||||
|
LOG.exception(err_msg)
|
||||||
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
# process all plan files and create or update a stack
|
# process all plan files and create or update a stack
|
||||||
processed_data = super(DeployStackAction, self).run(context)
|
processed_data = super(DeployStackAction, self).run(context)
|
||||||
|
@ -176,13 +182,12 @@ class DeployStackAction(templates.ProcessTemplatesAction):
|
||||||
stack_args['timeout_mins'] = self.timeout_mins
|
stack_args['timeout_mins'] = self.timeout_mins
|
||||||
|
|
||||||
if stack_is_new:
|
if stack_is_new:
|
||||||
swift_client = self.get_object_client(context)
|
|
||||||
try:
|
try:
|
||||||
swift_client.copy_object(
|
swift.copy_object(
|
||||||
"%s-swift-rings" % self.container, "swift-rings.tar.gz",
|
"%s-swift-rings" % self.container, "swift-rings.tar.gz",
|
||||||
"%s-swift-rings/%s-%d" % (
|
"%s-swift-rings/%s-%d" % (
|
||||||
self.container, "swift-rings.tar.gz", time.time()))
|
self.container, "swift-rings.tar.gz", time.time()))
|
||||||
swift_client.delete_object(
|
swift.delete_object(
|
||||||
"%s-swift-rings" % self.container, "swift-rings.tar.gz")
|
"%s-swift-rings" % self.container, "swift-rings.tar.gz")
|
||||||
except swiftexceptions.ClientException:
|
except swiftexceptions.ClientException:
|
||||||
pass
|
pass
|
||||||
|
@ -211,7 +216,7 @@ class OvercloudRcAction(base.TripleOAction):
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
orchestration_client = self.get_orchestration_client(context)
|
orchestration_client = self.get_orchestration_client(context)
|
||||||
workflow_client = self.get_workflow_client(context)
|
swift = self.get_object_client(context)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
stack = orchestration_client.stacks.get(self.container)
|
stack = orchestration_client.stacks.get(self.container)
|
||||||
|
@ -221,26 +226,27 @@ class OvercloudRcAction(base.TripleOAction):
|
||||||
"deployed before calling this action.").format(self.container)
|
"deployed before calling this action.").format(self.container)
|
||||||
return mistral_workflow_utils.Result(error=error)
|
return mistral_workflow_utils.Result(error=error)
|
||||||
|
|
||||||
try:
|
|
||||||
environment = workflow_client.environments.get(self.container)
|
|
||||||
except mistralclient_exc.APIException:
|
|
||||||
error = "The Mistral environment {} could not be found.".format(
|
|
||||||
self.container)
|
|
||||||
return mistral_workflow_utils.Result(error=error)
|
|
||||||
|
|
||||||
# We need to check parameter_defaults first for a user provided
|
# We need to check parameter_defaults first for a user provided
|
||||||
# password. If that doesn't exist, we then should look in the
|
# password. If that doesn't exist, we then should look in the
|
||||||
# automatically generated passwords.
|
# automatically generated passwords.
|
||||||
# TODO(d0ugal): Abstract this operation somewhere. We shouldn't need to
|
# TODO(d0ugal): Abstract this operation somewhere. We shouldn't need to
|
||||||
# know about the structure of the environment to get a password.
|
# know about the structure of the environment to get a password.
|
||||||
try:
|
try:
|
||||||
parameter_defaults = environment.variables['parameter_defaults']
|
env = plan_utils.get_env(swift, self.container)
|
||||||
passwords = environment.variables['passwords']
|
except swiftexceptions.ClientException as err:
|
||||||
|
err_msg = ("Error retrieving environment for plan %s: %s" % (
|
||||||
|
self.container, err))
|
||||||
|
LOG.error(err_msg)
|
||||||
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
|
try:
|
||||||
|
parameter_defaults = env['parameter_defaults']
|
||||||
|
passwords = env['passwords']
|
||||||
admin_pass = parameter_defaults.get('AdminPassword')
|
admin_pass = parameter_defaults.get('AdminPassword')
|
||||||
if admin_pass is None:
|
if admin_pass is None:
|
||||||
admin_pass = passwords['AdminPassword']
|
admin_pass = passwords['AdminPassword']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
error = ("Unable to find the AdminPassword in the Mistral "
|
error = ("Unable to find the AdminPassword in the plan "
|
||||||
"environment.")
|
"environment.")
|
||||||
return mistral_workflow_utils.Result(error=error)
|
return mistral_workflow_utils.Result(error=error)
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,11 @@ import logging
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from mistral.workflow import utils as mistral_workflow_utils
|
from mistral.workflow import utils as mistral_workflow_utils
|
||||||
|
from swiftclient import exceptions as swiftexceptions
|
||||||
|
|
||||||
from tripleo_common.actions import base
|
from tripleo_common.actions import base
|
||||||
from tripleo_common import constants
|
from tripleo_common import constants
|
||||||
|
from tripleo_common.utils import plan as plan_utils
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -40,8 +42,8 @@ class GetCapabilitiesAction(base.TripleOAction):
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
try:
|
try:
|
||||||
swift_client = self.get_object_client(context)
|
swift = self.get_object_client(context)
|
||||||
map_file = swift_client.get_object(
|
map_file = swift.get_object(
|
||||||
self.container, 'capabilities-map.yaml')
|
self.container, 'capabilities-map.yaml')
|
||||||
capabilities = yaml.safe_load(map_file[1])
|
capabilities = yaml.safe_load(map_file[1])
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -50,24 +52,23 @@ class GetCapabilitiesAction(base.TripleOAction):
|
||||||
LOG.exception(err_msg)
|
LOG.exception(err_msg)
|
||||||
return mistral_workflow_utils.Result(error=err_msg)
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
try:
|
try:
|
||||||
container_files = swift_client.get_container(self.container)
|
container_files = swift.get_container(self.container)
|
||||||
container_file_list = [entry['name'] for entry
|
container_file_list = [entry['name'] for entry
|
||||||
in container_files[1]]
|
in container_files[1]]
|
||||||
except Exception as swift_err:
|
except Exception as swift_err:
|
||||||
err_msg = ("Error retrieving plan files: %s" % swift_err)
|
err_msg = ("Error retrieving plan files: %s" % swift_err)
|
||||||
LOG.exception(err_msg)
|
LOG.exception(err_msg)
|
||||||
return mistral_workflow_utils.Result(error=err_msg)
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
mistral_client = self.get_workflow_client(context)
|
env = plan_utils.get_env(swift, self.container)
|
||||||
mistral_env = mistral_client.environments.get(self.container)
|
except swiftexceptions.ClientException as err:
|
||||||
except Exception as mistral_err:
|
err_msg = ("Error retrieving environment for plan %s: %s" % (
|
||||||
err_msg = ("Error retrieving mistral "
|
self.container, err))
|
||||||
"environment. %s" % mistral_err)
|
|
||||||
LOG.exception(err_msg)
|
LOG.exception(err_msg)
|
||||||
return mistral_workflow_utils.Result(error=err_msg)
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
selected_envs = [item['path'] for item in
|
selected_envs = [item['path'] for item in env['environments']
|
||||||
mistral_env.variables['environments']
|
|
||||||
if 'path' in item]
|
if 'path' in item]
|
||||||
|
|
||||||
# extract environment files
|
# extract environment files
|
||||||
|
@ -138,20 +139,20 @@ class GetCapabilitiesAction(base.TripleOAction):
|
||||||
|
|
||||||
|
|
||||||
class UpdateCapabilitiesAction(base.TripleOAction):
|
class UpdateCapabilitiesAction(base.TripleOAction):
|
||||||
"""Updates Mistral Environment with selected environments
|
"""Updates plan environment with selected environments
|
||||||
|
|
||||||
Takes a list of environment files and depending on the value of the
|
Takes a list of environment files and depending on the value of the
|
||||||
enabled flag, adds or removes them from the Mistral Environment.
|
enabled flag, adds or removes them from the plan environment.
|
||||||
|
|
||||||
:param environments: map of environments {'environment_path': True}
|
:param environments: map of environments {'environment_path': True}
|
||||||
the value passed can be false for disabled
|
the value passed can be false for disabled
|
||||||
environments, these will be removed from the
|
environments, these will be removed from the
|
||||||
mistral environment.
|
plan environment.
|
||||||
:param container: name of the swift container / plan name
|
:param container: name of the swift container / plan name
|
||||||
:param purge_missing: remove any environments from the mistral environment
|
:param purge_missing: remove any environments from the plan environment
|
||||||
that aren't included in the environments map
|
that aren't included in the environments map
|
||||||
defaults to False
|
defaults to False
|
||||||
:return: the updated mistral environment
|
:return: the updated plan environment
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, environments,
|
def __init__(self, environments,
|
||||||
|
@ -163,46 +164,39 @@ class UpdateCapabilitiesAction(base.TripleOAction):
|
||||||
self.purge_missing = purge_missing
|
self.purge_missing = purge_missing
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
mistral_client = self.get_workflow_client(context)
|
swift = self.get_object_client(context)
|
||||||
mistral_env = None
|
|
||||||
try:
|
try:
|
||||||
mistral_env = mistral_client.environments.get(self.container)
|
env = plan_utils.get_env(swift, self.container)
|
||||||
except Exception as mistral_err:
|
except swiftexceptions.ClientException as err:
|
||||||
err_msg = (
|
err_msg = ("Error retrieving environment for plan %s: %s" % (
|
||||||
"Error retrieving mistral "
|
self.container, err))
|
||||||
"environment. %s" % mistral_err)
|
|
||||||
LOG.exception(err_msg)
|
LOG.exception(err_msg)
|
||||||
return mistral_workflow_utils.Result(error=err_msg)
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
for k, v in self.environments.items():
|
for k, v in self.environments.items():
|
||||||
found = False
|
found = False
|
||||||
if {'path': k} in mistral_env.variables['environments']:
|
if {'path': k} in env['environments']:
|
||||||
found = True
|
found = True
|
||||||
if v:
|
if v:
|
||||||
if not found:
|
if not found:
|
||||||
mistral_env.variables['environments'].append(
|
env['environments'].append({'path': k})
|
||||||
{'path': k}
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
if found:
|
if found:
|
||||||
mistral_env.variables['environments'].remove({'path': k})
|
env['environments'].remove({'path': k})
|
||||||
|
|
||||||
if self.purge_missing:
|
if self.purge_missing:
|
||||||
for env in mistral_env.variables['environments']:
|
for e in env['environments']:
|
||||||
if env.get('path') not in self.environments:
|
if e.get('path') not in self.environments:
|
||||||
mistral_env.variables['environments'].remove(env)
|
env['environments'].remove(e)
|
||||||
|
|
||||||
self.cache_delete(context, self.container, "tripleo.parameters.get")
|
self.cache_delete(context, self.container, "tripleo.parameters.get")
|
||||||
|
|
||||||
env_kwargs = {
|
|
||||||
'name': mistral_env.name,
|
|
||||||
'variables': mistral_env.variables
|
|
||||||
}
|
|
||||||
try:
|
try:
|
||||||
mistral_client.environments.update(**env_kwargs)
|
plan_utils.put_env(swift, env)
|
||||||
except Exception as mistral_err:
|
except swiftexceptions.ClientException as err:
|
||||||
err_msg = (
|
err_msg = "Error uploading to container: %s" % err
|
||||||
"Error retrieving mistral environment. %s" % mistral_err)
|
|
||||||
LOG.exception(err_msg)
|
LOG.exception(err_msg)
|
||||||
return mistral_workflow_utils.Result(error=err_msg)
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
return mistral_env.variables
|
|
||||||
|
return env
|
||||||
|
|
|
@ -18,11 +18,13 @@ import time
|
||||||
from heatclient.common import template_utils
|
from heatclient.common import template_utils
|
||||||
from heatclient import exc as heat_exc
|
from heatclient import exc as heat_exc
|
||||||
from mistral.workflow import utils as mistral_workflow_utils
|
from mistral.workflow import utils as mistral_workflow_utils
|
||||||
|
from swiftclient import exceptions as swiftexceptions
|
||||||
|
|
||||||
from tripleo_common.actions import base
|
from tripleo_common.actions import base
|
||||||
from tripleo_common.actions import templates
|
from tripleo_common.actions import templates
|
||||||
from tripleo_common import constants
|
from tripleo_common import constants
|
||||||
from tripleo_common.update import PackageUpdateManager
|
from tripleo_common.update import PackageUpdateManager
|
||||||
|
from tripleo_common.utils import plan as plan_utils
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -63,24 +65,24 @@ class UpdateStackAction(templates.ProcessTemplatesAction):
|
||||||
parameters['UpdateIdentifier'] = timestamp
|
parameters['UpdateIdentifier'] = timestamp
|
||||||
parameters['StackAction'] = 'UPDATE'
|
parameters['StackAction'] = 'UPDATE'
|
||||||
|
|
||||||
wc = self.get_workflow_client(context)
|
swift = self.get_object_client(context)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
wf_env = wc.environments.get(self.container)
|
env = plan_utils.get_env(swift, self.container)
|
||||||
except Exception:
|
except swiftexceptions.ClientException as err:
|
||||||
msg = "Error retrieving mistral environment: %s" % self.container
|
err_msg = ("Error retrieving environment for plan %s: %s" % (
|
||||||
LOG.exception(msg)
|
self.container, err))
|
||||||
return mistral_workflow_utils.Result(error=msg)
|
LOG.exception(err_msg)
|
||||||
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
if 'parameter_defaults' not in wf_env.variables:
|
try:
|
||||||
wf_env.variables['parameter_defaults'] = {}
|
plan_utils.update_in_env(swift, env, 'parameter_defaults',
|
||||||
wf_env.variables['parameter_defaults'].update(parameters)
|
parameters)
|
||||||
env_kwargs = {
|
except swiftexceptions.ClientException as err:
|
||||||
'name': wf_env.name,
|
err_msg = ("Error updating environment for plan %s: %s" % (
|
||||||
'variables': wf_env.variables,
|
self.container, err))
|
||||||
}
|
LOG.exception(err_msg)
|
||||||
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
# store params changes back to db before call to process templates
|
|
||||||
wc.environments.update(**env_kwargs)
|
|
||||||
|
|
||||||
# process all plan files and create or update a stack
|
# process all plan files and create or update a stack
|
||||||
processed_data = super(UpdateStackAction, self).run(context)
|
processed_data = super(UpdateStackAction, self).run(context)
|
||||||
|
|
|
@ -31,6 +31,7 @@ import uuid
|
||||||
|
|
||||||
from heatclient import exc as heat_exc
|
from heatclient import exc as heat_exc
|
||||||
from mistral.workflow import utils as mistral_workflow_utils
|
from mistral.workflow import utils as mistral_workflow_utils
|
||||||
|
from swiftclient import exceptions as swiftexceptions
|
||||||
|
|
||||||
from tripleo_common.actions import base
|
from tripleo_common.actions import base
|
||||||
from tripleo_common.actions import templates
|
from tripleo_common.actions import templates
|
||||||
|
@ -38,6 +39,7 @@ from tripleo_common import constants
|
||||||
from tripleo_common.utils import nodes
|
from tripleo_common.utils import nodes
|
||||||
from tripleo_common.utils import parameters
|
from tripleo_common.utils import parameters
|
||||||
from tripleo_common.utils import passwords as password_utils
|
from tripleo_common.utils import passwords as password_utils
|
||||||
|
from tripleo_common.utils import plan as plan_utils
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -64,11 +66,18 @@ class GetParametersAction(templates.ProcessTemplatesAction):
|
||||||
processed_data['show_nested'] = True
|
processed_data['show_nested'] = True
|
||||||
|
|
||||||
# respect previously user set param values
|
# respect previously user set param values
|
||||||
wc = self.get_workflow_client(context)
|
swift = self.get_object_client(context)
|
||||||
wf_env = wc.environments.get(self.container)
|
heat = self.get_orchestration_client(context)
|
||||||
orc = self.get_orchestration_client(context)
|
|
||||||
|
|
||||||
params = wf_env.variables.get('parameter_defaults')
|
try:
|
||||||
|
env = plan_utils.get_env(swift, self.container)
|
||||||
|
except swiftexceptions.ClientException as err:
|
||||||
|
err_msg = ("Error retrieving environment for plan %s: %s" % (
|
||||||
|
self.container, err))
|
||||||
|
LOG.exception(err_msg)
|
||||||
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
|
params = env.get('parameter_defaults')
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
'template': processed_data['template'],
|
'template': processed_data['template'],
|
||||||
|
@ -76,9 +85,10 @@ class GetParametersAction(templates.ProcessTemplatesAction):
|
||||||
'environment': processed_data['environment'],
|
'environment': processed_data['environment'],
|
||||||
'show_nested': True
|
'show_nested': True
|
||||||
}
|
}
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
'heat_resource_tree': orc.stacks.validate(**fields),
|
'heat_resource_tree': heat.stacks.validate(**fields),
|
||||||
'mistral_environment_parameters': params,
|
'environment_parameters': params,
|
||||||
}
|
}
|
||||||
self.cache_set(context,
|
self.cache_set(context,
|
||||||
self.container,
|
self.container,
|
||||||
|
@ -95,25 +105,33 @@ class ResetParametersAction(base.TripleOAction):
|
||||||
self.container = container
|
self.container = container
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
wc = self.get_workflow_client(context)
|
swift = self.get_object_client(context)
|
||||||
wf_env = wc.environments.get(self.container)
|
|
||||||
|
|
||||||
if 'parameter_defaults' in wf_env.variables:
|
try:
|
||||||
wf_env.variables.pop('parameter_defaults')
|
env = plan_utils.get_env(swift, self.container)
|
||||||
|
except swiftexceptions.ClientException as err:
|
||||||
|
err_msg = ("Error retrieving environment for plan %s: %s" % (
|
||||||
|
self.container, err))
|
||||||
|
LOG.exception(err_msg)
|
||||||
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
|
try:
|
||||||
|
plan_utils.update_in_env(swift, env, 'parameter_defaults',
|
||||||
|
delete_key=True)
|
||||||
|
except swiftexceptions.ClientException as err:
|
||||||
|
err_msg = ("Error updating environment for plan %s: %s" % (
|
||||||
|
self.container, err))
|
||||||
|
LOG.exception(err_msg)
|
||||||
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
env_kwargs = {
|
|
||||||
'name': wf_env.name,
|
|
||||||
'variables': wf_env.variables
|
|
||||||
}
|
|
||||||
wc.environments.update(**env_kwargs)
|
|
||||||
self.cache_delete(context,
|
self.cache_delete(context,
|
||||||
self.container,
|
self.container,
|
||||||
"tripleo.parameters.get")
|
"tripleo.parameters.get")
|
||||||
return wf_env
|
return env
|
||||||
|
|
||||||
|
|
||||||
class UpdateParametersAction(base.TripleOAction):
|
class UpdateParametersAction(base.TripleOAction):
|
||||||
"""Updates Mistral Environment with parameters."""
|
"""Updates plan environment with parameters."""
|
||||||
|
|
||||||
def __init__(self, parameters,
|
def __init__(self, parameters,
|
||||||
container=constants.DEFAULT_CONTAINER_NAME):
|
container=constants.DEFAULT_CONTAINER_NAME):
|
||||||
|
@ -122,24 +140,33 @@ class UpdateParametersAction(base.TripleOAction):
|
||||||
self.parameters = parameters
|
self.parameters = parameters
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
wc = self.get_workflow_client(context)
|
swift = self.get_object_client(context)
|
||||||
wf_env = wc.environments.get(self.container)
|
|
||||||
if 'parameter_defaults' not in wf_env.variables:
|
try:
|
||||||
wf_env.variables['parameter_defaults'] = {}
|
env = plan_utils.get_env(swift, self.container)
|
||||||
wf_env.variables['parameter_defaults'].update(self.parameters)
|
except swiftexceptions.ClientException as err:
|
||||||
env_kwargs = {
|
err_msg = ("Error retrieving environment for plan %s: %s" % (
|
||||||
'name': wf_env.name,
|
self.container, err))
|
||||||
'variables': wf_env.variables
|
LOG.exception(err_msg)
|
||||||
}
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
wc.environments.update(**env_kwargs)
|
|
||||||
|
try:
|
||||||
|
plan_utils.update_in_env(swift, env, 'parameter_defaults',
|
||||||
|
self.parameters)
|
||||||
|
except swiftexceptions.ClientException as err:
|
||||||
|
err_msg = ("Error updating environment for plan %s: %s" % (
|
||||||
|
self.container, err))
|
||||||
|
LOG.exception(err_msg)
|
||||||
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
self.cache_delete(context,
|
self.cache_delete(context,
|
||||||
self.container,
|
self.container,
|
||||||
"tripleo.parameters.get")
|
"tripleo.parameters.get")
|
||||||
return wf_env
|
return env
|
||||||
|
|
||||||
|
|
||||||
class UpdateRoleParametersAction(UpdateParametersAction):
|
class UpdateRoleParametersAction(UpdateParametersAction):
|
||||||
"""Updates role related parameters in Mistral Environment ."""
|
"""Updates role related parameters in plan environment ."""
|
||||||
|
|
||||||
def __init__(self, role, container=constants.DEFAULT_CONTAINER_NAME):
|
def __init__(self, role, container=constants.DEFAULT_CONTAINER_NAME):
|
||||||
super(UpdateRoleParametersAction, self).__init__(parameters=None,
|
super(UpdateRoleParametersAction, self).__init__(parameters=None,
|
||||||
|
@ -158,8 +185,8 @@ class GeneratePasswordsAction(base.TripleOAction):
|
||||||
"""Generates passwords needed for Overcloud deployment
|
"""Generates passwords needed for Overcloud deployment
|
||||||
|
|
||||||
This method generates passwords and ensures they are stored in the
|
This method generates passwords and ensures they are stored in the
|
||||||
mistral environment associated with a plan. This method respects
|
plan environment. This method respects previously generated passwords and
|
||||||
previously generated passwords and adds new passwords as necessary.
|
adds new passwords as necessary.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, container=constants.DEFAULT_CONTAINER_NAME):
|
def __init__(self, container=constants.DEFAULT_CONTAINER_NAME):
|
||||||
|
@ -167,45 +194,47 @@ class GeneratePasswordsAction(base.TripleOAction):
|
||||||
self.container = container
|
self.container = container
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
|
heat = self.get_orchestration_client(context)
|
||||||
orchestration = self.get_orchestration_client(context)
|
swift = self.get_object_client(context)
|
||||||
wc = self.get_workflow_client(context)
|
mistral = self.get_workflow_client(context)
|
||||||
try:
|
|
||||||
wf_env = wc.environments.get(self.container)
|
|
||||||
except Exception:
|
|
||||||
msg = "Error retrieving mistral environment: %s" % self.container
|
|
||||||
LOG.exception(msg)
|
|
||||||
return mistral_workflow_utils.Result(error=msg)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
stack_env = orchestration.stacks.environment(
|
env = plan_utils.get_env(swift, self.container)
|
||||||
|
except swiftexceptions.ClientException as err:
|
||||||
|
err_msg = ("Error retrieving environment for plan %s: %s" % (
|
||||||
|
self.container, err))
|
||||||
|
LOG.exception(err_msg)
|
||||||
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
|
try:
|
||||||
|
stack_env = heat.stacks.environment(
|
||||||
stack_id=self.container)
|
stack_id=self.container)
|
||||||
except heat_exc.HTTPNotFound:
|
except heat_exc.HTTPNotFound:
|
||||||
stack_env = None
|
stack_env = None
|
||||||
|
|
||||||
passwords = password_utils.generate_passwords(wc, stack_env)
|
passwords = password_utils.generate_passwords(mistral, stack_env)
|
||||||
|
|
||||||
# if passwords don't yet exist in mistral environment
|
# if passwords don't yet exist in plan environment
|
||||||
if 'passwords' not in wf_env.variables:
|
if 'passwords' not in env:
|
||||||
wf_env.variables['passwords'] = {}
|
env['passwords'] = {}
|
||||||
|
|
||||||
# ensure all generated passwords are present in mistral env,
|
# ensure all generated passwords are present in plan env,
|
||||||
# but respect any values previously generated and stored
|
# but respect any values previously generated and stored
|
||||||
for name, password in passwords.items():
|
for name, password in passwords.items():
|
||||||
if name not in wf_env.variables['passwords']:
|
if name not in env['passwords']:
|
||||||
wf_env.variables['passwords'][name] = password
|
env['passwords'][name] = password
|
||||||
|
|
||||||
env_kwargs = {
|
try:
|
||||||
'name': wf_env.name,
|
plan_utils.put_env(swift, env)
|
||||||
'variables': wf_env.variables,
|
except swiftexceptions.ClientException as err:
|
||||||
}
|
err_msg = "Error uploading to container: %s" % err
|
||||||
|
LOG.exception(err_msg)
|
||||||
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
wc.environments.update(**env_kwargs)
|
|
||||||
self.cache_delete(context,
|
self.cache_delete(context,
|
||||||
self.container,
|
self.container,
|
||||||
"tripleo.parameters.get")
|
"tripleo.parameters.get")
|
||||||
|
return env['passwords']
|
||||||
return wf_env.variables['passwords']
|
|
||||||
|
|
||||||
|
|
||||||
class GetPasswordsAction(base.TripleOAction):
|
class GetPasswordsAction(base.TripleOAction):
|
||||||
|
@ -221,16 +250,18 @@ class GetPasswordsAction(base.TripleOAction):
|
||||||
self.container = container
|
self.container = container
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
wc = self.get_workflow_client(context)
|
swift = self.get_object_client(context)
|
||||||
try:
|
|
||||||
wf_env = wc.environments.get(self.container)
|
|
||||||
except Exception:
|
|
||||||
msg = "Error retrieving mistral environment: %s" % self.container
|
|
||||||
LOG.exception(msg)
|
|
||||||
return mistral_workflow_utils.Result(error=msg)
|
|
||||||
|
|
||||||
parameter_defaults = wf_env.variables.get('parameter_defaults', {})
|
try:
|
||||||
passwords = wf_env.variables.get('passwords', {})
|
env = plan_utils.get_env(swift, self.container)
|
||||||
|
except swiftexceptions.ClientException as err:
|
||||||
|
err_msg = ("Error retrieving environment for plan %s: %s" % (
|
||||||
|
self.container, err))
|
||||||
|
LOG.exception(err_msg)
|
||||||
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
|
parameter_defaults = env.get('parameter_defaults', {})
|
||||||
|
passwords = env.get('passwords', {})
|
||||||
for name in constants.PASSWORD_PARAMETER_NAMES:
|
for name in constants.PASSWORD_PARAMETER_NAMES:
|
||||||
if name in parameter_defaults:
|
if name in parameter_defaults:
|
||||||
passwords[name] = parameter_defaults[name]
|
passwords[name] = parameter_defaults[name]
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
@ -20,6 +19,7 @@ import tempfile
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from heatclient import exc as heatexceptions
|
from heatclient import exc as heatexceptions
|
||||||
|
from keystoneauth1 import exceptions as keystoneauth_exc
|
||||||
from mistral.workflow import utils as mistral_workflow_utils
|
from mistral.workflow import utils as mistral_workflow_utils
|
||||||
from mistralclient.api import base as mistralclient_base
|
from mistralclient.api import base as mistralclient_base
|
||||||
from oslo_concurrency import processutils
|
from oslo_concurrency import processutils
|
||||||
|
@ -29,6 +29,7 @@ from swiftclient import exceptions as swiftexceptions
|
||||||
from tripleo_common.actions import base
|
from tripleo_common.actions import base
|
||||||
from tripleo_common import constants
|
from tripleo_common import constants
|
||||||
from tripleo_common import exception
|
from tripleo_common import exception
|
||||||
|
from tripleo_common.utils import plan as plan_utils
|
||||||
from tripleo_common.utils import swift as swiftutils
|
from tripleo_common.utils import swift as swiftutils
|
||||||
from tripleo_common.utils import tarball
|
from tripleo_common.utils import tarball
|
||||||
from tripleo_common.utils.validations import pattern_validator
|
from tripleo_common.utils.validations import pattern_validator
|
||||||
|
@ -41,58 +42,6 @@ default_container_headers = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PlanEnvMixin(object):
|
|
||||||
@staticmethod
|
|
||||||
def get_plan_env_dict(swift, container):
|
|
||||||
"""Retrieves the plan environment from Swift.
|
|
||||||
|
|
||||||
Loads a plan environment file with a given container name from Swift.
|
|
||||||
Makes sure that the file contains valid YAML and that the mandatory
|
|
||||||
fields are present in the environment.
|
|
||||||
|
|
||||||
If the plan environment file is missing from Swift, fall back to the
|
|
||||||
capabilities-map.yaml.
|
|
||||||
|
|
||||||
Returns the plan environment dictionary, and a boolean indicator
|
|
||||||
whether the plan environment file was missing from Swift.
|
|
||||||
"""
|
|
||||||
plan_env_missing = False
|
|
||||||
|
|
||||||
try:
|
|
||||||
plan_env = swift.get_object(container,
|
|
||||||
constants.PLAN_ENVIRONMENT)[1]
|
|
||||||
except swiftexceptions.ClientException:
|
|
||||||
# If the plan environment file is missing from Swift, look for
|
|
||||||
# capabilities-map.yaml instead
|
|
||||||
plan_env_missing = True
|
|
||||||
try:
|
|
||||||
plan_env = swift.get_object(container,
|
|
||||||
'capabilities-map.yaml')[1]
|
|
||||||
except swiftexceptions.ClientException as err:
|
|
||||||
raise exception.PlanOperationError(
|
|
||||||
"File missing from container: %s" % err)
|
|
||||||
|
|
||||||
try:
|
|
||||||
plan_env_dict = yaml.safe_load(plan_env)
|
|
||||||
except yaml.YAMLError as err:
|
|
||||||
raise exception.PlanOperationError(
|
|
||||||
"Error parsing the yaml file: %s" % err)
|
|
||||||
|
|
||||||
if plan_env_missing:
|
|
||||||
plan_env_dict = {
|
|
||||||
'environments': [{'path': plan_env_dict['root_environment']}],
|
|
||||||
'template': plan_env_dict['root_template'],
|
|
||||||
'version': 1.0
|
|
||||||
}
|
|
||||||
|
|
||||||
for key in ('environments', 'template', 'version'):
|
|
||||||
if key not in plan_env_dict:
|
|
||||||
raise exception.PlanOperationError(
|
|
||||||
"%s missing key: %s" % (constants.PLAN_ENVIRONMENT, key))
|
|
||||||
|
|
||||||
return plan_env_dict, plan_env_missing
|
|
||||||
|
|
||||||
|
|
||||||
class CreateContainerAction(base.TripleOAction):
|
class CreateContainerAction(base.TripleOAction):
|
||||||
"""Creates an object container
|
"""Creates an object container
|
||||||
|
|
||||||
|
@ -122,121 +71,51 @@ class CreateContainerAction(base.TripleOAction):
|
||||||
oc.put_container(self.container, headers=default_container_headers)
|
oc.put_container(self.container, headers=default_container_headers)
|
||||||
|
|
||||||
|
|
||||||
class CreatePlanAction(base.TripleOAction, PlanEnvMixin):
|
class MigratePlanAction(base.TripleOAction):
|
||||||
"""Creates a plan
|
"""Migrate plan from using a Mistral environment to using Swift
|
||||||
|
|
||||||
Given a container, creates a Mistral environment with the same name.
|
This action creates a plan-environment.yaml file based on the
|
||||||
The contents of the environment are imported from the plan environment
|
Mistral environment or the default environment, if the file doesn't
|
||||||
file, which must contain entries for `template`, `environments` and
|
already exist in Swift.
|
||||||
`version` at a minimum.
|
|
||||||
|
This action will be deleted in Queens, as it will no longer be
|
||||||
|
needed by then - all plans will include plan-environment.yaml by
|
||||||
|
default.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, container):
|
def __init__(self, plan):
|
||||||
super(CreatePlanAction, self).__init__()
|
super(MigratePlanAction, self).__init__()
|
||||||
self.container = container
|
self.plan = plan
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
swift = self.get_object_client(context)
|
swift = self.get_object_client(context)
|
||||||
mistral = self.get_workflow_client(context)
|
mistral = self.get_workflow_client(context)
|
||||||
env_data = {
|
from_mistral = False
|
||||||
'name': self.container,
|
|
||||||
}
|
|
||||||
|
|
||||||
if not pattern_validator(constants.PLAN_NAME_PATTERN, self.container):
|
|
||||||
message = ("Unable to create plan. The plan name must "
|
|
||||||
"only contain letters, numbers or dashes")
|
|
||||||
return mistral_workflow_utils.Result(error=message)
|
|
||||||
|
|
||||||
# Check to see if an environment with that name already exists
|
|
||||||
try:
|
try:
|
||||||
mistral.environments.get(self.container)
|
env = plan_utils.get_env(swift, self.plan)
|
||||||
except mistralclient_base.APIException:
|
except swiftexceptions.ClientException:
|
||||||
# The environment doesn't exist, as expected. Proceed.
|
# The plan has not been migrated yet. Check if there is a
|
||||||
pass
|
# Mistral environment.
|
||||||
else:
|
|
||||||
message = ("Unable to create plan. The Mistral environment "
|
|
||||||
"already exists")
|
|
||||||
return mistral_workflow_utils.Result(error=message)
|
|
||||||
|
|
||||||
# Get plan environment from Swift
|
|
||||||
try:
|
|
||||||
plan_env_dict, plan_env_missing = self.get_plan_env_dict(
|
|
||||||
swift, self.container)
|
|
||||||
except exception.PlanOperationError as err:
|
|
||||||
return mistral_workflow_utils.Result(error=six.text_type(err))
|
|
||||||
|
|
||||||
# Create mistral environment
|
|
||||||
env_data['variables'] = json.dumps(plan_env_dict, sort_keys=True)
|
|
||||||
try:
|
|
||||||
mistral.environments.create(**env_data)
|
|
||||||
except Exception as err:
|
|
||||||
message = "Error occurred creating plan: %s" % err
|
|
||||||
return mistral_workflow_utils.Result(error=message)
|
|
||||||
|
|
||||||
# Delete the plan environment file from Swift, as it is no long needed.
|
|
||||||
# (If we were to leave the environment file behind, we would have to
|
|
||||||
# take care to keep it in sync with the actual contents of the Mistral
|
|
||||||
# environment. To avoid that, we simply delete it.)
|
|
||||||
# TODO(akrivoka): Once the 'Deployment plan management changes' spec
|
|
||||||
# (https://review.openstack.org/#/c/438918/) is implemented, we will no
|
|
||||||
# longer use Mistral environments for holding the plan data, so this
|
|
||||||
# code can go away.
|
|
||||||
if not plan_env_missing:
|
|
||||||
try:
|
try:
|
||||||
swift.delete_object(self.container, constants.PLAN_ENVIRONMENT)
|
env = mistral.environments.get(self.plan).variables
|
||||||
except swiftexceptions.ClientException as err:
|
from_mistral = True
|
||||||
message = "Error deleting file from container: %s" % err
|
except (mistralclient_base.APIException,
|
||||||
return mistral_workflow_utils.Result(error=message)
|
keystoneauth_exc.http.NotFound):
|
||||||
|
# No Mistral env and no template: likely deploying old
|
||||||
|
# templates aka previous version of OpenStack.
|
||||||
|
env = {'version': 1.0,
|
||||||
|
'name': self.plan,
|
||||||
|
'description': '',
|
||||||
|
'template': 'overcloud.yaml',
|
||||||
|
'environments': [
|
||||||
|
{'path': 'overcloud-resource-registry-puppet.yaml'}
|
||||||
|
]}
|
||||||
|
|
||||||
|
# Store the environment info into Swift
|
||||||
class UpdatePlanAction(base.TripleOAction, PlanEnvMixin):
|
plan_utils.put_env(swift, env)
|
||||||
"""Updates a plan
|
if from_mistral:
|
||||||
|
mistral.environments.delete(self.plan)
|
||||||
Given a container, update the Mistral environment with the same name.
|
|
||||||
The contents of the environment are imported (overwritten) from the plan
|
|
||||||
environment file, which must contain entries for `template`, `environments`
|
|
||||||
and `version` at a minimum.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, container):
|
|
||||||
super(UpdatePlanAction, self).__init__()
|
|
||||||
self.container = container
|
|
||||||
|
|
||||||
def run(self, context):
|
|
||||||
swift = self.get_object_client(context)
|
|
||||||
mistral = self.get_workflow_client(context)
|
|
||||||
|
|
||||||
# Get plan environment from Swift
|
|
||||||
try:
|
|
||||||
plan_env_dict, plan_env_missing = self.get_plan_env_dict(
|
|
||||||
swift, self.container)
|
|
||||||
except exception.PlanOperationError as err:
|
|
||||||
return mistral_workflow_utils.Result(error=six.text_type(err))
|
|
||||||
|
|
||||||
# Update mistral environment with contents from plan environment file
|
|
||||||
variables = json.dumps(plan_env_dict, sort_keys=True)
|
|
||||||
self.cache_delete(context, self.container, "tripleo.parameters.get")
|
|
||||||
try:
|
|
||||||
mistral.environments.update(
|
|
||||||
name=self.container, variables=variables)
|
|
||||||
except mistralclient_base.APIException:
|
|
||||||
message = "Error updating mistral environment: %s" % self.container
|
|
||||||
return mistral_workflow_utils.Result(error=message)
|
|
||||||
|
|
||||||
# Delete the plan environment file from Swift, as it is no long needed.
|
|
||||||
# (If we were to leave the environment file behind, we would have to
|
|
||||||
# take care to keep it in sync with the actual contents of the Mistral
|
|
||||||
# environment. To avoid that, we simply delete it.)
|
|
||||||
# TODO(akrivoka): Once the 'Deployment plan management changes' spec
|
|
||||||
# (https://review.openstack.org/#/c/438918/) is implemented, we will no
|
|
||||||
# longer use Mistral environments for holding the plan data, so this
|
|
||||||
# code can go away.
|
|
||||||
if not plan_env_missing:
|
|
||||||
try:
|
|
||||||
swift.delete_object(self.container, constants.PLAN_ENVIRONMENT)
|
|
||||||
except swiftexceptions.ClientException as err:
|
|
||||||
message = "Error deleting file from container: %s" % err
|
|
||||||
return mistral_workflow_utils.Result(error=message)
|
|
||||||
|
|
||||||
|
|
||||||
class ListPlansAction(base.TripleOAction):
|
class ListPlansAction(base.TripleOAction):
|
||||||
|
@ -244,23 +123,20 @@ class ListPlansAction(base.TripleOAction):
|
||||||
|
|
||||||
This action lists all deployment plans residing in the undercloud. A
|
This action lists all deployment plans residing in the undercloud. A
|
||||||
deployment plan consists of a container marked with metadata
|
deployment plan consists of a container marked with metadata
|
||||||
'x-container-meta-usage-tripleo' and a mistral environment with the same
|
'x-container-meta-usage-tripleo'.
|
||||||
name as the container.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
# plans consist of a container object and mistral environment
|
# Plans consist of a container object marked with metadata to ensure it
|
||||||
# with the same name. The container is marked with metadata
|
# isn't confused with another container
|
||||||
# to ensure it isn't confused with another container
|
|
||||||
plan_list = []
|
plan_list = []
|
||||||
oc = self.get_object_client(context)
|
oc = self.get_object_client(context)
|
||||||
mc = self.get_workflow_client(context)
|
|
||||||
for item in oc.get_account()[1]:
|
for item in oc.get_account()[1]:
|
||||||
container = oc.get_container(item['name'])[0]
|
container = oc.get_container(item['name'])[0]
|
||||||
if constants.TRIPLEO_META_USAGE_KEY in container.keys():
|
if constants.TRIPLEO_META_USAGE_KEY in container.keys():
|
||||||
plan_list.append(item['name'])
|
plan_list.append(item['name'])
|
||||||
return list(set(plan_list).intersection(
|
return list(set(plan_list))
|
||||||
[env.name for env in mc.environments.list()]))
|
|
||||||
|
|
||||||
|
|
||||||
class DeletePlanAction(base.TripleOAction):
|
class DeletePlanAction(base.TripleOAction):
|
||||||
|
@ -293,13 +169,6 @@ class DeletePlanAction(base.TripleOAction):
|
||||||
try:
|
try:
|
||||||
swift = self.get_object_client(context)
|
swift = self.get_object_client(context)
|
||||||
swiftutils.delete_container(swift, self.container)
|
swiftutils.delete_container(swift, self.container)
|
||||||
|
|
||||||
# if mistral environment exists, delete it too
|
|
||||||
mistral = self.get_workflow_client(context)
|
|
||||||
if self.container in [env.name for env in
|
|
||||||
mistral.environments.list()]:
|
|
||||||
# deletes environment
|
|
||||||
mistral.environments.delete(self.container)
|
|
||||||
except swiftexceptions.ClientException as ce:
|
except swiftexceptions.ClientException as ce:
|
||||||
LOG.exception("Swift error deleting plan.")
|
LOG.exception("Swift error deleting plan.")
|
||||||
error_text = ce.msg
|
error_text = ce.msg
|
||||||
|
@ -326,8 +195,8 @@ class ListRolesAction(base.TripleOAction):
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
try:
|
try:
|
||||||
oc = self.get_object_client(context)
|
swift = self.get_object_client(context)
|
||||||
roles_data = yaml.safe_load(oc.get_object(
|
roles_data = yaml.safe_load(swift.get_object(
|
||||||
self.container, constants.OVERCLOUD_J2_ROLES_NAME)[1])
|
self.container, constants.OVERCLOUD_J2_ROLES_NAME)[1])
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
err_msg = ("Error retrieving roles data from deployment plan: %s"
|
err_msg = ("Error retrieving roles data from deployment plan: %s"
|
||||||
|
@ -341,11 +210,9 @@ class ListRolesAction(base.TripleOAction):
|
||||||
class ExportPlanAction(base.TripleOAction):
|
class ExportPlanAction(base.TripleOAction):
|
||||||
"""Exports a deployment plan
|
"""Exports a deployment plan
|
||||||
|
|
||||||
This action exports a deployment plan with a given name. First, the plan
|
This action exports a deployment plan with a given name. The plan
|
||||||
templates are downloaded from the Swift container. Then the plan
|
templates are downloaded from the Swift container, packaged up in a tarball
|
||||||
environment file is generated from the associated Mistral environment.
|
and uploaded to Swift.
|
||||||
Finally, both the templates and the plan environment file are packaged up
|
|
||||||
in a tarball and uploaded to Swift.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, plan, delete_after, exports_container):
|
def __init__(self, plan, delete_after, exports_container):
|
||||||
|
@ -370,15 +237,6 @@ class ExportPlanAction(base.TripleOAction):
|
||||||
with open(path, 'w') as f:
|
with open(path, 'w') as f:
|
||||||
f.write(contents)
|
f.write(contents)
|
||||||
|
|
||||||
def _generate_plan_env_file(self, mistral, tmp_dir):
|
|
||||||
"""Generate plan environment file and add it to specified folder."""
|
|
||||||
environment = mistral.environments.get(self.plan).variables
|
|
||||||
yaml_string = yaml.safe_dump(environment, default_flow_style=False)
|
|
||||||
path = os.path.join(tmp_dir, constants.PLAN_ENVIRONMENT)
|
|
||||||
|
|
||||||
with open(path, 'w') as f:
|
|
||||||
f.write(yaml_string)
|
|
||||||
|
|
||||||
def _create_and_upload_tarball(self, swift, tmp_dir):
|
def _create_and_upload_tarball(self, swift, tmp_dir):
|
||||||
"""Create a tarball containing the tmp_dir and upload it to Swift."""
|
"""Create a tarball containing the tmp_dir and upload it to Swift."""
|
||||||
tarball_name = '%s.tar.gz' % self.plan
|
tarball_name = '%s.tar.gz' % self.plan
|
||||||
|
@ -397,21 +255,15 @@ class ExportPlanAction(base.TripleOAction):
|
||||||
headers=headers)
|
headers=headers)
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
swift = self.get_object_client(context)
|
swift = self.get_object_client()
|
||||||
mistral = self.get_workflow_client(context)
|
|
||||||
tmp_dir = tempfile.mkdtemp()
|
tmp_dir = tempfile.mkdtemp()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._download_templates(swift, tmp_dir)
|
self._download_templates(swift, tmp_dir)
|
||||||
self._generate_plan_env_file(mistral, tmp_dir)
|
|
||||||
self._create_and_upload_tarball(swift, tmp_dir)
|
self._create_and_upload_tarball(swift, tmp_dir)
|
||||||
except swiftexceptions.ClientException as err:
|
except swiftexceptions.ClientException as err:
|
||||||
msg = "Error attempting an operation on container: %s" % err
|
msg = "Error attempting an operation on container: %s" % err
|
||||||
return mistral_workflow_utils.Result(error=msg)
|
return mistral_workflow_utils.Result(error=msg)
|
||||||
except mistralclient_base.APIException:
|
|
||||||
msg = ("The Mistral environment %s could not be found."
|
|
||||||
% self.plan)
|
|
||||||
return mistral_workflow_utils.Result(error=msg)
|
|
||||||
except (OSError, IOError) as err:
|
except (OSError, IOError) as err:
|
||||||
msg = "Error while writing file: %s" % err
|
msg = "Error while writing file: %s" % err
|
||||||
return mistral_workflow_utils.Result(error=msg)
|
return mistral_workflow_utils.Result(error=msg)
|
||||||
|
|
|
@ -27,6 +27,7 @@ from swiftclient import exceptions as swiftexceptions
|
||||||
|
|
||||||
from tripleo_common.actions import base
|
from tripleo_common.actions import base
|
||||||
from tripleo_common import constants
|
from tripleo_common import constants
|
||||||
|
from tripleo_common.utils import plan as plan_utils
|
||||||
from tripleo_common.utils import tarball
|
from tripleo_common.utils import tarball
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
@ -240,14 +241,14 @@ class ProcessTemplatesAction(base.TripleOAction):
|
||||||
error_text = None
|
error_text = None
|
||||||
self.context = context
|
self.context = context
|
||||||
swift = self.get_object_client(context)
|
swift = self.get_object_client(context)
|
||||||
mistral = self.get_workflow_client(context)
|
|
||||||
try:
|
try:
|
||||||
mistral_environment = mistral.environments.get(self.container)
|
plan_env = plan_utils.get_env(swift, self.container)
|
||||||
except Exception as mistral_err:
|
except swiftexceptions.ClientException as err:
|
||||||
error_text = six.text_type(mistral_err)
|
err_msg = ("Error retrieving environment for plan %s: %s" % (
|
||||||
LOG.exception(
|
self.container, err))
|
||||||
"Error retrieving Mistral Environment: %s" % self.container)
|
LOG.exception(err_msg)
|
||||||
return mistral_workflow_utils.Result(error=error_text)
|
return mistral_workflow_utils.Result(error=err_msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# if the jinja overcloud template exists, process it and write it
|
# if the jinja overcloud template exists, process it and write it
|
||||||
|
@ -261,8 +262,8 @@ class ProcessTemplatesAction(base.TripleOAction):
|
||||||
LOG.exception("Error occurred while processing custom roles.")
|
LOG.exception("Error occurred while processing custom roles.")
|
||||||
return mistral_workflow_utils.Result(error=six.text_type(err))
|
return mistral_workflow_utils.Result(error=six.text_type(err))
|
||||||
|
|
||||||
template_name = mistral_environment.variables.get('template')
|
template_name = plan_env.get('template')
|
||||||
environments = mistral_environment.variables.get('environments')
|
environments = plan_env.get('environments')
|
||||||
env_paths = []
|
env_paths = []
|
||||||
temp_files = []
|
temp_files = []
|
||||||
|
|
||||||
|
@ -285,12 +286,11 @@ class ProcessTemplatesAction(base.TripleOAction):
|
||||||
# them in the appropriate order
|
# them in the appropriate order
|
||||||
merged_params = {}
|
merged_params = {}
|
||||||
# merge generated passwords into params first
|
# merge generated passwords into params first
|
||||||
passwords = mistral_environment.variables.get('passwords', {})
|
passwords = plan_env.get('passwords', {})
|
||||||
merged_params.update(passwords)
|
merged_params.update(passwords)
|
||||||
# handle user set parameter values next in case a user has set
|
# handle user set parameter values next in case a user has set
|
||||||
# a new value for a password parameter
|
# a new value for a password parameter
|
||||||
params = mistral_environment.variables.get(
|
params = plan_env.get('parameter_defaults', {})
|
||||||
'parameter_defaults', {})
|
|
||||||
merged_params.update(params)
|
merged_params.update(params)
|
||||||
if merged_params:
|
if merged_params:
|
||||||
env_temp_file = _create_temp_file(
|
env_temp_file = _create_temp_file(
|
||||||
|
|
|
@ -13,13 +13,14 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
import mock
|
import mock
|
||||||
|
import yaml
|
||||||
|
|
||||||
from heatclient import exc as heat_exc
|
from heatclient import exc as heat_exc
|
||||||
from mistral.workflow import utils as mistral_workflow_utils
|
from mistral.workflow import utils as mistral_workflow_utils
|
||||||
from mistralclient.api import base as mistralclient_exc
|
|
||||||
from swiftclient import exceptions as swiftexceptions
|
from swiftclient import exceptions as swiftexceptions
|
||||||
|
|
||||||
from tripleo_common.actions import deployment
|
from tripleo_common.actions import deployment
|
||||||
|
from tripleo_common import constants
|
||||||
from tripleo_common.tests import base
|
from tripleo_common.tests import base
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,39 +211,35 @@ class DeployStackActionTest(base.TestCase):
|
||||||
@mock.patch('heatclient.common.template_utils.'
|
@mock.patch('heatclient.common.template_utils.'
|
||||||
'process_multiple_environments_and_files')
|
'process_multiple_environments_and_files')
|
||||||
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
|
||||||
'get_workflow_client')
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'tripleo_common.actions.base.TripleOAction.get_orchestration_client')
|
'tripleo_common.actions.base.TripleOAction.get_orchestration_client')
|
||||||
def test_run(self, get_orchestration_client_mock,
|
def test_run(self, get_orchestration_client_mock,
|
||||||
mock_get_object_client, mock_get_workflow_client,
|
mock_get_object_client, mock_get_template_contents,
|
||||||
mock_get_template_contents,
|
|
||||||
mock_process_multiple_environments_and_files,
|
mock_process_multiple_environments_and_files,
|
||||||
mock_time):
|
mock_time):
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
# setup swift
|
# setup swift
|
||||||
swift = mock.MagicMock(url="http://test.com")
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
swift.get_object.side_effect = swiftexceptions.ClientException(
|
mock_env = yaml.safe_dump({
|
||||||
'atest2')
|
'name': 'overcloud',
|
||||||
|
'temp_environment': 'temp_environment',
|
||||||
|
'template': 'template',
|
||||||
|
'environments': [{u'path': u'environments/test.yaml'}],
|
||||||
|
'parameter_defaults': {'random_existing_data': 'a_value'},
|
||||||
|
}, default_flow_style=False)
|
||||||
|
swift.get_object.side_effect = (
|
||||||
|
({}, mock_env),
|
||||||
|
({}, mock_env),
|
||||||
|
swiftexceptions.ClientException('atest2')
|
||||||
|
)
|
||||||
mock_get_object_client.return_value = swift
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
heat = mock.MagicMock()
|
heat = mock.MagicMock()
|
||||||
heat.stacks.get.return_value = None
|
heat.stacks.get.return_value = None
|
||||||
get_orchestration_client_mock.return_value = heat
|
get_orchestration_client_mock.return_value = heat
|
||||||
|
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
|
||||||
mock_env.variables = {
|
|
||||||
'temp_environment': 'temp_environment',
|
|
||||||
'template': 'template',
|
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
|
||||||
'parameter_defaults': {'random_existing_data': 'a_value'},
|
|
||||||
}
|
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
|
||||||
|
|
||||||
mock_get_template_contents.return_value = ({}, {
|
mock_get_template_contents.return_value = ({}, {
|
||||||
'heat_template_version': '2016-04-30'
|
'heat_template_version': '2016-04-30'
|
||||||
})
|
})
|
||||||
|
@ -259,8 +256,20 @@ class DeployStackActionTest(base.TestCase):
|
||||||
'StackAction': 'CREATE',
|
'StackAction': 'CREATE',
|
||||||
'UpdateIdentifier': '',
|
'UpdateIdentifier': '',
|
||||||
'random_existing_data': 'a_value'}
|
'random_existing_data': 'a_value'}
|
||||||
self.assertEqual(expected_defaults,
|
|
||||||
mock_env.variables['parameter_defaults'])
|
mock_env_updated = yaml.safe_dump({
|
||||||
|
'name': 'overcloud',
|
||||||
|
'temp_environment': 'temp_environment',
|
||||||
|
'parameter_defaults': expected_defaults,
|
||||||
|
'template': 'template',
|
||||||
|
'environments': [{u'path': u'environments/test.yaml'}]
|
||||||
|
}, default_flow_style=False)
|
||||||
|
|
||||||
|
swift.put_object.assert_called_once_with(
|
||||||
|
'overcloud',
|
||||||
|
constants.PLAN_ENVIRONMENT,
|
||||||
|
mock_env_updated
|
||||||
|
)
|
||||||
|
|
||||||
heat.stacks.create.assert_called_once_with(
|
heat.stacks.create.assert_called_once_with(
|
||||||
environment={},
|
environment={},
|
||||||
|
@ -279,39 +288,36 @@ class DeployStackActionTest(base.TestCase):
|
||||||
@mock.patch('heatclient.common.template_utils.'
|
@mock.patch('heatclient.common.template_utils.'
|
||||||
'process_multiple_environments_and_files')
|
'process_multiple_environments_and_files')
|
||||||
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
|
||||||
'get_workflow_client')
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'tripleo_common.actions.base.TripleOAction.get_orchestration_client')
|
'tripleo_common.actions.base.TripleOAction.get_orchestration_client')
|
||||||
def test_run_skip_deploy_identifier(
|
def test_run_skip_deploy_identifier(
|
||||||
self, get_orchestration_client_mock,
|
self, get_orchestration_client_mock,
|
||||||
mock_get_object_client, mock_get_workflow_client,
|
mock_get_object_client, mock_get_template_contents,
|
||||||
mock_get_template_contents,
|
|
||||||
mock_process_multiple_environments_and_files,
|
mock_process_multiple_environments_and_files,
|
||||||
mock_time):
|
mock_time):
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
# setup swift
|
# setup swift
|
||||||
swift = mock.MagicMock(url="http://test.com")
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
swift.get_object.side_effect = swiftexceptions.ClientException(
|
|
||||||
'atest2')
|
|
||||||
mock_get_object_client.return_value = swift
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
heat = mock.MagicMock()
|
heat = mock.MagicMock()
|
||||||
heat.stacks.get.return_value = None
|
heat.stacks.get.return_value = None
|
||||||
get_orchestration_client_mock.return_value = heat
|
get_orchestration_client_mock.return_value = heat
|
||||||
|
|
||||||
mock_mistral = mock.MagicMock()
|
mock_env = yaml.safe_dump({
|
||||||
mock_env = mock.MagicMock()
|
'name': constants.DEFAULT_CONTAINER_NAME,
|
||||||
mock_env.variables = {
|
|
||||||
'temp_environment': 'temp_environment',
|
'temp_environment': 'temp_environment',
|
||||||
'template': 'template',
|
'template': 'template',
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
'environments': [{u'path': u'environments/test.yaml'}],
|
||||||
'parameter_defaults': {'random_existing_data': 'a_value'},
|
'parameter_defaults': {'random_existing_data': 'a_value'},
|
||||||
}
|
}, default_flow_style=False)
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
swift.get_object.side_effect = (
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
({}, mock_env),
|
||||||
|
({}, mock_env),
|
||||||
|
swiftexceptions.ClientException('atest2')
|
||||||
|
)
|
||||||
|
|
||||||
mock_get_template_contents.return_value = ({}, {
|
mock_get_template_contents.return_value = ({}, {
|
||||||
'heat_template_version': '2016-04-30'
|
'heat_template_version': '2016-04-30'
|
||||||
|
@ -326,11 +332,21 @@ class DeployStackActionTest(base.TestCase):
|
||||||
action.run(mock_ctx)
|
action.run(mock_ctx)
|
||||||
|
|
||||||
# verify parameters are as expected
|
# verify parameters are as expected
|
||||||
expected_defaults = {'StackAction': 'CREATE',
|
mock_env_updated = yaml.safe_dump({
|
||||||
'UpdateIdentifier': '',
|
'name': constants.DEFAULT_CONTAINER_NAME,
|
||||||
'random_existing_data': 'a_value'}
|
'temp_environment': 'temp_environment',
|
||||||
self.assertEqual(expected_defaults,
|
'parameter_defaults': {'StackAction': 'CREATE',
|
||||||
mock_env.variables['parameter_defaults'])
|
'UpdateIdentifier': '',
|
||||||
|
'random_existing_data': 'a_value'},
|
||||||
|
'template': 'template',
|
||||||
|
'environments': [{u'path': u'environments/test.yaml'}]
|
||||||
|
}, default_flow_style=False)
|
||||||
|
|
||||||
|
swift.put_object.assert_called_once_with(
|
||||||
|
constants.DEFAULT_CONTAINER_NAME,
|
||||||
|
constants.PLAN_ENVIRONMENT,
|
||||||
|
mock_env_updated
|
||||||
|
)
|
||||||
|
|
||||||
heat.stacks.create.assert_called_once_with(
|
heat.stacks.create.assert_called_once_with(
|
||||||
environment={},
|
environment={},
|
||||||
|
@ -347,13 +363,11 @@ class DeployStackActionTest(base.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class OvercloudRcActionTestCase(base.TestCase):
|
class OvercloudRcActionTestCase(base.TestCase):
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_workflow_client')
|
'get_object_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_orchestration_client')
|
'get_orchestration_client')
|
||||||
def test_no_stack(self, mock_get_orchestration,
|
def test_no_stack(self, mock_get_orchestration, mock_get_object):
|
||||||
mock_get_workflow):
|
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
|
|
||||||
|
@ -369,59 +383,64 @@ class OvercloudRcActionTestCase(base.TestCase):
|
||||||
))
|
))
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_workflow_client')
|
'get_object_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_orchestration_client')
|
'get_orchestration_client')
|
||||||
def test_no_env(self, mock_get_orchestration,
|
def test_no_env(self, mock_get_orchestration, mock_get_object):
|
||||||
mock_get_workflow):
|
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
|
|
||||||
not_found = mistralclient_exc.APIException()
|
mock_get_object.return_value.get_object.side_effect = (
|
||||||
mock_get_workflow.return_value.environments.get.side_effect = not_found
|
swiftexceptions.ClientException("overcast"))
|
||||||
|
|
||||||
|
action = deployment.OvercloudRcAction("overcast")
|
||||||
|
result = action.run(mock_ctx)
|
||||||
|
self.assertEqual(result.error, "Error retrieving environment for plan "
|
||||||
|
"overcast: overcast")
|
||||||
|
|
||||||
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
|
'get_object_client')
|
||||||
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
|
'get_orchestration_client')
|
||||||
|
def test_no_password(self, mock_get_orchestration, mock_get_object):
|
||||||
|
mock_ctx = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_get_object.return_value.get_object.return_value = (
|
||||||
|
{}, "version: 1.0")
|
||||||
|
|
||||||
action = deployment.OvercloudRcAction("overcast")
|
action = deployment.OvercloudRcAction("overcast")
|
||||||
result = action.run(mock_ctx)
|
result = action.run(mock_ctx)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
result.error,
|
result.error,
|
||||||
"The Mistral environment overcast could not be found.")
|
"Unable to find the AdminPassword in the plan environment.")
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_workflow_client')
|
'get_object_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
|
||||||
'get_orchestration_client')
|
|
||||||
def test_no_password(self, mock_get_orchestration,
|
|
||||||
mock_get_workflow):
|
|
||||||
mock_ctx = mock.MagicMock()
|
|
||||||
|
|
||||||
mock_env = mock.MagicMock(variables={})
|
|
||||||
mock_get_workflow.return_value.environments.get.return_value = mock_env
|
|
||||||
|
|
||||||
action = deployment.OvercloudRcAction("overcast")
|
|
||||||
result = action.run(mock_ctx)
|
|
||||||
|
|
||||||
self.assertEqual(
|
|
||||||
result.error,
|
|
||||||
"Unable to find the AdminPassword in the Mistral environment.")
|
|
||||||
|
|
||||||
@mock.patch('tripleo_common.utils.overcloudrc.create_overcloudrc')
|
@mock.patch('tripleo_common.utils.overcloudrc.create_overcloudrc')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
|
||||||
'get_workflow_client')
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_orchestration_client')
|
'get_orchestration_client')
|
||||||
def test_no_success(self, mock_get_orchestration,
|
def test_success(self, mock_get_orchestration, mock_create_overcloudrc,
|
||||||
mock_get_workflow, mock_create_overcloudrc):
|
mock_get_object):
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
|
|
||||||
|
mock_env = """
|
||||||
|
version: 1.0
|
||||||
|
|
||||||
|
template: overcloud.yaml
|
||||||
|
environments:
|
||||||
|
- path: overcloud-resource-registry-puppet.yaml
|
||||||
|
- path: environments/services/sahara.yaml
|
||||||
|
parameter_defaults:
|
||||||
|
BlockStorageCount: 42
|
||||||
|
OvercloudControlFlavor: yummy
|
||||||
|
passwords:
|
||||||
|
AdminPassword: SUPERSECUREPASSWORD
|
||||||
|
"""
|
||||||
|
mock_get_object.return_value.get_object.return_value = ({}, mock_env)
|
||||||
mock_create_overcloudrc.return_value = {
|
mock_create_overcloudrc.return_value = {
|
||||||
"overcloudrc": "fake overcloudrc"
|
"overcloudrc": "fake overcloudrc"
|
||||||
}
|
}
|
||||||
mock_env = mock.MagicMock(variables={
|
|
||||||
"parameter_defaults": {},
|
|
||||||
"passwords": {"AdminPassword": "SUPERSECUREPASSWORD"}
|
|
||||||
})
|
|
||||||
mock_get_workflow.return_value.environments.get.return_value = mock_env
|
|
||||||
|
|
||||||
action = deployment.OvercloudRcAction("overcast")
|
action = deployment.OvercloudRcAction("overcast")
|
||||||
result = action.run(mock_ctx)
|
result = action.run(mock_ctx)
|
||||||
|
|
|
@ -16,6 +16,7 @@ import mock
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from mistral.workflow import utils as mistral_workflow_utils
|
from mistral.workflow import utils as mistral_workflow_utils
|
||||||
|
from swiftclient import exceptions as swiftexceptions
|
||||||
|
|
||||||
from tripleo_common.actions import heat_capabilities
|
from tripleo_common.actions import heat_capabilities
|
||||||
from tripleo_common.tests import base
|
from tripleo_common.tests import base
|
||||||
|
@ -155,38 +156,40 @@ class GetCapabilitiesActionTest(base.TestCase):
|
||||||
self.assertEqual(expected, action.run(mock_ctx))
|
self.assertEqual(expected, action.run(mock_ctx))
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
@mock.patch(
|
def test_run_env_missing(self, get_obj_client_mock):
|
||||||
'tripleo_common.actions.base.TripleOAction.get_workflow_client')
|
|
||||||
def test_run_mistral_error(self, get_workflow_client_mock,
|
|
||||||
get_obj_client_mock):
|
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
# setup swift
|
# setup swift
|
||||||
swift = mock.MagicMock()
|
swift = mock.MagicMock()
|
||||||
swift.get_object.return_value = ({}, MAPPING_YAML_CONTENTS)
|
swift.get_object.side_effect = (
|
||||||
|
({}, MAPPING_YAML_CONTENTS),
|
||||||
|
swiftexceptions.ClientException(self.container_name)
|
||||||
|
)
|
||||||
get_obj_client_mock.return_value = swift
|
get_obj_client_mock.return_value = swift
|
||||||
|
|
||||||
# setup mistral
|
|
||||||
mistral = mock.MagicMock()
|
|
||||||
mistral.environments.get = mock.Mock(
|
|
||||||
side_effect=Exception)
|
|
||||||
get_workflow_client_mock.return_value = mistral
|
|
||||||
|
|
||||||
action = heat_capabilities.GetCapabilitiesAction(self.container_name)
|
action = heat_capabilities.GetCapabilitiesAction(self.container_name)
|
||||||
expected = mistral_workflow_utils.Result(
|
expected = mistral_workflow_utils.Result(
|
||||||
data=None,
|
data=None,
|
||||||
error="Error retrieving mistral environment. ")
|
error="Error retrieving environment for plan test-container: "
|
||||||
|
"test-container")
|
||||||
self.assertEqual(expected, action.run(mock_ctx))
|
self.assertEqual(expected, action.run(mock_ctx))
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
@mock.patch(
|
def test_run(self, get_obj_client_mock):
|
||||||
'tripleo_common.actions.base.TripleOAction.get_workflow_client')
|
|
||||||
def test_run(self, get_workflow_client_mock, get_obj_client_mock):
|
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
# setup swift
|
# setup swift
|
||||||
swift = mock.MagicMock()
|
swift = mock.MagicMock()
|
||||||
swift.get_object.return_value = ({}, MAPPING_YAML_CONTENTS)
|
|
||||||
|
mock_env = """
|
||||||
|
template: overcloud
|
||||||
|
environments:
|
||||||
|
- path: /path/to/network-isolation.json
|
||||||
|
"""
|
||||||
|
swift.get_object.side_effect = (
|
||||||
|
({}, MAPPING_YAML_CONTENTS),
|
||||||
|
({}, mock_env)
|
||||||
|
)
|
||||||
swift_files_data = ({
|
swift_files_data = ({
|
||||||
u'x-container-meta-usage-tripleo': u'plan',
|
u'x-container-meta-usage-tripleo': u'plan',
|
||||||
u'content-length': u'54271', u'x-container-object-count': u'3',
|
u'content-length': u'54271', u'x-container-object-count': u'3',
|
||||||
|
@ -217,18 +220,6 @@ class GetCapabilitiesActionTest(base.TestCase):
|
||||||
swift.get_container.return_value = swift_files_data
|
swift.get_container.return_value = swift_files_data
|
||||||
get_obj_client_mock.return_value = swift
|
get_obj_client_mock.return_value = swift
|
||||||
|
|
||||||
# setup mistral
|
|
||||||
mistral = mock.MagicMock()
|
|
||||||
get_workflow_client_mock.return_value = mistral
|
|
||||||
|
|
||||||
mock_env = mock.MagicMock()
|
|
||||||
mock_env.name = self.container_name
|
|
||||||
mock_env.variables = {
|
|
||||||
'template': 'overcloud',
|
|
||||||
'environments': [{'path': '/path/to/network-isolation.json'}]
|
|
||||||
}
|
|
||||||
mistral.environments.get.return_value = mock_env
|
|
||||||
|
|
||||||
action = heat_capabilities.GetCapabilitiesAction(self.container_name)
|
action = heat_capabilities.GetCapabilitiesAction(self.container_name)
|
||||||
yaml_mapping = yaml.safe_load(MAPPING_JSON_CONTENTS)
|
yaml_mapping = yaml.safe_load(MAPPING_JSON_CONTENTS)
|
||||||
self.assertEqual(yaml_mapping, action.run(mock_ctx))
|
self.assertEqual(yaml_mapping, action.run(mock_ctx))
|
||||||
|
@ -242,23 +233,21 @@ class UpdateCapabilitiesActionTest(base.TestCase):
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'cache_delete')
|
'cache_delete')
|
||||||
@mock.patch(
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
'tripleo_common.actions.base.TripleOAction.get_workflow_client')
|
def test_run(self, get_object_client_mock, mock_cache):
|
||||||
def test_run(self, get_workflow_client_mock, mock_cache):
|
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
|
|
||||||
# setup mistral
|
# setup swift
|
||||||
mistral = mock.MagicMock()
|
swift = mock.MagicMock()
|
||||||
mocked_env = mock.MagicMock()
|
mocked_env = """
|
||||||
mocked_env.variables = {
|
name: test-container
|
||||||
'environments': [
|
environments:
|
||||||
{'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)
|
||||||
mistral.environments.get.return_value = mocked_env
|
get_object_client_mock.return_value = swift
|
||||||
get_workflow_client_mock.return_value = mistral
|
|
||||||
|
|
||||||
environments = {
|
environments = {
|
||||||
'/path/to/ceph-storage-env.yaml': False,
|
'/path/to/ceph-storage-env.yaml': False,
|
||||||
|
@ -269,6 +258,7 @@ class UpdateCapabilitiesActionTest(base.TestCase):
|
||||||
action = heat_capabilities.UpdateCapabilitiesAction(
|
action = heat_capabilities.UpdateCapabilitiesAction(
|
||||||
environments, self.container_name)
|
environments, self.container_name)
|
||||||
self.assertEqual({
|
self.assertEqual({
|
||||||
|
'name': 'test-container',
|
||||||
'environments': [
|
'environments': [
|
||||||
{'path': '/path/to/overcloud-default-env.yaml'},
|
{'path': '/path/to/overcloud-default-env.yaml'},
|
||||||
{'path': '/path/to/poc-custom-env.yaml'}
|
{'path': '/path/to/poc-custom-env.yaml'}
|
||||||
|
@ -284,22 +274,21 @@ class UpdateCapabilitiesActionTest(base.TestCase):
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'cache_delete')
|
'cache_delete')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'tripleo_common.actions.base.TripleOAction.get_workflow_client')
|
'tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
def test_run_purge_missing(self, get_workflow_client_mock, mock_cache):
|
def test_run_purge_missing(self, get_object_client_mock, mock_cache):
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
|
|
||||||
# setup mistral
|
# setup swift
|
||||||
mistral = mock.MagicMock()
|
swift = mock.MagicMock()
|
||||||
mocked_env = mock.MagicMock()
|
mocked_env = """
|
||||||
mocked_env.variables = {
|
name: test-container
|
||||||
'environments': [
|
environments:
|
||||||
{'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)
|
||||||
mistral.environments.get.return_value = mocked_env
|
get_object_client_mock.return_value = swift
|
||||||
get_workflow_client_mock.return_value = mistral
|
|
||||||
|
|
||||||
environments = {
|
environments = {
|
||||||
'/path/to/overcloud-default-env.yaml': True,
|
'/path/to/overcloud-default-env.yaml': True,
|
||||||
|
@ -310,6 +299,7 @@ class UpdateCapabilitiesActionTest(base.TestCase):
|
||||||
action = heat_capabilities.UpdateCapabilitiesAction(
|
action = heat_capabilities.UpdateCapabilitiesAction(
|
||||||
environments, self.container_name, True)
|
environments, self.container_name, True)
|
||||||
self.assertEqual({
|
self.assertEqual({
|
||||||
|
'name': 'test-container',
|
||||||
'environments': [
|
'environments': [
|
||||||
{'path': '/path/to/overcloud-default-env.yaml'},
|
{'path': '/path/to/overcloud-default-env.yaml'},
|
||||||
{'path': '/path/to/poc-custom-env.yaml'}
|
{'path': '/path/to/poc-custom-env.yaml'}
|
||||||
|
@ -321,28 +311,21 @@ class UpdateCapabilitiesActionTest(base.TestCase):
|
||||||
"tripleo.parameters.get"
|
"tripleo.parameters.get"
|
||||||
)
|
)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
'tripleo_common.actions.base.TripleOAction.get_object_client')
|
def test_run_env_missing(self, get_obj_client_mock):
|
||||||
@mock.patch(
|
|
||||||
'tripleo_common.actions.base.TripleOAction.get_workflow_client')
|
|
||||||
def test_run_mistral_error(self, get_workflow_client_mock,
|
|
||||||
get_obj_client_mock):
|
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
# setup swift
|
# setup swift
|
||||||
swift = mock.MagicMock()
|
swift = mock.MagicMock()
|
||||||
swift.get_object.return_value = ({}, MAPPING_YAML_CONTENTS)
|
swift.get_object.side_effect = (
|
||||||
|
swiftexceptions.ClientException(self.container_name))
|
||||||
get_obj_client_mock.return_value = swift
|
get_obj_client_mock.return_value = swift
|
||||||
|
|
||||||
# setup mistral
|
|
||||||
mistral = mock.MagicMock()
|
|
||||||
mistral.environments.get = mock.Mock(
|
|
||||||
side_effect=Exception)
|
|
||||||
get_workflow_client_mock.return_value = mistral
|
|
||||||
|
|
||||||
action = heat_capabilities.UpdateCapabilitiesAction(
|
action = heat_capabilities.UpdateCapabilitiesAction(
|
||||||
{}, self.container_name)
|
{}, self.container_name)
|
||||||
expected = mistral_workflow_utils.Result(
|
expected = mistral_workflow_utils.Result(
|
||||||
data=None,
|
data=None,
|
||||||
error="Error retrieving mistral environment. ")
|
error="Error retrieving environment for plan test-container: "
|
||||||
|
"test-container"
|
||||||
|
)
|
||||||
self.assertEqual(expected, action.run(mock_ctx))
|
self.assertEqual(expected, action.run(mock_ctx))
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from tripleo_common.actions import package_update
|
from tripleo_common.actions import package_update
|
||||||
|
from tripleo_common import constants
|
||||||
from tripleo_common.tests import base
|
from tripleo_common.tests import base
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,8 +58,7 @@ class UpdateStackActionTest(base.TestCase):
|
||||||
self.container = 'container'
|
self.container = 'container'
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.templates.ProcessTemplatesAction.run')
|
@mock.patch('tripleo_common.actions.templates.ProcessTemplatesAction.run')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
'get_workflow_client')
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_orchestration_client')
|
'get_orchestration_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
|
@ -69,10 +69,10 @@ class UpdateStackActionTest(base.TestCase):
|
||||||
mock_time,
|
mock_time,
|
||||||
mock_compute_client,
|
mock_compute_client,
|
||||||
mock_orchestration_client,
|
mock_orchestration_client,
|
||||||
mock_workflow_client,
|
mock_object_client,
|
||||||
mock_templates_run
|
mock_templates_run):
|
||||||
):
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
|
|
||||||
heat = mock.MagicMock()
|
heat = mock.MagicMock()
|
||||||
heat.stacks.get.return_value = mock.MagicMock(
|
heat.stacks.get.return_value = mock.MagicMock(
|
||||||
stack_name='stack', id='stack_id')
|
stack_name='stack', id='stack_id')
|
||||||
|
@ -81,16 +81,17 @@ class UpdateStackActionTest(base.TestCase):
|
||||||
mock_template_contents.return_value = ({}, {
|
mock_template_contents.return_value = ({}, {
|
||||||
'heat_template_version': '2016-04-30'
|
'heat_template_version': '2016-04-30'
|
||||||
})
|
})
|
||||||
mock_mistral = mock.MagicMock()
|
mock_swift = mock.MagicMock()
|
||||||
mock_env = mock.MagicMock()
|
mock_env = """environments:
|
||||||
mock_env.variables = {
|
- path: environments/test.yaml
|
||||||
'temp_environment': 'temp_environment',
|
name: container
|
||||||
'template': 'template',
|
parameter_defaults:
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
random_data: a_value
|
||||||
'parameter_defaults': {'random_data': 'a_value'},
|
temp_environment: temp_environment
|
||||||
}
|
template: template
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
"""
|
||||||
mock_workflow_client.return_value = mock_mistral
|
mock_swift.get_object.return_value = ({}, mock_env)
|
||||||
|
mock_object_client.return_value = mock_swift
|
||||||
|
|
||||||
# freeze time at datetime.datetime(2016, 9, 8, 16, 24, 24)
|
# freeze time at datetime.datetime(2016, 9, 8, 16, 24, 24)
|
||||||
mock_time.time.return_value = 1473366264
|
mock_time.time.return_value = 1473366264
|
||||||
|
@ -106,16 +107,21 @@ class UpdateStackActionTest(base.TestCase):
|
||||||
action.run(mock_ctx)
|
action.run(mock_ctx)
|
||||||
|
|
||||||
# verify parameters are as expected
|
# verify parameters are as expected
|
||||||
expected_defaults = {
|
updated_mock_env = """environments:
|
||||||
'StackAction': 'UPDATE',
|
- path: environments/test.yaml
|
||||||
'DeployIdentifier': 1473366264,
|
name: container
|
||||||
'UpdateIdentifier': 1473366264,
|
parameter_defaults:
|
||||||
'random_data': 'a_value',
|
DeployIdentifier: 1473366264
|
||||||
}
|
StackAction: UPDATE
|
||||||
self.assertEqual(
|
UpdateIdentifier: 1473366264
|
||||||
expected_defaults, mock_env.variables['parameter_defaults'])
|
random_data: a_value
|
||||||
|
temp_environment: temp_environment
|
||||||
|
template: template
|
||||||
|
"""
|
||||||
|
mock_swift.put_object.assert_called_once_with(
|
||||||
|
self.container, constants.PLAN_ENVIRONMENT, updated_mock_env
|
||||||
|
)
|
||||||
|
|
||||||
print(heat.mock_calls)
|
|
||||||
heat.stacks.update.assert_called_once_with(
|
heat.stacks.update.assert_called_once_with(
|
||||||
'stack_id',
|
'stack_id',
|
||||||
StackAction='UPDATE',
|
StackAction='UPDATE',
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
import mock
|
import mock
|
||||||
|
import yaml
|
||||||
|
|
||||||
from swiftclient import exceptions as swiftexceptions
|
from swiftclient import exceptions as swiftexceptions
|
||||||
|
|
||||||
|
@ -147,11 +148,9 @@ class GetParametersActionTest(base.TestCase):
|
||||||
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_orchestration_client')
|
'get_orchestration_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
|
||||||
'get_workflow_client')
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
def test_run(self, mock_get_object_client,
|
def test_run(self, mock_get_object_client,
|
||||||
mock_get_workflow_client, mock_get_orchestration_client,
|
mock_get_orchestration_client,
|
||||||
mock_get_template_contents,
|
mock_get_template_contents,
|
||||||
mock_process_multiple_environments_and_files,
|
mock_process_multiple_environments_and_files,
|
||||||
mock_cache_get,
|
mock_cache_get,
|
||||||
|
@ -159,19 +158,17 @@ class GetParametersActionTest(base.TestCase):
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
swift = mock.MagicMock(url="http://test.com")
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
swift.get_object.side_effect = swiftexceptions.ClientException(
|
mock_env = yaml.safe_dump({
|
||||||
'atest2')
|
|
||||||
mock_get_object_client.return_value = swift
|
|
||||||
|
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
|
||||||
mock_env.variables = {
|
|
||||||
'temp_environment': 'temp_environment',
|
'temp_environment': 'temp_environment',
|
||||||
'template': 'template',
|
'template': 'template',
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
'environments': [{u'path': u'environments/test.yaml'}]
|
||||||
}
|
}, default_flow_style=False)
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
swift.get_object.side_effect = (
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
({}, mock_env),
|
||||||
|
swiftexceptions.ClientException('atest2'),
|
||||||
|
({}, mock_env)
|
||||||
|
)
|
||||||
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
mock_get_template_contents.return_value = ({}, {
|
mock_get_template_contents.return_value = ({}, {
|
||||||
'heat_template_version': '2016-04-30'
|
'heat_template_version': '2016-04-30'
|
||||||
|
@ -201,7 +198,7 @@ class GetParametersActionTest(base.TestCase):
|
||||||
mock_ctx,
|
mock_ctx,
|
||||||
"overcloud",
|
"overcloud",
|
||||||
"tripleo.parameters.get",
|
"tripleo.parameters.get",
|
||||||
{'heat_resource_tree': {}, 'mistral_environment_parameters': None}
|
{'heat_resource_tree': {}, 'environment_parameters': None}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,31 +206,36 @@ class ResetParametersActionTest(base.TestCase):
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'cache_delete')
|
'cache_delete')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
'get_workflow_client')
|
def test_run(self, mock_get_object_client, mock_cache):
|
||||||
def test_run(self, mock_get_workflow_client,
|
|
||||||
mock_cache):
|
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
mock_env.name = constants.DEFAULT_CONTAINER_NAME
|
mock_env = yaml.safe_dump({
|
||||||
mock_env.variables = {
|
'name': constants.DEFAULT_CONTAINER_NAME,
|
||||||
'template': 'template',
|
'template': 'template',
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
'environments': [{u'path': u'environments/test.yaml'}],
|
||||||
'parameter_defaults': {'SomeTestParameter': 42}
|
'parameter_defaults': {'SomeTestParameter': 42}
|
||||||
}
|
}, default_flow_style=False)
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
swift.get_object.return_value = ({}, mock_env)
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
# Test
|
# Test
|
||||||
action = parameters.ResetParametersAction()
|
action = parameters.ResetParametersAction()
|
||||||
|
|
||||||
action.run(mock_ctx)
|
action.run(mock_ctx)
|
||||||
mock_mistral.environments.update.assert_called_once_with(
|
|
||||||
name=constants.DEFAULT_CONTAINER_NAME,
|
mock_env_reset = yaml.safe_dump({
|
||||||
variables={
|
'name': constants.DEFAULT_CONTAINER_NAME,
|
||||||
'template': 'template',
|
'template': 'template',
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
'environments': [{u'path': u'environments/test.yaml'}]
|
||||||
}
|
}, default_flow_style=False)
|
||||||
|
|
||||||
|
swift.put_object.assert_called_once_with(
|
||||||
|
constants.DEFAULT_CONTAINER_NAME,
|
||||||
|
constants.PLAN_ENVIRONMENT,
|
||||||
|
mock_env_reset
|
||||||
)
|
)
|
||||||
mock_cache.assert_called_once_with(
|
mock_cache.assert_called_once_with(
|
||||||
mock_ctx,
|
mock_ctx,
|
||||||
|
@ -246,34 +248,38 @@ class UpdateParametersActionTest(base.TestCase):
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'cache_delete')
|
'cache_delete')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
'get_workflow_client')
|
def test_run(self, mock_get_object_client, mock_cache):
|
||||||
def test_run(self, mock_get_workflow_client, mock_cache):
|
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
mock_env.name = constants.DEFAULT_CONTAINER_NAME
|
mock_env = yaml.safe_dump({
|
||||||
mock_env.variables = {
|
'name': constants.DEFAULT_CONTAINER_NAME,
|
||||||
'temp_environment': 'temp_environment',
|
'temp_environment': 'temp_environment',
|
||||||
'template': 'template',
|
'template': 'template',
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
'environments': [{u'path': u'environments/test.yaml'}],
|
||||||
}
|
}, default_flow_style=False)
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
swift.get_object.return_value = ({}, mock_env)
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
# Test
|
# Test
|
||||||
test_parameters = {'SomeTestParameter': 42}
|
test_parameters = {'SomeTestParameter': 42}
|
||||||
action = parameters.UpdateParametersAction(test_parameters)
|
action = parameters.UpdateParametersAction(test_parameters)
|
||||||
action.run(mock_ctx)
|
action.run(mock_ctx)
|
||||||
|
|
||||||
mock_mistral.environments.update.assert_called_once_with(
|
mock_env_updated = yaml.safe_dump({
|
||||||
name=constants.DEFAULT_CONTAINER_NAME,
|
'name': constants.DEFAULT_CONTAINER_NAME,
|
||||||
variables={
|
'temp_environment': 'temp_environment',
|
||||||
'temp_environment': 'temp_environment',
|
'parameter_defaults': {'SomeTestParameter': 42},
|
||||||
'template': 'template',
|
'template': 'template',
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
'environments': [{u'path': u'environments/test.yaml'}]
|
||||||
'parameter_defaults': {'SomeTestParameter': 42}}
|
}, default_flow_style=False)
|
||||||
|
|
||||||
|
swift.put_object.assert_called_once_with(
|
||||||
|
constants.DEFAULT_CONTAINER_NAME,
|
||||||
|
constants.PLAN_ENVIRONMENT,
|
||||||
|
mock_env_updated
|
||||||
)
|
)
|
||||||
mock_cache.assert_called_once_with(
|
mock_cache.assert_called_once_with(
|
||||||
mock_ctx,
|
mock_ctx,
|
||||||
|
@ -291,19 +297,18 @@ class UpdateRoleParametersActionTest(base.TestCase):
|
||||||
'get_baremetal_client')
|
'get_baremetal_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_compute_client')
|
'get_compute_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
'get_workflow_client')
|
def test_run(self, mock_get_object_client, mock_get_compute_client,
|
||||||
def test_run(self, mock_get_workflow_client,
|
mock_get_baremetal_client, mock_set_count_and_flavor,
|
||||||
mock_get_compute_client, mock_get_baremetal_client,
|
mock_cache):
|
||||||
mock_set_count_and_flavor, mock_cache):
|
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
mock_env.name = 'overcast'
|
mock_env = yaml.safe_dump({'name': 'overcast'},
|
||||||
mock_env.variables = {}
|
default_flow_style=False)
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
swift.get_object.return_value = ({}, mock_env)
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
params = {'CephStorageCount': 1,
|
params = {'CephStorageCount': 1,
|
||||||
'OvercloudCephStorageFlavor': 'ceph-storage'}
|
'OvercloudCephStorageFlavor': 'ceph-storage'}
|
||||||
|
@ -313,8 +318,16 @@ class UpdateRoleParametersActionTest(base.TestCase):
|
||||||
'overcast')
|
'overcast')
|
||||||
action.run(mock_ctx)
|
action.run(mock_ctx)
|
||||||
|
|
||||||
mock_mistral.environments.update.assert_called_once_with(
|
mock_env_updated = yaml.safe_dump({
|
||||||
name='overcast', variables={'parameter_defaults': params})
|
'name': 'overcast',
|
||||||
|
'parameter_defaults': params,
|
||||||
|
}, default_flow_style=False)
|
||||||
|
|
||||||
|
swift.put_object.assert_called_once_with(
|
||||||
|
'overcast',
|
||||||
|
constants.PLAN_ENVIRONMENT,
|
||||||
|
mock_env_updated
|
||||||
|
)
|
||||||
mock_cache.assert_called_once_with(
|
mock_cache.assert_called_once_with(
|
||||||
mock_ctx,
|
mock_ctx,
|
||||||
"overcast",
|
"overcast",
|
||||||
|
@ -332,23 +345,24 @@ class GeneratePasswordsActionTest(base.TestCase):
|
||||||
'get_snmpd_readonly_user_password')
|
'get_snmpd_readonly_user_password')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_workflow_client', return_value="TestPassword")
|
'get_workflow_client', return_value="TestPassword")
|
||||||
def test_run(self, mock_get_workflow_client,
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
|
def test_run(self, mock_get_object_client,
|
||||||
|
mock_get_workflow_client,
|
||||||
mock_get_snmpd_readonly_user_password,
|
mock_get_snmpd_readonly_user_password,
|
||||||
mock_get_orchestration_client, mock_cache):
|
mock_get_orchestration_client, mock_cache):
|
||||||
|
|
||||||
mock_get_snmpd_readonly_user_password.return_value = "TestPassword"
|
mock_get_snmpd_readonly_user_password.return_value = "TestPassword"
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
mock_env.name = constants.DEFAULT_CONTAINER_NAME
|
mock_env = yaml.safe_dump({
|
||||||
mock_env.variables = {
|
'name': 'overcast',
|
||||||
'temp_environment': 'temp_environment',
|
'temp_environment': 'temp_environment',
|
||||||
'template': 'template',
|
'template': 'template',
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
'environments': [{u'path': u'environments/test.yaml'}],
|
||||||
}
|
}, default_flow_style=False)
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
swift.get_object.return_value = ({}, mock_env)
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
mock_orchestration = mock.MagicMock()
|
mock_orchestration = mock.MagicMock()
|
||||||
mock_orchestration.stacks.environment.return_value = {
|
mock_orchestration.stacks.environment.return_value = {
|
||||||
|
@ -378,7 +392,9 @@ class GeneratePasswordsActionTest(base.TestCase):
|
||||||
'get_snmpd_readonly_user_password')
|
'get_snmpd_readonly_user_password')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_workflow_client')
|
'get_workflow_client')
|
||||||
def test_run_passwords_exist(self, mock_get_workflow_client,
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
|
def test_run_passwords_exist(self, mock_get_object_client,
|
||||||
|
mock_get_workflow_client,
|
||||||
mock_get_snmpd_readonly_user_password,
|
mock_get_snmpd_readonly_user_password,
|
||||||
mock_create_ssh_keypair,
|
mock_create_ssh_keypair,
|
||||||
mock_get_orchestration_client,
|
mock_get_orchestration_client,
|
||||||
|
@ -389,17 +405,17 @@ class GeneratePasswordsActionTest(base.TestCase):
|
||||||
'private_key': 'Bar'}
|
'private_key': 'Bar'}
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
mock_env.name = constants.DEFAULT_CONTAINER_NAME
|
mock_env = yaml.safe_dump({
|
||||||
mock_env.variables = {
|
'name': constants.DEFAULT_CONTAINER_NAME,
|
||||||
'temp_environment': 'temp_environment',
|
'temp_environment': 'temp_environment',
|
||||||
'template': 'template',
|
'template': 'template',
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
'environments': [{u'path': u'environments/test.yaml'}],
|
||||||
'passwords': _EXISTING_PASSWORDS.copy()
|
'passwords': _EXISTING_PASSWORDS.copy()
|
||||||
}
|
}, default_flow_style=False)
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
swift.get_object.return_value = ({}, mock_env)
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
mock_orchestration = mock.MagicMock()
|
mock_orchestration = mock.MagicMock()
|
||||||
mock_orchestration.stacks.environment.return_value = {
|
mock_orchestration.stacks.environment.return_value = {
|
||||||
|
@ -428,7 +444,9 @@ class GeneratePasswordsActionTest(base.TestCase):
|
||||||
'get_snmpd_readonly_user_password')
|
'get_snmpd_readonly_user_password')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_workflow_client')
|
'get_workflow_client')
|
||||||
def test_passwords_exist_in_heat(self, mock_get_workflow_client,
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
|
def test_passwords_exist_in_heat(self, mock_get_object_client,
|
||||||
|
mock_get_workflow_client,
|
||||||
mock_get_snmpd_readonly_user_password,
|
mock_get_snmpd_readonly_user_password,
|
||||||
mock_create_ssh_keypair,
|
mock_create_ssh_keypair,
|
||||||
mock_get_orchestration_client,
|
mock_get_orchestration_client,
|
||||||
|
@ -442,17 +460,17 @@ class GeneratePasswordsActionTest(base.TestCase):
|
||||||
existing_passwords.pop("AdminPassword")
|
existing_passwords.pop("AdminPassword")
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
mock_mistral = mock.MagicMock()
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
mock_env = mock.MagicMock()
|
mock_env = yaml.safe_dump({
|
||||||
mock_env.name = constants.DEFAULT_CONTAINER_NAME
|
'name': constants.DEFAULT_CONTAINER_NAME,
|
||||||
mock_env.variables = {
|
|
||||||
'temp_environment': 'temp_environment',
|
'temp_environment': 'temp_environment',
|
||||||
'template': 'template',
|
'template': 'template',
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
'environments': [{u'path': u'environments/test.yaml'}],
|
||||||
'passwords': existing_passwords.copy()
|
'passwords': existing_passwords.copy()
|
||||||
}
|
}, default_flow_style=False)
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
swift.get_object.return_value = ({}, mock_env)
|
||||||
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
mock_orchestration = mock.MagicMock()
|
mock_orchestration = mock.MagicMock()
|
||||||
mock_orchestration.stacks.environment.return_value = {
|
mock_orchestration.stacks.environment.return_value = {
|
||||||
|
@ -479,22 +497,20 @@ class GetPasswordsActionTest(base.TestCase):
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_orchestration_client')
|
'get_orchestration_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
'get_workflow_client')
|
|
||||||
def test_password_from_parameter_defaults(self,
|
def test_password_from_parameter_defaults(self,
|
||||||
mock_get_workflow_client,
|
mock_get_object_client,
|
||||||
mock_get_orchestration_client):
|
mock_get_orchestration_client):
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
|
||||||
mock_env.name = constants.DEFAULT_CONTAINER_NAME
|
|
||||||
mock_env.variables = {
|
|
||||||
"parameter_defaults": _EXISTING_PASSWORDS,
|
|
||||||
}
|
|
||||||
|
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
mock_env = yaml.safe_dump({
|
||||||
|
"name": constants.DEFAULT_CONTAINER_NAME,
|
||||||
|
"parameter_defaults": _EXISTING_PASSWORDS,
|
||||||
|
}, default_flow_style=False)
|
||||||
|
swift.get_object.return_value = ({}, mock_env)
|
||||||
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
mock_orchestration = mock.MagicMock()
|
mock_orchestration = mock.MagicMock()
|
||||||
mock_get_orchestration_client.return_value = mock_orchestration
|
mock_get_orchestration_client.return_value = mock_orchestration
|
||||||
|
@ -507,24 +523,22 @@ class GetPasswordsActionTest(base.TestCase):
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_orchestration_client')
|
'get_orchestration_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
'get_workflow_client')
|
|
||||||
def test_password_from_generated_passwords(self,
|
def test_password_from_generated_passwords(self,
|
||||||
mock_get_workflow_client,
|
mock_get_object_client,
|
||||||
mock_get_orchestration_client):
|
mock_get_orchestration_client):
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
|
||||||
mock_env.name = constants.DEFAULT_CONTAINER_NAME
|
|
||||||
|
|
||||||
mock_env.variables = {
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
|
mock_env = yaml.safe_dump({
|
||||||
|
"name": constants.DEFAULT_CONTAINER_NAME,
|
||||||
"parameter_defaults": {},
|
"parameter_defaults": {},
|
||||||
"passwords": _EXISTING_PASSWORDS,
|
"passwords": _EXISTING_PASSWORDS,
|
||||||
}
|
|
||||||
|
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
}, default_flow_style=False)
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
swift.get_object.return_value = ({}, mock_env)
|
||||||
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
mock_orchestration = mock.MagicMock()
|
mock_orchestration = mock.MagicMock()
|
||||||
mock_get_orchestration_client.return_value = mock_orchestration
|
mock_get_orchestration_client.return_value = mock_orchestration
|
||||||
|
@ -537,26 +551,25 @@ class GetPasswordsActionTest(base.TestCase):
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_orchestration_client')
|
'get_orchestration_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
'get_workflow_client')
|
|
||||||
def test_password_merging_passwords(self,
|
def test_password_merging_passwords(self,
|
||||||
mock_get_workflow_client,
|
mock_get_object_client,
|
||||||
mock_get_orchestration_client):
|
mock_get_orchestration_client):
|
||||||
|
|
||||||
parameter_defaults = _EXISTING_PASSWORDS.copy()
|
parameter_defaults = _EXISTING_PASSWORDS.copy()
|
||||||
passwords = {"AdminPassword": parameter_defaults.pop("AdminPassword")}
|
passwords = {"AdminPassword": parameter_defaults.pop("AdminPassword")}
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
mock_env.name = constants.DEFAULT_CONTAINER_NAME
|
mock_env = yaml.safe_dump({
|
||||||
mock_env.variables = {
|
"name": constants.DEFAULT_CONTAINER_NAME,
|
||||||
"parameter_defaults": parameter_defaults,
|
"parameter_defaults": parameter_defaults,
|
||||||
"passwords": passwords
|
"passwords": passwords
|
||||||
}
|
}, default_flow_style=False)
|
||||||
|
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
swift.get_object.return_value = ({}, mock_env)
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
mock_orchestration = mock.MagicMock()
|
mock_orchestration = mock.MagicMock()
|
||||||
mock_get_orchestration_client.return_value = mock_orchestration
|
mock_get_orchestration_client.return_value = mock_orchestration
|
||||||
|
@ -570,19 +583,13 @@ class GetPasswordsActionTest(base.TestCase):
|
||||||
|
|
||||||
class GenerateFencingParametersActionTestCase(base.TestCase):
|
class GenerateFencingParametersActionTestCase(base.TestCase):
|
||||||
|
|
||||||
@mock.patch('tripleo_common.utils.nodes.'
|
@mock.patch('tripleo_common.utils.nodes.generate_hostmap')
|
||||||
'generate_hostmap')
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_compute_client')
|
'get_compute_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_baremetal_client')
|
'get_baremetal_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
def test_no_success(self, mock_get_baremetal, mock_get_compute,
|
||||||
'get_workflow_client')
|
mock_generate_hostmap):
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
|
||||||
'get_orchestration_client')
|
|
||||||
def test_no_success(self, mock_get_orchestration,
|
|
||||||
mock_get_workflow, mock_get_baremetal,
|
|
||||||
mock_get_compute, mock_generate_hostmap):
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
test_hostmap = {
|
test_hostmap = {
|
||||||
"00:11:22:33:44:55": {
|
"00:11:22:33:44:55": {
|
||||||
|
@ -678,35 +685,37 @@ class GenerateFencingParametersActionTestCase(base.TestCase):
|
||||||
|
|
||||||
class GetFlattenedParametersActionTest(base.TestCase):
|
class GetFlattenedParametersActionTest(base.TestCase):
|
||||||
|
|
||||||
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
|
'cache_set')
|
||||||
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
|
'cache_get')
|
||||||
@mock.patch('heatclient.common.template_utils.'
|
@mock.patch('heatclient.common.template_utils.'
|
||||||
'process_multiple_environments_and_files')
|
'process_multiple_environments_and_files')
|
||||||
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_orchestration_client')
|
'get_orchestration_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
|
||||||
'get_workflow_client')
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
def test_empty_resource_tree(self, mock_get_object_client,
|
def test_empty_resource_tree(self, mock_get_object_client,
|
||||||
mock_get_workflow_client,
|
|
||||||
mock_get_orchestration_client,
|
mock_get_orchestration_client,
|
||||||
mock_get_template_contents,
|
mock_get_template_contents,
|
||||||
mock_process_multiple_environments_and_files):
|
mock_process_multiple_environments_and_files,
|
||||||
|
mock_cache_get,
|
||||||
|
mock_cache_set):
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
|
mock_cache_get.return_value = None
|
||||||
swift = mock.MagicMock(url="http://test.com")
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
swift.get_object.side_effect = swiftexceptions.ClientException(
|
mock_env = yaml.safe_dump({
|
||||||
'atest2')
|
|
||||||
mock_get_object_client.return_value = swift
|
|
||||||
|
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
|
||||||
mock_env.variables = {
|
|
||||||
'temp_environment': 'temp_environment',
|
'temp_environment': 'temp_environment',
|
||||||
'template': 'template',
|
'template': 'template',
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
'environments': [{u'path': u'environments/test.yaml'}]
|
||||||
}
|
}, default_flow_style=False)
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
swift.get_object.side_effect = (
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
({}, mock_env),
|
||||||
|
swiftexceptions.ClientException('atest2'),
|
||||||
|
({}, mock_env)
|
||||||
|
)
|
||||||
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
mock_get_template_contents.return_value = ({}, {
|
mock_get_template_contents.return_value = ({}, {
|
||||||
'heat_template_version': '2016-04-30'
|
'heat_template_version': '2016-04-30'
|
||||||
|
@ -720,7 +729,7 @@ class GetFlattenedParametersActionTest(base.TestCase):
|
||||||
|
|
||||||
expected_value = {
|
expected_value = {
|
||||||
'heat_resource_tree': {},
|
'heat_resource_tree': {},
|
||||||
'mistral_environment_parameters': None,
|
'environment_parameters': None,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test
|
# Test
|
||||||
|
@ -734,37 +743,39 @@ class GetFlattenedParametersActionTest(base.TestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(result, expected_value)
|
self.assertEqual(result, expected_value)
|
||||||
|
|
||||||
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
|
'cache_set')
|
||||||
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
|
'cache_get')
|
||||||
@mock.patch('uuid.uuid4', side_effect=['1', '2'])
|
@mock.patch('uuid.uuid4', side_effect=['1', '2'])
|
||||||
@mock.patch('heatclient.common.template_utils.'
|
@mock.patch('heatclient.common.template_utils.'
|
||||||
'process_multiple_environments_and_files')
|
'process_multiple_environments_and_files')
|
||||||
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
||||||
'get_orchestration_client')
|
'get_orchestration_client')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
|
||||||
'get_workflow_client')
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
def test_valid_resource_tree(self, mock_get_object_client,
|
def test_valid_resource_tree(self, mock_get_object_client,
|
||||||
mock_get_workflow_client,
|
|
||||||
mock_get_orchestration_client,
|
mock_get_orchestration_client,
|
||||||
mock_get_template_contents,
|
mock_get_template_contents,
|
||||||
mock_process_multiple_environments_and_files,
|
mock_process_multiple_environments_and_files,
|
||||||
mock_uuid):
|
mock_uuid,
|
||||||
|
mock_cache_get,
|
||||||
|
mock_cache_set):
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
|
mock_cache_get.return_value = None
|
||||||
swift = mock.MagicMock(url="http://test.com")
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
swift.get_object.side_effect = swiftexceptions.ClientException(
|
mock_env = yaml.safe_dump({
|
||||||
'atest2')
|
|
||||||
mock_get_object_client.return_value = swift
|
|
||||||
|
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
|
||||||
mock_env.variables = {
|
|
||||||
'temp_environment': 'temp_environment',
|
'temp_environment': 'temp_environment',
|
||||||
'template': 'template',
|
'template': 'template',
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
'environments': [{u'path': u'environments/test.yaml'}]
|
||||||
}
|
}, default_flow_style=False)
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
swift.get_object.side_effect = (
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
({}, mock_env),
|
||||||
|
swiftexceptions.ClientException('atest2'),
|
||||||
|
({}, mock_env)
|
||||||
|
)
|
||||||
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
mock_get_template_contents.return_value = ({}, {
|
mock_get_template_contents.return_value = ({}, {
|
||||||
'heat_template_version': '2016-04-30'
|
'heat_template_version': '2016-04-30'
|
||||||
|
@ -816,7 +827,7 @@ class GetFlattenedParametersActionTest(base.TestCase):
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'mistral_environment_parameters': None,
|
'environment_parameters': None,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test
|
# Test
|
||||||
|
|
|
@ -12,40 +12,19 @@
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
import json
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from heatclient import exc as heatexceptions
|
from heatclient import exc as heatexceptions
|
||||||
from mistral.workflow import utils as mistral_workflow_utils
|
from mistral.workflow import utils as mistral_workflow_utils
|
||||||
from mistralclient.api import base as mistral_base
|
|
||||||
from oslo_concurrency import processutils
|
from oslo_concurrency import processutils
|
||||||
from swiftclient import exceptions as swiftexceptions
|
from swiftclient import exceptions as swiftexceptions
|
||||||
|
|
||||||
from tripleo_common.actions import plan
|
from tripleo_common.actions import plan
|
||||||
from tripleo_common import constants
|
|
||||||
from tripleo_common import exception
|
from tripleo_common import exception
|
||||||
from tripleo_common.tests import base
|
from tripleo_common.tests import base
|
||||||
|
|
||||||
JSON_CONTENTS = json.dumps({
|
|
||||||
"environments": [{
|
|
||||||
"path": "overcloud-resource-registry-puppet.yaml"
|
|
||||||
}, {
|
|
||||||
"path": "environments/services/sahara.yaml"
|
|
||||||
}],
|
|
||||||
"parameter_defaults": {
|
|
||||||
"BlockStorageCount": 42,
|
|
||||||
"OvercloudControlFlavor": "yummy"
|
|
||||||
},
|
|
||||||
"passwords": {
|
|
||||||
"AdminPassword": "aaaa",
|
|
||||||
"ZaqarPassword": "zzzz"
|
|
||||||
},
|
|
||||||
"template": "overcloud.yaml",
|
|
||||||
"version": 1.0
|
|
||||||
}, sort_keys=True)
|
|
||||||
|
|
||||||
|
ENV_YAML_CONTENTS = """
|
||||||
YAML_CONTENTS = """
|
|
||||||
version: 1.0
|
version: 1.0
|
||||||
|
|
||||||
template: overcloud.yaml
|
template: overcloud.yaml
|
||||||
|
@ -60,13 +39,6 @@ passwords:
|
||||||
ZaqarPassword: zzzz
|
ZaqarPassword: zzzz
|
||||||
"""
|
"""
|
||||||
|
|
||||||
YAML_CONTENTS_INVALID = "{bad_yaml"
|
|
||||||
|
|
||||||
# `environments` is missing
|
|
||||||
YAML_CONTENTS_MISSING_KEY = """
|
|
||||||
template: overcloud.yaml
|
|
||||||
"""
|
|
||||||
|
|
||||||
RESOURCES_YAML_CONTENTS = """heat_template_version: 2016-04-08
|
RESOURCES_YAML_CONTENTS = """heat_template_version: 2016-04-08
|
||||||
resources:
|
resources:
|
||||||
Controller:
|
Controller:
|
||||||
|
@ -160,197 +132,6 @@ class CreateContainerActionTest(base.TestCase):
|
||||||
None, error_str))
|
None, error_str))
|
||||||
|
|
||||||
|
|
||||||
class CreatePlanActionTest(base.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(CreatePlanActionTest, self).setUp()
|
|
||||||
# A container that name enforces all validation rules
|
|
||||||
self.container_name = 'Test-container-3'
|
|
||||||
self.plan_environment_name = constants.PLAN_ENVIRONMENT
|
|
||||||
|
|
||||||
# setup swift
|
|
||||||
self.swift = mock.MagicMock()
|
|
||||||
self.swift.get_object.return_value = ({}, YAML_CONTENTS)
|
|
||||||
swift_patcher = mock.patch(
|
|
||||||
'tripleo_common.actions.base.TripleOAction.get_object_client',
|
|
||||||
return_value=self.swift)
|
|
||||||
swift_patcher.start()
|
|
||||||
self.addCleanup(swift_patcher.stop)
|
|
||||||
|
|
||||||
# setup mistral
|
|
||||||
self.mistral = mock.MagicMock()
|
|
||||||
self.mistral.environments.get.side_effect = mistral_base.APIException
|
|
||||||
mistral_patcher = mock.patch(
|
|
||||||
'tripleo_common.actions.base.TripleOAction.get_workflow_client',
|
|
||||||
return_value=self.mistral)
|
|
||||||
mistral_patcher.start()
|
|
||||||
self.addCleanup(mistral_patcher.stop)
|
|
||||||
self.ctx = mock.MagicMock()
|
|
||||||
|
|
||||||
def test_run_success(self):
|
|
||||||
action = plan.CreatePlanAction(self.container_name)
|
|
||||||
action.run(self.ctx)
|
|
||||||
|
|
||||||
self.swift.get_object.assert_called_once_with(
|
|
||||||
self.container_name,
|
|
||||||
self.plan_environment_name
|
|
||||||
)
|
|
||||||
|
|
||||||
self.swift.delete_object.assert_called_once()
|
|
||||||
|
|
||||||
self.mistral.environments.create.assert_called_once_with(
|
|
||||||
name='Test-container-3',
|
|
||||||
variables=JSON_CONTENTS
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_run_invalid_plan_name(self):
|
|
||||||
action = plan.CreatePlanAction("invalid_underscore")
|
|
||||||
result = action.run(self.ctx)
|
|
||||||
|
|
||||||
error_str = ("Unable to create plan. The plan name must only contain "
|
|
||||||
"letters, numbers or dashes")
|
|
||||||
# don't bother checking the exact error (python versions different)
|
|
||||||
self.assertEqual(result.error.split(':')[0], error_str)
|
|
||||||
|
|
||||||
def test_run_mistral_env_already_exists(self):
|
|
||||||
self.mistral.environments.get.side_effect = None
|
|
||||||
self.mistral.environments.get.return_value = 'test-env'
|
|
||||||
|
|
||||||
action = plan.CreatePlanAction(self.container_name)
|
|
||||||
result = action.run(self.ctx)
|
|
||||||
|
|
||||||
error_str = ("Unable to create plan. The Mistral environment already "
|
|
||||||
"exists")
|
|
||||||
self.assertEqual(result.error, error_str)
|
|
||||||
self.mistral.environments.create.assert_not_called()
|
|
||||||
|
|
||||||
def test_run_missing_file(self):
|
|
||||||
self.swift.get_object.side_effect = swiftexceptions.ClientException(
|
|
||||||
self.plan_environment_name)
|
|
||||||
|
|
||||||
action = plan.CreatePlanAction(self.container_name)
|
|
||||||
result = action.run(self.ctx)
|
|
||||||
|
|
||||||
error_str = ('File missing from container: %s' %
|
|
||||||
self.plan_environment_name)
|
|
||||||
self.assertEqual(result.error, error_str)
|
|
||||||
|
|
||||||
def test_run_invalid_yaml(self):
|
|
||||||
self.swift.get_object.return_value = ({}, YAML_CONTENTS_INVALID)
|
|
||||||
|
|
||||||
action = plan.CreatePlanAction(self.container_name)
|
|
||||||
result = action.run(self.ctx)
|
|
||||||
|
|
||||||
error_str = 'Error parsing the yaml file'
|
|
||||||
self.assertEqual(result.error.split(':')[0], error_str)
|
|
||||||
|
|
||||||
def test_run_missing_key(self):
|
|
||||||
self.swift.get_object.return_value = ({}, YAML_CONTENTS_MISSING_KEY)
|
|
||||||
|
|
||||||
action = plan.CreatePlanAction(self.container_name)
|
|
||||||
result = action.run(self.ctx)
|
|
||||||
|
|
||||||
error_str = ("%s missing key: environments" %
|
|
||||||
self.plan_environment_name)
|
|
||||||
self.assertEqual(result.error, error_str)
|
|
||||||
|
|
||||||
|
|
||||||
class UpdatePlanActionTest(base.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(UpdatePlanActionTest, self).setUp()
|
|
||||||
self.container_name = 'Test-container-3'
|
|
||||||
self.plan_environment_name = constants.PLAN_ENVIRONMENT
|
|
||||||
|
|
||||||
# setup swift
|
|
||||||
self.swift = mock.MagicMock()
|
|
||||||
self.swift.get_object.return_value = ({}, YAML_CONTENTS)
|
|
||||||
swift_patcher = mock.patch(
|
|
||||||
'tripleo_common.actions.base.TripleOAction.get_object_client',
|
|
||||||
return_value=self.swift)
|
|
||||||
swift_patcher.start()
|
|
||||||
self.addCleanup(swift_patcher.stop)
|
|
||||||
|
|
||||||
# setup mistral
|
|
||||||
self.mistral = mock.MagicMock()
|
|
||||||
mistral_patcher = mock.patch(
|
|
||||||
'tripleo_common.actions.base.TripleOAction.get_workflow_client',
|
|
||||||
return_value=self.mistral)
|
|
||||||
mistral_patcher.start()
|
|
||||||
self.addCleanup(mistral_patcher.stop)
|
|
||||||
self.ctx = mock.MagicMock()
|
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.cache_delete')
|
|
||||||
def test_run_success(self, mock_cache):
|
|
||||||
action = plan.UpdatePlanAction(self.container_name)
|
|
||||||
action.run(self.ctx)
|
|
||||||
|
|
||||||
self.swift.get_object.assert_called_once_with(
|
|
||||||
self.container_name,
|
|
||||||
self.plan_environment_name
|
|
||||||
)
|
|
||||||
|
|
||||||
self.swift.delete_object.assert_called_once()
|
|
||||||
mock_cache.assert_called_once_with(
|
|
||||||
self.ctx,
|
|
||||||
"Test-container-3",
|
|
||||||
"tripleo.parameters.get"
|
|
||||||
)
|
|
||||||
|
|
||||||
self.mistral.environments.update.assert_called_once_with(
|
|
||||||
name='Test-container-3',
|
|
||||||
variables=JSON_CONTENTS
|
|
||||||
)
|
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.cache_delete')
|
|
||||||
def test_run_mistral_env_missing(self, mock_cache):
|
|
||||||
self.mistral.environments.update.side_effect = (
|
|
||||||
mistral_base.APIException)
|
|
||||||
|
|
||||||
action = plan.UpdatePlanAction(self.container_name)
|
|
||||||
result = action.run(self.ctx)
|
|
||||||
|
|
||||||
error_str = ("Error updating mistral environment: %s" %
|
|
||||||
self.container_name)
|
|
||||||
self.assertEqual(result.error, error_str)
|
|
||||||
self.swift.delete_object.assert_not_called()
|
|
||||||
mock_cache.assert_called_once_with(
|
|
||||||
self.ctx,
|
|
||||||
"Test-container-3",
|
|
||||||
"tripleo.parameters.get"
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_run_missing_file(self):
|
|
||||||
self.swift.get_object.side_effect = swiftexceptions.ClientException(
|
|
||||||
self.plan_environment_name)
|
|
||||||
|
|
||||||
action = plan.UpdatePlanAction(self.container_name)
|
|
||||||
result = action.run(self.ctx)
|
|
||||||
|
|
||||||
error_str = ('File missing from container: %s' %
|
|
||||||
self.plan_environment_name)
|
|
||||||
self.assertEqual(result.error, error_str)
|
|
||||||
|
|
||||||
def test_run_invalid_yaml(self):
|
|
||||||
self.swift.get_object.return_value = ({}, YAML_CONTENTS_INVALID)
|
|
||||||
|
|
||||||
action = plan.UpdatePlanAction(self.container_name)
|
|
||||||
result = action.run(self.ctx)
|
|
||||||
|
|
||||||
error_str = 'Error parsing the yaml file'
|
|
||||||
self.assertEqual(result.error.split(':')[0], error_str)
|
|
||||||
|
|
||||||
def test_run_missing_key(self):
|
|
||||||
self.swift.get_object.return_value = ({}, YAML_CONTENTS_MISSING_KEY)
|
|
||||||
|
|
||||||
action = plan.UpdatePlanAction(self.container_name)
|
|
||||||
result = action.run(self.ctx)
|
|
||||||
|
|
||||||
error_str = ("%s missing key: environments" %
|
|
||||||
self.plan_environment_name)
|
|
||||||
self.assertEqual(result.error, error_str)
|
|
||||||
|
|
||||||
|
|
||||||
class ListPlansActionTest(base.TestCase):
|
class ListPlansActionTest(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -359,9 +140,7 @@ class ListPlansActionTest(base.TestCase):
|
||||||
self.ctx = mock.MagicMock()
|
self.ctx = mock.MagicMock()
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
@mock.patch(
|
def test_run(self, get_obj_client_mock):
|
||||||
'tripleo_common.actions.base.TripleOAction.get_workflow_client')
|
|
||||||
def test_run(self, get_workflow_client_mock, get_obj_client_mock):
|
|
||||||
|
|
||||||
# setup swift
|
# setup swift
|
||||||
swift = mock.MagicMock()
|
swift = mock.MagicMock()
|
||||||
|
@ -377,13 +156,6 @@ class ListPlansActionTest(base.TestCase):
|
||||||
}, [])
|
}, [])
|
||||||
get_obj_client_mock.return_value = swift
|
get_obj_client_mock.return_value = swift
|
||||||
|
|
||||||
# setup mistral
|
|
||||||
mistral = mock.MagicMock()
|
|
||||||
env_item = mock.Mock()
|
|
||||||
env_item.name = self.container
|
|
||||||
mistral.environments.list.return_value = [env_item]
|
|
||||||
get_workflow_client_mock.return_value = mistral
|
|
||||||
|
|
||||||
# Test
|
# Test
|
||||||
action = plan.ListPlansAction()
|
action = plan.ListPlansAction()
|
||||||
action.run(self.ctx)
|
action.run(self.ctx)
|
||||||
|
@ -423,10 +195,7 @@ class DeletePlanActionTest(base.TestCase):
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'tripleo_common.actions.base.TripleOAction.get_orchestration_client')
|
'tripleo_common.actions.base.TripleOAction.get_orchestration_client')
|
||||||
@mock.patch(
|
def test_run(self, get_orchestration_client, get_obj_client_mock):
|
||||||
'tripleo_common.actions.base.TripleOAction.get_workflow_client')
|
|
||||||
def test_run(self, get_workflow_client_mock, get_orchestration_client,
|
|
||||||
get_obj_client_mock):
|
|
||||||
|
|
||||||
# setup swift
|
# setup swift
|
||||||
swift = mock.MagicMock()
|
swift = mock.MagicMock()
|
||||||
|
@ -445,15 +214,6 @@ class DeletePlanActionTest(base.TestCase):
|
||||||
|
|
||||||
get_obj_client_mock.return_value = swift
|
get_obj_client_mock.return_value = swift
|
||||||
|
|
||||||
# setup mistral
|
|
||||||
mistral = mock.MagicMock()
|
|
||||||
mistral_environment = mock.Mock()
|
|
||||||
mistral_environment.name = self.container_name
|
|
||||||
mistral.environments.list.return_value = [
|
|
||||||
mistral_environment,
|
|
||||||
]
|
|
||||||
get_workflow_client_mock.return_value = mistral
|
|
||||||
|
|
||||||
# setup heat
|
# setup heat
|
||||||
heat = mock.MagicMock()
|
heat = mock.MagicMock()
|
||||||
heat.stacks.get = mock.Mock(
|
heat.stacks.get = mock.Mock(
|
||||||
|
@ -474,8 +234,6 @@ class DeletePlanActionTest(base.TestCase):
|
||||||
|
|
||||||
swift.delete_container.assert_called_with(self.container_name)
|
swift.delete_container.assert_called_with(self.container_name)
|
||||||
|
|
||||||
mistral.environments.delete.assert_called_with(self.container_name)
|
|
||||||
|
|
||||||
|
|
||||||
class RoleListActionTest(base.TestCase):
|
class RoleListActionTest(base.TestCase):
|
||||||
|
|
||||||
|
@ -486,7 +244,6 @@ class RoleListActionTest(base.TestCase):
|
||||||
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
def test_run(self, get_obj_client_mock):
|
def test_run(self, get_obj_client_mock):
|
||||||
|
|
||||||
# setup swift
|
# setup swift
|
||||||
swift = mock.MagicMock()
|
swift = mock.MagicMock()
|
||||||
swift.get_object.return_value = ({}, ROLES_DATA_YAML_CONTENTS)
|
swift.get_object.return_value = ({}, ROLES_DATA_YAML_CONTENTS)
|
||||||
|
@ -542,21 +299,6 @@ class ExportPlanActionTest(base.TestCase):
|
||||||
swift_patcher.start()
|
swift_patcher.start()
|
||||||
self.addCleanup(swift_patcher.stop)
|
self.addCleanup(swift_patcher.stop)
|
||||||
|
|
||||||
# setup mistral
|
|
||||||
self.mistral = mock.MagicMock()
|
|
||||||
env_item = mock.Mock()
|
|
||||||
env_item.variables = {
|
|
||||||
'template': 'overcloud.yaml',
|
|
||||||
'environments': [
|
|
||||||
{'path': 'overcloud-resource-registry-puppet.yaml'}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
self.mistral.environments.get.return_value = env_item
|
|
||||||
mistral_patcher = mock.patch(
|
|
||||||
'tripleo_common.actions.base.TripleOAction.get_workflow_client',
|
|
||||||
return_value=self.mistral)
|
|
||||||
mistral_patcher.start()
|
|
||||||
self.addCleanup(mistral_patcher.stop)
|
|
||||||
self.ctx = mock.MagicMock()
|
self.ctx = mock.MagicMock()
|
||||||
|
|
||||||
@mock.patch('tripleo_common.utils.tarball.create_tarball')
|
@mock.patch('tripleo_common.utils.tarball.create_tarball')
|
||||||
|
@ -578,7 +320,6 @@ class ExportPlanActionTest(base.TestCase):
|
||||||
self.swift.get_container.assert_has_calls(get_container_mock_calls)
|
self.swift.get_container.assert_has_calls(get_container_mock_calls)
|
||||||
self.swift.get_object.assert_has_calls(
|
self.swift.get_object.assert_has_calls(
|
||||||
get_object_mock_calls, any_order=True)
|
get_object_mock_calls, any_order=True)
|
||||||
self.mistral.environments.get.assert_called_once_with(self.plan)
|
|
||||||
self.swift.put_object.assert_called_once()
|
self.swift.put_object.assert_called_once()
|
||||||
mock_create_tarball.assert_called_once()
|
mock_create_tarball.assert_called_once()
|
||||||
|
|
||||||
|
@ -593,16 +334,6 @@ class ExportPlanActionTest(base.TestCase):
|
||||||
error = "Error attempting an operation on container: %s" % self.plan
|
error = "Error attempting an operation on container: %s" % self.plan
|
||||||
self.assertIn(error, result.error)
|
self.assertIn(error, result.error)
|
||||||
|
|
||||||
def test_run_environment_does_not_exist(self):
|
|
||||||
self.mistral.environments.get.side_effect = mistral_base.APIException
|
|
||||||
|
|
||||||
action = plan.ExportPlanAction(self.plan, self.delete_after,
|
|
||||||
self.exports_container)
|
|
||||||
result = action.run(self.ctx)
|
|
||||||
|
|
||||||
error = "The Mistral environment %s could not be found." % self.plan
|
|
||||||
self.assertEqual(error, result.error)
|
|
||||||
|
|
||||||
@mock.patch('tripleo_common.utils.tarball.create_tarball')
|
@mock.patch('tripleo_common.utils.tarball.create_tarball')
|
||||||
def test_run_error_creating_tarball(self, mock_create_tarball):
|
def test_run_error_creating_tarball(self, mock_create_tarball):
|
||||||
mock_create_tarball.side_effect = processutils.ProcessExecutionError
|
mock_create_tarball.side_effect = processutils.ProcessExecutionError
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
import collections
|
import collections
|
||||||
import mock
|
import mock
|
||||||
|
import yaml
|
||||||
|
|
||||||
from swiftclient import exceptions as swiftexceptions
|
from swiftclient import exceptions as swiftexceptions
|
||||||
|
|
||||||
|
@ -47,13 +48,10 @@ class ScaleDownActionTest(base.TestCase):
|
||||||
@mock.patch('heatclient.common.template_utils.'
|
@mock.patch('heatclient.common.template_utils.'
|
||||||
'process_multiple_environments_and_files')
|
'process_multiple_environments_and_files')
|
||||||
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
|
||||||
'get_workflow_client')
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
def test_run(self, mock_get_object_client,
|
def test_run(self, mock_get_object_client,
|
||||||
mock_get_workflow_client, mock_get_template_contents,
|
mock_get_template_contents, mock_env_files,
|
||||||
mock_env_files, mock_get_heat_client,
|
mock_get_heat_client, mock_cache):
|
||||||
mock_cache):
|
|
||||||
|
|
||||||
mock_env_files.return_value = ({}, {})
|
mock_env_files.return_value = ({}, {})
|
||||||
heatclient = mock.MagicMock()
|
heatclient = mock.MagicMock()
|
||||||
|
@ -85,8 +83,17 @@ class ScaleDownActionTest(base.TestCase):
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
swift = mock.MagicMock(url="http://test.com")
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
swift.get_object.side_effect = swiftexceptions.ClientException(
|
mock_env = yaml.safe_dump({
|
||||||
'atest2')
|
'name': 'overcloud',
|
||||||
|
'temp_environment': 'temp_environment',
|
||||||
|
'template': 'template',
|
||||||
|
'environments': [{u'path': u'environments/test.yaml'}]
|
||||||
|
}, default_flow_style=False)
|
||||||
|
swift.get_object.side_effect = (
|
||||||
|
({}, mock_env),
|
||||||
|
({}, mock_env),
|
||||||
|
swiftexceptions.ClientException('atest2')
|
||||||
|
)
|
||||||
mock_get_object_client.return_value = swift
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
env = {
|
env = {
|
||||||
|
@ -95,16 +102,6 @@ class ScaleDownActionTest(base.TestCase):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
|
||||||
mock_env.variables = {
|
|
||||||
'temp_environment': 'temp_environment',
|
|
||||||
'template': 'template',
|
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
|
||||||
}
|
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
|
||||||
|
|
||||||
mock_get_template_contents.return_value = ({}, {
|
mock_get_template_contents.return_value = ({}, {
|
||||||
'heat_template_version': '2016-04-30'
|
'heat_template_version': '2016-04-30'
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
import jinja2
|
import jinja2
|
||||||
import mock
|
import mock
|
||||||
|
import yaml
|
||||||
|
|
||||||
from swiftclient import exceptions as swiftexceptions
|
from swiftclient import exceptions as swiftexceptions
|
||||||
|
|
||||||
|
@ -188,28 +189,23 @@ class ProcessTemplatesActionTest(base.TestCase):
|
||||||
@mock.patch('heatclient.common.template_utils.'
|
@mock.patch('heatclient.common.template_utils.'
|
||||||
'process_multiple_environments_and_files')
|
'process_multiple_environments_and_files')
|
||||||
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
@mock.patch('heatclient.common.template_utils.get_template_contents')
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.'
|
|
||||||
'get_workflow_client')
|
|
||||||
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
|
||||||
def test_run(self, mock_get_object_client,
|
def test_run(self, mock_get_object_client,
|
||||||
mock_get_workflow_client, mock_get_template_contents,
|
mock_get_template_contents,
|
||||||
mock_process_multiple_environments_and_files):
|
mock_process_multiple_environments_and_files):
|
||||||
|
|
||||||
mock_ctx = mock.MagicMock()
|
mock_ctx = mock.MagicMock()
|
||||||
swift = mock.MagicMock(url="http://test.com")
|
swift = mock.MagicMock(url="http://test.com")
|
||||||
swift.get_object.side_effect = swiftexceptions.ClientException(
|
mock_env = yaml.safe_dump({
|
||||||
'atest2')
|
|
||||||
mock_get_object_client.return_value = swift
|
|
||||||
|
|
||||||
mock_mistral = mock.MagicMock()
|
|
||||||
mock_env = mock.MagicMock()
|
|
||||||
mock_env.variables = {
|
|
||||||
'temp_environment': 'temp_environment',
|
'temp_environment': 'temp_environment',
|
||||||
'template': 'template',
|
'template': 'template',
|
||||||
'environments': [{u'path': u'environments/test.yaml'}],
|
'environments': [{u'path': u'environments/test.yaml'}]
|
||||||
}
|
}, default_flow_style=False)
|
||||||
mock_mistral.environments.get.return_value = mock_env
|
swift.get_object.side_effect = (
|
||||||
mock_get_workflow_client.return_value = mock_mistral
|
({}, mock_env),
|
||||||
|
swiftexceptions.ClientException('atest2')
|
||||||
|
)
|
||||||
|
mock_get_object_client.return_value = swift
|
||||||
|
|
||||||
mock_get_template_contents.return_value = ({}, {
|
mock_get_template_contents.return_value = ({}, {
|
||||||
'heat_template_version': '2016-04-30'
|
'heat_template_version': '2016-04-30'
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
# Copyright (c) 2017 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# 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 mock
|
||||||
|
|
||||||
|
from swiftclient import exceptions as swiftexceptions
|
||||||
|
|
||||||
|
from tripleo_common.tests import base
|
||||||
|
from tripleo_common.utils import plan as plan_utils
|
||||||
|
|
||||||
|
|
||||||
|
YAML_CONTENTS = """
|
||||||
|
version: 1.0
|
||||||
|
|
||||||
|
name: overcloud
|
||||||
|
template: overcloud.yaml
|
||||||
|
environments:
|
||||||
|
- path: overcloud-resource-registry-puppet.yaml
|
||||||
|
- path: environments/services/sahara.yaml
|
||||||
|
parameter_defaults:
|
||||||
|
BlockStorageCount: 42
|
||||||
|
OvercloudControlFlavor: yummy
|
||||||
|
passwords:
|
||||||
|
AdminPassword: aaaa
|
||||||
|
ZaqarPassword: zzzz
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class PlanTest(base.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(PlanTest, self).setUp()
|
||||||
|
self.container = 'overcloud'
|
||||||
|
self.swift = mock.MagicMock()
|
||||||
|
self.swift.get_object.return_value = ({}, YAML_CONTENTS)
|
||||||
|
|
||||||
|
def test_get_env(self):
|
||||||
|
env = plan_utils.get_env(self.swift, self.container)
|
||||||
|
|
||||||
|
self.swift.get_object.assert_called()
|
||||||
|
self.assertEqual(env['template'], 'overcloud.yaml')
|
||||||
|
|
||||||
|
def test_get_env_not_found(self):
|
||||||
|
self.swift.get_object.side_effect = swiftexceptions.ClientException
|
||||||
|
|
||||||
|
self. assertRaises(Exception, plan_utils.get_env, self.swift,
|
||||||
|
self.container)
|
||||||
|
|
||||||
|
def test_update_in_env(self):
|
||||||
|
env = plan_utils.get_env(self.swift, self.container)
|
||||||
|
|
||||||
|
updated_env = plan_utils.update_in_env(
|
||||||
|
self.swift,
|
||||||
|
env,
|
||||||
|
'template',
|
||||||
|
'updated-overcloud.yaml'
|
||||||
|
)
|
||||||
|
self.assertEqual(updated_env['template'], 'updated-overcloud.yaml')
|
||||||
|
|
||||||
|
updated_env = plan_utils.update_in_env(
|
||||||
|
self.swift,
|
||||||
|
env,
|
||||||
|
'parameter_defaults',
|
||||||
|
{'another-key': 'another-value'}
|
||||||
|
)
|
||||||
|
self.assertEqual(updated_env['parameter_defaults'], {
|
||||||
|
'BlockStorageCount': 42,
|
||||||
|
'OvercloudControlFlavor': 'yummy',
|
||||||
|
'another-key': 'another-value'
|
||||||
|
})
|
||||||
|
|
||||||
|
updated_env = plan_utils.update_in_env(
|
||||||
|
self.swift,
|
||||||
|
env,
|
||||||
|
'parameter_defaults',
|
||||||
|
delete_key=True
|
||||||
|
)
|
||||||
|
self.assertNotIn('parameter_defaults', updated_env)
|
||||||
|
|
||||||
|
self.swift.get_object.assert_called()
|
||||||
|
self.swift.put_object.assert_called()
|
|
@ -0,0 +1,58 @@
|
||||||
|
# Copyright 2017 Red Hat, Inc.
|
||||||
|
# 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.
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from tripleo_common import constants
|
||||||
|
|
||||||
|
|
||||||
|
def update_in_env(swift, env, key, value='', delete_key=False):
|
||||||
|
"""Update plan environment."""
|
||||||
|
if delete_key:
|
||||||
|
try:
|
||||||
|
del env[key]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
env[key].update(value)
|
||||||
|
except (KeyError, AttributeError):
|
||||||
|
env[key] = value
|
||||||
|
|
||||||
|
put_env(swift, env)
|
||||||
|
return env
|
||||||
|
|
||||||
|
|
||||||
|
def get_env(swift, name):
|
||||||
|
"""Get plan environment from Swift and convert it to a dictionary."""
|
||||||
|
env = yaml.safe_load(
|
||||||
|
swift.get_object(name, constants.PLAN_ENVIRONMENT)[1]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ensure the name is correct, as it will be used to update the
|
||||||
|
# container later
|
||||||
|
if env.get('name') != name:
|
||||||
|
env['name'] = name
|
||||||
|
|
||||||
|
return env
|
||||||
|
|
||||||
|
|
||||||
|
def put_env(swift, env):
|
||||||
|
"""Convert given environment to yaml and upload it to Swift."""
|
||||||
|
swift.put_object(
|
||||||
|
env['name'],
|
||||||
|
constants.PLAN_ENVIRONMENT,
|
||||||
|
yaml.safe_dump(env, default_flow_style=False)
|
||||||
|
)
|
|
@ -68,7 +68,7 @@ workflows:
|
||||||
description: >
|
description: >
|
||||||
If using the default templates or importing templates from a git
|
If using the default templates or importing templates from a git
|
||||||
repository, a new container needs to be created. If using an existing
|
repository, a new container needs to be created. If using an existing
|
||||||
container containing templates, skip straight to create_plan
|
container containing templates, skip straight to create_plan.
|
||||||
on-success:
|
on-success:
|
||||||
- verify_container_doesnt_exist: <% $.use_default_templates or $.source_url %>
|
- verify_container_doesnt_exist: <% $.use_default_templates or $.source_url %>
|
||||||
- create_plan: <% $.use_default_templates = false and $.source_url = null %>
|
- create_plan: <% $.use_default_templates = false and $.source_url = null %>
|
||||||
|
@ -76,18 +76,10 @@ workflows:
|
||||||
verify_container_doesnt_exist:
|
verify_container_doesnt_exist:
|
||||||
action: swift.head_container container=<% $.container %>
|
action: swift.head_container container=<% $.container %>
|
||||||
on-success: notify_zaqar
|
on-success: notify_zaqar
|
||||||
on-error: verify_environment_doesnt_exist
|
|
||||||
publish:
|
|
||||||
status: FAILED
|
|
||||||
message: "Unable to create plan. The Swift container already exists"
|
|
||||||
|
|
||||||
verify_environment_doesnt_exist:
|
|
||||||
action: mistral.environments_get name=<% $.container %>
|
|
||||||
on-success: notify_zaqar
|
|
||||||
on-error: create_container
|
on-error: create_container
|
||||||
publish:
|
publish:
|
||||||
status: FAILED
|
status: FAILED
|
||||||
message: "Unable to create plan. The Mistral environment already exists"
|
message: "Unable to create plan. The Swift container already exists"
|
||||||
|
|
||||||
create_container:
|
create_container:
|
||||||
action: tripleo.plan.create_container container=<% $.container %>
|
action: tripleo.plan.create_container container=<% $.container %>
|
||||||
|
@ -119,11 +111,15 @@ workflows:
|
||||||
on-error: upload_to_container_set_status_failed
|
on-error: upload_to_container_set_status_failed
|
||||||
|
|
||||||
create_plan:
|
create_plan:
|
||||||
action: tripleo.plan.create container=<% $.container %>
|
description: >
|
||||||
|
Migrate the plan if needed, then continue with the workflow.
|
||||||
|
TODO(jpichon) - In Queens, the tripleo.plan.migrate action and on_error will
|
||||||
|
be removed, but the on-success will still be needed.
|
||||||
|
action: tripleo.plan.migrate plan=<% $.container %>
|
||||||
on-success:
|
on-success:
|
||||||
- ensure_passwords_exist: <% $.generate_passwords = true %>
|
- ensure_passwords_exist: <% $.generate_passwords = true %>
|
||||||
- process_templates: <% $.generate_passwords != true %>
|
- process_templates: <% $.generate_passwords != true %>
|
||||||
on-error: create_plan_set_status_failed
|
on-error: migrate_plan_set_status_failed
|
||||||
|
|
||||||
ensure_passwords_exist:
|
ensure_passwords_exist:
|
||||||
action: tripleo.parameters.generate_passwords container=<% $.container %>
|
action: tripleo.parameters.generate_passwords container=<% $.container %>
|
||||||
|
@ -139,7 +135,7 @@ workflows:
|
||||||
on-success: notify_zaqar
|
on-success: notify_zaqar
|
||||||
publish:
|
publish:
|
||||||
status: SUCCESS
|
status: SUCCESS
|
||||||
message: <% task(create_plan).result %>
|
message: 'Plan created.'
|
||||||
|
|
||||||
create_container_set_status_failed:
|
create_container_set_status_failed:
|
||||||
on-success: notify_zaqar
|
on-success: notify_zaqar
|
||||||
|
@ -165,12 +161,6 @@ workflows:
|
||||||
status: FAILED
|
status: FAILED
|
||||||
message: <% task(upload_default_templates).result %>
|
message: <% task(upload_default_templates).result %>
|
||||||
|
|
||||||
create_plan_set_status_failed:
|
|
||||||
on-success: notify_zaqar
|
|
||||||
publish:
|
|
||||||
status: FAILED
|
|
||||||
message: <% task(create_plan).result %>
|
|
||||||
|
|
||||||
ensure_passwords_exist_set_status_failed:
|
ensure_passwords_exist_set_status_failed:
|
||||||
on-success: notify_zaqar
|
on-success: notify_zaqar
|
||||||
publish:
|
publish:
|
||||||
|
@ -183,6 +173,12 @@ workflows:
|
||||||
status: FAILED
|
status: FAILED
|
||||||
message: <% task(process_templates).result %>
|
message: <% task(process_templates).result %>
|
||||||
|
|
||||||
|
migrate_plan_set_status_failed:
|
||||||
|
on-success: notify_zaqar
|
||||||
|
publish:
|
||||||
|
status: FAILED
|
||||||
|
message: <% task(create_plan).result %>
|
||||||
|
|
||||||
notify_zaqar:
|
notify_zaqar:
|
||||||
action: zaqar.queue_post
|
action: zaqar.queue_post
|
||||||
retry: count=5 delay=1
|
retry: count=5 delay=1
|
||||||
|
@ -225,27 +221,31 @@ workflows:
|
||||||
action: tripleo.git.clean container=<% $.container %>
|
action: tripleo.git.clean container=<% $.container %>
|
||||||
|
|
||||||
update_plan:
|
update_plan:
|
||||||
action: tripleo.plan.update container=<% $.container %>
|
description: >
|
||||||
|
Migrate the plan if needed, then continue with the workflow.
|
||||||
|
TODO(jpichon) - In Queens, the tripleo.plan.migrate action and on_error will
|
||||||
|
be removed, but the on-success will still be needed.
|
||||||
|
action: tripleo.plan.migrate plan=<% $.container %>
|
||||||
on-success:
|
on-success:
|
||||||
- ensure_passwords_exist: <% $.generate_passwords = true %>
|
- ensure_passwords_exist: <% $.generate_passwords = true %>
|
||||||
- process_templates: <% $.generate_passwords != true %>
|
- process_templates: <% $.generate_passwords != true %>
|
||||||
on-error: update_plan_set_status_failed
|
on-error: migrate_plan_set_status_failed
|
||||||
|
|
||||||
process_templates:
|
|
||||||
action: tripleo.templates.process container=<% $.container %>
|
|
||||||
on-success: set_status_success
|
|
||||||
on-error: process_templates_set_status_failed
|
|
||||||
|
|
||||||
ensure_passwords_exist:
|
ensure_passwords_exist:
|
||||||
action: tripleo.parameters.generate_passwords container=<% $.container %>
|
action: tripleo.parameters.generate_passwords container=<% $.container %>
|
||||||
on-success: process_templates
|
on-success: process_templates
|
||||||
on-error: ensure_passwords_exist_set_status_failed
|
on-error: ensure_passwords_exist_set_status_failed
|
||||||
|
|
||||||
|
process_templates:
|
||||||
|
action: tripleo.templates.process container=<% $.container %>
|
||||||
|
on-success: set_status_success
|
||||||
|
on-error: process_templates_set_status_failed
|
||||||
|
|
||||||
set_status_success:
|
set_status_success:
|
||||||
on-success: notify_zaqar
|
on-success: notify_zaqar
|
||||||
publish:
|
publish:
|
||||||
status: SUCCESS
|
status: SUCCESS
|
||||||
message: <% task(update_plan).result %>
|
message: 'Plan updated.'
|
||||||
|
|
||||||
clone_git_repo_set_status_failed:
|
clone_git_repo_set_status_failed:
|
||||||
on-success: notify_zaqar
|
on-success: notify_zaqar
|
||||||
|
@ -259,12 +259,6 @@ workflows:
|
||||||
status: FAILED
|
status: FAILED
|
||||||
message: <% task(upload_templates_directory).result %>
|
message: <% task(upload_templates_directory).result %>
|
||||||
|
|
||||||
update_plan_set_status_failed:
|
|
||||||
on-success: notify_zaqar
|
|
||||||
publish:
|
|
||||||
status: FAILED
|
|
||||||
message: <% task(update_plan).result %>
|
|
||||||
|
|
||||||
process_templates_set_status_failed:
|
process_templates_set_status_failed:
|
||||||
on-success: notify_zaqar
|
on-success: notify_zaqar
|
||||||
publish:
|
publish:
|
||||||
|
@ -277,6 +271,12 @@ workflows:
|
||||||
status: FAILED
|
status: FAILED
|
||||||
message: <% task(ensure_passwords_exist).result %>
|
message: <% task(ensure_passwords_exist).result %>
|
||||||
|
|
||||||
|
migrate_plan_set_status_failed:
|
||||||
|
on-success: notify_zaqar
|
||||||
|
publish:
|
||||||
|
status: FAILED
|
||||||
|
message: <% task(update_plan).result %>
|
||||||
|
|
||||||
notify_zaqar:
|
notify_zaqar:
|
||||||
action: zaqar.queue_post
|
action: zaqar.queue_post
|
||||||
retry: count=5 delay=1
|
retry: count=5 delay=1
|
||||||
|
@ -302,15 +302,10 @@ workflows:
|
||||||
|
|
||||||
verify_container_exists:
|
verify_container_exists:
|
||||||
action: swift.head_container container=<% $.container %>
|
action: swift.head_container container=<% $.container %>
|
||||||
on-success: verify_environment_exists
|
on-success: get_environment_passwords
|
||||||
on-error: verify_container_set_status_failed
|
on-error: verify_container_set_status_failed
|
||||||
|
|
||||||
verify_environment_exists:
|
get_environment_passwords:
|
||||||
action: mistral.environments_get name=<% $.container %>
|
|
||||||
on-success: get_environement_passwords
|
|
||||||
on-error: verify_environment_set_status_failed
|
|
||||||
|
|
||||||
get_environement_passwords:
|
|
||||||
action: tripleo.parameters.get_passwords container=<% $.container %>
|
action: tripleo.parameters.get_passwords container=<% $.container %>
|
||||||
on-success: get_passwords_set_status_success
|
on-success: get_passwords_set_status_success
|
||||||
on-error: get_passwords_set_status_failed
|
on-error: get_passwords_set_status_failed
|
||||||
|
@ -319,13 +314,13 @@ workflows:
|
||||||
on-success: notify_zaqar
|
on-success: notify_zaqar
|
||||||
publish:
|
publish:
|
||||||
status: SUCCESS
|
status: SUCCESS
|
||||||
message: <% task(get_environement_passwords).result %>
|
message: <% task(get_environment_passwords).result %>
|
||||||
|
|
||||||
get_passwords_set_status_failed:
|
get_passwords_set_status_failed:
|
||||||
on-success: notify_zaqar
|
on-success: notify_zaqar
|
||||||
publish:
|
publish:
|
||||||
status: FAILED
|
status: FAILED
|
||||||
message: <% task(get_environement_passwords).result %>
|
message: <% task(get_environment_passwords).result %>
|
||||||
|
|
||||||
verify_container_set_status_failed:
|
verify_container_set_status_failed:
|
||||||
on-success: notify_zaqar
|
on-success: notify_zaqar
|
||||||
|
@ -333,12 +328,6 @@ workflows:
|
||||||
status: FAILED
|
status: FAILED
|
||||||
message: <% task(verify_container_exists).result %>
|
message: <% task(verify_container_exists).result %>
|
||||||
|
|
||||||
verify_environment_set_status_failed:
|
|
||||||
on-success: notify_zaqar
|
|
||||||
publish:
|
|
||||||
status: FAILED
|
|
||||||
message: <% task(verify_environment_exists).result %>
|
|
||||||
|
|
||||||
notify_zaqar:
|
notify_zaqar:
|
||||||
action: zaqar.queue_post
|
action: zaqar.queue_post
|
||||||
input:
|
input:
|
||||||
|
|
Loading…
Reference in New Issue