Action to perform container image prepare

This action will be called 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

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.

Blueprint: container-prepare-workflow
Change-Id: Id5a4bec2d82e69ef53e7809984b4adba67deef3e
This commit is contained in:
Steve Baker
2018-07-26 00:05:44 +00:00
parent 05532448ee
commit 2dcf24e060
3 changed files with 127 additions and 1 deletions

View File

@@ -83,6 +83,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

View File

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

View File

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