From f51ca84197f0206b4bce88040235ff04570e5f19 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Thu, 9 May 2024 17:12:36 +0200 Subject: [PATCH] docker_prune: add new options for cleaning build caches (#845) * Add new options for cleaning build caches to docker_prune. * Add tests. --- changelogs/fragments/845-docker_prune.yml | 2 + plugins/modules/docker_prune.py | 60 ++++++++++++++++++- .../targets/docker_prune/tasks/main.yml | 22 +++++++ 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/845-docker_prune.yml diff --git a/changelogs/fragments/845-docker_prune.yml b/changelogs/fragments/845-docker_prune.yml new file mode 100644 index 000000000..6ee56adba --- /dev/null +++ b/changelogs/fragments/845-docker_prune.yml @@ -0,0 +1,2 @@ +minor_changes: + - "docker_prune - add new options ``builder_cache_all``, ``builder_cache_filters``, and ``builder_cache_keep_storage``, and a new return value ``builder_cache_caches_deleted`` for pruning build caches (https://github.com/ansible-collections/community.docker/issues/844, https://github.com/ansible-collections/community.docker/issues/845)." diff --git a/plugins/modules/docker_prune.py b/plugins/modules/docker_prune.py index 1dfbf290e..a333c52fe 100644 --- a/plugins/modules/docker_prune.py +++ b/plugins/modules/docker_prune.py @@ -81,6 +81,28 @@ - Whether to prune the builder cache. type: bool default: false + builder_cache_all: + description: + - Whether to remove all types of build cache. + type: bool + default: false + version_added: 3.10.0 + builder_cache_filters: + description: + - A dictionary of filter values used for selecting images to delete. + - "For example, C(until: 10m)." + - See L(the API documentation,https://docs.docker.com/engine/api/v1.44/#tag/Image/operation/BuildPrune) + for more information on possible filters. + type: dict + version_added: 3.10.0 + builder_cache_keep_storage: + description: + - Amount of disk space to keep for cache in format C([])." + - "Number is a positive integer. Unit can be one of V(B) (byte), V(K) (kibibyte, 1024B), V(M) (mebibyte), V(G) (gibibyte), + V(T) (tebibyte), or V(P) (pebibyte)." + - "Omitting the unit defaults to bytes." + type: str + version_added: 3.10.0 author: - "Felix Fontein (@felixfontein)" @@ -181,11 +203,20 @@ returned: O(builder_cache=true) type: int sample: 0 +builder_cache_caches_deleted: + description: + - The build caches that were deleted. + returned: O(builder_cache=true) and API version is 1.39 or later + type: list + elements: str + sample: [] + version_added: 3.10.0 ''' import traceback from ansible.module_utils.common.text.converters import to_native +from ansible.module_utils.common.text.formatters import human_to_bytes from ansible_collections.community.docker.plugins.module_utils.common_api import ( AnsibleDockerClient, @@ -209,13 +240,29 @@ def main(): volumes=dict(type='bool', default=False), volumes_filters=dict(type='dict'), builder_cache=dict(type='bool', default=False), + builder_cache_all=dict(type='bool', default=False), + builder_cache_filters=dict(type='dict'), + builder_cache_keep_storage=dict(type='str'), # convert to bytes ) client = AnsibleDockerClient( argument_spec=argument_spec, + option_minimal_versions=dict( + builder_cache=dict(docker_py_version='1.31'), + builder_cache_all=dict(docker_py_version='1.39'), + builder_cache_filters=dict(docker_py_version='1.31'), + builder_cache_keep_storage=dict(docker_py_version='1.39'), + ), # supports_check_mode=True, ) + builder_cache_keep_storage = None + if client.module.params.get('builder_cache_keep_storage') is not None: + try: + builder_cache_keep_storage = human_to_bytes(client.module.params.get('builder_cache_keep_storage')) + except ValueError as exc: + client.module.fail_json(msg='Error while parsing value of builder_cache_keep_storage: {0}'.format(exc)) + try: result = dict() changed = False @@ -256,10 +303,21 @@ def main(): changed = True if client.module.params['builder_cache']: - res = client.post_to_json('/build/prune') + filters = clean_dict_booleans_for_docker_api(client.module.params.get('builder_cache_filters')) + params = {'filters': convert_filters(filters)} + if client.module.params.get('builder_cache_all'): + params['all'] = 'true' + if builder_cache_keep_storage is not None: + params['keep-storage'] = builder_cache_keep_storage + res = client.post_to_json('/build/prune', params=params) result['builder_cache_space_reclaimed'] = res['SpaceReclaimed'] if result['builder_cache_space_reclaimed']: changed = True + if 'CachesDeleted' in res: + # API version 1.39+: return value CachesDeleted (list of str) + result['builder_cache_caches_deleted'] = res['CachesDeleted'] + if result['builder_cache_caches_deleted']: + changed = True result['changed'] = changed client.module.exit_json(**result) diff --git a/tests/integration/targets/docker_prune/tasks/main.yml b/tests/integration/targets/docker_prune/tasks/main.yml index b2160ef0e..8c1309bc4 100644 --- a/tests/integration/targets/docker_prune/tasks/main.yml +++ b/tests/integration/targets/docker_prune/tasks/main.yml @@ -126,6 +126,28 @@ debug: var: result + - name: Prune build cache (API version 1.39+) + when: docker_api_version is version('1.39', '>=') + block: + - name: Prune build cache with option + docker_prune: + builder_cache: true + builder_cache_all: true + builder_cache_filters: + until: 10m + builder_cache_keep_storage: 1MB + register: result + + - name: Show results + debug: + var: result + + - name: Check results + assert: + that: + - "'builder_cache_space_reclaimed' in result" + - "'builder_cache_caches_deleted' in result" + - name: Prune volumes with all filter (API version 1.42+) when: docker_api_version is version('1.42', '>=') block: