#!/usr/bin/python # -*- coding: utf-8 -*- # Copyright (c) 2018 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from __future__ import absolute_import from __future__ import division from __future__ import print_function __metaclass__ = type ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} DOCUMENTATION = """ --- module: docker_facts author: - Sam Doran (@samdoran) version_added: '2.6' short_description: Gather list of volumes, images, containers notes: - When specifying mulitple filters, only assets matching B(all) filters will be returned. description: - Gather a list of volumes, images, and containers on a running system - Return both filtered and unfiltered lists of volumes, images, and containers. options: image_filter: description: - List of k=v pairs to use as a filter for images. type: list required: false volume_filter: description: - List of k=v pairs to use as a filter for volumes. type: list required: false container_filter: description: - List of k=v pairs to use as a filter for containers. type: list required: false """ EXAMPLES = """ - name: Gather Docker facts docker_facts: - name: Gather filtered Docker facts docker_facts: image_filter: - dangling=true volume_filter: - dangling=true container_filter: - status=exited - status=dead - name: Remove containers that matched filters docker_container: name: "{{ item }}" state: absent loop: "{{ docker.containers_filtered | map(attribute='id') | list }}" """ RETURN = """ docker: description: > Lists of container, volume, and image IDs, both filtered and unfiltered. returned: always type: complex contains: containers: description: List of dictionaries of container name, state, and ID returned: always type: complex containers_filtered: description: > List of dictionaries of container name, state, and ID that matched the filter(s) returned: always type: complex images: description: List of image UUIDs returned: always type: list images_filtered: description: List of UUIDs that matched the filter(s) returned: always type: list volumes: description: List of volume UUIDs returned: always type: list volumes_filtered: description: List of UUIDs that matched the filter(s) returned: always type: list """ from ansible.module_utils.docker_common import AnsibleDockerClient # noqa: E402,E501 def _list_or_dict(value): if isinstance(value, list): return value elif isinstance(value, dict): return value raise TypeError def _to_dict(client, filters): filter_dict = {} if isinstance(filters, list): for item in filters: a = item.split('=') filter_dict[a[0]] = a[1] return filter_dict elif isinstance(filters, str): a = filters.split('=') filter_dict[a[0]] = a[1] return filter_dict elif isinstance(filters, dict): return filters def get_facts(client, docker_type, filters=None): result = [] function_to_call = globals()['get_{}'.format(docker_type)] if filters and len(filters) > 1: for f in filters: result.extend(function_to_call(client, f)) else: result = function_to_call(client, filters) return result def get_images(client, filters=None): result = [] if filters: filters = _to_dict(client, filters) images = client.images(filters=filters) if images: images = [i['Id'].strip('sha256:') for i in images] result = images return result def get_containers(client, filters=None): result = [] if filters: filters = _to_dict(client, filters) containers = client.containers(filters=filters) if containers: containers = [c['Id'].strip('sha256:') for c in containers] result = containers return result def get_volumes(client, filters=None): result = [] if filters: filters = _to_dict(client, filters) volumes = client.volumes(filters=filters) if volumes['Volumes']: volumes = [v['Name'] for v in volumes['Volumes']] result = volumes return result def main(): argument_spec = dict( image_filter=dict(type=list, default=[]), volume_filter=dict(type=list, default=[]), container_filter=dict(type=list, default=[]), ) docker_client = AnsibleDockerClient( argument_spec=argument_spec, supports_check_mode=True, ) docker_facts = {} types_to_get = ['volumes', 'images', 'containers'] for t in types_to_get: singular = t.rstrip('s') filter_key = '{}_filter'.format(singular) docker_facts[t] = get_facts(docker_client, t) filters = docker_client.module.params[filter_key] # Ensure we got a list of k=v filters if filters and len(filters[0]) <= 1: docker_client.module.fail_json( msg='The supplied {filter_key} does not appear to be a list of' ' k=v filters: {filter_value}'.format( filter_key=filter_key, filter_value=filters) ) else: docker_facts['{}_filtered'.format(t)] = get_facts( docker_client, t, filters=docker_client.module.params[filter_key]) results = dict( ansible_facts=dict( docker=docker_facts ) ) docker_client.module.exit_json(**results) if __name__ == '__main__': main()