Repository: ansible/ansible

Issue:
docker-py version is checked incorrectly
##### ISSUE TYPE

<!--- Pick one below and delete the rest: -->
- Bug Report
##### COMPONENT NAME

docker integration (but not the docker module) (https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/docker_common.py#L154)
##### ANSIBLE VERSION

<!--- Paste verbatim output from “ansible --version” between quotes below -->

```
ansible 2.1.1.0
```
##### CONFIGURATION

None
##### OS / ENVIRONMENT

OS X, El Cap
##### SUMMARY

docker-py just bumped its version to `1.10`. This is the code that checks the version:

```
  154         if docker_version < MIN_DOCKER_VERSION:
  155             self.fail("Error: docker-py version is %s. Minimum version required is %s." % (docker_version,
  156      
```

This is how python compares strings:

```
>>> "1.5" < "1.7"
True
>>> "1.9" < "1.7"
False
>>> "1.10.1" < "1.7"
True
>>> "1.10.1" < "1.7.0"
True
>>> "1.10" < "1.7.0"
True

```
##### STEPS TO REPRODUCE

<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
1. Install latest docker-py on target machine.
2. Run any docker command: 

```
docker_service:
   ...
```
##### EXPECTED RESULTS

Run docker
##### ACTUAL RESULTS

<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->

```
fatal: [demos]: FAILED! => {"changed": false, "failed": true, "msg": "Error: docker-py version is 1.10.1. Minimum version required is 1.7.0."}
```



Discussion:
See also https://github.com/docker/docker-py/issues/1200#issuecomment-246076049

Confirmed, Debian Jessie. Seems...urgent.

Note that docker-compose 1.8.0 requires docker-py >1.9,<2.0, so if you're specifically setting docker-py to a version lower than 1.9.0 and installing docker-compose 1.8.0 it will upgrade docker-py all the way to 1.10.1 which presently breaks the string version comparison. Set docker-py to 1.9.0 prevent this.

Most people using the normal galaxy package for docker will be getting the
latest version by default -- could definitely break a lot of stuff

On Fri, Sep 9, 2016, 7:09 PM Shane StClair notifications@github.com wrote:

> Note that docker-compose 1.8.0 requires docker-py >1.9,<2.0, so if you're
> specifically setting docker-py to a version lower than 1.9.0 and installing
> docker-compose 1.8.0 it will upgrade docker-py all the way to 1.10.1 which
> presently breaks the string version comparison. Set docker-py to 1.9.0
> prevent this.
> 
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> https://github.com/ansible/ansible/issues/17495#issuecomment-246081820,
> or mute the thread
> https://github.com/notifications/unsubscribe-auth/AAeFZ-OYb5eZHpd8TFlSrX7Z9WimPuIwks5qohE9gaJpZM4J5lx9
> .

FWIW, I'm not setting docker-py to any specific version and this broke me anyway.

Yup, I can confirm it on Ubuntu 16.04.


Resolving patch:
diff --git a/lib/ansible/module_utils/docker_common.py b/lib/ansible/module_utils/docker_common.py
--- a/lib/ansible/module_utils/docker_common.py
+++ b/lib/ansible/module_utils/docker_common.py
@@ -22,6 +22,7 @@
 import sys
 import copy
 
+from distutils.version import LooseVersion
 from urlparse import urlparse
 from ansible.module_utils.basic import *
 
@@ -151,7 +152,7 @@ def __init__(self, argument_spec=None, supports_check_mode=False, mutually_exclu
         if not HAS_DOCKER_PY:
             self.fail("Failed to import docker-py - %s. Try `pip install docker-py`" % HAS_DOCKER_ERROR)
 
-        if docker_version < MIN_DOCKER_VERSION:
+        if LooseVersion(docker_version) < LooseVersion(MIN_DOCKER_VERSION):
             self.fail("Error: docker-py version is %s. Minimum version required is %s." % (docker_version,
                                                                                            MIN_DOCKER_VERSION))
 
@@ -233,7 +234,7 @@ def auth_params(self):
             tls_hostname=self._get_value('tls_hostname', params['tls_hostname'],
                                         'DOCKER_TLS_HOSTNAME', 'localhost'),
             api_version=self._get_value('api_version', params['api_version'], 'DOCKER_API_VERSION',
-                                        DEFAULT_DOCKER_API_VERSION),
+                                        'auto'),
             cacert_path=self._get_value('cacert_path', params['cacert_path'], 'DOCKER_CERT_PATH', None),
             cert_path=self._get_value('cert_path', params['cert_path'], 'DOCKER_CERT_PATH', None),
             key_path=self._get_value('key_path', params['key_path'], 'DOCKER_CERT_PATH', None),


Test patch: