Add an "includes" prepare filter to match "excludes"

As per the docs change[1], support an 'includes' list so that only
images which match at least one entry in the list will be included in
the prepare results. This will be useful in a few situations:

* Separate ContainerImagePrepare entries with include:[ceph] and
  exclude[ceph] when this one non-kolla image needs to be treated
  differently (such as container-check style package updates)
* Invoking the tripleo-modify-image[2] on just one or a few images

[1] https://review.openstack.org/#/c/553104/2
[2] https://github.com/steveb/ansible-role-tripleo-modify-image

Blueprint: container-prepare-workflow
Change-Id: I751670f3788898d78f261000c0f51049948e8544
This commit is contained in:
Steve Baker 2018-05-21 13:48:50 +12:00
parent 4d7258c2d8
commit 5640ca8cba
3 changed files with 70 additions and 5 deletions

View File

@ -0,0 +1,6 @@
---
features:
- |
ContainerImagePrepare entries can now take an `includes` option, which like
`excludes` will take a list of regex patterns. `includes` will filter
entries which do not match at least one of the include expressions.

View File

@ -130,6 +130,7 @@ def container_images_prepare_multi(environment, roles_data):
prepare_data = container_images_prepare(
excludes=cip_entry.get('excludes'),
includes=cip_entry.get('includes'),
service_filter=service_filter,
pull_source=pull_source,
push_destination=push_destination,
@ -167,7 +168,7 @@ def container_images_prepare_defaults():
def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
excludes=None, service_filter=None,
excludes=None, includes=None, service_filter=None,
pull_source=None, push_destination=None,
mapping_args=None, output_env_file=None,
output_images_file=None, tag_from_label=None,
@ -177,6 +178,8 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
:param template_file: path to Jinja2 file containing all image entries
:param excludes: list of image name substrings to use for exclude filter
:param includes: list of image name substrings, at least one must match.
All excludes are ignored if includes is specified.
:param service_filter: set of heat resource types for containerized
services to filter by. Disable by passing None.
:param pull_source: DEPRECATED namespace for pulling during image uploads
@ -210,15 +213,20 @@ def container_images_prepare(template_file=DEFAULT_TEMPLATE_FILE,
def ffunc(entry):
imagename = entry.get('imagename', '')
if excludes:
for p in excludes:
if re.search(p, imagename):
return None
if service_filter is not None:
# check the entry is for a service being deployed
image_services = set(entry.get('services', []))
if not image_services.intersection(service_filter):
return None
if includes:
for p in includes:
if re.search(p, imagename):
return entry
return None
if excludes:
for p in excludes:
if re.search(p, imagename):
return None
return entry
builder = KollaImageBuilder([template_file])

View File

@ -401,6 +401,54 @@ class TestPrepare(base.TestCase):
)
)
@mock.patch('requests.get')
def test_prepare_includes(self, mock_get):
self.assertEqual({
'container_images.yaml': [
{'imagename': '192.0.2.0:8787/t/p-nova-libvirt:l'}
],
'environments/containers-default-parameters.yaml': {
'DockerNovaLibvirtImage': '192.0.2.0:8787/t/p-nova-libvirt:l'
}},
kb.container_images_prepare(
template_file=TEMPLATE_PATH,
output_env_file=constants.CONTAINER_DEFAULTS_ENVIRONMENT,
output_images_file='container_images.yaml',
includes=['libvirt'],
mapping_args={
'namespace': '192.0.2.0:8787/t',
'name_prefix': 'p',
'name_suffix': '',
'tag': 'l',
}
)
)
@mock.patch('requests.get')
def test_prepare_includes_excludes(self, mock_get):
# assert same result as includes only. includes trumps excludes
self.assertEqual({
'container_images.yaml': [
{'imagename': '192.0.2.0:8787/t/p-nova-libvirt:l'}
],
'environments/containers-default-parameters.yaml': {
'DockerNovaLibvirtImage': '192.0.2.0:8787/t/p-nova-libvirt:l'
}},
kb.container_images_prepare(
template_file=TEMPLATE_PATH,
output_env_file=constants.CONTAINER_DEFAULTS_ENVIRONMENT,
output_images_file='container_images.yaml',
includes=['libvirt'],
excludes=['libvirt'],
mapping_args={
'namespace': '192.0.2.0:8787/t',
'name_prefix': 'p',
'name_suffix': '',
'tag': 'l',
}
)
)
@mock.patch('requests.get')
def test_prepare_push_dest(self, mock_get):
self.assertEqual({
@ -665,6 +713,7 @@ class TestPrepare(base.TestCase):
'ContainerImagePrepare': [{
'set': mapping_args,
'tag_from_label': 'foo',
'includes': ['nova', 'neutron'],
}, {
'set': mapping_args,
'tag_from_label': 'bar',
@ -705,6 +754,7 @@ class TestPrepare(base.TestCase):
mock_cip.assert_has_calls([
mock.call(
excludes=None,
includes=['nova', 'neutron'],
mapping_args=mapping_args,
output_env_file='image_params',
output_images_file='upload_data',
@ -718,6 +768,7 @@ class TestPrepare(base.TestCase):
),
mock.call(
excludes=['nova', 'neutron'],
includes=None,
mapping_args=mapping_args,
output_env_file='image_params',
output_images_file='upload_data',