Merge "Define the interface for multi arch image prepare"

This commit is contained in:
Zuul 2019-05-18 00:39:34 +00:00 committed by Gerrit Code Review
commit 6087a692f8
5 changed files with 63 additions and 22 deletions

View File

@ -0,0 +1,9 @@
---
features:
- |
If the `AdditionalArchitectures` parameter has entries then the container
image prepare will prepare images for all architectures instead of just
the default one. A new boolean field `multi_arch` can also be set in
`ContainerImagePrepare` entries to determine the multi arch behaviour for
images in that entry. If any entry sets a `multi_arch` value then
`AdditionalArchitectures` is ignored.

View File

@ -109,7 +109,8 @@ class ImageUploadManager(BaseImageManager):
def __init__(self, config_files=None, def __init__(self, config_files=None,
dry_run=False, cleanup=CLEANUP_FULL, dry_run=False, cleanup=CLEANUP_FULL,
mirrors=None, registry_credentials=None): mirrors=None, registry_credentials=None,
multi_arch=False):
if config_files is None: if config_files is None:
config_files = [] config_files = []
super(ImageUploadManager, self).__init__(config_files) super(ImageUploadManager, self).__init__(config_files)
@ -126,6 +127,7 @@ class ImageUploadManager(BaseImageManager):
self.validate_registry_credentials(registry_credentials) self.validate_registry_credentials(registry_credentials)
for uploader in self.uploaders.values(): for uploader in self.uploaders.values():
uploader.registry_credentials = registry_credentials uploader.registry_credentials = registry_credentials
self.multi_arch = multi_arch
def validate_registry_credentials(self, creds_data): def validate_registry_credentials(self, creds_data):
if not isinstance(creds_data, dict): if not isinstance(creds_data, dict):
@ -189,12 +191,13 @@ class ImageUploadManager(BaseImageManager):
append_tag = item.get('modify_append_tag') append_tag = item.get('modify_append_tag')
modify_role = item.get('modify_role') modify_role = item.get('modify_role')
modify_vars = item.get('modify_vars') modify_vars = item.get('modify_vars')
multi_arch = item.get('multi_arch', self.multi_arch)
uploader = self.uploader(uploader) uploader = self.uploader(uploader)
task = UploadTask( task = UploadTask(
image_name, pull_source, push_destination, image_name, pull_source, push_destination,
append_tag, modify_role, modify_vars, self.dry_run, append_tag, modify_role, modify_vars, self.dry_run,
self.cleanup) self.cleanup, multi_arch)
uploader.add_upload_task(task) uploader.add_upload_task(task)
for uploader in self.uploaders.values(): for uploader in self.uploaders.values():
@ -1645,7 +1648,8 @@ class PythonImageUploader(BaseImageUploader):
class UploadTask(object): class UploadTask(object):
def __init__(self, image_name, pull_source, push_destination, def __init__(self, image_name, pull_source, push_destination,
append_tag, modify_role, modify_vars, dry_run, cleanup): append_tag, modify_role, modify_vars, dry_run, cleanup,
multi_arch):
self.image_name = image_name self.image_name = image_name
self.pull_source = pull_source self.pull_source = pull_source
self.push_destination = push_destination self.push_destination = push_destination
@ -1654,6 +1658,7 @@ class UploadTask(object):
self.modify_vars = modify_vars self.modify_vars = modify_vars
self.dry_run = dry_run self.dry_run = dry_run
self.cleanup = cleanup self.cleanup = cleanup
self.multi_arch = multi_arch
if ':' in image_name: if ':' in image_name:
image = image_name.rpartition(':')[0] image = image_name.rpartition(':')[0]

View File

