Docker: mention Docker SDK for Python instead of docker/docker-py (#53917)

* Mention Docker SDK for Python instead of docker-py / docker.

* Docs fixes.

* Add myself as docker_container author.

* Use array syntax for running command.

* Break long lines.

* Avoid failure when docker_version is None.

* Improve docker-py vs. docker note in requirements.

* Canonicalize Docker SDK for Python upgrade instructions.

* Split long line.

* Make it clearer which hostnames are meant.
This commit is contained in:
Felix Fontein 2019-03-20 18:27:44 +01:00 committed by ansibot
parent a916b3606c
commit 4ced1c693c
24 changed files with 144 additions and 128 deletions

View file

@ -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)