From 49c169a144b6bbe23f1f1ff525183ce8c0351fc1 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Tue, 3 Apr 2018 23:18:11 +0000 Subject: [PATCH] Action to perform container image prepare This action runs in the deployment workflow just after validation. It does the following: - Fetches the plan, environment files and role data - Builds a merged environment from the fetched plans - If a ContainerImagePrepare parameter is defined, do a dry-run prepare to determine the image parameters for when the actual prepare is run during the deployment. - Write the resulting image parameters to environments/containers-default-parameters.yaml and insert that file into the environments file list in the plan If no ContainerImagePrepare parameter, this action has no effect, so it can be inserted into the deployment workflow now without affecting any existing image prepare. This dry-run prepare is the same approach used for containerized undercloud deployment. Doing a dry-run is fast compared to a full deploy because there are no image transfers or build performed, only inspect calls to image registries. The actual prepare will be done during the deployment when change I8b0c5e630e63ef6a2e6f70f1eb00fd02f4cfd1c0 lands. Change-Id: Ifb1f81d4f7db3efd2799beca8705957e29ba16bd Blueprint: container-prepare-workflow --- setup.cfg | 1 + tripleo_common/actions/container_images.py | 74 ++++++++++++++++++- .../tests/actions/test_container_images.py | 53 +++++++++++++ workbooks/deployment.yaml | 11 ++- 4 files changed, 137 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 667d859da..e75d5f369 100644 --- a/setup.cfg +++ b/setup.cfg @@ -82,6 +82,7 @@ mistral.actions = tripleo.config.download_config = tripleo_common.actions.config:DownloadConfigAction tripleo.config.get_overcloud_config = tripleo_common.actions.config:GetOvercloudConfig tripleo.container_images.prepare = tripleo_common.actions.container_images:PrepareContainerImageEnv + tripleo.container_images.prepare_params = tripleo_common.actions.container_images:PrepareContainerImageParameters tripleo.deployment.config = tripleo_common.actions.deployment:OrchestrationDeployAction tripleo.deployment.deploy = tripleo_common.actions.deployment:DeployStackAction tripleo.deployment.get_deployment_failures = tripleo_common.actions.deployment:DeploymentFailuresAction diff --git a/tripleo_common/actions/container_images.py b/tripleo_common/actions/container_images.py index f53e15d3e..b7e15e1f6 100644 --- a/tripleo_common/actions/container_images.py +++ b/tripleo_common/actions/container_images.py @@ -13,12 +13,12 @@ # License for the specific language governing permissions and limitations # under the License. - import logging import os import sys from mistral_lib import actions +import six from swiftclient import exceptions as swiftexceptions import yaml @@ -26,6 +26,7 @@ from tripleo_common.actions import base from tripleo_common.actions import heat_capabilities from tripleo_common import constants from tripleo_common.image import kolla_builder +from tripleo_common.utils import plan as plan_utils LOG = logging.getLogger(__name__) @@ -81,3 +82,74 @@ class PrepareContainerImageEnv(base.TripleOAction): update_action = heat_capabilities.UpdateCapabilitiesAction( environments, container=self.container) return update_action.run(context) + + +class PrepareContainerImageParameters(base.TripleOAction): + """Populate environment with image params + + """ + + def __init__(self, container=constants.DEFAULT_CONTAINER_NAME): + super(PrepareContainerImageParameters, self).__init__() + self.container = container + + def _get_role_data(self, swift): + try: + j2_role_file = swift.get_object( + self.container, constants.OVERCLOUD_J2_ROLES_NAME)[1] + role_data = yaml.safe_load(j2_role_file) + except swiftexceptions.ClientException: + LOG.info("No %s file found, not filtering container images by role" + % constants.OVERCLOUD_J2_ROLES_NAME) + role_data = None + return role_data + + def run(self, context): + self.context = context + swift = self.get_object_client(context) + + try: + 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 actions.Result(error=err_msg) + + try: + env_paths, temp_env_paths = plan_utils.build_env_paths( + swift, self.container, plan_env) + env_files, env = plan_utils.process_environments_and_files( + swift, env_paths) + + role_data = self._get_role_data(swift) + image_params = kolla_builder.container_images_prepare_multi( + env, role_data, dry_run=True) + except Exception as err: + LOG.exception("Error occurred while processing plan files.") + return actions.Result(error=six.text_type(err)) + finally: + # cleanup any local temp files + for f in temp_env_paths: + os.remove(f) + + try: + swift.put_object( + self.container, + constants.CONTAINER_DEFAULTS_ENVIRONMENT, + yaml.safe_dump( + {'parameter_defaults': image_params}, + default_flow_style=False + ) + ) + except swiftexceptions.ClientException as err: + err_msg = ("Error updating %s for plan %s: %s" % ( + constants.CONTAINER_DEFAULTS_ENVIRONMENT, self.container, err)) + LOG.exception(err_msg) + return actions.Result(error=err_msg) + + environments = {constants.CONTAINER_DEFAULTS_ENVIRONMENT: True} + + update_action = heat_capabilities.UpdateCapabilitiesAction( + environments, container=self.container) + return update_action.run(context) diff --git a/tripleo_common/tests/actions/test_container_images.py b/tripleo_common/tests/actions/test_container_images.py index b9a6cddaa..d7ffacefc 100644 --- a/tripleo_common/tests/actions/test_container_images.py +++ b/tripleo_common/tests/actions/test_container_images.py @@ -116,3 +116,56 @@ class PrepareContainerImageEnvTest(base.TestCase): 'for plan overcloud: nope', action.run(self.ctx).error ) + + +class PrepareContainerImageParametersTest(base.TestCase): + + def setUp(self): + super(PrepareContainerImageParametersTest, self).setUp() + self.ctx = mock.MagicMock() + + @mock.patch("tripleo_common.actions.container_images." + "PrepareContainerImageParameters._get_role_data") + @mock.patch("tripleo_common.actions.container_images." + "PrepareContainerImageParameters.get_object_client") + @mock.patch("tripleo_common.actions.heat_capabilities." + "UpdateCapabilitiesAction") + @mock.patch("tripleo_common.utils.plan.get_env", autospec=True) + @mock.patch("tripleo_common.image.kolla_builder." + "container_images_prepare_multi") + def test_run(self, prepare, get_env, update_action, goc, grd): + plan = { + 'version': '1.0', + 'environments': [], + 'parameter_defaults': {} + } + role_data = [{'name': 'Controller'}] + final_env = {'environments': [ + {'path': 'overcloud-resource-registry-puppet.yaml'}, + {'path': 'environments/containers-default-parameters.yaml'}, + {'path': 'user-environment.yaml'} + ]} + image_params = {'FooContainerImage': '192.0.2.1/foo/image'} + image_env_contents = yaml.safe_dump( + {'parameter_defaults': image_params}, + default_flow_style=False + ) + + swift = goc.return_value + swift.get_object.return_value = role_data + prepare.return_value = image_params + grd.return_value = role_data + + get_env.return_value = plan + update_action.return_value.run.return_value = final_env + action = container_images.PrepareContainerImageParameters( + container='overcloud') + self.assertEqual(final_env, action.run(self.ctx)) + + get_env.assert_called_once_with(swift, 'overcloud') + prepare.assert_called_once_with({}, role_data, dry_run=True) + swift.put_object.assert_called_once_with( + 'overcloud', + 'environments/containers-default-parameters.yaml', + image_env_contents + ) diff --git a/workbooks/deployment.yaml b/workbooks/deployment.yaml index a722b9e30..15bd1fefa 100644 --- a/workbooks/deployment.yaml +++ b/workbooks/deployment.yaml @@ -150,7 +150,7 @@ workflows: queue_name: <% $.queue_name %> on-complete: - run_validations: <% $.run_validations %> - - create_swift_rings_backup_plan: <% not $.run_validations %> + - container_image_prepare_params: <% not $.run_validations %> run_validations: workflow: tripleo.validations.v1.run_groups @@ -161,6 +161,15 @@ workflows: queue_name: <% $.queue_name %> publish-on-error: message: <% task().result %> + on-success: container_image_prepare_params + on-error: set_deployment_failed + + container_image_prepare_params: + action: tripleo.container_images.prepare_params + input: + container: <% $.container %> + publish-on-error: + message: <% task().result %> on-success: create_swift_rings_backup_plan on-error: set_deployment_failed