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:
Ana Krivokapic 2017-03-31 20:43:07 +02:00
parent 1c162d61e2
commit bd4e26e823
18 changed files with 802 additions and 1030 deletions

View File

@ -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.

View File

@ -87,8 +87,6 @@ mistral.actions =
tripleo.parameters.generate_passwords = tripleo_common.actions.parameters:GeneratePasswordsAction
tripleo.parameters.get_passwords = tripleo_common.actions.parameters:GetPasswordsAction
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.delete = tripleo_common.actions.plan:DeletePlanAction
tripleo.plan.list = tripleo_common.actions.plan:ListPlansAction
@ -111,3 +109,4 @@ mistral.actions =
tripleo.validations.verify_profiles = tripleo_common.actions.validations:VerifyProfilesAction
# deprecated for pike release, will be removed in queens
tripleo.templates.upload_default = tripleo_common.actions.templates:UploadTemplatesAction
tripleo.plan.migrate = tripleo_common.actions.plan:MigratePlanAction

View File

@ -19,13 +19,13 @@ import time
from heatclient.common import deployment_utils
from heatclient import exc as heat_exc
from mistral.workflow import utils as mistral_workflow_utils
from mistralclient.api import base as mistralclient_exc
from swiftclient import exceptions as swiftexceptions
from tripleo_common.actions import base
from tripleo_common.actions import templates
from tripleo_common import constants
from tripleo_common.utils import overcloudrc
from tripleo_common.utils import plan as plan_utils
LOG = logging.getLogger(__name__)
@ -145,8 +145,7 @@ class DeployStackAction(templates.ProcessTemplatesAction):
stack_is_new = stack is None
# update StackAction, DeployIdentifier and UpdateIdentifier
wc = self.get_workflow_client(context)
wf_env = wc.environments.get(self.container)
swift = self.get_object_client(context)
parameters = dict()
if not self.skip_deploy_identifier:
@ -154,15 +153,22 @@ class DeployStackAction(templates.ProcessTemplatesAction):
parameters['UpdateIdentifier'] = ''
parameters['StackAction'] = 'CREATE' if stack_is_new else 'UPDATE'
if 'parameter_defaults' not in wf_env.variables:
wf_env.variables['parameter_defaults'] = {}
wf_env.variables['parameter_defaults'].update(parameters)
env_kwargs = {
'name': wf_env.name,
'variables': wf_env.variables,
}
# store params changes back to db before call to process templates
wc.environments.update(**env_kwargs)
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)
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
processed_data = super(DeployStackAction, self).run(context)
@ -176,13 +182,12 @@ class DeployStackAction(templates.ProcessTemplatesAction):
stack_args['timeout_mins'] = self.timeout_mins
if stack_is_new:
swift_client = self.get_object_client(context)
try:
swift_client.copy_object(
swift.copy_object(
"%s-swift-rings" % self.container, "swift-rings.tar.gz",
"%s-swift-rings/%s-%d" % (
self.container, "swift-rings.tar.gz", time.time()))
swift_client.delete_object(
swift.delete_object(
"%s-swift-rings" % self.container, "swift-rings.tar.gz")
except swiftexceptions.ClientException:
pass
@ -211,7 +216,7 @@ class OvercloudRcAction(base.TripleOAction):
def run(self, context):
orchestration_client = self.get_orchestration_client(context)
workflow_client = self.get_workflow_client(context)
swift = self.get_object_client(context)
try:
stack = orchestration_client.stacks.get(self.container)
@ -221,26 +226,27 @@ class OvercloudRcAction(base.TripleOAction):
"deployed before calling this action.").format(self.container)
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
# password. If that doesn't exist, we then should look in the
# automatically generated passwords.
# TODO(d0ugal): Abstract this operation somewhere. We shouldn't need to
# know about the structure of the environment to get a password.
try:
parameter_defaults = environment.variables['parameter_defaults']
passwords = environment.variables['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.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')
if admin_pass is None:
admin_pass = passwords['AdminPassword']
except KeyError:
error = ("Unable to find the AdminPassword in the Mistral "
error = ("Unable to find the AdminPassword in the plan "
"environment.")
return mistral_workflow_utils.Result(error=error)

View File

@ -17,9 +17,11 @@ import logging
import yaml
from mistral.workflow import utils as mistral_workflow_utils
from swiftclient import exceptions as swiftexceptions
from tripleo_common.actions import base
from tripleo_common import constants
from tripleo_common.utils import plan as plan_utils
LOG = logging.getLogger(__name__)
@ -40,8 +42,8 @@ class GetCapabilitiesAction(base.TripleOAction):
def run(self, context):
try:
swift_client = self.get_object_client(context)
map_file = swift_client.get_object(
swift = self.get_object_client(context)
map_file = swift.get_object(
self.container, 'capabilities-map.yaml')
capabilities = yaml.safe_load(map_file[1])
except Exception:
@ -50,24 +52,23 @@ class GetCapabilitiesAction(base.TripleOAction):
LOG.exception(err_msg)
return mistral_workflow_utils.Result(error=err_msg)
try:
container_files = swift_client.get_container(self.container)
container_files = swift.get_container(self.container)
container_file_list = [entry['name'] for entry
in container_files[1]]
except Exception as swift_err:
err_msg = ("Error retrieving plan files: %s" % swift_err)
LOG.exception(err_msg)
return mistral_workflow_utils.Result(error=err_msg)
try:
mistral_client = self.get_workflow_client(context)
mistral_env = mistral_client.environments.get(self.container)
except Exception as mistral_err:
err_msg = ("Error retrieving mistral "
"environment. %s" % mistral_err)
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)
selected_envs = [item['path'] for item in
mistral_env.variables['environments']
selected_envs = [item['path'] for item in env['environments']
if 'path' in item]
# extract environment files
@ -138,20 +139,20 @@ class GetCapabilitiesAction(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
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}
the value passed can be false for disabled
environments, these will be removed from the
mistral environment.
plan environment.
: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
defaults to False
:return: the updated mistral environment
:return: the updated plan environment
"""
def __init__(self, environments,
@ -163,46 +164,39 @@ class UpdateCapabilitiesAction(base.TripleOAction):
self.purge_missing = purge_missing
def run(self, context):
mistral_client = self.get_workflow_client(context)
mistral_env = None
swift = self.get_object_client(context)
try:
mistral_env = mistral_client.environments.get(self.container)
except Exception as mistral_err:
err_msg = (
"Error retrieving mistral "
"environment. %s" % mistral_err)
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)
for k, v in self.environments.items():
found = False
if {'path': k} in mistral_env.variables['environments']:
if {'path': k} in env['environments']:
found = True
if v:
if not found:
mistral_env.variables['environments'].append(
{'path': k}
)
env['environments'].append({'path': k})
else:
if found:
mistral_env.variables['environments'].remove({'path': k})
env['environments'].remove({'path': k})
if self.purge_missing:
for env in mistral_env.variables['environments']:
if env.get('path') not in self.environments:
mistral_env.variables['environments'].remove(env)
for e in env['environments']:
if e.get('path') not in self.environments:
env['environments'].remove(e)
self.cache_delete(context, self.container, "tripleo.parameters.get")
env_kwargs = {
'name': mistral_env.name,
'variables': mistral_env.variables
}
try:
mistral_client.environments.update(**env_kwargs)
except Exception as mistral_err:
err_msg = (
"Error retrieving mistral environment. %s" % mistral_err)
plan_utils.put_env(swift, env)
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)
return mistral_env.variables
return env

View File

@ -18,11 +18,13 @@ import time
from heatclient.common import template_utils
from heatclient import exc as heat_exc
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 templates
from tripleo_common import constants
from tripleo_common.update import PackageUpdateManager
from tripleo_common.utils import plan as plan_utils
LOG = logging.getLogger(__name__)
@ -63,24 +65,24 @@ class UpdateStackAction(templates.ProcessTemplatesAction):
parameters['UpdateIdentifier'] = timestamp
parameters['StackAction'] = 'UPDATE'
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)
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)
if 'parameter_defaults' not in wf_env.variables:
wf_env.variables['parameter_defaults'] = {}
wf_env.variables['parameter_defaults'].update(parameters)
env_kwargs = {
'name': wf_env.name,
'variables': wf_env.variables,
}
# 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
processed_data = super(UpdateStackAction, self).run(context)

View File

@ -31,6 +31,7 @@ import uuid
from heatclient import exc as heat_exc
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 templates
@ -38,6 +39,7 @@ from tripleo_common import constants
from tripleo_common.utils import nodes
from tripleo_common.utils import parameters
from tripleo_common.utils import passwords as password_utils
from tripleo_common.utils import plan as plan_utils
LOG = logging.getLogger(__name__)
@ -64,11 +66,18 @@ class GetParametersAction(templates.ProcessTemplatesAction):
processed_data['show_nested'] = True
# respect previously user set param values
wc = self.get_workflow_client(context)
wf_env = wc.environments.get(self.container)
orc = self.get_orchestration_client(context)
swift = self.get_object_client(context)
heat = 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 = {
'template': processed_data['template'],
@ -76,9 +85,10 @@ class GetParametersAction(templates.ProcessTemplatesAction):
'environment': processed_data['environment'],
'show_nested': True
}
result = {
'heat_resource_tree': orc.stacks.validate(**fields),
'mistral_environment_parameters': params,
'heat_resource_tree': heat.stacks.validate(**fields),
'environment_parameters': params,
}
self.cache_set(context,
self.container,
@ -95,25 +105,33 @@ class ResetParametersAction(base.TripleOAction):
self.container = container
def run(self, context):
wc = self.get_workflow_client(context)
wf_env = wc.environments.get(self.container)
swift = self.get_object_client(context)
if 'parameter_defaults' in wf_env.variables:
wf_env.variables.pop('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)
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.container,
"tripleo.parameters.get")
return wf_env
return env
class UpdateParametersAction(base.TripleOAction):
"""Updates Mistral Environment with parameters."""
"""Updates plan environment with parameters."""
def __init__(self, parameters,
container=constants.DEFAULT_CONTAINER_NAME):
@ -122,24 +140,33 @@ class UpdateParametersAction(base.TripleOAction):
self.parameters = parameters
def run(self, context):
wc = self.get_workflow_client(context)
wf_env = wc.environments.get(self.container)
if 'parameter_defaults' not in wf_env.variables:
wf_env.variables['parameter_defaults'] = {}
wf_env.variables['parameter_defaults'].update(self.parameters)
env_kwargs = {
'name': wf_env.name,
'variables': wf_env.variables
}
wc.environments.update(**env_kwargs)
swift = self.get_object_client(context)
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)
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.container,
"tripleo.parameters.get")
return wf_env
return env
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):
super(UpdateRoleParametersAction, self).__init__(parameters=None,
@ -158,8 +185,8 @@ class GeneratePasswordsAction(base.TripleOAction):
"""Generates passwords needed for Overcloud deployment
This method generates passwords and ensures they are stored in the
mistral environment associated with a plan. This method respects
previously generated passwords and adds new passwords as necessary.
plan environment. This method respects previously generated passwords and
adds new passwords as necessary.
"""
def __init__(self, container=constants.DEFAULT_CONTAINER_NAME):
@ -167,45 +194,47 @@ class GeneratePasswordsAction(base.TripleOAction):
self.container = container
def run(self, context):
orchestration = self.get_orchestration_client(context)
wc = 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)
heat = self.get_orchestration_client(context)
swift = self.get_object_client(context)
mistral = self.get_workflow_client(context)
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)
except heat_exc.HTTPNotFound:
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' not in wf_env.variables:
wf_env.variables['passwords'] = {}
# if passwords don't yet exist in plan environment
if 'passwords' not in env:
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
for name, password in passwords.items():
if name not in wf_env.variables['passwords']:
wf_env.variables['passwords'][name] = password
if name not in env['passwords']:
env['passwords'][name] = password
env_kwargs = {
'name': wf_env.name,
'variables': wf_env.variables,
}
try:
plan_utils.put_env(swift, env)
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.container,
"tripleo.parameters.get")
return wf_env.variables['passwords']
return env['passwords']
class GetPasswordsAction(base.TripleOAction):
@ -221,16 +250,18 @@ class GetPasswordsAction(base.TripleOAction):
self.container = container
def run(self, context):
wc = 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)
swift = self.get_object_client(context)
parameter_defaults = wf_env.variables.get('parameter_defaults', {})
passwords = wf_env.variables.get('passwords', {})
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)
parameter_defaults = env.get('parameter_defaults', {})
passwords = env.get('passwords', {})
for name in constants.PASSWORD_PARAMETER_NAMES:
if name in parameter_defaults:
passwords[name] = parameter_defaults[name]

View File

@ -12,7 +12,6 @@
# 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 json
import logging
import os
import shutil
@ -20,6 +19,7 @@ import tempfile
import yaml
from heatclient import exc as heatexceptions
from keystoneauth1 import exceptions as keystoneauth_exc
from mistral.workflow import utils as mistral_workflow_utils
from mistralclient.api import base as mistralclient_base
from oslo_concurrency import processutils
@ -29,6 +29,7 @@ from swiftclient import exceptions as swiftexceptions
from tripleo_common.actions import base
from tripleo_common import constants
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 tarball
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):
"""Creates an object container
@ -122,121 +71,51 @@ class CreateContainerAction(base.TripleOAction):
oc.put_container(self.container, headers=default_container_headers)
class CreatePlanAction(base.TripleOAction, PlanEnvMixin):
"""Creates a plan
class MigratePlanAction(base.TripleOAction):
"""Migrate plan from using a Mistral environment to using Swift
Given a container, creates a Mistral environment with the same name.
The contents of the environment are imported from the plan environment
file, which must contain entries for `template`, `environments` and
`version` at a minimum.
This action creates a plan-environment.yaml file based on the
Mistral environment or the default environment, if the file doesn't
already exist in Swift.
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):
super(CreatePlanAction, self).__init__()
self.container = container
def __init__(self, plan):
super(MigratePlanAction, self).__init__()
self.plan = plan
def run(self, context):
swift = self.get_object_client(context)
mistral = self.get_workflow_client(context)
env_data = {
'name': self.container,
}
from_mistral = False
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:
mistral.environments.get(self.container)
except mistralclient_base.APIException:
# The environment doesn't exist, as expected. Proceed.
pass
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:
env = plan_utils.get_env(swift, self.plan)
except swiftexceptions.ClientException:
# The plan has not been migrated yet. Check if there is a
# Mistral environment.
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)
env = mistral.environments.get(self.plan).variables
from_mistral = True
except (mistralclient_base.APIException,
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'}
]}
class UpdatePlanAction(base.TripleOAction, PlanEnvMixin):
"""Updates a 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)
# Store the environment info into Swift
plan_utils.put_env(swift, env)
if from_mistral:
mistral.environments.delete(self.plan)
class ListPlansAction(base.TripleOAction):
@ -244,23 +123,20 @@ class ListPlansAction(base.TripleOAction):
This action lists all deployment plans residing in the undercloud. A
deployment plan consists of a container marked with metadata
'x-container-meta-usage-tripleo' and a mistral environment with the same
name as the container.
'x-container-meta-usage-tripleo'.
"""
def run(self, context):
# plans consist of a container object and mistral environment
# with the same name. The container is marked with metadata
# to ensure it isn't confused with another container
# Plans consist of a container object marked with metadata to ensure it
# isn't confused with another container
plan_list = []
oc = self.get_object_client(context)
mc = self.get_workflow_client(context)
for item in oc.get_account()[1]:
container = oc.get_container(item['name'])[0]
if constants.TRIPLEO_META_USAGE_KEY in container.keys():
plan_list.append(item['name'])
return list(set(plan_list).intersection(
[env.name for env in mc.environments.list()]))
return list(set(plan_list))
class DeletePlanAction(base.TripleOAction):
@ -293,13 +169,6 @@ class DeletePlanAction(base.TripleOAction):
try:
swift = self.get_object_client(context)
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:
LOG.exception("Swift error deleting plan.")
error_text = ce.msg
@ -326,8 +195,8 @@ class ListRolesAction(base.TripleOAction):
def run(self, context):
try:
oc = self.get_object_client(context)
roles_data = yaml.safe_load(oc.get_object(
swift = self.get_object_client(context)
roles_data = yaml.safe_load(swift.get_object(
self.container, constants.OVERCLOUD_J2_ROLES_NAME)[1])
except Exception as err:
err_msg = ("Error retrieving roles data from deployment plan: %s"
@ -341,11 +210,9 @@ class ListRolesAction(base.TripleOAction):
class ExportPlanAction(base.TripleOAction):
"""Exports a deployment plan
This action exports a deployment plan with a given name. First, the plan
templates are downloaded from the Swift container. Then the plan
environment file is generated from the associated Mistral environment.
Finally, both the templates and the plan environment file are packaged up
in a tarball and uploaded to Swift.
This action exports a deployment plan with a given name. The plan
templates are downloaded from the Swift container, packaged up in a tarball
and uploaded to Swift.
"""
def __init__(self, plan, delete_after, exports_container):
@ -370,15 +237,6 @@ class ExportPlanAction(base.TripleOAction):
with open(path, 'w') as f:
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):
"""Create a tarball containing the tmp_dir and upload it to Swift."""
tarball_name = '%s.tar.gz' % self.plan
@ -397,21 +255,15 @@ class ExportPlanAction(base.TripleOAction):
headers=headers)
def run(self, context):
swift = self.get_object_client(context)
mistral = self.get_workflow_client(context)
swift = self.get_object_client()
tmp_dir = tempfile.mkdtemp()
try:
self._download_templates(swift, tmp_dir)
self._generate_plan_env_file(mistral, tmp_dir)
self._create_and_upload_tarball(swift, tmp_dir)
except swiftexceptions.ClientException as err:
msg = "Error attempting an operation on container: %s" % err
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:
msg = "Error while writing file: %s" % err
return mistral_workflow_utils.Result(error=msg)

View File

@ -27,6 +27,7 @@ from swiftclient import exceptions as swiftexceptions
from tripleo_common.actions import base
from tripleo_common import constants
from tripleo_common.utils import plan as plan_utils
from tripleo_common.utils import tarball
LOG = logging.getLogger(__name__)
@ -240,14 +241,14 @@ class ProcessTemplatesAction(base.TripleOAction):
error_text = None
self.context = context
swift = self.get_object_client(context)
mistral = self.get_workflow_client(context)
try:
mistral_environment = mistral.environments.get(self.container)
except Exception as mistral_err:
error_text = six.text_type(mistral_err)
LOG.exception(
"Error retrieving Mistral Environment: %s" % self.container)
return mistral_workflow_utils.Result(error=error_text)
plan_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:
# 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.")
return mistral_workflow_utils.Result(error=six.text_type(err))
template_name = mistral_environment.variables.get('template')
environments = mistral_environment.variables.get('environments')
template_name = plan_env.get('template')
environments = plan_env.get('environments')
env_paths = []
temp_files = []
@ -285,12 +286,11 @@ class ProcessTemplatesAction(base.TripleOAction):
# them in the appropriate order
merged_params = {}
# merge generated passwords into params first
passwords = mistral_environment.variables.get('passwords', {})
passwords = plan_env.get('passwords', {})
merged_params.update(passwords)
# handle user set parameter values next in case a user has set
# a new value for a password parameter
params = mistral_environment.variables.get(
'parameter_defaults', {})
params = plan_env.get('parameter_defaults', {})
merged_params.update(params)
if merged_params:
env_temp_file = _create_temp_file(

View File

@ -13,13 +13,14 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
import yaml
from heatclient import exc as heat_exc
from mistral.workflow import utils as mistral_workflow_utils
from mistralclient.api import base as mistralclient_exc
from swiftclient import exceptions as swiftexceptions
from tripleo_common.actions import deployment
from tripleo_common import constants
from tripleo_common.tests import base
@ -210,39 +211,35 @@ class DeployStackActionTest(base.TestCase):
@mock.patch('heatclient.common.template_utils.'
'process_multiple_environments_and_files')
@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_orchestration_client')
def test_run(self, get_orchestration_client_mock,
mock_get_object_client, mock_get_workflow_client,
mock_get_template_contents,
mock_get_object_client, mock_get_template_contents,
mock_process_multiple_environments_and_files,
mock_time):
mock_ctx = mock.MagicMock()
# setup swift
swift = mock.MagicMock(url="http://test.com")
swift.get_object.side_effect = swiftexceptions.ClientException(
'atest2')
mock_env = yaml.safe_dump({
'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
heat = mock.MagicMock()
heat.stacks.get.return_value = None
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 = ({}, {
'heat_template_version': '2016-04-30'
})
@ -259,8 +256,20 @@ class DeployStackActionTest(base.TestCase):
'StackAction': 'CREATE',
'UpdateIdentifier': '',
'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(
environment={},
@ -279,39 +288,36 @@ class DeployStackActionTest(base.TestCase):
@mock.patch('heatclient.common.template_utils.'
'process_multiple_environments_and_files')
@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_orchestration_client')
def test_run_skip_deploy_identifier(
self, get_orchestration_client_mock,
mock_get_object_client, mock_get_workflow_client,
mock_get_template_contents,
mock_get_object_client, mock_get_template_contents,
mock_process_multiple_environments_and_files,
mock_time):
mock_ctx = mock.MagicMock()
# setup swift
swift = mock.MagicMock(url="http://test.com")
swift.get_object.side_effect = swiftexceptions.ClientException(
'atest2')
mock_get_object_client.return_value = swift
heat = mock.MagicMock()
heat.stacks.get.return_value = None
get_orchestration_client_mock.return_value = heat
mock_mistral = mock.MagicMock()
mock_env = mock.MagicMock()
mock_env.variables = {
mock_env = yaml.safe_dump({
'name': constants.DEFAULT_CONTAINER_NAME,
'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
}, default_flow_style=False)
swift.get_object.side_effect = (
({}, mock_env),
({}, mock_env),
swiftexceptions.ClientException('atest2')
)
mock_get_template_contents.return_value = ({}, {
'heat_template_version': '2016-04-30'
@ -326,11 +332,21 @@ class DeployStackActionTest(base.TestCase):
action.run(mock_ctx)
# verify parameters are as expected
expected_defaults = {'StackAction': 'CREATE',
'UpdateIdentifier': '',
'random_existing_data': 'a_value'}
self.assertEqual(expected_defaults,
mock_env.variables['parameter_defaults'])
mock_env_updated = yaml.safe_dump({
'name': constants.DEFAULT_CONTAINER_NAME,
'temp_environment': 'temp_environment',
'parameter_defaults': {'StackAction': 'CREATE',
'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(
environment={},
@ -347,13 +363,11 @@ class DeployStackActionTest(base.TestCase):
class OvercloudRcActionTestCase(base.TestCase):
@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_stack(self, mock_get_orchestration,
mock_get_workflow):
def test_no_stack(self, mock_get_orchestration, mock_get_object):
mock_ctx = mock.MagicMock()
@ -369,59 +383,64 @@ class OvercloudRcActionTestCase(base.TestCase):
))
@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_env(self, mock_get_orchestration,
mock_get_workflow):
def test_no_env(self, mock_get_orchestration, mock_get_object):
mock_ctx = mock.MagicMock()
not_found = mistralclient_exc.APIException()
mock_get_workflow.return_value.environments.get.side_effect = not_found
mock_get_object.return_value.get_object.side_effect = (
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")
result = action.run(mock_ctx)
self.assertEqual(
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.'
'get_workflow_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.")
'get_object_client')
@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.'
'get_orchestration_client')
def test_no_success(self, mock_get_orchestration,
mock_get_workflow, mock_create_overcloudrc):
def test_success(self, mock_get_orchestration, mock_create_overcloudrc,
mock_get_object):
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 = {
"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")
result = action.run(mock_ctx)

View File

@ -16,6 +16,7 @@ import mock
import yaml
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.tests import base
@ -155,38 +156,40 @@ class GetCapabilitiesActionTest(base.TestCase):
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_workflow_client')
def test_run_mistral_error(self, get_workflow_client_mock,
get_obj_client_mock):
def test_run_env_missing(self, get_obj_client_mock):
mock_ctx = mock.MagicMock()
# setup swift
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
# 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)
expected = mistral_workflow_utils.Result(
data=None,
error="Error retrieving mistral environment. ")
error="Error retrieving environment for plan test-container: "
"test-container")
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_workflow_client')
def test_run(self, get_workflow_client_mock, get_obj_client_mock):
def test_run(self, get_obj_client_mock):
mock_ctx = mock.MagicMock()
# setup swift
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 = ({
u'x-container-meta-usage-tripleo': u'plan',
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
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)
yaml_mapping = yaml.safe_load(MAPPING_JSON_CONTENTS)
self.assertEqual(yaml_mapping, action.run(mock_ctx))
@ -242,23 +233,21 @@ class UpdateCapabilitiesActionTest(base.TestCase):
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'cache_delete')
@mock.patch(
'tripleo_common.actions.base.TripleOAction.get_workflow_client')
def test_run(self, get_workflow_client_mock, mock_cache):
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
def test_run(self, get_object_client_mock, mock_cache):
mock_ctx = mock.MagicMock()
# setup mistral
mistral = mock.MagicMock()
mocked_env = mock.MagicMock()
mocked_env.variables = {
'environments': [
{'path': '/path/to/overcloud-default-env.yaml'},
{'path': '/path/to/ceph-storage-env.yaml'},
]
}
mistral.environments.get.return_value = mocked_env
get_workflow_client_mock.return_value = mistral
# setup swift
swift = mock.MagicMock()
mocked_env = """
name: test-container
environments:
- path: /path/to/overcloud-default-env.yaml
- path: /path/to/ceph-storage-env.yaml
"""
swift.get_object.return_value = ({}, mocked_env)
get_object_client_mock.return_value = swift
environments = {
'/path/to/ceph-storage-env.yaml': False,
@ -269,6 +258,7 @@ class UpdateCapabilitiesActionTest(base.TestCase):
action = heat_capabilities.UpdateCapabilitiesAction(
environments, self.container_name)
self.assertEqual({
'name': 'test-container',
'environments': [
{'path': '/path/to/overcloud-default-env.yaml'},
{'path': '/path/to/poc-custom-env.yaml'}
@ -284,22 +274,21 @@ class UpdateCapabilitiesActionTest(base.TestCase):
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'cache_delete')
@mock.patch(
'tripleo_common.actions.base.TripleOAction.get_workflow_client')
def test_run_purge_missing(self, get_workflow_client_mock, mock_cache):
'tripleo_common.actions.base.TripleOAction.get_object_client')
def test_run_purge_missing(self, get_object_client_mock, mock_cache):
mock_ctx = mock.MagicMock()
# setup mistral
mistral = mock.MagicMock()
mocked_env = mock.MagicMock()
mocked_env.variables = {
'environments': [
{'path': '/path/to/overcloud-default-env.yaml'},
{'path': '/path/to/ceph-storage-env.yaml'},
]
}
mistral.environments.get.return_value = mocked_env
get_workflow_client_mock.return_value = mistral
# setup swift
swift = mock.MagicMock()
mocked_env = """
name: test-container
environments:
- path: /path/to/overcloud-default-env.yaml
- path: /path/to/ceph-storage-env.yaml
"""
swift.get_object.return_value = ({}, mocked_env)
get_object_client_mock.return_value = swift
environments = {
'/path/to/overcloud-default-env.yaml': True,
@ -310,6 +299,7 @@ class UpdateCapabilitiesActionTest(base.TestCase):
action = heat_capabilities.UpdateCapabilitiesAction(
environments, self.container_name, True)
self.assertEqual({
'name': 'test-container',
'environments': [
{'path': '/path/to/overcloud-default-env.yaml'},
{'path': '/path/to/poc-custom-env.yaml'}
@ -321,28 +311,21 @@ class UpdateCapabilitiesActionTest(base.TestCase):
"tripleo.parameters.get"
)
@mock.patch(
'tripleo_common.actions.base.TripleOAction.get_object_client')
@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.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
def test_run_env_missing(self, get_obj_client_mock):
mock_ctx = mock.MagicMock()
# setup swift
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
# setup mistral
mistral = mock.MagicMock()
mistral.environments.get = mock.Mock(
side_effect=Exception)
get_workflow_client_mock.return_value = mistral
action = heat_capabilities.UpdateCapabilitiesAction(
{}, self.container_name)
expected = mistral_workflow_utils.Result(
data=None,
error="Error retrieving mistral environment. ")
error="Error retrieving environment for plan test-container: "
"test-container"
)
self.assertEqual(expected, action.run(mock_ctx))

View File

@ -15,6 +15,7 @@
import mock
from tripleo_common.actions import package_update
from tripleo_common import constants
from tripleo_common.tests import base
@ -57,8 +58,7 @@ class UpdateStackActionTest(base.TestCase):
self.container = 'container'
@mock.patch('tripleo_common.actions.templates.ProcessTemplatesAction.run')
@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_orchestration_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
@ -69,10 +69,10 @@ class UpdateStackActionTest(base.TestCase):
mock_time,
mock_compute_client,
mock_orchestration_client,
mock_workflow_client,
mock_templates_run
):
mock_object_client,
mock_templates_run):
mock_ctx = mock.MagicMock()
heat = mock.MagicMock()
heat.stacks.get.return_value = mock.MagicMock(
stack_name='stack', id='stack_id')
@ -81,16 +81,17 @@ class UpdateStackActionTest(base.TestCase):
mock_template_contents.return_value = ({}, {
'heat_template_version': '2016-04-30'
})
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_data': 'a_value'},
}
mock_mistral.environments.get.return_value = mock_env
mock_workflow_client.return_value = mock_mistral
mock_swift = mock.MagicMock()
mock_env = """environments:
- path: environments/test.yaml
name: container
parameter_defaults:
random_data: a_value
temp_environment: temp_environment
template: template
"""
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)
mock_time.time.return_value = 1473366264
@ -106,16 +107,21 @@ class UpdateStackActionTest(base.TestCase):
action.run(mock_ctx)
# verify parameters are as expected
expected_defaults = {
'StackAction': 'UPDATE',
'DeployIdentifier': 1473366264,
'UpdateIdentifier': 1473366264,
'random_data': 'a_value',
}
self.assertEqual(
expected_defaults, mock_env.variables['parameter_defaults'])
updated_mock_env = """environments:
- path: environments/test.yaml
name: container
parameter_defaults:
DeployIdentifier: 1473366264
StackAction: UPDATE
UpdateIdentifier: 1473366264
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(
'stack_id',
StackAction='UPDATE',

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
import yaml
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('tripleo_common.actions.base.TripleOAction.'
'get_orchestration_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'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_orchestration_client,
mock_get_orchestration_client,
mock_get_template_contents,
mock_process_multiple_environments_and_files,
mock_cache_get,
@ -159,19 +158,17 @@ class GetParametersActionTest(base.TestCase):
mock_ctx = mock.MagicMock()
swift = mock.MagicMock(url="http://test.com")
swift.get_object.side_effect = swiftexceptions.ClientException(
'atest2')
mock_get_object_client.return_value = swift
mock_mistral = mock.MagicMock()
mock_env = mock.MagicMock()
mock_env.variables = {
mock_env = yaml.safe_dump({
'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
'environments': [{u'path': u'environments/test.yaml'}]
}, default_flow_style=False)
swift.get_object.side_effect = (
({}, mock_env),
swiftexceptions.ClientException('atest2'),
({}, mock_env)
)
mock_get_object_client.return_value = swift
mock_get_template_contents.return_value = ({}, {
'heat_template_version': '2016-04-30'
@ -201,7 +198,7 @@ class GetParametersActionTest(base.TestCase):
mock_ctx,
"overcloud",
"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.'
'cache_delete')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_workflow_client')
def test_run(self, mock_get_workflow_client,
mock_cache):
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
def test_run(self, mock_get_object_client, mock_cache):
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,
'template': 'template',
'environments': [{u'path': u'environments/test.yaml'}],
'parameter_defaults': {'SomeTestParameter': 42}
}
mock_mistral.environments.get.return_value = mock_env
mock_get_workflow_client.return_value = mock_mistral
}, default_flow_style=False)
swift.get_object.return_value = ({}, mock_env)
mock_get_object_client.return_value = swift
# Test
action = parameters.ResetParametersAction()
action.run(mock_ctx)
mock_mistral.environments.update.assert_called_once_with(
name=constants.DEFAULT_CONTAINER_NAME,
variables={
'template': 'template',
'environments': [{u'path': u'environments/test.yaml'}],
}
mock_env_reset = yaml.safe_dump({
'name': constants.DEFAULT_CONTAINER_NAME,
'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_reset
)
mock_cache.assert_called_once_with(
mock_ctx,
@ -246,34 +248,38 @@ class UpdateParametersActionTest(base.TestCase):
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'cache_delete')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_workflow_client')
def test_run(self, mock_get_workflow_client, mock_cache):
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
def test_run(self, mock_get_object_client, mock_cache):
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,
'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
}, default_flow_style=False)
swift.get_object.return_value = ({}, mock_env)
mock_get_object_client.return_value = swift
# Test
test_parameters = {'SomeTestParameter': 42}
action = parameters.UpdateParametersAction(test_parameters)
action.run(mock_ctx)
mock_mistral.environments.update.assert_called_once_with(
name=constants.DEFAULT_CONTAINER_NAME,
variables={
'temp_environment': 'temp_environment',
'template': 'template',
'environments': [{u'path': u'environments/test.yaml'}],
'parameter_defaults': {'SomeTestParameter': 42}}
mock_env_updated = yaml.safe_dump({
'name': constants.DEFAULT_CONTAINER_NAME,
'temp_environment': 'temp_environment',
'parameter_defaults': {'SomeTestParameter': 42},
'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
)
mock_cache.assert_called_once_with(
mock_ctx,
@ -291,19 +297,18 @@ class UpdateRoleParametersActionTest(base.TestCase):
'get_baremetal_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_compute_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_workflow_client')
def test_run(self, mock_get_workflow_client,
mock_get_compute_client, mock_get_baremetal_client,
mock_set_count_and_flavor, mock_cache):
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
def test_run(self, mock_get_object_client, mock_get_compute_client,
mock_get_baremetal_client, mock_set_count_and_flavor,
mock_cache):
mock_ctx = mock.MagicMock()
mock_mistral = mock.MagicMock()
mock_env = mock.MagicMock()
mock_env.name = 'overcast'
mock_env.variables = {}
mock_mistral.environments.get.return_value = mock_env
mock_get_workflow_client.return_value = mock_mistral
swift = mock.MagicMock(url="http://test.com")
mock_env = yaml.safe_dump({'name': 'overcast'},
default_flow_style=False)
swift.get_object.return_value = ({}, mock_env)
mock_get_object_client.return_value = swift
params = {'CephStorageCount': 1,
'OvercloudCephStorageFlavor': 'ceph-storage'}
@ -313,8 +318,16 @@ class UpdateRoleParametersActionTest(base.TestCase):
'overcast')
action.run(mock_ctx)
mock_mistral.environments.update.assert_called_once_with(
name='overcast', variables={'parameter_defaults': params})
mock_env_updated = yaml.safe_dump({
'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_ctx,
"overcast",
@ -332,23 +345,24 @@ class GeneratePasswordsActionTest(base.TestCase):
'get_snmpd_readonly_user_password')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'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_orchestration_client, mock_cache):
mock_get_snmpd_readonly_user_password.return_value = "TestPassword"
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': 'overcast',
'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
}, default_flow_style=False)
swift.get_object.return_value = ({}, mock_env)
mock_get_object_client.return_value = swift
mock_orchestration = mock.MagicMock()
mock_orchestration.stacks.environment.return_value = {
@ -378,7 +392,9 @@ class GeneratePasswordsActionTest(base.TestCase):
'get_snmpd_readonly_user_password')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'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_create_ssh_keypair,
mock_get_orchestration_client,
@ -389,17 +405,17 @@ class GeneratePasswordsActionTest(base.TestCase):
'private_key': 'Bar'}
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,
'temp_environment': 'temp_environment',
'template': 'template',
'environments': [{u'path': u'environments/test.yaml'}],
'passwords': _EXISTING_PASSWORDS.copy()
}
mock_mistral.environments.get.return_value = mock_env
mock_get_workflow_client.return_value = mock_mistral
}, default_flow_style=False)
swift.get_object.return_value = ({}, mock_env)
mock_get_object_client.return_value = swift
mock_orchestration = mock.MagicMock()
mock_orchestration.stacks.environment.return_value = {
@ -428,7 +444,9 @@ class GeneratePasswordsActionTest(base.TestCase):
'get_snmpd_readonly_user_password')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'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_create_ssh_keypair,
mock_get_orchestration_client,
@ -442,17 +460,17 @@ class GeneratePasswordsActionTest(base.TestCase):
existing_passwords.pop("AdminPassword")
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,
'temp_environment': 'temp_environment',
'template': 'template',
'environments': [{u'path': u'environments/test.yaml'}],
'passwords': existing_passwords.copy()
}
mock_mistral.environments.get.return_value = mock_env
mock_get_workflow_client.return_value = mock_mistral
}, default_flow_style=False)
swift.get_object.return_value = ({}, mock_env)
mock_get_object_client.return_value = swift
mock_orchestration = mock.MagicMock()
mock_orchestration.stacks.environment.return_value = {
@ -479,22 +497,20 @@ class GetPasswordsActionTest(base.TestCase):
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_orchestration_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_workflow_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
def test_password_from_parameter_defaults(self,
mock_get_workflow_client,
mock_get_object_client,
mock_get_orchestration_client):
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
mock_get_workflow_client.return_value = mock_mistral
swift = mock.MagicMock(url="http://test.com")
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_get_orchestration_client.return_value = mock_orchestration
@ -507,24 +523,22 @@ class GetPasswordsActionTest(base.TestCase):
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_orchestration_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_workflow_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
def test_password_from_generated_passwords(self,
mock_get_workflow_client,
mock_get_object_client,
mock_get_orchestration_client):
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": {},
"passwords": _EXISTING_PASSWORDS,
}
mock_mistral.environments.get.return_value = mock_env
mock_get_workflow_client.return_value = mock_mistral
}, default_flow_style=False)
swift.get_object.return_value = ({}, mock_env)
mock_get_object_client.return_value = swift
mock_orchestration = mock.MagicMock()
mock_get_orchestration_client.return_value = mock_orchestration
@ -537,26 +551,25 @@ class GetPasswordsActionTest(base.TestCase):
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_orchestration_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_workflow_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
def test_password_merging_passwords(self,
mock_get_workflow_client,
mock_get_object_client,
mock_get_orchestration_client):
parameter_defaults = _EXISTING_PASSWORDS.copy()
passwords = {"AdminPassword": parameter_defaults.pop("AdminPassword")}
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": passwords
}
}, 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_get_orchestration_client.return_value = mock_orchestration
@ -570,19 +583,13 @@ class GetPasswordsActionTest(base.TestCase):
class GenerateFencingParametersActionTestCase(base.TestCase):
@mock.patch('tripleo_common.utils.nodes.'
'generate_hostmap')
@mock.patch('tripleo_common.utils.nodes.generate_hostmap')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_compute_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_baremetal_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_workflow_client')
@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):
def test_no_success(self, mock_get_baremetal, mock_get_compute,
mock_generate_hostmap):
mock_ctx = mock.MagicMock()
test_hostmap = {
"00:11:22:33:44:55": {
@ -678,35 +685,37 @@ class GenerateFencingParametersActionTestCase(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.'
'process_multiple_environments_and_files')
@mock.patch('heatclient.common.template_utils.get_template_contents')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_orchestration_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_workflow_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
def test_empty_resource_tree(self, mock_get_object_client,
mock_get_workflow_client,
mock_get_orchestration_client,
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_cache_get.return_value = None
swift = mock.MagicMock(url="http://test.com")
swift.get_object.side_effect = swiftexceptions.ClientException(
'atest2')
mock_get_object_client.return_value = swift
mock_mistral = mock.MagicMock()
mock_env = mock.MagicMock()
mock_env.variables = {
mock_env = yaml.safe_dump({
'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
'environments': [{u'path': u'environments/test.yaml'}]
}, default_flow_style=False)
swift.get_object.side_effect = (
({}, mock_env),
swiftexceptions.ClientException('atest2'),
({}, mock_env)
)
mock_get_object_client.return_value = swift
mock_get_template_contents.return_value = ({}, {
'heat_template_version': '2016-04-30'
@ -720,7 +729,7 @@ class GetFlattenedParametersActionTest(base.TestCase):
expected_value = {
'heat_resource_tree': {},
'mistral_environment_parameters': None,
'environment_parameters': None,
}
# Test
@ -734,37 +743,39 @@ class GetFlattenedParametersActionTest(base.TestCase):
)
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('heatclient.common.template_utils.'
'process_multiple_environments_and_files')
@mock.patch('heatclient.common.template_utils.get_template_contents')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_orchestration_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.'
'get_workflow_client')
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
def test_valid_resource_tree(self, mock_get_object_client,
mock_get_workflow_client,
mock_get_orchestration_client,
mock_get_template_contents,
mock_process_multiple_environments_and_files,
mock_uuid):
mock_uuid,
mock_cache_get,
mock_cache_set):
mock_ctx = mock.MagicMock()
mock_cache_get.return_value = None
swift = mock.MagicMock(url="http://test.com")
swift.get_object.side_effect = swiftexceptions.ClientException(
'atest2')
mock_get_object_client.return_value = swift
mock_mistral = mock.MagicMock()
mock_env = mock.MagicMock()
mock_env.variables = {
mock_env = yaml.safe_dump({
'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
'environments': [{u'path': u'environments/test.yaml'}]
}, default_flow_style=False)
swift.get_object.side_effect = (
({}, mock_env),
swiftexceptions.ClientException('atest2'),
({}, mock_env)
)
mock_get_object_client.return_value = swift
mock_get_template_contents.return_value = ({}, {
'heat_template_version': '2016-04-30'
@ -816,7 +827,7 @@ class GetFlattenedParametersActionTest(base.TestCase):
}
},
},
'mistral_environment_parameters': None,
'environment_parameters': None,
}
# Test

View File

@ -12,40 +12,19 @@
# 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 json
import mock
from heatclient import exc as heatexceptions
from mistral.workflow import utils as mistral_workflow_utils
from mistralclient.api import base as mistral_base
from oslo_concurrency import processutils
from swiftclient import exceptions as swiftexceptions
from tripleo_common.actions import plan
from tripleo_common import constants
from tripleo_common import exception
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)
YAML_CONTENTS = """
ENV_YAML_CONTENTS = """
version: 1.0
template: overcloud.yaml
@ -60,13 +39,6 @@ passwords:
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:
Controller:
@ -160,197 +132,6 @@ class CreateContainerActionTest(base.TestCase):
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):
def setUp(self):
@ -359,9 +140,7 @@ class ListPlansActionTest(base.TestCase):
self.ctx = mock.MagicMock()
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
@mock.patch(
'tripleo_common.actions.base.TripleOAction.get_workflow_client')
def test_run(self, get_workflow_client_mock, get_obj_client_mock):
def test_run(self, get_obj_client_mock):
# setup swift
swift = mock.MagicMock()
@ -377,13 +156,6 @@ class ListPlansActionTest(base.TestCase):
}, [])
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
action = plan.ListPlansAction()
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_orchestration_client')
@mock.patch(
'tripleo_common.actions.base.TripleOAction.get_workflow_client')
def test_run(self, get_workflow_client_mock, get_orchestration_client,
get_obj_client_mock):
def test_run(self, get_orchestration_client, get_obj_client_mock):
# setup swift
swift = mock.MagicMock()
@ -445,15 +214,6 @@ class DeletePlanActionTest(base.TestCase):
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
heat = mock.MagicMock()
heat.stacks.get = mock.Mock(
@ -474,8 +234,6 @@ class DeletePlanActionTest(base.TestCase):
swift.delete_container.assert_called_with(self.container_name)
mistral.environments.delete.assert_called_with(self.container_name)
class RoleListActionTest(base.TestCase):
@ -486,7 +244,6 @@ class RoleListActionTest(base.TestCase):
@mock.patch('tripleo_common.actions.base.TripleOAction.get_object_client')
def test_run(self, get_obj_client_mock):
# setup swift
swift = mock.MagicMock()
swift.get_object.return_value = ({}, ROLES_DATA_YAML_CONTENTS)
@ -542,21 +299,6 @@ class ExportPlanActionTest(base.TestCase):
swift_patcher.start()
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()
@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_object.assert_has_calls(
get_object_mock_calls, any_order=True)
self.mistral.environments.get.assert_called_once_with(self.plan)
self.swift.put_object.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
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')
def test_run_error_creating_tarball(self, mock_create_tarball):
mock_create_tarball.side_effect = processutils.ProcessExecutionError

View File

@ -14,6 +14,7 @@
# under the License.
import collections
import mock
import yaml
from swiftclient import exceptions as swiftexceptions
@ -47,13 +48,10 @@ class ScaleDownActionTest(base.TestCase):
@mock.patch('heatclient.common.template_utils.'
'process_multiple_environments_and_files')
@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')
def test_run(self, mock_get_object_client,
mock_get_workflow_client, mock_get_template_contents,
mock_env_files, mock_get_heat_client,
mock_cache):
mock_get_template_contents, mock_env_files,
mock_get_heat_client, mock_cache):
mock_env_files.return_value = ({}, {})
heatclient = mock.MagicMock()
@ -85,8 +83,17 @@ class ScaleDownActionTest(base.TestCase):
mock_ctx = mock.MagicMock()
swift = mock.MagicMock(url="http://test.com")
swift.get_object.side_effect = swiftexceptions.ClientException(
'atest2')
mock_env = yaml.safe_dump({
'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
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 = ({}, {
'heat_template_version': '2016-04-30'
})

View File

@ -14,6 +14,7 @@
# under the License.
import jinja2
import mock
import yaml
from swiftclient import exceptions as swiftexceptions
@ -188,28 +189,23 @@ class ProcessTemplatesActionTest(base.TestCase):
@mock.patch('heatclient.common.template_utils.'
'process_multiple_environments_and_files')
@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')
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_ctx = mock.MagicMock()
swift = mock.MagicMock(url="http://test.com")
swift.get_object.side_effect = swiftexceptions.ClientException(
'atest2')
mock_get_object_client.return_value = swift
mock_mistral = mock.MagicMock()
mock_env = mock.MagicMock()
mock_env.variables = {
mock_env = yaml.safe_dump({
'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
'environments': [{u'path': u'environments/test.yaml'}]
}, default_flow_style=False)
swift.get_object.side_effect = (
({}, mock_env),
swiftexceptions.ClientException('atest2')
)
mock_get_object_client.return_value = swift
mock_get_template_contents.return_value = ({}, {
'heat_template_version': '2016-04-30'

View File

@ -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()

View File

@ -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)
)

View File

@ -68,7 +68,7 @@ workflows:
description: >
If using the default templates or importing templates from a git
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:
- verify_container_doesnt_exist: <% $.use_default_templates or $.source_url %>
- create_plan: <% $.use_default_templates = false and $.source_url = null %>
@ -76,18 +76,10 @@ workflows:
verify_container_doesnt_exist:
action: swift.head_container container=<% $.container %>
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
publish:
status: FAILED
message: "Unable to create plan. The Mistral environment already exists"
message: "Unable to create plan. The Swift container already exists"
create_container:
action: tripleo.plan.create_container container=<% $.container %>
@ -119,11 +111,15 @@ workflows:
on-error: upload_to_container_set_status_failed
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:
- ensure_passwords_exist: <% $.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:
action: tripleo.parameters.generate_passwords container=<% $.container %>
@ -139,7 +135,7 @@ workflows:
on-success: notify_zaqar
publish:
status: SUCCESS
message: <% task(create_plan).result %>
message: 'Plan created.'
create_container_set_status_failed:
on-success: notify_zaqar
@ -165,12 +161,6 @@ workflows:
status: FAILED
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:
on-success: notify_zaqar
publish:
@ -183,6 +173,12 @@ workflows:
status: FAILED
message: <% task(process_templates).result %>
migrate_plan_set_status_failed:
on-success: notify_zaqar
publish:
status: FAILED
message: <% task(create_plan).result %>
notify_zaqar:
action: zaqar.queue_post
retry: count=5 delay=1
@ -225,27 +221,31 @@ workflows:
action: tripleo.git.clean container=<% $.container %>
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:
- ensure_passwords_exist: <% $.generate_passwords = true %>
- process_templates: <% $.generate_passwords != true %>
on-error: update_plan_set_status_failed
process_templates:
action: tripleo.templates.process container=<% $.container %>
on-success: set_status_success
on-error: process_templates_set_status_failed
on-error: migrate_plan_set_status_failed
ensure_passwords_exist:
action: tripleo.parameters.generate_passwords container=<% $.container %>
on-success: process_templates
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:
on-success: notify_zaqar
publish:
status: SUCCESS
message: <% task(update_plan).result %>
message: 'Plan updated.'
clone_git_repo_set_status_failed:
on-success: notify_zaqar
@ -259,12 +259,6 @@ workflows:
status: FAILED
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:
on-success: notify_zaqar
publish:
@ -277,6 +271,12 @@ workflows:
status: FAILED
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:
action: zaqar.queue_post
retry: count=5 delay=1
@ -302,15 +302,10 @@ workflows:
verify_container_exists:
action: swift.head_container container=<% $.container %>
on-success: verify_environment_exists
on-success: get_environment_passwords
on-error: verify_container_set_status_failed
verify_environment_exists:
action: mistral.environments_get name=<% $.container %>
on-success: get_environement_passwords
on-error: verify_environment_set_status_failed
get_environement_passwords:
get_environment_passwords:
action: tripleo.parameters.get_passwords container=<% $.container %>
on-success: get_passwords_set_status_success
on-error: get_passwords_set_status_failed
@ -319,13 +314,13 @@ workflows:
on-success: notify_zaqar
publish:
status: SUCCESS
message: <% task(get_environement_passwords).result %>
message: <% task(get_environment_passwords).result %>
get_passwords_set_status_failed:
on-success: notify_zaqar
publish:
status: FAILED
message: <% task(get_environement_passwords).result %>
message: <% task(get_environment_passwords).result %>
verify_container_set_status_failed:
on-success: notify_zaqar
@ -333,12 +328,6 @@ workflows:
status: FAILED
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:
action: zaqar.queue_post
input: