From 495a426039a2e8f19384cb9ada3fc5591d2581e0 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 10 Dec 2018 09:39:28 +0100 Subject: [PATCH] docker_swarm: fix minimal API version (#49691) * Reduce minimally required docker API version to 1.25, with selective features requiring 1.30. * Adjust test requirements. * Forgot some imports. --- .../modules/cloud/docker/docker_swarm.py | 67 ++++++++++++++++++- .../targets/docker_config/tasks/main.yml | 5 +- .../docker_network/tasks/tests/options.yml | 2 +- .../docker_network/tasks/tests/overlay.yml | 2 +- .../targets/docker_secret/tasks/main.yml | 5 +- .../targets/docker_swarm/tasks/main.yml | 4 +- .../docker_swarm_service/tasks/main.yml | 5 +- 7 files changed, 74 insertions(+), 16 deletions(-) diff --git a/lib/ansible/modules/cloud/docker/docker_swarm.py b/lib/ansible/modules/cloud/docker/docker_swarm.py index 9fd0c3ba64b..baf4bcface4 100644 --- a/lib/ansible/modules/cloud/docker/docker_swarm.py +++ b/lib/ansible/modules/cloud/docker/docker_swarm.py @@ -141,7 +141,7 @@ requirements: 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). Version 2.1.0 or newer is only available with the C(docker) module." - - Docker API >= 1.35 + - Docker API >= 1.25 author: - Thierry Bouvet (@tbouvet) ''' @@ -214,6 +214,7 @@ actions: ''' import json +from distutils.version import LooseVersion from time import sleep try: from docker.errors import APIError @@ -221,7 +222,11 @@ except ImportError: # missing docker-py handled in ansible.module_utils.docker_common pass -from ansible.module_utils.docker_common import AnsibleDockerClient, DockerBaseClass +from ansible.module_utils.docker_common import ( + AnsibleDockerClient, + DockerBaseClass, + docker_version, +) from ansible.module_utils._text import to_native @@ -283,6 +288,60 @@ class TaskParameters(DockerBaseClass): class SwarmManager(DockerBaseClass): + def _get_minimal_versions(self): + # TODO: Move this and the same from docker_container.py to docker_common.py + self.option_minimal_versions = dict() + for option, data in self.client.module.argument_spec.items(): + self.option_minimal_versions[option] = dict() + self.option_minimal_versions.update(dict( + signing_ca_cert=dict(docker_api_version='1.30'), + signing_ca_key=dict(docker_api_version='1.30'), + ca_force_rotate=dict(docker_api_version='1.30'), + )) + + for option, data in self.option_minimal_versions.items(): + # Test whether option is supported, and store result + support_docker_py = True + support_docker_api = True + if 'docker_py_version' in data: + support_docker_py = self.client.docker_py_version >= LooseVersion(data['docker_py_version']) + if 'docker_api_version' in data: + support_docker_api = self.client.docker_api_version >= LooseVersion(data['docker_api_version']) + data['supported'] = support_docker_py and support_docker_api + # Fail if option is not supported but used + if not data['supported']: + # Test whether option is specified + if 'detect_usage' in data: + used = data['detect_usage']() + else: + used = self.client.module.params.get(option) is not None + if used and 'default' in self.client.module.argument_spec[option]: + used = self.client.module.params[option] != self.client.module.argument_spec[option]['default'] + if used: + # If the option is used, compose error message. + if 'usage_msg' in data: + usg = data['usage_msg'] + 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 = msg % (self.client.docker_api_version_str, data['docker_api_version'], usg) + elif not support_docker_py: + 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.") + elif self.client.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.") + else: + msg = "docker version is %s. Minimum version required is %s to %s." + msg = msg % (docker_version, data['docker_py_version'], usg) + else: + # should not happen + msg = 'Cannot %s with your configuration.' % (usg, ) + self.client.fail(msg) + def __init__(self, client, results): super(SwarmManager, self).__init__() @@ -291,6 +350,8 @@ class SwarmManager(DockerBaseClass): self.results = results self.check_mode = self.client.check_mode + self._get_minimal_versions() + self.parameters = TaskParameters(client) def __call__(self): @@ -506,7 +567,7 @@ def main(): supports_check_mode=True, required_if=required_if, min_docker_version='2.6.0', - min_docker_api_version='1.35', + min_docker_api_version='1.25', ) results = dict( diff --git a/test/integration/targets/docker_config/tasks/main.yml b/test/integration/targets/docker_config/tasks/main.yml index 4154255ace3..710643651f8 100644 --- a/test/integration/targets/docker_config/tasks/main.yml +++ b/test/integration/targets/docker_config/tasks/main.yml @@ -1,7 +1,6 @@ --- - include_tasks: test_docker_config.yml - # Maximum of 1.30 (docker API version for docker_config) and 1.35 (docker API version for docker_swarm) is 1.35 - when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.35', '>=') + when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.30', '>=') - fail: msg="Too old docker / docker-py version to run docker_config tests!" - when: not(docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.35', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6) + when: not(docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.30', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6) diff --git a/test/integration/targets/docker_network/tasks/tests/options.yml b/test/integration/targets/docker_network/tasks/tests/options.yml index b3ac57b416b..19248e6d6e0 100644 --- a/test/integration/targets/docker_network/tasks/tests/options.yml +++ b/test/integration/targets/docker_network/tasks/tests/options.yml @@ -145,7 +145,7 @@ force: yes # Requirements for docker_swarm - when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.35', '>=') + when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.25', '>=') #################################################################### ## attachable ###################################################### diff --git a/test/integration/targets/docker_network/tasks/tests/overlay.yml b/test/integration/targets/docker_network/tasks/tests/overlay.yml index b2e4b8dbe85..177996e1c3f 100644 --- a/test/integration/targets/docker_network/tasks/tests/overlay.yml +++ b/test/integration/targets/docker_network/tasks/tests/overlay.yml @@ -58,4 +58,4 @@ force: yes # Requirements for docker_swarm - when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.35', '>=') + when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.25', '>=') diff --git a/test/integration/targets/docker_secret/tasks/main.yml b/test/integration/targets/docker_secret/tasks/main.yml index 2fff38b2100..5ea5c36d7fa 100644 --- a/test/integration/targets/docker_secret/tasks/main.yml +++ b/test/integration/targets/docker_secret/tasks/main.yml @@ -1,7 +1,6 @@ - include_tasks: test_secrets.yml # Maximum of 2.1.0 (docker-py version for docker_secrets) and 2.6.0 (docker-py version for docker_swarm) is 2.6.0 - # Maximum of 1.25 (docker API version for docker_secrets) and 1.35 (docker API version for docker_swarm) is 1.35 - when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.35', '>=') + when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.25', '>=') - fail: msg="Too old docker / docker-py version to run docker_secrets tests!" - when: not(docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.35', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6) + when: not(docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6) diff --git a/test/integration/targets/docker_swarm/tasks/main.yml b/test/integration/targets/docker_swarm/tasks/main.yml index d5705d53e50..94a923c138a 100644 --- a/test/integration/targets/docker_swarm/tasks/main.yml +++ b/test/integration/targets/docker_swarm/tasks/main.yml @@ -1,5 +1,5 @@ - include_tasks: test_swarm.yml - when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.35', '>=') + when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.25', '>=') - fail: msg="Too old docker / docker-py version to run docker_swarm tests!" - when: not(docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.35', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6) + when: not(docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6) diff --git a/test/integration/targets/docker_swarm_service/tasks/main.yml b/test/integration/targets/docker_swarm_service/tasks/main.yml index a5dcc10bf37..9904a8a190a 100644 --- a/test/integration/targets/docker_swarm_service/tasks/main.yml +++ b/test/integration/targets/docker_swarm_service/tasks/main.yml @@ -1,6 +1,5 @@ - include_tasks: test_swarm_service.yml - # Maximum of 2.0.0 (docker-py version for docker_swarm_service) and 2.6.0 (docker-py version for docker_swarm) is 2.6.0 - when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.35', '>=') + when: docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.25', '>=') - fail: msg="Too old docker / docker-py version to run docker_swarm_service tests!" - when: not(docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.35', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6) + when: not(docker_py_version is version('2.6.0', '>=') and docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)