@ -157,6 +157,7 @@ def container_images_prepare_multi(environment, roles_data, dry_run=False,
mirrors['docker.io'] = mirror mirrors['docker.io'] = mirror
creds = pd.get('ContainerImageRegistryCredentials') creds = pd.get('ContainerImageRegistryCredentials')
multi_arch = len(pd.get('AdditionalArchitectures', []))
env_params = {} env_params = {}
service_filter = build_service_filter(environment, roles_data) service_filter = build_service_filter(environment, roles_data)
@ -178,6 +179,10 @@ def container_images_prepare_multi(environment, roles_data, dry_run=False,
modify_append_tag = cip_entry.get('modify_append_tag', modify_append_tag = cip_entry.get('modify_append_tag',
time.strftime( time.strftime(
'-modified-%Y%m%d%H%M%S')) '-modified-%Y%m%d%H%M%S'))
if multi_arch and 'multi_arch' in cip_entry:
# individual entry sets multi_arch,
# so set global multi_arch to False
multi_arch = False
prepare_data = container_images_prepare( prepare_data = container_images_prepare(
excludes=cip_entry.get('excludes'), excludes=cip_entry.get('excludes'),
@ -194,7 +199,8 @@ def container_images_prepare_multi(environment, roles_data, dry_run=False,
modify_vars=modify_vars, modify_vars=modify_vars,
modify_only_with_labels=modify_only_with_labels, modify_only_with_labels=modify_only_with_labels,
mirrors=mirrors, mirrors=mirrors,
registry_credentials=creds registry_credentials=creds,
multi_arch=multi_arch
) )
env_params.update(prepare_data['image_params']) env_params.update(prepare_data['image_params'])
@ -208,7 +214,8 @@ def container_images_prepare_multi(environment, roles_data, dry_run=False,
dry_run=dry_run, dry_run=dry_run,
cleanup=cleanup, cleanup=cleanup,
mirrors=mirrors, mirrors=mirrors,
registry_credentials=creds registry_credentials=creds,
multi_arch=multi_arch
) )
uploader.upload() uploader.upload()
return env_params return env_params
@ -231,7 +238,8 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
output_images_file=None, tag_from_label=None, output_images_file=None, tag_from_label=None,
append_tag=None, modify_role=None, append_tag=None, modify_role=None,
modify_vars=None, modify_only_with_labels=None, modify_vars=None, modify_only_with_labels=None,
mirrors=None, registry_credentials=None): mirrors=None, registry_credentials=None,
multi_arch=False):
"""Perform container image preparation """Perform container image preparation
:param template_file: path to Jinja2 file containing all image entries :param template_file: path to Jinja2 file containing all image entries
@ -263,6 +271,8 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
The value is a single-entry dict where the The value is a single-entry dict where the
username is the key and the password is the username is the key and the password is the
value. value.
:param multi_arch: boolean whether to prepare every architecture of
each image
:returns: dict with entries for the supplied output_env_file or :returns: dict with entries for the supplied output_env_file or
output_images_file output_images_file
""" """
@ -293,7 +303,10 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
filter=ffunc, **mapping_args) filter=ffunc, **mapping_args)
manager = image_uploader.ImageUploadManager( manager = image_uploader.ImageUploadManager(
mirrors=mirrors, registry_credentials=registry_credentials) mirrors=mirrors,
registry_credentials=registry_credentials,
multi_arch=multi_arch
)
uploader = manager.uploader('python') uploader = manager.uploader('python')
images = [i.get('imagename', '') for i in result] images = [i.get('imagename', '') for i in result]

View File

