From f8f2738351cfe4e1285c3040b52b31f5373c6237 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 20 Jun 2019 22:59:15 +0200 Subject: [PATCH] docker_*: make modules more robust on Docker errors (#57913) * Improve general error behavior if a Docker error is not caught. * Don't die when network doesn't exist. * Add changelog. * Make API version always available. Also catch errors when retrieving version. * Fix error message. * Adjust fallback error messages. --- .../fragments/57913-docker-robustness.yaml | 2 + lib/ansible/module_utils/docker/common.py | 4 +- .../modules/cloud/docker/docker_compose.py | 19 +++-- .../modules/cloud/docker/docker_config.py | 16 +++-- .../modules/cloud/docker/docker_container.py | 26 ++++--- .../cloud/docker/docker_container_info.py | 23 ++++-- .../modules/cloud/docker/docker_host_info.py | 17 +++-- .../modules/cloud/docker/docker_image.py | 20 ++++-- .../modules/cloud/docker/docker_image_info.py | 18 +++-- .../modules/cloud/docker/docker_login.py | 28 +++++--- .../modules/cloud/docker/docker_network.py | 9 ++- .../cloud/docker/docker_network_info.py | 23 ++++-- .../modules/cloud/docker/docker_node.py | 17 +++-- .../modules/cloud/docker/docker_node_info.py | 17 +++-- .../modules/cloud/docker/docker_prune.py | 71 +++++++++++-------- .../modules/cloud/docker/docker_secret.py | 18 +++-- .../modules/cloud/docker/docker_swarm.py | 20 +++--- .../modules/cloud/docker/docker_swarm_info.py | 19 +++-- .../cloud/docker/docker_swarm_service.py | 30 ++++---- .../cloud/docker/docker_swarm_service_info.py | 23 ++++-- .../modules/cloud/docker/docker_volume.py | 11 ++- .../cloud/docker/docker_volume_info.py | 21 +++--- 22 files changed, 295 insertions(+), 157 deletions(-) create mode 100644 changelogs/fragments/57913-docker-robustness.yaml diff --git a/changelogs/fragments/57913-docker-robustness.yaml b/changelogs/fragments/57913-docker-robustness.yaml new file mode 100644 index 00000000000..3d036897632 --- /dev/null +++ b/changelogs/fragments/57913-docker-robustness.yaml @@ -0,0 +1,2 @@ +bugfixes: +- "docker_* modules - improve robustness when not handled Docker errors occur." diff --git a/lib/ansible/module_utils/docker/common.py b/lib/ansible/module_utils/docker/common.py index cda14889700..6c8d5851bee 100644 --- a/lib/ansible/module_utils/docker/common.py +++ b/lib/ansible/module_utils/docker/common.py @@ -332,14 +332,14 @@ class AnsibleDockerClient(Client): try: super(AnsibleDockerClient, self).__init__(**self._connect_params) + self.docker_api_version_str = self.version()['ApiVersion'] except APIError as exc: self.fail("Docker API error: %s" % exc) except Exception as exc: self.fail("Error connecting: %s" % exc) + self.docker_api_version = LooseVersion(self.docker_api_version_str) if min_docker_api_version is not None: - self.docker_api_version_str = self.version()['ApiVersion'] - self.docker_api_version = LooseVersion(self.docker_api_version_str) if self.docker_api_version < LooseVersion(min_docker_api_version): self.fail('Docker API version is %s. Minimum version required is %s.' % (self.docker_api_version_str, min_docker_api_version)) diff --git a/lib/ansible/modules/cloud/docker/docker_compose.py b/lib/ansible/modules/cloud/docker/docker_compose.py index e63e627748f..c3b14d10024 100644 --- a/lib/ansible/modules/cloud/docker/docker_compose.py +++ b/lib/ansible/modules/cloud/docker/docker_compose.py @@ -443,6 +443,7 @@ import os import re import sys import tempfile +import traceback from contextlib import contextmanager from distutils.version import LooseVersion @@ -452,7 +453,13 @@ try: HAS_YAML_EXC = None except ImportError as exc: HAS_YAML = False - HAS_YAML_EXC = str(exc) + HAS_YAML_EXC = traceback.format_exc() + +try: + from docker.errors import DockerException +except ImportError: + # missing Docker SDK for Python handled in ansible.module_utils.docker.common + pass try: from compose import __version__ as compose_version @@ -463,10 +470,9 @@ try: HAS_COMPOSE = True HAS_COMPOSE_EXC = None MINIMUM_COMPOSE_VERSION = '1.7.0' - except ImportError as exc: HAS_COMPOSE = False - HAS_COMPOSE_EXC = str(exc) + HAS_COMPOSE_EXC = traceback.format_exc() DEFAULT_TIMEOUT = 10 from ansible.module_utils.docker.common import AnsibleDockerClient, DockerBaseClass @@ -1090,8 +1096,11 @@ def main(): if client.module._name == 'docker_service': client.module.deprecate("The 'docker_service' module has been renamed to 'docker_compose'.", version='2.12') - result = ContainerManager(client).exec_module() - client.module.exit_json(**result) + try: + result = ContainerManager(client).exec_module() + client.module.exit_json(**result) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_config.py b/lib/ansible/modules/cloud/docker/docker_config.py index ccb6876b418..876f96124d4 100644 --- a/lib/ansible/modules/cloud/docker/docker_config.py +++ b/lib/ansible/modules/cloud/docker/docker_config.py @@ -152,9 +152,10 @@ config_id: import base64 import hashlib +import traceback try: - from docker.errors import APIError + from docker.errors import DockerException, APIError except ImportError: # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -281,12 +282,15 @@ def main(): min_docker_api_version='1.30', ) - results = dict( - changed=False, - ) + try: + results = dict( + changed=False, + ) - ConfigManager(client, results)() - client.module.exit_json(**results) + ConfigManager(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()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_container.py b/lib/ansible/modules/cloud/docker/docker_container.py index 52e575418dd..277c3f33c12 100644 --- a/lib/ansible/modules/cloud/docker/docker_container.py +++ b/lib/ansible/modules/cloud/docker/docker_container.py @@ -942,6 +942,7 @@ container: import os import re import shlex +import traceback from distutils.version import LooseVersion from ansible.module_utils.common.text.formatters import human_to_bytes @@ -964,7 +965,7 @@ try: from docker.types import Ulimit, LogConfig else: from docker.utils.types import Ulimit, LogConfig - from docker.errors import APIError, NotFound + from docker.errors import DockerException, APIError, NotFound except Exception: # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -1410,11 +1411,17 @@ class TaskParameters(DockerBaseClass): return ip for net in self.networks: if net.get('name'): - network = self.client.inspect_network(net['name']) - if network.get('Driver') == 'bridge' and \ - network.get('Options', {}).get('com.docker.network.bridge.host_binding_ipv4'): - ip = network['Options']['com.docker.network.bridge.host_binding_ipv4'] - break + try: + network = self.client.inspect_network(net['name']) + if network.get('Driver') == 'bridge' and \ + network.get('Options', {}).get('com.docker.network.bridge.host_binding_ipv4'): + ip = network['Options']['com.docker.network.bridge.host_binding_ipv4'] + break + except NotFound as e: + self.client.fail( + "Cannot inspect the network '{0}' to determine the default IP.".format(net['name']), + exception=traceback.format_exc() + ) return ip def _parse_publish_ports(self): @@ -3017,8 +3024,11 @@ def main(): version='2.12' ) - cm = ContainerManager(client) - client.module.exit_json(**sanitize_result(cm.results)) + try: + cm = ContainerManager(client) + client.module.exit_json(**sanitize_result(cm.results)) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_container_info.py b/lib/ansible/modules/cloud/docker/docker_container_info.py index 72147aad00a..59211a622c9 100644 --- a/lib/ansible/modules/cloud/docker/docker_container_info.py +++ b/lib/ansible/modules/cloud/docker/docker_container_info.py @@ -107,6 +107,14 @@ container: }' ''' +import traceback + +try: + from docker.errors import DockerException +except ImportError: + # missing Docker SDK for Python handled in ansible.module_utils.docker.common + pass + from ansible.module_utils.docker.common import AnsibleDockerClient @@ -121,13 +129,16 @@ def main(): min_docker_api_version='1.20', ) - container = client.get_container(client.module.params['name']) + try: + container = client.get_container(client.module.params['name']) - client.module.exit_json( - changed=False, - exists=(True if container else False), - container=container, - ) + client.module.exit_json( + changed=False, + exists=(True if container else False), + container=container, + ) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_host_info.py b/lib/ansible/modules/cloud/docker/docker_host_info.py index 9568e7d4b89..64ce257b7de 100644 --- a/lib/ansible/modules/cloud/docker/docker_host_info.py +++ b/lib/ansible/modules/cloud/docker/docker_host_info.py @@ -185,11 +185,13 @@ disk_usage: ''' +import traceback + from ansible.module_utils.docker.common import AnsibleDockerClient, DockerBaseClass from ansible.module_utils._text import to_native try: - from docker.errors import APIError + from docker.errors import DockerException, APIError except ImportError: # Missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -321,12 +323,15 @@ def main(): ) client.fail_results['can_talk_to_docker'] = True - results = dict( - changed=False, - ) + try: + results = dict( + changed=False, + ) - DockerHostManager(client, results) - client.module.exit_json(**results) + DockerHostManager(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()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_image.py b/lib/ansible/modules/cloud/docker/docker_image.py index 4ff5b26dfa1..b87f14a1178 100644 --- a/lib/ansible/modules/cloud/docker/docker_image.py +++ b/lib/ansible/modules/cloud/docker/docker_image.py @@ -410,8 +410,10 @@ image: type: dict sample: {} ''' + import os import re +import traceback from distutils.version import LooseVersion @@ -427,6 +429,7 @@ if docker_version is not None: else: from docker.auth.auth import resolve_repository_name from docker.utils.utils import parse_repository_tag + from docker.errors import DockerException except ImportError: # missing Docker SDK for Python handled in module_utils.docker.common pass @@ -914,14 +917,17 @@ def main(): 'use the "force_source", "force_absent" or "force_tag" option ' 'instead, depending on what you want to force.') - results = dict( - changed=False, - actions=[], - image={} - ) + try: + results = dict( + changed=False, + actions=[], + image={} + ) - ImageManager(client, results) - client.module.exit_json(**results) + 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()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_image_info.py b/lib/ansible/modules/cloud/docker/docker_image_info.py index 8c1f2151bfc..773aa188b42 100644 --- a/lib/ansible/modules/cloud/docker/docker_image_info.py +++ b/lib/ansible/modules/cloud/docker/docker_image_info.py @@ -154,8 +154,11 @@ images: ] ''' +import traceback + try: from docker import utils + from docker.errors import DockerException except ImportError: # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -234,13 +237,16 @@ def main(): if client.module._name == 'docker_image_facts': client.module.deprecate("The 'docker_image_facts' module has been renamed to 'docker_image_info'", version='2.12') - results = dict( - changed=False, - images=[] - ) + try: + results = dict( + changed=False, + images=[] + ) - ImageManager(client, results) - client.module.exit_json(**results) + 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()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_login.py b/lib/ansible/modules/cloud/docker/docker_login.py index 7879cb20244..60475be9edb 100644 --- a/lib/ansible/modules/cloud/docker/docker_login.py +++ b/lib/ansible/modules/cloud/docker/docker_login.py @@ -129,6 +129,13 @@ import base64 import json import os import re +import traceback + +try: + from docker.errors import DockerException +except ImportError: + # missing Docker SDK for Python handled in ansible.module_utils.docker.common + pass from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils.docker.common import AnsibleDockerClient, DEFAULT_DOCKER_REGISTRY, DockerBaseClass, EMAIL_REGEX @@ -311,16 +318,19 @@ def main(): min_docker_api_version='1.20', ) - results = dict( - changed=False, - actions=[], - login_result={} - ) + try: + results = dict( + changed=False, + actions=[], + login_result={} + ) - LoginManager(client, results) - if 'actions' in results: - del results['actions'] - client.module.exit_json(**results) + LoginManager(client, results) + if 'actions' in results: + del results['actions'] + client.module.exit_json(**results) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_network.py b/lib/ansible/modules/cloud/docker/docker_network.py index 4f237702a93..7496094045b 100644 --- a/lib/ansible/modules/cloud/docker/docker_network.py +++ b/lib/ansible/modules/cloud/docker/docker_network.py @@ -276,6 +276,7 @@ network: ''' import re +import traceback from distutils.version import LooseVersion @@ -289,6 +290,7 @@ from ansible.module_utils.docker.common import ( try: from docker import utils + from docker.errors import DockerException if LooseVersion(docker_version) >= LooseVersion('2.0.0'): from docker.types import IPAMPool, IPAMConfig except Exception: @@ -681,8 +683,11 @@ def main(): option_minimal_versions=option_minimal_versions, ) - cm = DockerNetworkManager(client) - client.module.exit_json(**cm.results) + try: + cm = DockerNetworkManager(client) + client.module.exit_json(**cm.results) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_network_info.py b/lib/ansible/modules/cloud/docker/docker_network_info.py index 3a7d885162a..40d02c21c05 100644 --- a/lib/ansible/modules/cloud/docker/docker_network_info.py +++ b/lib/ansible/modules/cloud/docker/docker_network_info.py @@ -103,6 +103,14 @@ network: }' ''' +import traceback + +try: + from docker.errors import DockerException +except ImportError: + # missing Docker SDK for Python handled in ansible.module_utils.docker.common + pass + from ansible.module_utils.docker.common import AnsibleDockerClient @@ -117,13 +125,16 @@ def main(): min_docker_api_version='1.21', ) - network = client.get_network(client.module.params['name']) + try: + network = client.get_network(client.module.params['name']) - client.module.exit_json( - changed=False, - exists=(True if network else False), - network=network, - ) + client.module.exit_json( + changed=False, + exists=(True if network else False), + network=network, + ) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_node.py b/lib/ansible/modules/cloud/docker/docker_node.py index 0ae974fae7c..1c2455dbbe8 100644 --- a/lib/ansible/modules/cloud/docker/docker_node.py +++ b/lib/ansible/modules/cloud/docker/docker_node.py @@ -129,8 +129,10 @@ node: ''' +import traceback + try: - from docker.errors import APIError + from docker.errors import DockerException, APIError except ImportError: # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -277,12 +279,15 @@ def main(): min_docker_api_version='1.25', ) - results = dict( - changed=False, - ) + try: + results = dict( + changed=False, + ) - SwarmNodeManager(client, results) - client.module.exit_json(**results) + SwarmNodeManager(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()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_node_info.py b/lib/ansible/modules/cloud/docker/docker_node_info.py index e85857b3173..38fe2fbc43b 100644 --- a/lib/ansible/modules/cloud/docker/docker_node_info.py +++ b/lib/ansible/modules/cloud/docker/docker_node_info.py @@ -87,10 +87,12 @@ nodes: type: list ''' +import traceback + from ansible.module_utils.docker.swarm import AnsibleDockerSwarmClient try: - from docker.errors import APIError, NotFound + from docker.errors import DockerException, APIError, NotFound except ImportError: # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -136,12 +138,15 @@ def main(): client.fail_task_if_not_swarm_manager() - nodes = get_node_facts(client) + try: + nodes = get_node_facts(client) - client.module.exit_json( - changed=False, - nodes=nodes, - ) + client.module.exit_json( + changed=False, + nodes=nodes, + ) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_prune.py b/lib/ansible/modules/cloud/docker/docker_prune.py index 3c7c8d410f4..902e6fbb515 100644 --- a/lib/ansible/modules/cloud/docker/docker_prune.py +++ b/lib/ansible/modules/cloud/docker/docker_prune.py @@ -177,6 +177,14 @@ builder_cache_space_reclaimed: sample: '0' ''' +import traceback + +try: + from docker.errors import DockerException +except ImportError: + # missing Docker SDK for Python handled in ansible.module_utils.docker.common + pass + from distutils.version import LooseVersion from ansible.module_utils.docker.common import AnsibleDockerClient @@ -214,36 +222,39 @@ def main(): msg = "Error: Docker SDK for Python's version is %s. Minimum version required for builds option is %s. Use `pip install --upgrade docker` to upgrade." client.fail(msg % (docker_version, cache_min_version)) - result = dict() - - if client.module.params['containers']: - filters = clean_dict_booleans_for_docker_api(client.module.params.get('containers_filters')) - res = client.prune_containers(filters=filters) - result['containers'] = res.get('ContainersDeleted') or [] - result['containers_space_reclaimed'] = res['SpaceReclaimed'] - - if client.module.params['images']: - filters = clean_dict_booleans_for_docker_api(client.module.params.get('images_filters')) - res = client.prune_images(filters=filters) - result['images'] = res.get('ImagesDeleted') or [] - result['images_space_reclaimed'] = res['SpaceReclaimed'] - - if client.module.params['networks']: - filters = clean_dict_booleans_for_docker_api(client.module.params.get('networks_filters')) - res = client.prune_networks(filters=filters) - result['networks'] = res.get('NetworksDeleted') or [] - - if client.module.params['volumes']: - filters = clean_dict_booleans_for_docker_api(client.module.params.get('volumes_filters')) - res = client.prune_volumes(filters=filters) - result['volumes'] = res.get('VolumesDeleted') or [] - result['volumes_space_reclaimed'] = res['SpaceReclaimed'] - - if client.module.params['builder_cache']: - res = client.prune_builds() - result['builder_cache_space_reclaimed'] = res['SpaceReclaimed'] - - client.module.exit_json(**result) + try: + result = dict() + + if client.module.params['containers']: + filters = clean_dict_booleans_for_docker_api(client.module.params.get('containers_filters')) + res = client.prune_containers(filters=filters) + result['containers'] = res.get('ContainersDeleted') or [] + result['containers_space_reclaimed'] = res['SpaceReclaimed'] + + if client.module.params['images']: + filters = clean_dict_booleans_for_docker_api(client.module.params.get('images_filters')) + res = client.prune_images(filters=filters) + result['images'] = res.get('ImagesDeleted') or [] + result['images_space_reclaimed'] = res['SpaceReclaimed'] + + if client.module.params['networks']: + filters = clean_dict_booleans_for_docker_api(client.module.params.get('networks_filters')) + res = client.prune_networks(filters=filters) + result['networks'] = res.get('NetworksDeleted') or [] + + if client.module.params['volumes']: + filters = clean_dict_booleans_for_docker_api(client.module.params.get('volumes_filters')) + res = client.prune_volumes(filters=filters) + result['volumes'] = res.get('VolumesDeleted') or [] + result['volumes_space_reclaimed'] = res['SpaceReclaimed'] + + if client.module.params['builder_cache']: + res = client.prune_builds() + result['builder_cache_space_reclaimed'] = res['SpaceReclaimed'] + + client.module.exit_json(**result) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_secret.py b/lib/ansible/modules/cloud/docker/docker_secret.py index 2554d90ac01..5822a2719d9 100644 --- a/lib/ansible/modules/cloud/docker/docker_secret.py +++ b/lib/ansible/modules/cloud/docker/docker_secret.py @@ -152,9 +152,10 @@ secret_id: import base64 import hashlib +import traceback try: - from docker.errors import APIError + from docker.errors import DockerException, APIError except ImportError: # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -281,13 +282,16 @@ def main(): min_docker_api_version='1.25', ) - results = dict( - changed=False, - secret_id='' - ) + try: + results = dict( + changed=False, + secret_id='' + ) - SecretManager(client, results)() - client.module.exit_json(**results) + SecretManager(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()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_swarm.py b/lib/ansible/modules/cloud/docker/docker_swarm.py index 9e2c71add4e..d6ff74a6400 100644 --- a/lib/ansible/modules/cloud/docker/docker_swarm.py +++ b/lib/ansible/modules/cloud/docker/docker_swarm.py @@ -267,9 +267,10 @@ actions: ''' import json +import traceback try: - from docker.errors import APIError + from docker.errors import DockerException, APIError except ImportError: # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -659,14 +660,17 @@ def main(): option_minimal_versions=option_minimal_versions, ) - results = dict( - changed=False, - result='', - actions=[] - ) + try: + results = dict( + changed=False, + result='', + actions=[] + ) - SwarmManager(client, results)() - client.module.exit_json(**results) + SwarmManager(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()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_swarm_info.py b/lib/ansible/modules/cloud/docker/docker_swarm_info.py index 0f260b2871f..8cde9b4576a 100644 --- a/lib/ansible/modules/cloud/docker/docker_swarm_info.py +++ b/lib/ansible/modules/cloud/docker/docker_swarm_info.py @@ -192,8 +192,10 @@ tasks: ''' +import traceback + try: - from docker.errors import APIError, NotFound + from docker.errors import DockerException, APIError, NotFound except ImportError: # missing Docker SDK for Python handled in ansible.module_utils.docker_common pass @@ -361,13 +363,16 @@ def main(): client.fail_results['docker_swarm_active'] = client.check_if_swarm_node() client.fail_results['docker_swarm_manager'] = client.check_if_swarm_manager() - results = dict( - changed=False, - ) + try: + results = dict( + changed=False, + ) - DockerSwarmManager(client, results) - results.update(client.fail_results) - client.module.exit_json(**results) + DockerSwarmManager(client, results) + results.update(client.fail_results) + client.module.exit_json(**results) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_swarm_service.py b/lib/ansible/modules/cloud/docker/docker_swarm_service.py index 96cc5f8aa16..e33fba7a314 100644 --- a/lib/ansible/modules/cloud/docker/docker_swarm_service.py +++ b/lib/ansible/modules/cloud/docker/docker_swarm_service.py @@ -1046,6 +1046,7 @@ EXAMPLES = ''' import shlex import time import operator +import traceback from distutils.version import LooseVersion @@ -2740,21 +2741,24 @@ def main(): option_minimal_versions=option_minimal_versions, ) - dsm = DockerServiceManager(client) - msg, changed, rebuilt, changes, facts = dsm.run_safe() + try: + dsm = DockerServiceManager(client) + msg, changed, rebuilt, changes, facts = dsm.run_safe() - results = dict( - msg=msg, - changed=changed, - rebuilt=rebuilt, - changes=changes, - swarm_service=facts, - ) - if client.module._diff: - before, after = dsm.diff_tracker.get_before_after() - results['diff'] = dict(before=before, after=after) + results = dict( + msg=msg, + changed=changed, + rebuilt=rebuilt, + changes=changes, + swarm_service=facts, + ) + if client.module._diff: + before, after = dsm.diff_tracker.get_before_after() + results['diff'] = dict(before=before, after=after) - client.module.exit_json(**results) + client.module.exit_json(**results) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_swarm_service_info.py b/lib/ansible/modules/cloud/docker/docker_swarm_service_info.py index 072f97e72ad..9ec4cb3aeca 100644 --- a/lib/ansible/modules/cloud/docker/docker_swarm_service_info.py +++ b/lib/ansible/modules/cloud/docker/docker_swarm_service_info.py @@ -66,6 +66,14 @@ service: type: dict ''' +import traceback + +try: + from docker.errors import DockerException +except ImportError: + # missing Docker SDK for Python handled in ansible.module_utils.docker.common + pass + from ansible.module_utils.docker.swarm import AnsibleDockerSwarmClient @@ -91,13 +99,16 @@ def main(): client.fail_task_if_not_swarm_manager() - service = get_service_info(client) + try: + service = get_service_info(client) - client.module.exit_json( - changed=False, - service=service, - exists=bool(service) - ) + client.module.exit_json( + changed=False, + service=service, + exists=bool(service) + ) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_volume.py b/lib/ansible/modules/cloud/docker/docker_volume.py index 67e80c706ec..66eade09b70 100644 --- a/lib/ansible/modules/cloud/docker/docker_volume.py +++ b/lib/ansible/modules/cloud/docker/docker_volume.py @@ -125,8 +125,10 @@ volume: sample: {} ''' +import traceback + try: - from docker.errors import APIError + from docker.errors import DockerException, APIError except ImportError: # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -323,8 +325,11 @@ def main(): option_minimal_versions=option_minimal_versions, ) - cm = DockerVolumeManager(client) - client.module.exit_json(**cm.results) + try: + cm = DockerVolumeManager(client) + client.module.exit_json(**cm.results) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__': diff --git a/lib/ansible/modules/cloud/docker/docker_volume_info.py b/lib/ansible/modules/cloud/docker/docker_volume_info.py index 58edd152933..3bad1a937cb 100644 --- a/lib/ansible/modules/cloud/docker/docker_volume_info.py +++ b/lib/ansible/modules/cloud/docker/docker_volume_info.py @@ -80,8 +80,10 @@ volume: }' ''' +import traceback + try: - from docker.errors import NotFound + from docker.errors import DockerException, NotFound except ImportError: # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -110,13 +112,16 @@ def main(): min_docker_api_version='1.21', ) - volume = get_existing_volume(client, client.module.params['name']) - - client.module.exit_json( - changed=False, - exists=(True if volume else False), - volume=volume, - ) + try: + volume = get_existing_volume(client, client.module.params['name']) + + client.module.exit_json( + changed=False, + exists=(True if volume else False), + volume=volume, + ) + except DockerException as e: + client.fail('An unexpected docker error occurred: {0}'.format(e), exception=traceback.format_exc()) if __name__ == '__main__':