Add docker_prune module (#48063)

* Add docker_prune module.

* Fix spelling error.
This commit is contained in:
Felix Fontein 2018-11-05 18:05:26 +01:00 committed by John R Barker
parent c1385b6073
commit 2728a22f73
4 changed files with 326 additions and 0 deletions

View file

@ -0,0 +1,259 @@
#!/usr/bin/python
#
# Copyright 2016 Red Hat | Ansible
# 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 = '''
---
module: docker_prune
short_description: Allows to prune various docker objects
description:
- Allows to run C(docker container prune), C(docker image prune), C(docker network prune)
and C(docker volume prune) via the Docker API.
version_added: "2.8"
options:
containers:
description:
- Whether to prune containers.
type: bool
default: no
containers_filters:
description:
- A dictionary of filter values used for selecting containers to delete.
- "For example, C(until: 24h)."
- See L(the docker documentation,https://docs.docker.com/engine/reference/commandline/container_prune/#filtering)
for more information on possible filters.
type: dict
images:
description:
- Whether to prune images.
type: bool
default: no
images_filters:
description:
- A dictionary of filter values used for selecting images to delete.
- "For example, C(dangling: true)."
- See L(the docker documentation,https://docs.docker.com/engine/reference/commandline/image_prune/#filtering)
for more information on possible filters.
type: dict
networks:
description:
- Whether to prune networks.
type: bool
default: no
networks_filters:
description:
- A dictionary of filter values used for selecting networks to delete.
- See L(the docker documentation,https://docs.docker.com/engine/reference/commandline/network_prune/#filtering)
for more information on possible filters.
type: dict
volumes:
description:
- Whether to prune volumes.
type: bool
default: no
volumes_filters:
description:
- A dictionary of filter values used for selecting volumes to delete.
- See L(the docker documentation,https://docs.docker.com/engine/reference/commandline/volume_prune/#filtering)
for more information on possible filters.
type: dict
builder_cache:
description:
- Whether to prune the builder cache.
- Requires version 3.3.0 of the Python Docker SDK or newer.
type: bool
default: no
extends_documentation_fragment:
- docker
author:
- "Felix Fontein (@felixfontein)"
requirements:
- "python >= 2.6"
- "docker >= 2.1.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).
Version 2.1.0 or newer is only available with the C(docker) module."
- "Docker API >= 1.25"
'''
EXAMPLES = '''
- name: Prune containers older than 24h
docker_prune:
containers: yes
containers_filters:
# only consider containers created more than 24 hours ago
until: 24h
- name: Prune everything
docker_prune:
containers: yes
images: yes
networks: yes
volumes: yes
builder_cache: yes
'''
RETURN = '''
# containers
containers:
description:
- List of IDs of deleted containers.
returned: C(containers) is C(true)
type: list
sample: '[]'
containers_space_reclaimed:
description:
- Amount of reclaimed disk space from container pruning in bytes.
returned: C(containers) is C(true)
type: int
sample: '0'
# images
images:
description:
- List of IDs of deleted images.
returned: C(images) is C(true)
type: list
sample: '[]'
images_space_reclaimed:
description:
- Amount of reclaimed disk space from image pruning in bytes.
returned: C(images) is C(true)
type: int
sample: '0'
# networks
networks:
description:
- List of IDs of deleted networks.
returned: C(networks) is C(true)
type: list
sample: '[]'
# volumes
volumes:
description:
- List of IDs of deleted volumes.
returned: C(volumes) is C(true)
type: list
sample: '[]'
volumes_space_reclaimed:
description:
- Amount of reclaimed disk space from volumes pruning in bytes.
returned: C(volumes) is C(true)
type: int
sample: '0'
# builder_cache
builder_cache_space_reclaimed:
description:
- Amount of reclaimed disk space from builder cache pruning in bytes.
returned: C(builder_cache) is C(true)
type: int
sample: '0'
'''
from distutils.version import LooseVersion
from ansible.module_utils.docker_common import AnsibleDockerClient
try:
from ansible.module_utils.docker_common import docker_version
except Exception as dummy:
# missing docker-py handled in ansible.module_utils.docker
pass
def get_filters(module, name):
result = dict()
filters = module.params.get(name)
if filters is not None:
for k, v in filters.items():
# Go doesn't like 'True' or 'False'
if v is True:
v = 'true'
elif v is False:
v = 'false'
else:
v = str(v)
result[str(k)] = v
return result
def main():
argument_spec = dict(
containers=dict(type='bool', default=False),
containers_filters=dict(type='dict'),
images=dict(type='bool', default=False),
images_filters=dict(type='dict'),
networks=dict(type='bool', default=False),
networks_filters=dict(type='dict'),
volumes=dict(type='bool', default=False),
volumes_filters=dict(type='dict'),
builder_cache=dict(type='bool', default=False),
)
client = AnsibleDockerClient(
argument_spec=argument_spec,
# supports_check_mode=True,
min_docker_api_version='1.25',
min_docker_version='2.1.0',
)
# Version checks
if client.module.params['builder_cache'] and LooseVersion(docker_version) < LooseVersion('3.3.0'):
msg = "Error: docker version is %s. Minimum version required for builds option is %s. Use `pip install --upgrade docker` to upgrade."
client.module.fail(msg=(msg % (docker_version, )))
result = dict()
if client.module.params['containers']:
filters = get_filters(client.module, 'containers_filters')
res = client.prune_containers(filters=filters)
result['containers'] = res.get('ContainersDeleted') or []
result['containers_space_reclaimed'] = res['SpaceReclaimed']
if client.module.params['images']:
filters = get_filters(client.module, 'images_filters')
res = client.prune_images(filters=filters)
result['images'] = res.get('ImagesDeleted') or []
result['images_space_reclaimed'] = res['SpaceReclaimed']
if client.module.params['networks']:
filters = get_filters(client.module, 'networks_filters')
res = client.prune_networks(filters=filters)
result['networks'] = res.get('NetworksDeleted') or []
if client.module.params['volumes']:
filters = get_filters(client.module, 'volumes_filters')
res = client.prune_volumes(filters=filters)
result['volumes'] = res.get('VolumesDeleted') or []
result['volumes_space_reclaimed'] = res['SpaceReclaimed']
if client.module.params['builder_cache']:
res = client.prune_builds()
result['builder_cache_space_reclaimed'] = res['SpaceReclaimed']
client.module.exit_json(**result)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,4 @@
shippable/posix/group2
skip/osx
skip/freebsd
destructive

View file

@ -0,0 +1,3 @@
---
dependencies:
- setup_docker

View file

@ -0,0 +1,60 @@
---
- name: Create random names
set_fact:
cname: "{{ 'ansible-container-%0x' % ((2**32) | random) }}"
nname: "{{ 'ansible-network-%0x' % ((2**32) | random) }}"
vname: "{{ 'ansible-volume-%0x' % ((2**32) | random) }}"
- block:
# Create objects to be pruned
- docker_container:
name: "{{ cname }}"
image: hello-world
state: present
register: container
- docker_network:
name: "{{ nname }}"
state: present
register: network
- docker_volume:
name: "{{ vname }}"
state: present
register: volume
# Prune objects
- docker_prune:
containers: yes
images: yes
networks: yes
volumes: yes
builder_cache: yes
register: result
# Analyze result
- debug: var=result
- assert:
that:
# containers
- container.ansible_facts.docker_container.Id in result.containers
- "'containers_space_reclaimed' in result"
# images
- "'images_space_reclaimed' in result"
# networks
- network.ansible_facts.docker_network.Name in result.networks
# volumes
- volume.ansible_facts.docker_volume.Name in result.volumes
- "'volumes_space_reclaimed' in result"
# builder_cache
- "'builder_cache_space_reclaimed' in result"
# Test with filters
- docker_prune:
images: yes
images_filters:
dangling: true
register: result
- debug: var=result
# Skip for CentOS 6
when: ansible_distribution != 'CentOS' or ansible_distribution_major_version|int > 6