@ -857,7 +857,8 @@ class TestSkopeoImageUploader(base.TestCase):
None, None,
None, None,
False, False,
'full') 'full',
False)
) )
) )
mock_popen.assert_called_once_with([ mock_popen.assert_called_once_with([
@ -921,7 +922,8 @@ class TestSkopeoImageUploader(base.TestCase):
'add-foo-plugin', 'add-foo-plugin',
{'foo_version': '1.0.1'}, {'foo_version': '1.0.1'},
False, False,
'partial') 'partial',
False)
) )
) )
@ -981,7 +983,7 @@ class TestSkopeoImageUploader(base.TestCase):
self.uploader.upload_image, image_uploader.UploadTask( self.uploader.upload_image, image_uploader.UploadTask(
image + ':' + tag, None, push_destination, image + ':' + tag, None, push_destination,
append_tag, 'add-foo-plugin', {'foo_version': '1.0.1'}, append_tag, 'add-foo-plugin', {'foo_version': '1.0.1'},
False, 'full') False, 'full', False)
) )
mock_copy.assert_called_once_with( mock_copy.assert_called_once_with(
@ -1009,7 +1011,8 @@ class TestSkopeoImageUploader(base.TestCase):
'add-foo-plugin', 'add-foo-plugin',
{'foo_version': '1.0.1'}, {'foo_version': '1.0.1'},
True, True,
'full') 'full',
False)
) )
mock_ansible.assert_not_called() mock_ansible.assert_not_called()
@ -1039,7 +1042,8 @@ class TestSkopeoImageUploader(base.TestCase):
'add-foo-plugin', 'add-foo-plugin',
{'foo_version': '1.0.1'}, {'foo_version': '1.0.1'},
False, False,
'full') 'full',
False)
) )
mock_ansible.assert_not_called() mock_ansible.assert_not_called()
@ -1149,7 +1153,8 @@ class TestPythonImageUploader(base.TestCase):
modify_role=None, modify_role=None,
modify_vars=None, modify_vars=None,
dry_run=False, dry_run=False,
cleanup='full' cleanup='full',
multi_arch=False
) )
self.assertEqual( self.assertEqual(
@ -1241,7 +1246,8 @@ class TestPythonImageUploader(base.TestCase):
modify_role=None, modify_role=None,
modify_vars=None, modify_vars=None,
dry_run=False, dry_run=False,
cleanup='full' cleanup='full',
multi_arch=False
) )
self.assertEqual( self.assertEqual(
@ -1307,7 +1313,8 @@ class TestPythonImageUploader(base.TestCase):
modify_role=None, modify_role=None,
modify_vars=None, modify_vars=None,
dry_run=False, dry_run=False,
cleanup='full' cleanup='full',
multi_arch=False
) )
self.assertEqual( self.assertEqual(
@ -1372,7 +1379,8 @@ class TestPythonImageUploader(base.TestCase):
modify_role=None, modify_role=None,
modify_vars=None, modify_vars=None,
dry_run=False, dry_run=False,
cleanup='full' cleanup='full',
multi_arch=False
) )
self.assertEqual( self.assertEqual(
@ -1471,7 +1479,8 @@ class TestPythonImageUploader(base.TestCase):
modify_role='add-foo-plugin', modify_role='add-foo-plugin',
modify_vars={'foo_version': '1.0.1'}, modify_vars={'foo_version': '1.0.1'},
dry_run=False, dry_run=False,
cleanup='full' cleanup='full',
multi_arch=False
) )
source_url = urlparse( source_url = urlparse(

View File

@ -1104,7 +1104,8 @@ class TestPrepare(base.TestCase):
}, },
registry_credentials={ registry_credentials={
'docker.io': {'my_username': 'my_password'} 'docker.io': {'my_username': 'my_password'}
} },
multi_arch=False
), ),
mock.call( mock.call(
excludes=['nova', 'neutron'], excludes=['nova', 'neutron'],
@ -1125,7 +1126,8 @@ class TestPrepare(base.TestCase):
}, },
registry_credentials={ registry_credentials={
'docker.io': {'my_username': 'my_password'} 'docker.io': {'my_username': 'my_password'}
} },
multi_arch=False
) )
]) ])
@ -1211,7 +1213,8 @@ class TestPrepare(base.TestCase):
modify_only_with_labels=None, modify_only_with_labels=None,
modify_vars=None, modify_vars=None,
mirrors={}, mirrors={},
registry_credentials=None registry_credentials=None,
multi_arch=False
), ),
mock.call( mock.call(
excludes=['nova', 'neutron'], excludes=['nova', 'neutron'],
@ -1228,12 +1231,14 @@ class TestPrepare(base.TestCase):
modify_only_with_labels=['kolla_version'], modify_only_with_labels=['kolla_version'],
modify_vars={'foo_version': '1.0.1'}, modify_vars={'foo_version': '1.0.1'},
mirrors={}, mirrors={},
registry_credentials=None registry_credentials=None,
multi_arch=False
) )
]) ])
mock_im.assert_called_once_with(mock.ANY, dry_run=True, cleanup='full', mock_im.assert_called_once_with(mock.ANY, dry_run=True, cleanup='full',
mirrors={}, registry_credentials=None) mirrors={}, registry_credentials=None,
multi_arch=False)
self.assertEqual( self.assertEqual(
{ {