Add image_label_mismatch parameter to docker_container (#370)

* Add image_label_mismatch to docker_container

* Apply suggestions from code review

Co-authored-by: Felix Fontein <felix@fontein.de>

* Test image_label_mismatch error message

* Add change fragment for image_label_mismatch

* Break long line in docker_container.py for pep-8 compliance

* pep8 compliance

* Update changelogs/fragments/370-add-image-label-mismatch.yml

Co-authored-by: Felix Fontein <felix@fontein.de>

* fix: add expected_labels to parameters_map in docker_container

* Apply suggestions from code review

* Apply suggestions from code review

* Update tests/integration/targets/docker_container/tasks/tests/options.yml

Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
Rodrigo Candido Gryzinski
2022-05-24 03:35:33 -03:00
committed by GitHub
parent 9580c25579
commit 497c2fda91
4 changed files with 223 additions and 1 deletions
+52 -1
View File
@@ -394,6 +394,22 @@ options:
- Can also be an image ID. If this is the case, the image is assumed to be available locally.
The I(pull) option is ignored for this case.
type: str
image_label_mismatch:
description:
- How to handle labels inherited from the image that are not set explicitly.
- When C(ignore), labels that are present in the image but not specified in I(labels) will be
ignored. This is useful to avoid having to specify the image labels in I(labels) while keeping
labels I(comparisons) C(strict).
- When C(fail), if there are labels present in the image which are not set from I(labels), the
module will fail. This prevents introducing unexpected labels from the base image.
- "B(Warning:) This option is ignored unless C(labels: strict) or C(*: strict) is specified in
the I(comparisons) option."
type: str
choices:
- 'ignore'
- 'fail'
default: ignore
version_added: 2.6.0
init:
description:
- Run an init inside the container that forwards signals and reaps processes.
@@ -2170,6 +2186,7 @@ class Container(DockerBaseClass):
self.parameters.expected_env = None
self.parameters.expected_device_requests = None
self.parameters_map = dict()
self.parameters_map['expected_labels'] = 'labels'
self.parameters_map['expected_links'] = 'links'
self.parameters_map['expected_ports'] = 'expected_ports'
self.parameters_map['expected_exposed'] = 'exposed_ports'
@@ -2180,6 +2197,7 @@ class Container(DockerBaseClass):
self.parameters_map['expected_env'] = 'env'
self.parameters_map['expected_entrypoint'] = 'entrypoint'
self.parameters_map['expected_binds'] = 'volumes'
self.parameters_map['expected_labels'] = 'labels'
self.parameters_map['expected_cmd'] = 'command'
self.parameters_map['expected_devices'] = 'devices'
self.parameters_map['expected_healthcheck'] = 'healthcheck'
@@ -2251,6 +2269,7 @@ class Container(DockerBaseClass):
self.parameters.expected_exposed = self._get_expected_exposed(image)
self.parameters.expected_volumes = self._get_expected_volumes(image)
self.parameters.expected_binds = self._get_expected_binds(image)
self.parameters.expected_labels = self._get_expected_labels(image)
self.parameters.expected_ulimits = self._get_expected_ulimits(self.parameters.ulimits)
self.parameters.expected_sysctls = self._get_expected_sysctls(self.parameters.sysctls)
self.parameters.expected_etc_hosts = self._convert_simple_dict_to_list('etc_hosts')
@@ -2304,7 +2323,7 @@ class Container(DockerBaseClass):
expected_exposed=expected_exposed,
groups=host_config.get('GroupAdd'),
ipc_mode=host_config.get("IpcMode"),
labels=config.get('Labels'),
expected_labels=config.get('Labels'),
expected_links=host_config.get('Links'),
mac_address=config.get('MacAddress', network.get('MacAddress')),
memory_swappiness=host_config.get('MemorySwappiness'),
@@ -2406,6 +2425,20 @@ class Container(DockerBaseClass):
# expected_healthcheck comparison in this case.
continue
if key == 'expected_labels' and compare['comparison'] == 'strict' and self.parameters.image_label_mismatch == 'fail':
# If there are labels from the base image that should be removed and
# base_image_mismatch is fail we want raise an error.
image_labels = self._get_image_labels(image)
would_remove_labels = []
for label in image_labels:
if label not in self.parameters.labels:
# Format label for error message
would_remove_labels.append(label)
if would_remove_labels:
msg = ("Some labels should be removed but are present in the base image. You can set image_label_mismatch to 'ignore' to ignore"
" this error. Labels: {0}")
self.fail(msg.format(', '.join(['"%s"' % label for label in would_remove_labels])))
# no match. record the differences
p = getattr(self.parameters, key)
c = value
@@ -2644,6 +2677,23 @@ class Container(DockerBaseClass):
self.log(result, pretty_print=True)
return result
def _get_expected_labels(self, image):
if self.parameters.labels is None:
return None
if self.parameters.image_label_mismatch == 'ignore':
expected_labels = dict(self._get_image_labels(image))
else:
expected_labels = {}
expected_labels.update(self.parameters.labels)
return expected_labels
def _get_image_labels(self, image):
if not image:
return {}
# Can't use get('Labels', {}) because 'Labels' may be present and be None
return image[self.parameters.client.image_inspect_source].get('Labels') or {}
def _get_expected_device_requests(self):
if self.parameters.device_requests is None:
return None
@@ -3555,6 +3605,7 @@ def main():
hostname=dict(type='str'),
ignore_image=dict(type='bool', default=False),
image=dict(type='str'),
image_label_mismatch=dict(type='str', choices=['ignore', 'fail'], default='ignore'),
init=dict(type='bool'),
interactive=dict(type='bool'),
ipc_mode=dict(type='str'),