From aec98b6aab9c4d181e1837b5cbd1a59e168433ae Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Mon, 10 Dec 2018 06:41:46 +0100 Subject: [PATCH] Add docker_volume_facts module (#49692) * Add docker_volume_facts module. * Fix type confusion. * Improve tests. --- .../cloud/docker/docker_container_facts.py | 2 +- .../modules/cloud/docker/docker_volume.py | 6 +- .../cloud/docker/docker_volume_facts.py | 131 ++++++++++++++++++ .../docker_container_facts/tasks/main.yml | 2 +- .../targets/docker_volume_facts/aliases | 5 + .../targets/docker_volume_facts/meta/main.yml | 3 + .../docker_volume_facts/tasks/main.yml | 60 ++++++++ 7 files changed, 204 insertions(+), 5 deletions(-) create mode 100644 lib/ansible/modules/cloud/docker/docker_volume_facts.py create mode 100644 test/integration/targets/docker_volume_facts/aliases create mode 100644 test/integration/targets/docker_volume_facts/meta/main.yml create mode 100644 test/integration/targets/docker_volume_facts/tasks/main.yml diff --git a/lib/ansible/modules/cloud/docker/docker_container_facts.py b/lib/ansible/modules/cloud/docker/docker_container_facts.py index 683d160f57..043044d359 100644 --- a/lib/ansible/modules/cloud/docker/docker_container_facts.py +++ b/lib/ansible/modules/cloud/docker/docker_container_facts.py @@ -77,7 +77,7 @@ exists: docker_container: description: - Facts representing the current state of the container. Matches the docker inspection output. - - Will be empty if container does not exist. + - Will be C(None) if container does not exist. returned: always type: dict sample: '{ diff --git a/lib/ansible/modules/cloud/docker/docker_volume.py b/lib/ansible/modules/cloud/docker/docker_volume.py index bf99334ca6..c543ab4768 100644 --- a/lib/ansible/modules/cloud/docker/docker_volume.py +++ b/lib/ansible/modules/cloud/docker/docker_volume.py @@ -21,13 +21,13 @@ description: - Create/remove Docker volumes. - Performs largely the same function as the "docker volume" CLI subcommand. options: - name: + volume_name: description: - Name of the volume to operate on. required: true - type: dict + type: str aliases: - - volume_name + - name driver: description: diff --git a/lib/ansible/modules/cloud/docker/docker_volume_facts.py b/lib/ansible/modules/cloud/docker/docker_volume_facts.py new file mode 100644 index 0000000000..6870a4538f --- /dev/null +++ b/lib/ansible/modules/cloud/docker/docker_volume_facts.py @@ -0,0 +1,131 @@ +#!/usr/bin/python +# coding: utf-8 +# +# Copyright 2017 Red Hat | Ansible, Alex Grönholm +# 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 + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = u''' +module: docker_volume_facts +version_added: "2.8" +short_description: Retrieve facts about Docker volumes +description: + - Performs largely the same function as the "docker volume inspect" CLI subcommand. +options: + name: + description: + - Name of the volume to inspect. + required: true + type: str + aliases: + - volume_name + +extends_documentation_fragment: + - docker + +author: + - Felix Fontein (@felixfontein) + +requirements: + - "python >= 2.6" + - "docker-py >= 1.8.0" + - "Please note that the L(docker-py,https://pypi.org/project/docker-py/) Python + 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). + For Python 2.6, C(docker-py) must be used. Otherwise, it is recommended to + install the C(docker) Python module. Note that both modules should I(not) + be installed at the same time. Also note that when both modules are installed + and one of them is uninstalled, the other might no longer function and a + reinstall of it is required." + - "Docker API >= 1.21" +''' + +EXAMPLES = ''' +- name: Get infos on volume + docker_volume_facts: + name: mydata + register: result + +- name: Does volume exist? + debug: + msg: "The volume {{ 'exists' if result.exists else 'does not exist' }}" + +- name: Print information about volume + debug: + var: result.docker_volume + when: result.exists +''' + +RETURN = ''' +exists: + description: + - Returns whether the volume exists. + type: bool + returned: always + sample: true +docker_volume: + description: + - Volume inspection results for the affected volume. + - Will be C(None) if volume does not exist. + returned: success + type: dict + sample: '{ + "CreatedAt": "2018-12-09T17:43:44+01:00", + "Driver": "local", + "Labels": null, + "Mountpoint": "/var/lib/docker/volumes/ansible-test-bd3f6172/_data", + "Name": "ansible-test-bd3f6172", + "Options": {}, + "Scope": "local" + }' +''' + +try: + from docker.errors import NotFound +except ImportError: + # missing docker-py handled in ansible.module_utils.docker_common + pass + +from ansible.module_utils.docker_common import AnsibleDockerClient + + +def get_existing_volume(client, volume_name): + try: + return client.inspect_volume(volume_name) + except NotFound as dummy: + return None + except Exception as exc: + client.module.fail_json(msg="Error inspecting volume: %s" % exc) + + +def main(): + argument_spec = dict( + name=dict(type='str', required=True, aliases=['volume_name']), + ) + + client = AnsibleDockerClient( + argument_spec=argument_spec, + supports_check_mode=True, + min_docker_version='1.8.0', + min_docker_api_version='1.21', + ) + + volume = get_existing_volume(client, client.module.params['name']) + + client.module.exit_json( + changed=False, + exists=(True if volume else False), + docker_volume=volume, + ) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/docker_container_facts/tasks/main.yml b/test/integration/targets/docker_container_facts/tasks/main.yml index 82c630ef5c..937cabc7ea 100644 --- a/test/integration/targets/docker_container_facts/tasks/main.yml +++ b/test/integration/targets/docker_container_facts/tasks/main.yml @@ -19,7 +19,7 @@ that: - "not result.exists" - "'docker_container' in result" - - "not result.docker_container" + - "result.docker_container is none" - name: Make sure container exists docker_container: diff --git a/test/integration/targets/docker_volume_facts/aliases b/test/integration/targets/docker_volume_facts/aliases new file mode 100644 index 0000000000..80f0500dff --- /dev/null +++ b/test/integration/targets/docker_volume_facts/aliases @@ -0,0 +1,5 @@ +shippable/posix/group2 +skip/osx +skip/freebsd +destructive +skip/rhel8.0 diff --git a/test/integration/targets/docker_volume_facts/meta/main.yml b/test/integration/targets/docker_volume_facts/meta/main.yml new file mode 100644 index 0000000000..07da8c6dda --- /dev/null +++ b/test/integration/targets/docker_volume_facts/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - setup_docker diff --git a/test/integration/targets/docker_volume_facts/tasks/main.yml b/test/integration/targets/docker_volume_facts/tasks/main.yml new file mode 100644 index 0000000000..1c834e5071 --- /dev/null +++ b/test/integration/targets/docker_volume_facts/tasks/main.yml @@ -0,0 +1,60 @@ +--- +- block: + - name: Create random volume name + set_fact: + cname: "{{ 'ansible-test-%0x' % ((2**32) | random) }}" + + - name: Make sure volume is not there + docker_volume: + name: "{{ cname }}" + state: absent + force: yes + + - name: Inspect a non-present volume + docker_volume_facts: + name: "{{ cname }}" + register: result + + - assert: + that: + - "not result.exists" + - "'docker_volume' in result" + - "result.docker_volume is none" + + - name: Make sure volume exists + docker_volume: + name: "{{ cname }}" + + - name: Inspect a present volume + docker_volume_facts: + name: "{{ cname }}" + register: result + - name: Dump docker_volume_facts result + debug: var=result + + - name: "Comparison: use 'docker volume inspect'" + command: docker volume inspect "{{ cname }}" + register: docker_volume_inspect + - set_fact: + docker_volume_inspect_result: "{{ docker_volume_inspect.stdout | from_json }}" + - name: Dump docker volume inspect result + debug: var=docker_volume_inspect_result + + - name: Cleanup + docker_volume: + name: "{{ cname }}" + state: absent + force: yes + + - assert: + that: + - result.exists + - "'docker_volume' in result" + - "result.docker_volume" + - "result.docker_volume == docker_volume_inspect_result[0]" + + # Requirements for docker_volume + when: docker_py_version is version('1.10.0', '>=') and docker_api_version is version('1.24', '>=') + +- fail: msg="Too old docker / docker-py version to run docker_volume_facts tests!" + when: not(docker_py_version is version('1.10.0', '>=') and docker_api_version is version('1.24', '>=')) and (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6)