From 6869eaf8694b687f8a7df22195511e5d58b71115 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 6 Jul 2022 21:48:16 +0200 Subject: [PATCH] Rewrite the docker_volume module (#411) * Rewrite the docker_volume module. * Improve error messages. --- changelogs/fragments/411-docker-api.yml | 4 ++ plugins/modules/docker_volume.py | 50 ++++++++----------- .../targets/docker_volume/tasks/main.yml | 4 +- .../plugins/modules/test_docker_volume.py | 36 ------------- 4 files changed, 26 insertions(+), 68 deletions(-) create mode 100644 changelogs/fragments/411-docker-api.yml delete mode 100644 tests/unit/plugins/modules/test_docker_volume.py diff --git a/changelogs/fragments/411-docker-api.yml b/changelogs/fragments/411-docker-api.yml new file mode 100644 index 00000000..163ec859 --- /dev/null +++ b/changelogs/fragments/411-docker-api.yml @@ -0,0 +1,4 @@ +major_changes: + - "docker_volume - no longer uses the Docker SDK for Python. It requires ``requests`` to be installed, + and depending on the features used has some more requirements. If the Docker SDK for Python is installed, + these requirements are likely met (https://github.com/ansible-collections/community.docker/pull/411)." diff --git a/plugins/modules/docker_volume.py b/plugins/modules/docker_volume.py index 90e20709..fd5e775f 100644 --- a/plugins/modules/docker_volume.py +++ b/plugins/modules/docker_volume.py @@ -68,15 +68,13 @@ options: - present extends_documentation_fragment: -- community.docker.docker -- community.docker.docker.docker_py_1_documentation +- community.docker.docker.api_documentation author: - Alex Grönholm (@agronholm) requirements: - - "L(Docker SDK for Python,https://docker-py.readthedocs.io/en/stable/) >= 1.10.0" - "Docker API >= 1.25" ''' @@ -110,14 +108,9 @@ volume: import traceback from ansible.module_utils.common.text.converters import to_native +from ansible.module_utils.six import iteritems, text_type -try: - from docker.errors import DockerException, APIError -except ImportError: - # missing Docker SDK for Python handled in ansible.module_utils.docker.common - pass - -from ansible_collections.community.docker.plugins.module_utils.common import ( +from ansible_collections.community.docker.plugins.module_utils.common_api import ( AnsibleDockerClient, RequestException, ) @@ -125,7 +118,11 @@ from ansible_collections.community.docker.plugins.module_utils.util import ( DockerBaseClass, DifferenceTracker, ) -from ansible.module_utils.six import iteritems, text_type +from ansible_collections.community.docker.plugins.module_utils._api.errors import ( + APIError, + DockerException, + NotFound, +) class TaskParameters(DockerBaseClass): @@ -173,7 +170,7 @@ class DockerVolumeManager(object): def get_existing_volume(self): try: - volumes = self.client.volumes() + volumes = self.client.get_json('/volumes') except APIError as e: self.client.fail(to_native(e)) @@ -221,16 +218,15 @@ class DockerVolumeManager(object): if not self.existing_volume: if not self.check_mode: try: - params = dict( - driver=self.parameters.driver, - driver_opts=self.parameters.driver_options, - ) - + data = { + 'Name': self.parameters.volume_name, + 'Driver': self.parameters.driver, + 'DriverOpts': self.parameters.driver_options, + } if self.parameters.labels is not None: - params['labels'] = self.parameters.labels - - resp = self.client.create_volume(self.parameters.volume_name, **params) - self.existing_volume = self.client.inspect_volume(resp['Name']) + data['Labels'] = self.parameters.labels + resp = self.client.post_json_to_json('/volumes/create', data=data) + self.existing_volume = self.client.get_json('/volumes/{0}', resp['Name']) except APIError as e: self.client.fail(to_native(e)) @@ -241,7 +237,7 @@ class DockerVolumeManager(object): if self.existing_volume: if not self.check_mode: try: - self.client.remove_volume(self.parameters.volume_name) + self.client.delete_call('/volumes/{0}', self.parameters.volume_name) except APIError as e: self.client.fail(to_native(e)) @@ -286,26 +282,20 @@ def main(): debug=dict(type='bool', default=False) ) - option_minimal_versions = dict( - labels=dict(docker_py_version='1.10.0'), - ) - client = AnsibleDockerClient( argument_spec=argument_spec, supports_check_mode=True, - min_docker_version='1.10.0', # "The docker server >= 1.9.0" - option_minimal_versions=option_minimal_versions, ) try: cm = DockerVolumeManager(client) client.module.exit_json(**cm.results) except DockerException as e: - client.fail('An unexpected docker error occurred: {0}'.format(to_native(e)), exception=traceback.format_exc()) + client.fail('An unexpected Docker error occurred: {0}'.format(to_native(e)), exception=traceback.format_exc()) except RequestException as e: client.fail( - 'An unexpected requests error occurred when Docker SDK for Python tried to talk to the docker daemon: {0}'.format(to_native(e)), + 'An unexpected requests error occurred when trying to talk to the Docker daemon: {0}'.format(to_native(e)), exception=traceback.format_exc()) diff --git a/tests/integration/targets/docker_volume/tasks/main.yml b/tests/integration/targets/docker_volume/tasks/main.yml index 906d1615..c796fb57 100644 --- a/tests/integration/targets/docker_volume/tasks/main.yml +++ b/tests/integration/targets/docker_volume/tasks/main.yml @@ -24,7 +24,7 @@ state: absent with_items: "{{ vnames }}" - when: docker_py_version is version('1.10.0', '>=') and docker_api_version is version('1.25', '>=') # FIXME: find out API version! + when: docker_api_version is version('1.25', '>=') - fail: msg="Too old docker / docker-py version to run docker_volume tests!" - when: not(docker_py_version is version('1.10.0', '>=') and docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6) + when: not(docker_api_version is version('1.25', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6) diff --git a/tests/unit/plugins/modules/test_docker_volume.py b/tests/unit/plugins/modules/test_docker_volume.py deleted file mode 100644 index 6bce3f38..00000000 --- a/tests/unit/plugins/modules/test_docker_volume.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) 2018 Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -import json - -import pytest - -from ansible_collections.community.docker.plugins.modules import docker_volume -from ansible_collections.community.docker.plugins.module_utils import common - -pytestmark = pytest.mark.usefixtures('patch_ansible_module') - -TESTCASE_DOCKER_VOLUME = [ - { - 'name': 'daemon_config', - 'state': 'present' - } -] - - -@pytest.mark.parametrize('patch_ansible_module', TESTCASE_DOCKER_VOLUME, indirect=['patch_ansible_module']) -def test_create_volume_on_invalid_docker_version(mocker, capfd): - mocker.patch.object(common, 'HAS_DOCKER_PY', True) - mocker.patch.object(common, 'docker_version', '1.8.0') - - with pytest.raises(SystemExit): - docker_volume.main() - - out, dummy = capfd.readouterr() - results = json.loads(out) - assert results['failed'] - assert 'Error: Docker SDK for Python version is 1.8.0 ' in results['msg'] - assert 'Minimum version required is 1.10.0.' in results['msg']