diff --git a/lib/ansible/module_utils/docker/common.py b/lib/ansible/module_utils/docker/common.py index 6056bc68f7..995ae1b0e3 100644 --- a/lib/ansible/module_utils/docker/common.py +++ b/lib/ansible/module_utils/docker/common.py @@ -58,14 +58,14 @@ except ImportError as exc: # to ensure the user does not have both ``docker`` and ``docker-py`` modules # installed, as they utilize the same namespace are are incompatible try: - # docker + # docker (Docker SDK for Python >= 2.0.0) import docker.models # noqa: F401 HAS_DOCKER_MODELS = True except ImportError: HAS_DOCKER_MODELS = False try: - # docker-py + # docker-py (Docker SDK for Python < 2.0.0) import docker.ssladapter # noqa: F401 HAS_DOCKER_SSLADAPTER = True except ImportError: @@ -107,7 +107,7 @@ BYTE_SUFFIXES = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'] if not HAS_DOCKER_PY: docker_version = None - # No docker-py. Create a place holder client to allow + # No Docker SDK for Python. Create a place holder client to allow # instantiation of AnsibleModule and proper error handing class Client(object): # noqa: F811 def __init__(self, **kwargs): @@ -254,6 +254,13 @@ def get_connect_params(auth, fail_function): timeout=auth['timeout']) +DOCKERPYUPGRADE_SWITCH_TO_DOCKER = "Try `pip uninstall docker-py` followed by `pip install docker`." +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`.") + + class AnsibleDockerClient(Client): def __init__(self, argument_spec=None, supports_check_mode=False, mutually_exclusive=None, @@ -293,29 +300,30 @@ class AnsibleDockerClient(Client): self.docker_py_version = LooseVersion(docker_version) if HAS_DOCKER_MODELS and HAS_DOCKER_SSLADAPTER: - self.fail("Cannot have both the docker-py and docker python modules 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.") + 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.") if not HAS_DOCKER_PY: if NEEDS_DOCKER_PY2: - msg = "Failed to import docker - %s. Try `pip install docker`" + msg = "Failed to import docker (Docker SDK for Python) - %s. Try `pip install docker`." else: - msg = "Failed to import docker or docker-py - %s. Try `pip install docker` or `pip install docker-py` (Python 2.6)" + 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)." self.fail(msg % HAS_DOCKER_ERROR) if self.docker_py_version < LooseVersion(min_docker_version): - if NEEDS_DOCKER_PY2: - if docker_version < LooseVersion('2.0'): - msg = "Error: docker-py version is %s, while this module requires docker %s. Try `pip uninstall docker-py` and then `pip install docker`" - else: - msg = "Error: docker version is %s. Minimum version required is %s. Use `pip install --upgrade docker` to upgrade." - else: + msg = "Error: Docker SDK for Python version is %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. - msg = ("Error: docker / docker-py version is %s. Minimum version required is %s. " - "Hint: if you do not need Python 2.6 support, try `pip uninstall docker-py` followed by `pip install docker`") + msg += DOCKERPYUPGRADE_RECOMMEND_DOCKER + elif docker_version < LooseVersion('2.0'): + msg += DOCKERPYUPGRADE_SWITCH_TO_DOCKER + else: + msg += DOCKERPYUPGRADE_UPGRADE_DOCKER self.fail(msg % (docker_version, min_docker_version)) self.debug = self.module.params.get('debug') @@ -333,7 +341,7 @@ class AnsibleDockerClient(Client): 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)) + self.fail('Docker API version is %s. Minimum version required is %s.' % (self.docker_api_version_str, min_docker_api_version)) if option_minimal_versions is not None: self._get_minimal_versions(option_minimal_versions, option_minimal_versions_ignore_params) @@ -425,9 +433,10 @@ class AnsibleDockerClient(Client): def _handle_ssl_error(self, error): match = re.match(r"hostname.*doesn\'t match (\'.*\')", str(error)) if match: - self.fail("You asked for verification that Docker host name matches %s. The actual hostname is %s. " - "Most likely you need to set DOCKER_TLS_HOSTNAME or pass tls_hostname with a value of %s. " - "You may also use TLS without verification by setting the tls parameter to true." + self.fail("You asked for verification that Docker daemons certificate's hostname matches %s. " + "The actual certificate's hostname is %s. Most likely you need to set DOCKER_TLS_HOSTNAME " + "or pass `tls_hostname` with a value of %s. You may also use TLS without verification by " + "setting the `tls` parameter to true." % (self.auth_params['tls_hostname'], match.group(1), match.group(1))) self.fail("SSL Exception: %s" % (error)) @@ -465,18 +474,16 @@ class AnsibleDockerClient(Client): else: usg = 'set %s option' % (option, ) if not support_docker_api: - msg = 'docker API version is %s. Minimum version required is %s to %s.' + 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. " if LooseVersion(data['docker_py_version']) < LooseVersion('2.0.0'): - msg = ("docker-py version is %s. Minimum version required is %s to %s. " - "Consider switching to the 'docker' package if you do not require Python 2.6 support.") + msg += DOCKERPYUPGRADE_RECOMMEND_DOCKER elif self.docker_py_version < LooseVersion('2.0.0'): - msg = ("docker-py version is %s. Minimum version required is %s to %s. " - "You have to switch to the Python 'docker' package. First uninstall 'docker-py' before " - "installing 'docker' to avoid a broken installation.") + msg += DOCKERPYUPGRADE_SWITCH_TO_DOCKER else: - msg = "docker version is %s. Minimum version required is %s to %s." + msg += DOCKERPYUPGRADE_UPGRADE_DOCKER msg = msg % (docker_version, data['docker_py_version'], usg) else: # should not happen @@ -621,9 +628,9 @@ class AnsibleDockerClient(Client): def _image_lookup(self, name, tag): ''' - Including a tag in the name parameter sent to the docker-py images method does not - work consistently. Instead, get the result set for name and manually check if the tag - exists. + Including a tag in the name parameter sent to the Docker SDK for Python images method + does not work consistently. Instead, get the result set for name and manually check + if the tag exists. ''' try: response = self.images(name=name) diff --git a/lib/ansible/module_utils/docker/swarm.py b/lib/ansible/module_utils/docker/swarm.py index 9cdd52746d..e8eec4b689 100644 --- a/lib/ansible/module_utils/docker/swarm.py +++ b/lib/ansible/module_utils/docker/swarm.py @@ -9,7 +9,7 @@ from re import split try: from docker.errors import APIError except ImportError: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass from ansible.module_utils._text import to_native diff --git a/lib/ansible/modules/cloud/docker/docker_compose.py b/lib/ansible/modules/cloud/docker/docker_compose.py index a46c635ea1..01963b21b7 100644 --- a/lib/ansible/modules/cloud/docker/docker_compose.py +++ b/lib/ansible/modules/cloud/docker/docker_compose.py @@ -153,7 +153,7 @@ extends_documentation_fragment: - docker.docker_py_1_documentation requirements: - - "docker-py >= 1.8.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.8.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - "docker-compose >= 1.7.0" - "Docker API >= 1.20" - "PyYAML >= 3.11" diff --git a/lib/ansible/modules/cloud/docker/docker_config.py b/lib/ansible/modules/cloud/docker/docker_config.py index 042a7f72b6..6527f46640 100644 --- a/lib/ansible/modules/cloud/docker/docker_config.py +++ b/lib/ansible/modules/cloud/docker/docker_config.py @@ -69,7 +69,7 @@ extends_documentation_fragment: - docker.docker_py_2_documentation requirements: - - "docker >= 2.6.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 2.6.0" - "Docker API >= 1.30" author: @@ -156,7 +156,7 @@ import hashlib try: from docker.errors import APIError except ImportError: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass from ansible.module_utils.docker.common import AnsibleDockerClient, DockerBaseClass, compare_generic diff --git a/lib/ansible/modules/cloud/docker/docker_container.py b/lib/ansible/modules/cloud/docker/docker_container.py index 9801fff3a9..8a1730dffa 100644 --- a/lib/ansible/modules/cloud/docker/docker_container.py +++ b/lib/ansible/modules/cloud/docker/docker_container.py @@ -293,7 +293,7 @@ options: init: description: - Run an init inside the container that forwards signals and reaps processes. - This option requires Docker API 1.25+. + This option requires Docker API >= 1.25. type: bool default: no version_added: "2.6" @@ -429,12 +429,14 @@ options: type: bool oom_score_adj: description: - - An integer value containing the score given to the container in order to tune OOM killer preferences. + - An integer value containing the score given to the container in order to tune + OOM killer preferences. type: int version_added: "2.2" output_logs: description: - - If set to true, output of the container command will be printed (only effective when log_driver is set to json-file or journald. + - If set to true, output of the container command will be printed (only effective + when log_driver is set to json-file or journald. type: bool default: no version_added: "2.7" @@ -446,7 +448,8 @@ options: pid_mode: description: - Set the PID namespace mode for the container. - - Note that docker-py < 2.0 only supports 'host'. Newer versions allow all values supported by the docker daemon. + - Note that Docker SDK for Python < 2.0 only supports 'host'. Newer versions of the + Docker SDK for Python (docker) allow all values supported by the docker daemon. type: str pids_limit: description: @@ -579,9 +582,9 @@ options: will be set to this value. - When the container is stopped, will be used as a timeout for stopping the container. In case the container has a custom C(StopTimeout) configuration, - the behavior depends on the version of docker. New versions of docker will - always use the container's configured C(StopTimeout) value if it has been - configured. + the behavior depends on the version of the docker daemon. New versions of + the docker daemon will always use the container's configured C(StopTimeout) + value if it has been configured. type: int trust_image_content: description: @@ -622,7 +625,7 @@ options: - "Use docker CLI-style syntax: C(/host:/container[:mode])" - "Mount modes can be a comma-separated list of various modes such as C(ro), C(rw), C(consistent), C(delegated), C(cached), C(rprivate), C(private), C(rshared), C(shared), C(rslave), C(slave). - Note that docker might not support all modes and combinations of such modes." + Note that the docker daemon might not support all modes and combinations of such modes." - SELinux hosts can additionally use C(z) or C(Z) to use a shared or private label for the volume. - "Note that Ansible 2.7 and earlier only supported one mode, which had to be one of C(ro), C(rw), @@ -654,9 +657,10 @@ author: - "Daan Oosterveld (@dusdanig)" - "Chris Houseknecht (@chouseknecht)" - "Kassian Sun (@kassiansun)" + - "Felix Fontein (@felixfontein)" requirements: - - "docker-py >= 1.8.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.8.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - "Docker API >= 1.20" ''' @@ -945,7 +949,7 @@ try: from docker.utils.types import Ulimit, LogConfig from docker.errors import APIError, NotFound except Exception: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -1351,7 +1355,7 @@ class TaskParameters(DockerBaseClass): if self.client.docker_py_version >= LooseVersion('1.9') and self.client.docker_api_version >= LooseVersion('1.22'): # blkio_weight can always be updated, but can only be set on creation - # when docker-py and docker API are new enough + # when Docker SDK for Python and Docker API are new enough host_config_params['blkio_weight'] = 'blkio_weight' if self.client.docker_py_version >= LooseVersion('3.0'): @@ -1819,15 +1823,15 @@ class Container(DockerBaseClass): config_mapping['log_options'] = log_config.get('Config') if self.parameters.client.option_minimal_versions['auto_remove']['supported']: - # auto_remove is only supported in docker>=2; unfortunately it has a default - # value, that's why we have to jump through the hoops here + # auto_remove is only supported in Docker SDK for Python >= 2.0.0; unfortunately + # it has a default value, that's why we have to jump through the hoops here config_mapping['auto_remove'] = host_config.get('AutoRemove') if self.parameters.client.option_minimal_versions['stop_timeout']['supported']: - # stop_timeout is only supported in docker>=2.1. Note that stop_timeout - # has a hybrid role, in that it used to be something only used for stopping - # containers, and is now also used as a container property. That's why - # it needs special handling here. + # stop_timeout is only supported in Docker SDK for Python >= 2.1. Note that + # stop_timeout has a hybrid role, in that it used to be something only used + # for stopping containers, and is now also used as a container property. + # That's why it needs special handling here. config_mapping['stop_timeout'] = config.get('StopTimeout') if self.parameters.client.docker_api_version < LooseVersion('1.22'): @@ -2544,8 +2548,8 @@ class ContainerManager(DockerBaseClass): pass 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 + # New docker daemon 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 @@ -2611,8 +2615,8 @@ class ContainerManager(DockerBaseClass): 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 + # New docker daemon 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 @@ -2754,14 +2758,14 @@ class AnsibleDockerClientContainer(AnsibleDockerClient): if stop_timeout_needed_for_update and not stop_timeout_supported: # We warn (instead of fail) since in older versions, stop_timeout was not used # to update the container's configuration, but only when stopping a container. - self.module.warn("docker or docker-py version is %s. Minimum version required is 2.1 to update " + self.module.warn("Docker SDK for Python's version is %s. Minimum version required is 2.1 to update " "the container's stop_timeout configuration. " - "If you use the 'docker-py' module, you have to switch to the docker 'Python' package." % (docker_version,)) + "If you use the 'docker-py' module, you have to switch to the 'docker' Python package." % (docker_version,)) else: if stop_timeout_needed_for_update and not stop_timeout_supported: # We warn (instead of fail) since in older versions, stop_timeout was not used # to update the container's configuration, but only when stopping a container. - self.module.warn("docker API version is %s. Minimum version required is 1.25 to set or " + self.module.warn("Docker API version is %s. Minimum version required is 1.25 to set or " "update the container's stop_timeout configuration." % (self.docker_api_version_str,)) self.option_minimal_versions['stop_timeout']['supported'] = stop_timeout_supported diff --git a/lib/ansible/modules/cloud/docker/docker_container_facts.py b/lib/ansible/modules/cloud/docker/docker_container_facts.py index 4d9cd9be24..6fbe667042 100644 --- a/lib/ansible/modules/cloud/docker/docker_container_facts.py +++ b/lib/ansible/modules/cloud/docker/docker_container_facts.py @@ -40,7 +40,7 @@ author: - "Felix Fontein (@felixfontein)" requirements: - - "docker-py >= 1.8.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.8.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - "Docker API >= 1.20" ''' diff --git a/lib/ansible/modules/cloud/docker/docker_host_facts.py b/lib/ansible/modules/cloud/docker/docker_host_facts.py index c28512435c..8f713879c0 100644 --- a/lib/ansible/modules/cloud/docker/docker_host_facts.py +++ b/lib/ansible/modules/cloud/docker/docker_host_facts.py @@ -99,7 +99,7 @@ author: - Piotr Wojciechowski (@WojciechowskiPiotr) requirements: - - "docker-py >= 1.10.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.10.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - "Docker API >= 1.21" ''' @@ -191,7 +191,7 @@ from ansible.module_utils._text import to_native try: from docker.errors import APIError except ImportError: - # missing docker-py handled in ansible.module_utils.docker.common + # Missing Docker SDK for Python handled in ansible.module_utils.docker.common pass from ansible.module_utils.docker.common import clean_dict_booleans_for_docker_api diff --git a/lib/ansible/modules/cloud/docker/docker_image.py b/lib/ansible/modules/cloud/docker/docker_image.py index 86fcc726c0..f2389e04cd 100644 --- a/lib/ansible/modules/cloud/docker/docker_image.py +++ b/lib/ansible/modules/cloud/docker/docker_image.py @@ -241,11 +241,13 @@ options: - When C(absent) an image will be removed. Use the force option to un-tag and remove all images matching the provided name. - When C(present) check if an image exists using the provided name and tag. If the image is not found or the - force option is used, the image will either be pulled, built or loaded. By default the image will be pulled - from Docker Hub. To build the image, provide a path value set to a directory containing a context and - Dockerfile. To load an image, specify load_path to provide a path to an archive file. To tag an image to a - repository, provide a repository path. If the name contains a repository path, it will be pushed. - - "NOTE: C(build) is DEPRECATED and will be removed in release 2.11. Specifying C(build) will behave the + force option is used, the image will either be pulled, built or loaded, depending on the I(source) option. + - By default the image will be pulled from Docker Hub, or the registry specified in the image's name. Note that + this will change in Ansible 2.12, so to make sure that you are pulling, set I(source) to C(pull). To build + the image, provide a I(path) value set to a directory containing a context and Dockerfile, and set I(source) + to C(build). To load an image, specify I(load_path) to provide a path to an archive file. To tag an image to + a repository, provide a I(repository) path. If the name contains a repository path, it will be pushed. + - "NOTE: C(state=build) is DEPRECATED and will be removed in release 2.11. Specifying C(build) will behave the same as C(present)." type: str default: present @@ -293,7 +295,7 @@ options: version_added: "2.1" use_tls: description: - - "DEPRECATED. Whether to use tls to connect to the docker server. Set to + - "DEPRECATED. Whether to use tls to connect to the docker daemon. Set to C(encrypt) to use TLS. And set to C(verify) to use TLS and verify that the server's certificate is valid for the server." - "NOTE: If you specify this option, it will set the value of the I(tls) or @@ -311,7 +313,7 @@ extends_documentation_fragment: - docker.docker_py_1_documentation requirements: - - "docker-py >= 1.8.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.8.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - "Docker API >= 1.20" author: @@ -412,20 +414,23 @@ image: import os import re +from distutils.version import LooseVersion + from ansible.module_utils.docker.common import ( - HAS_DOCKER_PY_2, HAS_DOCKER_PY_3, AnsibleDockerClient, DockerBaseClass, is_image_name_id, + docker_version, AnsibleDockerClient, DockerBaseClass, is_image_name_id, ) from ansible.module_utils._text import to_native -try: - if HAS_DOCKER_PY_2 or HAS_DOCKER_PY_3: - from docker.auth import resolve_repository_name - else: - from docker.auth.auth import resolve_repository_name - from docker.utils.utils import parse_repository_tag -except ImportError: - # missing docker-py handled in docker_common - pass +if docker_version is not None: + try: + if LooseVersion(docker_version) >= LooseVersion('2.0.0'): + from docker.auth import resolve_repository_name + else: + from docker.auth.auth import resolve_repository_name + from docker.utils.utils import parse_repository_tag + except ImportError: + # missing Docker SDK for Python handled in module_utils.docker.common + pass class ImageManager(DockerBaseClass): @@ -587,7 +592,7 @@ class ImageManager(DockerBaseClass): try: with open(self.archive_path, 'wb') as fd: - if HAS_DOCKER_PY_3: + if self.client.docker_py_version >= LooseVersion('3.0.0'): for chunk in image: fd.write(chunk) else: @@ -704,7 +709,7 @@ class ImageManager(DockerBaseClass): dockerfile=self.dockerfile, decode=True, ) - if not HAS_DOCKER_PY_3: + if self.client.docker_py_version < LooseVersion('3.0.0'): params['stream'] = True build_output = [] if self.tag: diff --git a/lib/ansible/modules/cloud/docker/docker_image_facts.py b/lib/ansible/modules/cloud/docker/docker_image_facts.py index 98ecba3568..4f17f7f749 100644 --- a/lib/ansible/modules/cloud/docker/docker_image_facts.py +++ b/lib/ansible/modules/cloud/docker/docker_image_facts.py @@ -37,7 +37,7 @@ extends_documentation_fragment: - docker.docker_py_1_documentation requirements: - - "docker-py >= 1.8.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.8.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - "Docker API >= 1.20" author: @@ -154,7 +154,7 @@ images: try: from docker import utils except ImportError: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass from ansible.module_utils.docker.common import AnsibleDockerClient, DockerBaseClass, is_image_name_id diff --git a/lib/ansible/modules/cloud/docker/docker_login.py b/lib/ansible/modules/cloud/docker/docker_login.py index 4d69265590..7879cb2024 100644 --- a/lib/ansible/modules/cloud/docker/docker_login.py +++ b/lib/ansible/modules/cloud/docker/docker_login.py @@ -24,7 +24,7 @@ description: - Provides functionality similar to the "docker login" command. - Authenticate with a docker registry and add the credentials to your local Docker config file. Adding the credentials to the config files allows future connections to the registry using tools such as Ansible's Docker - modules, the Docker CLI and docker-py without needing to provide credentials. + modules, the Docker CLI and Docker SDK for Python without needing to provide credentials. - Running in check mode will perform the authentication without updating the config file. options: registry_url: @@ -71,7 +71,7 @@ options: - This controls the current state of the user. C(present) will login in a user, C(absent) will log them out. - To logout you only need the registry server, which defaults to DockerHub. - Before 2.1 you could ONLY log in. - - docker does not support 'logout' with a custom config file. + - Docker does not support 'logout' with a custom config file. type: str default: 'present' choices: ['present', 'absent'] @@ -80,7 +80,7 @@ extends_documentation_fragment: - docker - docker.docker_py_1_documentation requirements: - - "docker-py >= 1.8.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.8.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - "Docker API >= 1.20" - "Only to be able to logout, that is for I(state) = C(absent): the C(docker) command line utility" author: @@ -203,11 +203,10 @@ class LoginManager(DockerBaseClass): :return: None ''' - cmd = "%s logout " % self.client.module.get_bin_path('docker', True) + cmd = [self.client.module.get_bin_path('docker', True), "logout", self.registry_url] # TODO: docker does not support config file in logout, restore this when they do # if self.config_path and self.config_file_exists(self.config_path): - # cmd += "--config '%s' " % self.config_path - cmd += "'%s'" % self.registry_url + # cmd.extend(["--config", self.config_path]) (rc, out, err) = self.client.module.run_command(cmd) if rc != 0: diff --git a/lib/ansible/modules/cloud/docker/docker_network.py b/lib/ansible/modules/cloud/docker/docker_network.py index fb10e95f35..21510c882b 100644 --- a/lib/ansible/modules/cloud/docker/docker_network.py +++ b/lib/ansible/modules/cloud/docker/docker_network.py @@ -89,7 +89,7 @@ options: description: - List of IPAM config blocks. Consult L(Docker docs,https://docs.docker.com/compose/compose-file/compose-file-v2/#ipam) for valid options and values. - Note that I(iprange) is spelled differently here (we use the notation from the Docker Python SDK). + Note that I(iprange) is spelled differently here (we use the notation from the Docker SDK for Python). type: list suboptions: subnet: @@ -165,7 +165,7 @@ author: - "Dave Bendit (@DBendit)" requirements: - - "docker-py >= 1.10.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.10.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - "The docker server >= 1.10.0" ''' @@ -268,7 +268,7 @@ try: if LooseVersion(docker_version) >= LooseVersion('2.0.0'): from docker.types import IPAMPool, IPAMConfig except Exception: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass diff --git a/lib/ansible/modules/cloud/docker/docker_network_facts.py b/lib/ansible/modules/cloud/docker/docker_network_facts.py index 92af680583..4c89ec400f 100644 --- a/lib/ansible/modules/cloud/docker/docker_network_facts.py +++ b/lib/ansible/modules/cloud/docker/docker_network_facts.py @@ -40,7 +40,7 @@ author: - "Dave Bendit (@DBendit)" requirements: - - "docker-py >= 1.8.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.8.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - "Docker API >= 1.21" ''' diff --git a/lib/ansible/modules/cloud/docker/docker_node.py b/lib/ansible/modules/cloud/docker/docker_node.py index 12835af202..f27ee487fe 100644 --- a/lib/ansible/modules/cloud/docker/docker_node.py +++ b/lib/ansible/modules/cloud/docker/docker_node.py @@ -76,7 +76,7 @@ extends_documentation_fragment: - docker - docker.docker_py_1_documentation requirements: - - "docker-py >= 2.4.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 2.4.0" - Docker API >= 1.25 author: - Piotr Wojciechowski (@WojciechowskiPiotr) @@ -132,7 +132,7 @@ node_facts: try: from docker.errors import APIError except ImportError: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass from ansible.module_utils.docker.common import ( diff --git a/lib/ansible/modules/cloud/docker/docker_node_facts.py b/lib/ansible/modules/cloud/docker/docker_node_facts.py index cd5bccf402..5ed0710f71 100644 --- a/lib/ansible/modules/cloud/docker/docker_node_facts.py +++ b/lib/ansible/modules/cloud/docker/docker_node_facts.py @@ -48,7 +48,7 @@ author: - Piotr Wojciechowski (@wojciechowskipiotr) requirements: - - "docker-py >= 2.4.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 2.4.0" - "Docker API >= 1.24" ''' @@ -92,7 +92,7 @@ from ansible.module_utils.docker.swarm import AnsibleDockerSwarmClient try: from docker.errors import APIError, NotFound except ImportError: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass diff --git a/lib/ansible/modules/cloud/docker/docker_prune.py b/lib/ansible/modules/cloud/docker/docker_prune.py index 6ed20f0069..3c7c8d410f 100644 --- a/lib/ansible/modules/cloud/docker/docker_prune.py +++ b/lib/ansible/modules/cloud/docker/docker_prune.py @@ -74,7 +74,7 @@ options: builder_cache: description: - Whether to prune the builder cache. - - Requires version 3.3.0 of the Python Docker SDK or newer. + - Requires version 3.3.0 of the Docker SDK for Python or newer. type: bool default: no @@ -86,7 +86,7 @@ author: - "Felix Fontein (@felixfontein)" requirements: - - "docker >= 2.1.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 2.1.0" - "Docker API >= 1.25" ''' @@ -184,7 +184,7 @@ from ansible.module_utils.docker.common import AnsibleDockerClient try: from ansible.module_utils.docker.common import docker_version, clean_dict_booleans_for_docker_api except Exception as dummy: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -211,7 +211,7 @@ def main(): # Version checks cache_min_version = '3.3.0' if client.module.params['builder_cache'] and client.docker_py_version < LooseVersion(cache_min_version): - msg = "Error: docker version is %s. Minimum version required for builds option is %s. Use `pip install --upgrade docker` to upgrade." + 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() diff --git a/lib/ansible/modules/cloud/docker/docker_secret.py b/lib/ansible/modules/cloud/docker/docker_secret.py index b4b321c678..3acc51be07 100644 --- a/lib/ansible/modules/cloud/docker/docker_secret.py +++ b/lib/ansible/modules/cloud/docker/docker_secret.py @@ -21,7 +21,7 @@ short_description: Manage docker secrets. version_added: "2.4" description: - - Create and remove Docker secrets in a Swarm environment. Similar to `docker secret create` and `docker secret rm`. + - Create and remove Docker secrets in a Swarm environment. Similar to C(docker secret create) and C(docker secret rm). - Adds to the metadata of new secrets 'ansible_key', an encrypted hash representation of the data, which is then used in future runs to test if a secret has changed. If 'ansible_key is not present, then a secret will not be updated unless the C(force) option is set. @@ -70,7 +70,7 @@ extends_documentation_fragment: - docker.docker_py_2_documentation requirements: - - "docker >= 2.1.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 2.1.0" - "Docker API >= 1.25" author: @@ -156,7 +156,7 @@ import hashlib try: from docker.errors import APIError except ImportError: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass from ansible.module_utils.docker.common import AnsibleDockerClient, DockerBaseClass, compare_generic diff --git a/lib/ansible/modules/cloud/docker/docker_swarm.py b/lib/ansible/modules/cloud/docker/docker_swarm.py index 6e172acffc..176ccde0aa 100644 --- a/lib/ansible/modules/cloud/docker/docker_swarm.py +++ b/lib/ansible/modules/cloud/docker/docker_swarm.py @@ -52,7 +52,7 @@ options: - Set to C(join), to join an existing cluster. - Set to C(absent), to leave an existing cluster. - Set to C(remove), to remove an absent node from the cluster. - Note that removing requires docker-py >= 2.4.0. + Note that removing requires Docker SDK for Python >= 2.4.0. - Set to C(inspect) to display swarm informations. type: str required: yes @@ -164,7 +164,7 @@ extends_documentation_fragment: - docker - docker.docker_py_1_documentation requirements: - - "docker-py >= 1.10.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.10.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - Docker API >= 1.25 author: - Thierry Bouvet (@tbouvet) @@ -243,7 +243,7 @@ import json try: from docker.errors import APIError except ImportError: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass from ansible.module_utils.docker.common import ( diff --git a/lib/ansible/modules/cloud/docker/docker_swarm_facts.py b/lib/ansible/modules/cloud/docker/docker_swarm_facts.py index 78a6ce44fd..e5c11c59c3 100644 --- a/lib/ansible/modules/cloud/docker/docker_swarm_facts.py +++ b/lib/ansible/modules/cloud/docker/docker_swarm_facts.py @@ -82,7 +82,7 @@ extends_documentation_fragment: - docker.docker_py_1_documentation requirements: - - "docker-py >= 1.10.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.10.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - "Docker API >= 1.24" ''' @@ -177,7 +177,7 @@ tasks: try: from docker.errors import APIError, NotFound except ImportError: - # missing docker-py handled in ansible.module_utils.docker_common + # missing Docker SDK for Python handled in ansible.module_utils.docker_common pass from ansible.module_utils._text import to_native diff --git a/lib/ansible/modules/cloud/docker/docker_swarm_service.py b/lib/ansible/modules/cloud/docker/docker_swarm_service.py index 0ff7de8acd..b940e0ce79 100644 --- a/lib/ansible/modules/cloud/docker/docker_swarm_service.py +++ b/lib/ansible/modules/cloud/docker/docker_swarm_service.py @@ -776,10 +776,10 @@ extends_documentation_fragment: - docker - docker.docker_py_2_documentation requirements: - - "docker >= 2.0.2" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 2.0.2" - "Docker API >= 1.24" notes: - - "Images will only resolve to the latest digest when using Docker API >= 1.30 and docker-py >= 3.2.0. + - "Images will only resolve to the latest digest when using Docker API >= 1.30 and Docker SDK for Python >= 3.2.0. When using older versions use C(force_update: true) to trigger the swarm to resolve a new image." ''' @@ -1078,7 +1078,7 @@ try: NotFound, ) except ImportError: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass @@ -2257,6 +2257,7 @@ class DockerServiceManager(object): **service_data ) # Prior to Docker SDK 4.0.0 no warnings were returned and will thus be ignored. + # (see https://github.com/docker/docker-py/pull/2272) self.client.report_warnings(result, ['Warning']) def create_service(self, name, service): diff --git a/lib/ansible/modules/cloud/docker/docker_volume.py b/lib/ansible/modules/cloud/docker/docker_volume.py index 963218940b..67e80c706e 100644 --- a/lib/ansible/modules/cloud/docker/docker_volume.py +++ b/lib/ansible/modules/cloud/docker/docker_volume.py @@ -92,7 +92,7 @@ author: - Alex Grönholm (@agronholm) requirements: - - "docker-py >= 1.10.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.10.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - "The docker server >= 1.9.0" ''' @@ -128,7 +128,7 @@ volume: try: from docker.errors import APIError except ImportError: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass from ansible.module_utils.docker.common import ( diff --git a/lib/ansible/modules/cloud/docker/docker_volume_facts.py b/lib/ansible/modules/cloud/docker/docker_volume_facts.py index 8647da0e26..a9a6f7be03 100644 --- a/lib/ansible/modules/cloud/docker/docker_volume_facts.py +++ b/lib/ansible/modules/cloud/docker/docker_volume_facts.py @@ -36,7 +36,7 @@ author: - Felix Fontein (@felixfontein) requirements: - - "docker-py >= 1.8.0" + - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.8.0 (use L(docker-py,https://pypi.org/project/docker-py/) for Python 2.6)" - "Docker API >= 1.21" ''' @@ -83,7 +83,7 @@ volume: try: from docker.errors import NotFound except ImportError: - # missing docker-py handled in ansible.module_utils.docker.common + # missing Docker SDK for Python handled in ansible.module_utils.docker.common pass from ansible.module_utils.docker.common import AnsibleDockerClient diff --git a/lib/ansible/plugins/doc_fragments/docker.py b/lib/ansible/plugins/doc_fragments/docker.py index 4e199145d3..caac724021 100644 --- a/lib/ansible/plugins/doc_fragments/docker.py +++ b/lib/ansible/plugins/doc_fragments/docker.py @@ -29,7 +29,7 @@ options: api_version: description: - The version of the Docker API running on the Docker Host. - - Defaults to the latest version of the API supported by docker-py. + - Defaults to the latest version of the API supported by Docker SDK for Python and the docker daemon. - If the value is not specified in the task, the value of environment variable C(DOCKER_API_VERSION) will be used instead. If the environment variable is not set, the default value will be used. type: str @@ -103,13 +103,13 @@ notes: and use C($DOCKER_CONFIG/config.json) otherwise. ''' - # Additional, more specific stuff for minimal docker-py version < 2.0 + # Additional, more specific stuff for minimal Docker SDK for Python version < 2.0 DOCKER_PY_1_DOCUMENTATION = r''' options: {} requirements: - - "Please note that the L(docker-py,https://pypi.org/project/docker-py/) Python - module has been superseded by L(docker,https://pypi.org/project/docker/) + - "Docker SDK for Python: Please note that the L(docker-py,https://pypi.org/project/docker-py/) + Python module has been superseded by L(docker,https://pypi.org/project/docker/) (see L(here,https://github.com/docker/docker-py/issues/1310) for details). For Python 2.6, C(docker-py) must be used. Otherwise, it is recommended to install the C(docker) Python module. Note that both modules should I(not) @@ -118,15 +118,15 @@ requirements: reinstall of it is required." ''' - # Additional, more specific stuff for minimal docker-py version >= 2.0. - # Note that docker-py >= 2.0 requires Python 2.7 or newer. + # Additional, more specific stuff for minimal Docker SDK for Python version >= 2.0. + # Note that Docker SDK for Python >= 2.0 requires Python 2.7 or newer. DOCKER_PY_2_DOCUMENTATION = r''' options: {} requirements: - "Python >= 2.7" - - "Please note that the L(docker-py,https://pypi.org/project/docker-py/) Python - module has been superseded by L(docker,https://pypi.org/project/docker/) + - "Docker SDK for Python: Please note that the L(docker-py,https://pypi.org/project/docker-py/) + Python module has been superseded by L(docker,https://pypi.org/project/docker/) (see L(here,https://github.com/docker/docker-py/issues/1310) for details). This module does I(not) work with docker-py." ''' diff --git a/lib/ansible/plugins/inventory/docker_swarm.py b/lib/ansible/plugins/inventory/docker_swarm.py index 8f140bbe08..ff652df33d 100644 --- a/lib/ansible/plugins/inventory/docker_swarm.py +++ b/lib/ansible/plugins/inventory/docker_swarm.py @@ -16,7 +16,7 @@ DOCUMENTATION = ''' short_description: Ansible dynamic inventory plugin for Docker swarm nodes. requirements: - python >= 2.7 - - Docker SDK for Python > 1.10.0 + - L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.10.0 extends_documentation_fragment: - constructed description: @@ -24,7 +24,7 @@ DOCUMENTATION = ''' - Uses a YAML configuration file docker_swarm.[yml|yaml]. options: plugin: - description: The name of this plugin, it should always be set to 'docker_swarm' for this plugin to recognize it as it's own. + description: The name of this plugin, it should always be set to C(docker_swarm) for this plugin to recognize it as it's own. type: str required: true choices: docker_swarm @@ -56,7 +56,7 @@ DOCUMENTATION = ''' description: Path to the client's TLS certificate file. type: path tls_hostname: - description: When verifying the authenticity of the Docker Host server, provide the expected name of the server. + description: When verifying the authenticity of the Docker host server, provide the expected name of the server. type: str ssl_version: description: Provide a valid SSL version number. Default value determined by ssl.py module. diff --git a/test/units/modules/cloud/docker/test_docker_volume.py b/test/units/modules/cloud/docker/test_docker_volume.py index 2eadb989e6..ea83999e27 100644 --- a/test/units/modules/cloud/docker/test_docker_volume.py +++ b/test/units/modules/cloud/docker/test_docker_volume.py @@ -28,4 +28,4 @@ def test_create_volume_on_invalid_docker_version(mocker, capfd): out, dummy = capfd.readouterr() results = json.loads(out) assert results['failed'] - assert 'Error: docker / docker-py 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. Minimum version required is 1.10.0.' in results['msg']