From 910e1f550bd5f8685b04ae02dc641da787df6245 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 18 Feb 2021 13:00:06 +0100 Subject: [PATCH 01/13] Add docker_image_load module. --- plugins/modules/docker_image_load.py | 184 +++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 plugins/modules/docker_image_load.py diff --git a/plugins/modules/docker_image_load.py b/plugins/modules/docker_image_load.py new file mode 100644 index 000000000..9d739a5ea --- /dev/null +++ b/plugins/modules/docker_image_load.py @@ -0,0 +1,184 @@ +#!/usr/bin/python +# +# Copyright 2016 Red Hat | Ansible +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: docker_image_load + +short_description: Load docker images from archives + +version_added: 1.3.0 + +description: + - Load one or multiple images from a C(.tar) archive. + +options: + path: + description: + - Use with state C(present) to load an image from a .tar file. + - Set I(source) to C(load) if you want to load the image. + type: path + required: true + +extends_documentation_fragment: +- community.docker.docker +- community.docker.docker.docker_py_2_documentation + + +requirements: + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 2.5.0" + - "Docker API >= 1.23" + +author: + - Felix Fontein (@felixfontein) + +''' + +EXAMPLES = ''' + +- name: Load all images from the given tar file + community.docker.docker_image_load: + path: /path/to/images.tar + register: result + +- name: Print the loaded image names + debug: + msg: "Loaded the following images: {{ resut.image_names | join(', ') }}" +''' + +RETURN = ''' +image_names: + description: List of image names and IDs loaded from the archive. + returned: success + type: list + elements: str + sample: + - 'hello-world:latest' + - 'sha256:e004c2cc521c95383aebb1fb5893719aa7a8eae2e7a71f316a4410784edb00a9' +images: + description: Image inspection results for the loaded images. + returned: success + type: list + elements: dict + sample: [] +''' + +import errno +import traceback + +from ansible_collections.community.docker.plugins.module_utils.common import ( + AnsibleDockerClient, + DockerBaseClass, + is_image_name_id, + RequestException, +) + +try: + from docker.errors import DockerException +except ImportError: + # missing Docker SDK for Python handled in module_utils.docker.common + pass + + +class ImageManager(DockerBaseClass): + def __init__(self, client, results): + super(ImageManager, self).__init__() + + self.client = client + self.results = results + parameters = self.client.module.params + self.check_mode = self.client.check_mode + + self.path = parameters['path'] + + self.load_images() + + @staticmethod + def _extract_output_line(line, output): + ''' + Extract text line from stream output and, if found, adds it to output. + ''' + if 'stream' in line or 'status' in line: + # Make sure we have a string (assuming that line['stream'] and + # line['status'] are either not defined, falsish, or a string) + text_line = line.get('stream') or line.get('status') or '' + output.append(text_line) + + def load_images(self): + ''' + Load images from a .tar archive + ''' + # Load image(s) from file + load_output = [] + try: + self.log("Opening image {0}".format(self.load_path)) + with open(self.load_path, 'rb') as image_tar: + self.log("Loading images from {0}".format(self.load_path)) + for line in self.client.load_image(image_tar): + self.log(line, pretty_print=True) + self._extract_output_line(line, load_output) + except EnvironmentError as exc: + if exc.errno == errno.ENOENT: + self.client.fail("Error opening archive {0} - {1}".format(self.path, str(exc))) + self.client.fail("Error loading archive {0} - {1}".format(self.path, str(exc)), stdout='\n'.join(load_output)) + except Exception as exc: + self.client.fail("Error loading archive {0} - {1}".format(self.path, str(exc)), stdout='\n'.join(load_output)) + + # Collect loaded images + loaded_images = [] + for line in load_output: + if line.startswith('Loaded image:'): + loaded_images.add(line[len('Loaded image:'):].strip()) + if line.startswith('Loaded image ID:'): + loaded_images.add(line[len('Loaded image ID:'):].strip()) + + if not loaded_images: + self.client.fail("Detected no loaded images. Archive potentially corrupt?", stdout='\n'.join(load_output)) + + images = [] + for image_name in loaded_images: + if is_image_name_id(image_name): + images.append(self.client.find_image_by_id(image_name)) + elif ':' in image_name: + image_name, tag = image_name.rsplit(':', 1) + images.append(self.client.find_image(image_name, tag)) + else: + self.client.module.warn('Image name "{0}" is neither ID nor has a tag'.format(image_name)) + + self.results['image_names'] = loaded_images + self.results['images'] = images + + +def main(): + client = AnsibleDockerClient( + argument_spec=dict( + path=dict(type='path', required=True), + ), + supports_check_mode=True, + min_docker_version='2.5.0', + min_docker_api_version='1.23', + ) + + try: + results = dict( + changed=False, + actions=[], + image={} + ) + + ImageManager(client, results) + client.module.exit_json(**results) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) + except RequestException as e: + client.fail('An unexpected requests error occurred when docker-py tried to talk to the docker daemon: {0}'.format(e), exception=traceback.format_exc()) + + +if __name__ == '__main__': + main() From 5cf75fefd88e9c071eb5fb474f2f8d8eccc312b6 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 18 Feb 2021 20:54:46 +0100 Subject: [PATCH 02/13] Polish module. --- plugins/modules/docker_image_load.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/plugins/modules/docker_image_load.py b/plugins/modules/docker_image_load.py index 9d739a5ea..50e0249e9 100644 --- a/plugins/modules/docker_image_load.py +++ b/plugins/modules/docker_image_load.py @@ -16,13 +16,13 @@ version_added: 1.3.0 description: - - Load one or multiple images from a C(.tar) archive. + - Load one or multiple Docker images from a C(.tar) archive, and return information on + the loaded images. options: path: description: - - Use with state C(present) to load an image from a .tar file. - - Set I(source) to C(load) if you want to load the image. + - The path to the C(.tar) archive to load Docker images from. type: path required: true @@ -30,6 +30,8 @@ - community.docker.docker - community.docker.docker.docker_py_2_documentation +notes: + - Does not support C(check_mode). requirements: - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 2.5.0" @@ -41,7 +43,6 @@ ''' EXAMPLES = ''' - - name: Load all images from the given tar file community.docker.docker_image_load: path: /path/to/images.tar @@ -153,6 +154,7 @@ def load_images(self): self.results['image_names'] = loaded_images self.results['images'] = images + self.results['changed'] = True def main(): @@ -160,16 +162,15 @@ def main(): argument_spec=dict( path=dict(type='path', required=True), ), - supports_check_mode=True, + supports_check_mode=False, min_docker_version='2.5.0', min_docker_api_version='1.23', ) try: results = dict( - changed=False, - actions=[], - image={} + image_names=[], + images=[], ) ImageManager(client, results) From 130a4db833645160052e27445fb5f865c6f1f8bb Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 18 Feb 2021 21:27:54 +0100 Subject: [PATCH 03/13] Fix bug and add tests. --- plugins/modules/docker_image_load.py | 12 +- .../targets/docker_image_load/aliases | 2 + .../targets/docker_image_load/meta/main.yml | 3 + .../targets/docker_image_load/tasks/main.yml | 8 + .../docker_image_load/tasks/run-test.yml | 3 + .../targets/docker_image_load/tasks/test.yml | 34 ++++ .../docker_image_load/tasks/tests/basic.yml | 181 ++++++++++++++++++ 7 files changed, 237 insertions(+), 6 deletions(-) create mode 100644 tests/integration/targets/docker_image_load/aliases create mode 100644 tests/integration/targets/docker_image_load/meta/main.yml create mode 100644 tests/integration/targets/docker_image_load/tasks/main.yml create mode 100644 tests/integration/targets/docker_image_load/tasks/run-test.yml create mode 100644 tests/integration/targets/docker_image_load/tasks/test.yml create mode 100644 tests/integration/targets/docker_image_load/tasks/tests/basic.yml diff --git a/plugins/modules/docker_image_load.py b/plugins/modules/docker_image_load.py index 50e0249e9..08e769fbe 100644 --- a/plugins/modules/docker_image_load.py +++ b/plugins/modules/docker_image_load.py @@ -109,7 +109,7 @@ def _extract_output_line(line, output): # Make sure we have a string (assuming that line['stream'] and # line['status'] are either not defined, falsish, or a string) text_line = line.get('stream') or line.get('status') or '' - output.append(text_line) + output.extend(text_line.splitlines()) def load_images(self): ''' @@ -118,9 +118,9 @@ def load_images(self): # Load image(s) from file load_output = [] try: - self.log("Opening image {0}".format(self.load_path)) - with open(self.load_path, 'rb') as image_tar: - self.log("Loading images from {0}".format(self.load_path)) + self.log("Opening image {0}".format(self.path)) + with open(self.path, 'rb') as image_tar: + self.log("Loading images from {0}".format(self.path)) for line in self.client.load_image(image_tar): self.log(line, pretty_print=True) self._extract_output_line(line, load_output) @@ -135,9 +135,9 @@ def load_images(self): loaded_images = [] for line in load_output: if line.startswith('Loaded image:'): - loaded_images.add(line[len('Loaded image:'):].strip()) + loaded_images.append(line[len('Loaded image:'):].strip()) if line.startswith('Loaded image ID:'): - loaded_images.add(line[len('Loaded image ID:'):].strip()) + loaded_images.append(line[len('Loaded image ID:'):].strip()) if not loaded_images: self.client.fail("Detected no loaded images. Archive potentially corrupt?", stdout='\n'.join(load_output)) diff --git a/tests/integration/targets/docker_image_load/aliases b/tests/integration/targets/docker_image_load/aliases new file mode 100644 index 000000000..02b78723c --- /dev/null +++ b/tests/integration/targets/docker_image_load/aliases @@ -0,0 +1,2 @@ +shippable/posix/group4 +destructive diff --git a/tests/integration/targets/docker_image_load/meta/main.yml b/tests/integration/targets/docker_image_load/meta/main.yml new file mode 100644 index 000000000..07da8c6dd --- /dev/null +++ b/tests/integration/targets/docker_image_load/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - setup_docker diff --git a/tests/integration/targets/docker_image_load/tasks/main.yml b/tests/integration/targets/docker_image_load/tasks/main.yml new file mode 100644 index 000000000..2be493eb1 --- /dev/null +++ b/tests/integration/targets/docker_image_load/tasks/main.yml @@ -0,0 +1,8 @@ +#################################################################### +# WARNING: These are designed specifically for Ansible tests # +# and should not be used as examples of how to write Ansible roles # +#################################################################### + +- when: ansible_facts.distribution ~ ansible_facts.distribution_major_version not in ['CentOS6', 'RedHat6'] + include_tasks: + file: test.yml diff --git a/tests/integration/targets/docker_image_load/tasks/run-test.yml b/tests/integration/targets/docker_image_load/tasks/run-test.yml new file mode 100644 index 000000000..a29993701 --- /dev/null +++ b/tests/integration/targets/docker_image_load/tasks/run-test.yml @@ -0,0 +1,3 @@ +--- +- name: "Loading tasks from {{ item }}" + include_tasks: "{{ item }}" diff --git a/tests/integration/targets/docker_image_load/tasks/test.yml b/tests/integration/targets/docker_image_load/tasks/test.yml new file mode 100644 index 000000000..28248351a --- /dev/null +++ b/tests/integration/targets/docker_image_load/tasks/test.yml @@ -0,0 +1,34 @@ +--- +- name: Create random name prefix + set_fact: + name_prefix: "{{ 'ansible-test-%0x' % ((2**32) | random) }}" +- name: Create image and container list + set_fact: + inames: [] + cnames: [] + +- debug: + msg: "Using name prefix {{ name_prefix }}" + +- block: + - include_tasks: run-test.yml + with_fileglob: + - "tests/*.yml" + + always: + - name: "Make sure all images are removed" + docker_image: + name: "{{ item }}" + state: absent + with_items: "{{ inames }}" + - name: "Make sure all containers are removed" + docker_container: + name: "{{ item }}" + state: absent + force_kill: yes + with_items: "{{ cnames }}" + + when: docker_py_version is version('2.5.0', '>=') and docker_api_version is version('1.23', '>=') + +- fail: msg="Too old docker / docker-py version to run docker_image tests!" + when: not(docker_py_version is version('2.5.0', '>=') and docker_api_version is version('1.23', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6) diff --git a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml new file mode 100644 index 000000000..7468dd6c0 --- /dev/null +++ b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml @@ -0,0 +1,181 @@ +--- +- set_fact: + image_names: + - "{{ docker_test_image_hello_world }}" + - "{{ docker_test_image_busybox }}" + - "{{ docker_test_image_alpine }}" + +- name: Make sure images are there + docker_image: + name: "{{ item }}" + source: pull + register: images + loop: "{{ image_names }}" + +- name: Compile list of all image names and IDs + set_fact: + image_ids: "{{ images.results | map(attribute='image') | map(attribute='Id') | list }}" + all_images: "{{ image_names + (images.results | map(attribute='image') | map(attribute='Id') | list) }}" + +- name: Create archives + command: docker save {{ item.images | join(' ') }} -o {{ output_dir }}/{{ item.file }} + loop: + - file: archive-1.tar + images: "{{ image_names }}" + - file: archive-2.tar + images: "{{ image_ids }}" + - file: archive-3.tar + images: + - "{{ image_names[0] }}" + - "{{ image_ids[1] }}" + - file: archive-4.tar + images: + - "{{ image_ids[0] }}" + - "{{ image_names[0] }}" + - file: archive-5.tar + images: + - "{{ image_ids[0] }}" + +# All images by IDs + +- name: Remove all images + docker_image: + name: "{{ item }}" + state: absent + loop: "{{ all_images }}" + +- name: Load all images (IDs) + docker_image_load: + path: "{{ output_dir }}/archive-2.tar" + register: result + +- name: Print loaded image names + debug: + var: result.image_names + +- assert: + that: + - result is changed + - result.image_names | sort == image_ids | sort + - result.image_names | length == result.images | length + +- name: Load all images (IDs, should be same result) + docker_image_load: + path: "{{ output_dir }}/archive-2.tar" + register: result_2 + +- name: Print loaded image names + debug: + var: result_2.image_names + +- assert: + that: + - result_2 is changed + - result_2.image_names | sort == image_ids | sort + - result_2.image_names | length == result_2.images | length + +# Mixed images and IDs + +- name: Remove all images + docker_image: + name: "{{ item }}" + state: absent + loop: "{{ all_images }}" + +- name: Load all images (mixed images and IDs) + docker_image_load: + path: "{{ output_dir }}/archive-3.tar" + register: result + +- name: Print loaded image names + debug: + var: result.image_names + +- assert: + that: + - result is changed + - result.image_names | sort == [image_names[0], image_ids[0], image_ids[1]] | sort + - result.images | length == 3 + - result.images | map(attribute='Id') | sort == [image_ids[0], image_ids[0], image_ids[1]] | sort + +# Same image twice + +- name: Remove all images + docker_image: + name: "{{ item }}" + state: absent + loop: "{{ all_images }}" + +- name: Load all images (same image twice) + docker_image_load: + path: "{{ output_dir }}/archive-4.tar" + register: result + +- name: Print loaded image names + debug: + var: result.image_names + +- assert: + that: + - result is changed + - result.image_names | length == 1 + - result.image_names[0] == image_names[0] + - result.images | length == 1 + - result.images[0].Id == image_ids[0] + +# Single image by ID + +- name: Remove all images + docker_image: + name: "{{ item }}" + state: absent + loop: "{{ all_images }}" + +- name: Load all images (single image by ID) + docker_image_load: + path: "{{ output_dir }}/archive-5.tar" + register: result + +- name: Print loaded image names + debug: + var: result.image_names + +- assert: + that: + - result is changed + - result.image_names | length == 1 + - result.image_names[0] == image_ids[0] + - result.images | length == 1 + - result.images[0].Id == image_ids[0] + +- name: Try to get image info by name + docker_image_info: + name: "{{ image_names[0] }}" + register: result + +- name: Make sure that image does not exist by name + assert: + that: + - result.images | length == 0 + +# All images by names + +- name: Remove all images + docker_image: + name: "{{ item }}" + state: absent + loop: "{{ all_images }}" + +- name: Load all images (names) + docker_image_load: + path: "{{ output_dir }}/archive-1.tar" + register: result + +- name: Print loaded image names + debug: + var: result.image_names + +- assert: + that: + - result.image_names | sort == image_names | sort + - result.image_names | length == result.images | length From fb52e4c29fc8ca7d7d2f23c65aa29b584bf71618 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sat, 27 Feb 2021 23:22:26 +0100 Subject: [PATCH 04/13] Apply suggestions from code review Co-authored-by: Amin Vakil --- plugins/modules/docker_image_load.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/modules/docker_image_load.py b/plugins/modules/docker_image_load.py index 08e769fbe..34c206222 100644 --- a/plugins/modules/docker_image_load.py +++ b/plugins/modules/docker_image_load.py @@ -11,18 +11,18 @@ --- module: docker_image_load -short_description: Load docker images from archives +short_description: Load docker image(s) from archives version_added: 1.3.0 description: - Load one or multiple Docker images from a C(.tar) archive, and return information on - the loaded images. + the loaded image(s). options: path: description: - - The path to the C(.tar) archive to load Docker images from. + - The path to the C(.tar) archive to load Docker image(s) from. type: path required: true @@ -43,14 +43,14 @@ ''' EXAMPLES = ''' -- name: Load all images from the given tar file +- name: Load all image(s) from the given tar file community.docker.docker_image_load: path: /path/to/images.tar register: result - name: Print the loaded image names debug: - msg: "Loaded the following images: {{ resut.image_names | join(', ') }}" + msg: "Loaded the following images: {{ result.image_names | join(', ') }}" ''' RETURN = ''' From 79aef5917ed10044870379f1d4f0d69d39a2fa20 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 28 Feb 2021 11:25:41 +0100 Subject: [PATCH 05/13] Make sure that containers that still exist are also cleared. --- .../integration/targets/docker_image_load/tasks/tests/basic.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml index 7468dd6c0..1554aa543 100644 --- a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml +++ b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml @@ -42,6 +42,7 @@ docker_image: name: "{{ item }}" state: absent + force_absent: true loop: "{{ all_images }}" - name: Load all images (IDs) From f045610eace68ed2d306186658f69f5240986a30 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 28 Feb 2021 11:37:23 +0100 Subject: [PATCH 06/13] Always return stdout. --- plugins/modules/docker_image_load.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/docker_image_load.py b/plugins/modules/docker_image_load.py index 34c206222..a5d2026a5 100644 --- a/plugins/modules/docker_image_load.py +++ b/plugins/modules/docker_image_load.py @@ -155,6 +155,7 @@ def load_images(self): self.results['image_names'] = loaded_images self.results['images'] = images self.results['changed'] = True + self.results['stdout'] = '\n'.join(load_output) def main(): From 1f6c5a84a369fbfae1697acdfe2782a49b2c2e2f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 28 Feb 2021 11:55:34 +0100 Subject: [PATCH 07/13] Try to work around removal problems. --- .../docker_image_load/tasks/tests/basic.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml index 1554aa543..5abd37046 100644 --- a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml +++ b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml @@ -44,6 +44,21 @@ state: absent force_absent: true loop: "{{ all_images }}" + ignore_errors: true + register: remove_all_images + +- name: Prune all images (if removing failed) + docker_prune: + images: true + when: remove_all_images is failed + +- name: Remove all images (after pruning) + docker_image: + name: "{{ item }}" + state: absent + force_absent: true + loop: "{{ all_images }}" + when: remove_all_images is failed - name: Load all images (IDs) docker_image_load: From 335eeb1708dcc0d585f3447906c33a7e3b05fcbb Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 28 Feb 2021 12:35:49 +0100 Subject: [PATCH 08/13] Accept that the Docker daemon sometimes only reports the named image. --- .../targets/docker_image_load/tasks/tests/basic.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml index 5abd37046..c49c5c9d4 100644 --- a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml +++ b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml @@ -103,6 +103,10 @@ path: "{{ output_dir }}/archive-3.tar" register: result +- name: Print loading log + debug: + var: result.stdout_lines + - name: Print loaded image names debug: var: result.image_names @@ -110,9 +114,11 @@ - assert: that: - result is changed - - result.image_names | sort == [image_names[0], image_ids[0], image_ids[1]] | sort - - result.images | length == 3 - - result.images | map(attribute='Id') | sort == [image_ids[0], image_ids[0], image_ids[1]] | sort + # For some reason, *sometimes* only the named image is found; in fact, in that case, the log only mentions that image and nothing else + - "result.images | length == 3 or ('Loaded image: ' ~ docker_test_image_hello_world) == result.stdout" + - (result.image_names | sort) in [[image_names[0], image_ids[0], image_ids[1]] | sort, [image_names[0]]] + - result.images | length in [1, 3] + - (result.images | map(attribute='Id') | sort) in [[image_ids[0], image_ids[0], image_ids[1]] | sort, [image_ids[0]]] # Same image twice From 9087ca682bcde6caa5c71590d99d712b377db20f Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 28 Feb 2021 12:51:33 +0100 Subject: [PATCH 09/13] More debug output. --- .../targets/docker_image_load/tasks/tests/basic.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml index c49c5c9d4..5b62bf595 100644 --- a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml +++ b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml @@ -52,6 +52,16 @@ images: true when: remove_all_images is failed +- name: Obtain all docker containers and images (if removing failed) + shell: docker ps -a ; docker images -a + when: remove_all_images is failed + register: docker_container_image_list + +- name: Show all docker containers and images (if removing failed) + debug: + var: docker_container_image_list.stdout_lines + when: remove_all_images is failed + - name: Remove all images (after pruning) docker_image: name: "{{ item }}" From a9f6325a66f0bfae467f0637e286f26e098946ac Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 28 Feb 2021 13:05:39 +0100 Subject: [PATCH 10/13] Also prune containers, in the hope that these cause the problems. --- .../integration/targets/docker_image_load/tasks/tests/basic.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml index 5b62bf595..f3583a858 100644 --- a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml +++ b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml @@ -49,6 +49,7 @@ - name: Prune all images (if removing failed) docker_prune: + containers: true images: true when: remove_all_images is failed From d04b36bb078f76dd0ee70ac7e844c1caa292cae9 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 28 Feb 2021 13:13:38 +0100 Subject: [PATCH 11/13] Let's see whether pruning containers (but not images) is enough. --- .../targets/docker_image_load/tasks/tests/basic.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml index f3583a858..0748edf78 100644 --- a/tests/integration/targets/docker_image_load/tasks/tests/basic.yml +++ b/tests/integration/targets/docker_image_load/tasks/tests/basic.yml @@ -47,10 +47,9 @@ ignore_errors: true register: remove_all_images -- name: Prune all images (if removing failed) +- name: Prune all containers (if removing failed) docker_prune: containers: true - images: true when: remove_all_images is failed - name: Obtain all docker containers and images (if removing failed) From 06addf00d61ac4d9a0446666773e517536efdb6b Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 4 Mar 2021 20:40:17 +0100 Subject: [PATCH 12/13] Apply suggestions from code review Co-authored-by: Andrew Klychkov --- plugins/modules/docker_image_load.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/modules/docker_image_load.py b/plugins/modules/docker_image_load.py index a5d2026a5..6350376f3 100644 --- a/plugins/modules/docker_image_load.py +++ b/plugins/modules/docker_image_load.py @@ -39,7 +39,6 @@ author: - Felix Fontein (@felixfontein) - ''' EXAMPLES = ''' @@ -49,7 +48,7 @@ register: result - name: Print the loaded image names - debug: + ansible.builtin.debug: msg: "Loaded the following images: {{ result.image_names | join(', ') }}" ''' @@ -179,7 +178,8 @@ def main(): except DockerException as e: client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) except RequestException as e: - client.fail('An unexpected requests error occurred when docker-py tried to talk to the docker daemon: {0}'.format(e), exception=traceback.format_exc()) + client.fail('An unexpected requests error occurred when docker-py tried to talk ' + 'to the docker daemon: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': From 9ab4089868db32d11b1909bf22a048f646f7880a Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Fri, 5 Mar 2021 08:01:21 +0100 Subject: [PATCH 13/13] Update plugins/modules/docker_image_load.py Co-authored-by: Andrew Klychkov --- plugins/modules/docker_image_load.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/docker_image_load.py b/plugins/modules/docker_image_load.py index 6350376f3..920520b15 100644 --- a/plugins/modules/docker_image_load.py +++ b/plugins/modules/docker_image_load.py @@ -1,4 +1,5 @@ #!/usr/bin/python +# -*- coding: utf-8 -*- # # Copyright 2016 Red Hat | Ansible # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)