diff --git a/tripleo_common/image/image_uploader.py b/tripleo_common/image/image_uploader.py index 8ae6f4783..eb9d21784 100644 --- a/tripleo_common/image/image_uploader.py +++ b/tripleo_common/image/image_uploader.py @@ -325,6 +325,12 @@ class DockerImageUploader(ImageUploader): i = DockerImageUploader._inspect(image_url.geturl(), insecure) return i.get('Digest') + @staticmethod + def _image_labels(image, insecure): + image_url = DockerImageUploader._image_to_url(image) + i = DockerImageUploader._inspect(image_url.geturl(), insecure) + return i.get('Labels', {}) or {} + @staticmethod def _image_exists(image, insecure_registries): try: @@ -446,6 +452,18 @@ class DockerImageUploader(ImageUploader): return self._discover_tag_from_inspect(i, image, tag_from_label, fallback_tag) + def filter_images_with_labels(self, images, labels): + images_with_labels = [] + for image in images: + url = self._image_to_url(image) + image_labels = self._image_labels(url.geturl(), + self.is_insecure_registry( + url.netloc)) + if set(labels).issubset(set(image_labels)): + images_with_labels.append(image) + + return images_with_labels + def cleanup(self, local_images): if not local_images: return [] diff --git a/tripleo_common/image/kolla_builder.py b/tripleo_common/image/kolla_builder.py index 8f876b32b..2ce5ea2e2 100644 --- a/tripleo_common/image/kolla_builder.py +++ b/tripleo_common/image/kolla_builder.py @@ -138,13 +138,10 @@ def container_images_prepare_multi(environment, roles_data, dry_run=False, pull_source = cip_entry.get('pull_source') modify_role = cip_entry.get('modify_role') modify_vars = cip_entry.get('modify_vars') - if modify_role: - append_tag = cip_entry.get( - 'modify_append_tag', - time.strftime('-modified-%Y%m%d%H%M%S') - ) - else: - append_tag = None + modify_only_with_labels = cip_entry.get('modify_only_with_labels') + modify_append_tag = cip_entry.get('modify_append_tag', + time.strftime( + '-modified-%Y%m%d%H%M%S')) prepare_data = container_images_prepare( excludes=cip_entry.get('excludes'), @@ -156,9 +153,10 @@ def container_images_prepare_multi(environment, roles_data, dry_run=False, output_env_file='image_params', output_images_file='upload_data', tag_from_label=cip_entry.get('tag_from_label'), - append_tag=append_tag, + modify_append_tag=modify_append_tag, modify_role=modify_role, modify_vars=modify_vars, + modify_only_with_labels=modify_only_with_labels, ) env_params.update(prepare_data['image_params']) @@ -192,8 +190,8 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE, pull_source=None, push_destination=None, mapping_args=None, output_env_file=None, output_images_file=None, tag_from_label=None, - append_tag=None, modify_role=None, - modify_vars=None): + modify_append_tag=None, modify_role=None, + modify_vars=None, modify_only_with_labels=None): """Perform container image preparation :param template_file: path to Jinja2 file containing all image entries @@ -212,18 +210,19 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE, :param output_images_file: key to use for image upload data :param tag_from_label: string when set will trigger tag discovery on every image - :param append_tag: string to append to the tag for the destination image + :param modify_append_tag: string to append to the tag for the destination + image :param modify_role: string of ansible role name to run during upload before the push to destination :param modify_vars: dict of variables to pass to modify_role + :param modify_only_with_labels: only modify the container images with the + given labels :returns: dict with entries for the supplied output_env_file or output_images_file """ if mapping_args is None: mapping_args = {} - if not append_tag: - append_tag = '' if service_filter: if 'OS::TripleO::Services::OpenDaylightApi' in service_filter: @@ -253,9 +252,10 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE, result = builder.container_images_from_template( filter=ffunc, **mapping_args) + uploader = image_uploader.ImageUploadManager().uploader('docker') + images = [i.get('imagename', '') for i in result] + if tag_from_label: - uploader = image_uploader.ImageUploadManager().uploader('docker') - images = [i.get('imagename', '') for i in result] image_version_tags = uploader.discover_image_tags( images, tag_from_label) for entry in result: @@ -265,9 +265,23 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE, entry['imagename'] = '%s:%s' % ( image_no_tag, image_version_tags[image_no_tag]) + if modify_only_with_labels: + images_with_labels = uploader.filter_images_with_labels( + images, modify_only_with_labels) + params = {} for entry in result: imagename = entry.get('imagename', '') + append_tag = '' + if modify_role and ( + (not modify_only_with_labels) + or imagename in images_with_labels): + entry['modify_role'] = modify_role + if modify_append_tag: + entry['modify_append_tag'] = modify_append_tag + append_tag = modify_append_tag + if modify_vars: + entry['modify_vars'] = modify_vars if pull_source: entry['pull_source'] = pull_source if push_destination: @@ -276,12 +290,6 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE, # push_destination, since that is where they will be uploaded to image = imagename.partition('/')[2] imagename = '/'.join((push_destination, image)) - if append_tag: - entry['modify_append_tag'] = append_tag - if modify_role: - entry['modify_role'] = modify_role - if modify_vars: - entry['modify_vars'] = modify_vars if 'params' in entry: for p in entry.pop('params'): params[p] = imagename + append_tag diff --git a/tripleo_common/tests/image/test_kolla_builder.py b/tripleo_common/tests/image/test_kolla_builder.py index ce8c95c1f..9d0fc66ca 100644 --- a/tripleo_common/tests/image/test_kolla_builder.py +++ b/tripleo_common/tests/image/test_kolla_builder.py @@ -792,6 +792,7 @@ class TestPrepare(base.TestCase): 'excludes': ['nova', 'neutron'], 'push_destination': '192.0.2.1:8787', 'modify_role': 'add-foo-plugin', + 'modify_only_with_labels': ['kolla_version'], 'modify_vars': {'foo_version': '1.0.1'} }] } @@ -834,8 +835,9 @@ class TestPrepare(base.TestCase): push_destination=None, service_filter=None, tag_from_label='foo', - append_tag=None, + modify_append_tag=mock.ANY, modify_role=None, + modify_only_with_labels=None, modify_vars=None ), mock.call( @@ -848,8 +850,9 @@ class TestPrepare(base.TestCase): push_destination='192.0.2.1:8787', service_filter=None, tag_from_label='bar', - append_tag=mock.ANY, + modify_append_tag=mock.ANY, modify_role='add-foo-plugin', + modify_only_with_labels=['kolla_version'], modify_vars={'foo_version': '1.0.1'} ) ]) @@ -887,6 +890,7 @@ class TestPrepare(base.TestCase): 'excludes': ['nova', 'neutron'], 'push_destination': '192.0.2.1:8787', 'modify_role': 'add-foo-plugin', + 'modify_only_with_labels': ['kolla_version'], 'modify_vars': {'foo_version': '1.0.1'}, 'modify_append_tag': 'modify-123' }] @@ -930,8 +934,9 @@ class TestPrepare(base.TestCase): push_destination=None, service_filter=None, tag_from_label='foo', - append_tag=None, + modify_append_tag=mock.ANY, modify_role=None, + modify_only_with_labels=None, modify_vars=None ), mock.call( @@ -944,8 +949,9 @@ class TestPrepare(base.TestCase): push_destination='192.0.2.1:8787', service_filter=None, tag_from_label='bar', - append_tag=mock.ANY, + modify_append_tag=mock.ANY, modify_role='add-foo-plugin', + modify_only_with_labels=['kolla_version'], modify_vars={'foo_version': '1.0.1'} ) ])