[2.6] Fix docker container init check requirements (#42533)

* docker_container: fix init check requirements (#40839)

* docker_container: ensure 'init' is supported

Check docker-py version too.

Move API version check in docker_container module since 'init' module
parameter isn't defined by other docker modules.

docker-py supports 'init' since 2.2.0:
https://github.com/docker/docker-py/blob/2.2.0/docs/change-log.md

* docker_container: fix compat with docker-py<2.2

Exception was:
TypeError: create_host_config() got an unexpected keyword argument 'init'
fatal: [localhost]: FAILED! => {
    "changed": false,
    "module_stderr": "Traceback (most recent call last):
                        File ansible_module_docker_container.py, line 2089, in <module>
                          main()
                        File ansible_module_docker_container.py, line 2084, in main
                          cm = ContainerManager(client)
                        File ansible_module_docker_container.py, line 1704, in __init__
                            self.present(state)
                        File ansible_module_docker_container.py, line 1724, in present
                            new_container = self.container_create(self.parameters.image, self.parameters.create_parameters)
                        File ansible_module_docker_container.py, line 826, in create_parameters
                            host_config=self._host_config(),
                        File ansible_module_docker_container.py, line 932, in _host_config
                            return self.client.create_host_config(**params)
                        File lib/python3.6/site-packages/docker/api/container.py, line 157, in create_host_config
                            return utils.create_host_config(*args, **kwargs)
                      TypeError: create_host_config() got an unexpected keyword argument 'init'",
    "module_stdout": "",
    "msg": "MODULE FAILURE",
    "rc": 1
}

(cherry picked from commit 3301a0b530)

* add changelog fragment
pull/42147/merge
René Moser 6 years ago committed by Matt Clay
parent 44edfd96f1
commit e4e0433d2f

@ -0,0 +1,2 @@
bugfixes:
- fixes docker_container compatibilty with docker-py < 2.2

@ -187,10 +187,6 @@ class AnsibleDockerClient(Client):
except Exception as exc: except Exception as exc:
self.fail("Error connecting: %s" % exc) self.fail("Error connecting: %s" % exc)
docker_api_version = self.version()["ApiVersion"]
if self.module.params.get("init") and LooseVersion(docker_api_version) < LooseVersion("1.25"):
self.fail("docker API version is %s. Minimum version required is 1.25 to set init option." % (docker_api_version,))
def log(self, msg, pretty_print=False): def log(self, msg, pretty_print=False):
pass pass
# if self.debug: # if self.debug:

@ -598,6 +598,7 @@ docker_container:
import os import os
import re import re
import shlex import shlex
from distutils.version import LooseVersion
from ansible.module_utils.basic import human_to_bytes from ansible.module_utils.basic import human_to_bytes
from ansible.module_utils.docker_common import HAS_DOCKER_PY_2, HAS_DOCKER_PY_3, AnsibleDockerClient, DockerBaseClass from ansible.module_utils.docker_common import HAS_DOCKER_PY_2, HAS_DOCKER_PY_3, AnsibleDockerClient, DockerBaseClass
@ -609,6 +610,7 @@ try:
from docker.types import Ulimit, LogConfig from docker.types import Ulimit, LogConfig
else: else:
from docker.utils.types import Ulimit, LogConfig from docker.utils.types import Ulimit, LogConfig
from ansible.module_utils.docker_common import docker_version
except: except:
# missing docker-py handled in ansible.module_utils.docker # missing docker-py handled in ansible.module_utils.docker
pass pass
@ -907,10 +909,9 @@ class TaskParameters(DockerBaseClass):
devices='devices', devices='devices',
pid_mode='pid_mode', pid_mode='pid_mode',
tmpfs='tmpfs', tmpfs='tmpfs',
init='init'
) )
if HAS_DOCKER_PY_2 or HAS_DOCKER_PY_3: if self.client.HAS_AUTO_REMOVE_OPT:
# auto_remove is only supported in docker>=2 # auto_remove is only supported in docker>=2
host_config_params['auto_remove'] = 'auto_remove' host_config_params['auto_remove'] = 'auto_remove'
@ -919,6 +920,9 @@ class TaskParameters(DockerBaseClass):
host_config_params['cpu_shares'] = 'cpu_shares' host_config_params['cpu_shares'] = 'cpu_shares'
host_config_params['volume_driver'] = 'volume_driver' host_config_params['volume_driver'] = 'volume_driver'
if self.client.HAS_INIT_OPT:
host_config_params['init'] = 'init'
params = dict() params = dict()
for key, value in host_config_params.items(): for key, value in host_config_params.items():
if getattr(self, value, None) is not None: if getattr(self, value, None) is not None:
@ -1980,6 +1984,26 @@ class ContainerManager(DockerBaseClass):
return response return response
class AnsibleDockerClientContainer(AnsibleDockerClient):
def __init__(self, **kwargs):
super(AnsibleDockerClientContainer, self).__init__(**kwargs)
docker_api_version = self.version()['ApiVersion']
init_supported = LooseVersion(docker_api_version) >= LooseVersion('1.25')
if self.module.params.get("init") and not init_supported:
self.fail('docker API version is %s. Minimum version required is 1.25 to set init option.' % (docker_api_version,))
init_supported = init_supported and LooseVersion(docker_version) >= LooseVersion('2.2')
if self.module.params.get("init") and not init_supported:
self.fail('docker-py version is %s. Minimum version required is 2.2 to set init option.' % (docker_version,))
self.HAS_INIT_OPT = init_supported
self.HAS_AUTO_REMOVE_OPT = HAS_DOCKER_PY_2 or HAS_DOCKER_PY_3
if self.module.params.get('auto_remove') and not self.HAS_AUTO_REMOVE_OPT:
self.fail("'auto_remove' is not compatible with the 'docker-py' Python package. It requires the newer 'docker' Python package.")
def main(): def main():
argument_spec = dict( argument_spec = dict(
auto_remove=dict(type='bool', default=False), auto_remove=dict(type='bool', default=False),
@ -2064,15 +2088,12 @@ def main():
('state', 'present', ['image']) ('state', 'present', ['image'])
] ]
client = AnsibleDockerClient( client = AnsibleDockerClientContainer(
argument_spec=argument_spec, argument_spec=argument_spec,
required_if=required_if, required_if=required_if,
supports_check_mode=True supports_check_mode=True
) )
if (not (HAS_DOCKER_PY_2 or HAS_DOCKER_PY_3)) and client.module.params.get('auto_remove'):
client.module.fail_json(msg="'auto_remove' is not compatible with the 'docker-py' Python package. It requires the newer 'docker' Python package.")
cm = ContainerManager(client) cm = ContainerManager(client)
client.module.exit_json(**cm.results) client.module.exit_json(**cm.results)

Loading…
Cancel
Save