From 4a12be31fba6509637d72f0642db3295c0b095ef Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 23 Jun 2019 12:27:33 +0200 Subject: [PATCH] docker_* modules: improve error message when docker-py is missing (#57914) * Improve error for docker modules when docker-py can't be imported. * Add changelog. * Mention platform and Python interpreter in more cases. * Clarify wording. * Adjust tests. --- .../fragments/57914-docker-py-missing.yaml | 2 ++ lib/ansible/module_utils/docker/common.py | 26 +++++++++++-------- .../cloud/docker/test_docker_volume.py | 3 ++- 3 files changed, 19 insertions(+), 12 deletions(-) create mode 100644 changelogs/fragments/57914-docker-py-missing.yaml diff --git a/changelogs/fragments/57914-docker-py-missing.yaml b/changelogs/fragments/57914-docker-py-missing.yaml new file mode 100644 index 00000000000..2ca7b7b65bc --- /dev/null +++ b/changelogs/fragments/57914-docker-py-missing.yaml @@ -0,0 +1,2 @@ +bugfixes: +- "docker_* modules - improve error message when docker-py is missing / has wrong version." diff --git a/lib/ansible/module_utils/docker/common.py b/lib/ansible/module_utils/docker/common.py index 6c8d5851bee..f530bcc2556 100644 --- a/lib/ansible/module_utils/docker/common.py +++ b/lib/ansible/module_utils/docker/common.py @@ -17,12 +17,14 @@ # along with Ansible. If not, see . import os +import platform import re +import sys from datetime import timedelta from distutils.version import LooseVersion -from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.basic import AnsibleModule, env_fallback, missing_required_lib from ansible.module_utils.common._collections_compat import Mapping, Sequence from ansible.module_utils.six import string_types from ansible.module_utils.six.moves.urllib.parse import urlparse @@ -258,7 +260,7 @@ DOCKERPYUPGRADE_SWITCH_TO_DOCKER = "Try `pip uninstall docker-py` followed by `p DOCKERPYUPGRADE_UPGRADE_DOCKER = "Use `pip install --upgrade docker` to upgrade." DOCKERPYUPGRADE_RECOMMEND_DOCKER = ("Use `pip install --upgrade docker-py` to upgrade. " "Hint: if you do not need Python 2.6 support, try " - "`pip uninstall docker-py` instead followed by `pip install docker`.") + "`pip uninstall docker-py` instead, followed by `pip install docker`.") class AnsibleDockerClient(Client): @@ -303,19 +305,21 @@ class AnsibleDockerClient(Client): self.fail("Cannot have both the docker-py and docker python modules (old and new version of Docker " "SDK for Python) installed together as they use the same namespace and cause a corrupt " "installation. Please uninstall both packages, and re-install only the docker-py or docker " - "python module. It is recommended to install the docker module if no support for Python 2.6 " - "is required. Please note that simply uninstalling one of the modules can leave the other " - "module in a broken state.") + "python module (for %s's Python %s). It is recommended to install the docker module if no " + "support for Python 2.6 is required. Please note that simply uninstalling one of the modules " + "can leave the other module in a broken state." % (platform.node(), sys.executable)) if not HAS_DOCKER_PY: if NEEDS_DOCKER_PY2: - msg = "Failed to import docker (Docker SDK for Python) - %s. Try `pip install docker`." + msg = missing_required_lib("Docker SDK for Python: docker") + msg = msg + ", for example via `pip install docker`. The error was: %s" else: - msg = "Failed to import docker or docker-py (Docker SDK for Python) - %s. Try `pip install docker` or `pip install docker-py` (Python 2.6)." + msg = missing_required_lib("Docker SDK for Python: docker (Python >= 2.7) or docker-py (Python 2.6)") + msg = msg + ", for example via `pip install docker` or `pip install docker-py` (Python 2.6). The error was: %s" self.fail(msg % HAS_DOCKER_ERROR) if self.docker_py_version < LooseVersion(min_docker_version): - msg = "Error: Docker SDK for Python version is %s. Minimum version required is %s. " + msg = "Error: Docker SDK for Python version is %s (%s's Python %s). Minimum version required is %s." if not NEEDS_DOCKER_PY2: # The minimal required version is < 2.0 (and the current version as well). # Advertise docker (instead of docker-py) for non-Python-2.6 users. @@ -324,7 +328,7 @@ class AnsibleDockerClient(Client): msg += DOCKERPYUPGRADE_SWITCH_TO_DOCKER else: msg += DOCKERPYUPGRADE_UPGRADE_DOCKER - self.fail(msg % (docker_version, min_docker_version)) + self.fail(msg % (docker_version, platform.node(), sys.executable, min_docker_version)) self.debug = self.module.params.get('debug') self.check_mode = self.module.check_mode @@ -477,14 +481,14 @@ class AnsibleDockerClient(Client): msg = 'Docker API version is %s. Minimum version required is %s to %s.' msg = msg % (self.docker_api_version_str, data['docker_api_version'], usg) elif not support_docker_py: - msg = "Docker SDK for Python version is %s. Minimum version required is %s to %s. " + msg = "Docker SDK for Python version is %s (%s's Python %s). Minimum version required is %s to %s. " if LooseVersion(data['docker_py_version']) < LooseVersion('2.0.0'): msg += DOCKERPYUPGRADE_RECOMMEND_DOCKER elif self.docker_py_version < LooseVersion('2.0.0'): msg += DOCKERPYUPGRADE_SWITCH_TO_DOCKER else: msg += DOCKERPYUPGRADE_UPGRADE_DOCKER - msg = msg % (docker_version, data['docker_py_version'], usg) + msg = msg % (docker_version, platform.node(), sys.executable, data['docker_py_version'], usg) else: # should not happen msg = 'Cannot %s with your configuration.' % (usg, ) diff --git a/test/units/modules/cloud/docker/test_docker_volume.py b/test/units/modules/cloud/docker/test_docker_volume.py index ea83999e274..9a1b96cf7b2 100644 --- a/test/units/modules/cloud/docker/test_docker_volume.py +++ b/test/units/modules/cloud/docker/test_docker_volume.py @@ -28,4 +28,5 @@ def test_create_volume_on_invalid_docker_version(mocker, capfd): out, dummy = capfd.readouterr() results = json.loads(out) assert results['failed'] - assert 'Error: Docker SDK for Python version is 1.8.0. Minimum version required is 1.10.0.' in results['msg'] + assert 'Error: Docker SDK for Python version is 1.8.0 ' in results['msg'] + assert 'Minimum version required is 1.10.0.' in results['msg']