From f3a3f424902d208c8fdbfa9983559251faad875a Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 13 Nov 2018 09:21:55 +0100 Subject: [PATCH] docker_container: make condition less specific (#48590) * Code seems to have changed from 409 to 400, so let's not check the code. * Unpause container before removing it. * Improve code. * Same for stop_container. --- .../modules/cloud/docker/docker_container.py | 69 ++++++++++++++----- 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/lib/ansible/modules/cloud/docker/docker_container.py b/lib/ansible/modules/cloud/docker/docker_container.py index 688d7a4043..c853055638 100644 --- a/lib/ansible/modules/cloud/docker/docker_container.py +++ b/lib/ansible/modules/cloud/docker/docker_container.py @@ -2505,18 +2505,34 @@ class ContainerManager(DockerBaseClass): self.results['changed'] = True response = None if not self.check_mode: - try: - response = self.client.remove_container(container_id, v=volume_state, link=link, force=force) - except NotFound as exc: - pass - except APIError as exc: - if exc.response.status_code == 409 and ('removal of container ' in exc.explanation and - ' is already in progress' in exc.explanation): + count = 0 + while True: + try: + response = self.client.remove_container(container_id, v=volume_state, link=link, force=force) + except NotFound as exc: pass - else: + except APIError as exc: + if 'Unpause the container before stopping or killing' in exc.explanation: + # New docker versions do not allow containers to be removed if they are paused + # Make sure we don't end up in an infinite loop + if count == 3: + self.fail("Error removing container %s (tried to unpause three times): %s" % (container_id, str(exc))) + count += 1 + # Unpause + try: + self.client.unpause(container=container_id) + except Exception as exc2: + self.fail("Error unpausing container %s for removal: %s" % (container_id, str(exc2))) + # Now try again + continue + if 'removal of container ' in exc.explanation and ' is already in progress' in exc.explanation: + pass + else: + self.fail("Error removing container %s: %s" % (container_id, str(exc))) + except Exception as exc: self.fail("Error removing container %s: %s" % (container_id, str(exc))) - except Exception as exc: - self.fail("Error removing container %s: %s" % (container_id, str(exc))) + # We only loop when explicitly requested by 'continue' + break return response def container_update(self, container_id, update_parameters): @@ -2554,13 +2570,32 @@ class ContainerManager(DockerBaseClass): self.results['changed'] = True response = None if not self.check_mode: - try: - if self.parameters.stop_timeout: - response = self.client.stop(container_id, timeout=self.parameters.stop_timeout) - else: - response = self.client.stop(container_id) - except Exception as exc: - self.fail("Error stopping container %s: %s" % (container_id, str(exc))) + count = 0 + while True: + try: + if self.parameters.stop_timeout: + response = self.client.stop(container_id, timeout=self.parameters.stop_timeout) + else: + response = self.client.stop(container_id) + except APIError as exc: + if 'Unpause the container before stopping or killing' in exc.explanation: + # New docker versions do not allow containers to be removed if they are paused + # Make sure we don't end up in an infinite loop + if count == 3: + self.fail("Error removing container %s (tried to unpause three times): %s" % (container_id, str(exc))) + count += 1 + # Unpause + try: + self.client.unpause(container=container_id) + except Exception as exc2: + self.fail("Error unpausing container %s for removal: %s" % (container_id, str(exc2))) + # Now try again + continue + self.fail("Error stopping container %s: %s" % (container_id, str(exc))) + except Exception as exc: + self.fail("Error stopping container %s: %s" % (container_id, str(exc))) + # We only loop when explicitly requested by 'continue' + break return response