1
0
Fork 0
mirror of https://github.com/containers/ansible-podman-collections.git synced 2026-02-04 07:11:49 +00:00
ansible-podman-collections/plugins/modules/podman_prune.py
igor-belousov 5416c5dfd8
fix(podman_prune): set top-level changed status (#997)
* fix(podman_prune): set top-level changed status

The module was returning changed status inside nested dicts,
but Ansible expects it at the top level of the result.

Before: {"image": {"changed": true, ...}} -> Ansible sees changed=false
After:  {"changed": true, "image": {...}} -> Ansible sees changed=true
Signed-off-by: Igor Belousov <igor-belousov@users.noreply.github.com>

* Update plugins/modules/podman_prune.py

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: Igor Belousov <igor-belousov@users.noreply.github.com>

---------

Signed-off-by: Igor Belousov <igor-belousov@users.noreply.github.com>
Co-authored-by: Igor Belousov <igor-belousov@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-01-15 13:04:16 +02:00

261 lines
8 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# Copyright (c) 2023, Roberto Alfieri <ralfieri@redhat.com>
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = r"""
module: podman_prune
author:
- 'Roberto Alfieri (@rebtoor)'
version_added: '1.10.0'
short_description: Allows to prune various podman objects
notes: []
description:
- Allows to run C(podman container prune), C(podman image prune), C(podman network prune),
C(podman volume prune) and C(podman system prune)
requirements:
- 'Podman installed on host'
options:
executable:
description:
- Podman binary.
type: str
default: podman
container:
description:
- Whether to prune containers.
type: bool
default: false
container_filters:
description:
- A dictionary of filter values used for selecting containers to delete.
- 'For example, C(until: 24h).'
- See L(the podman documentation,
https://docs.podman.io/en/latest/markdown/podman-container-prune.1.html#filter-filters)
for more information on possible filters.
type: dict
image:
description:
- Whether to prune images.
type: bool
default: false
image_filters:
description:
- A dictionary of filter values used for selecting images to delete.
- 'You can also use C(dangling_only: false) to delete dangling and non-dangling images or C(external: true)
to delete images even when they are used by external containers.'
- See L(the podman documentation,
https://docs.podman.io/en/latest/markdown/podman-image-prune.1.html#filter-filters)
for more information on possible filters.
type: dict
network:
description:
- Whether to prune networks.
type: bool
default: false
network_filters:
description:
- A dictionary of filter values used for selecting networks to delete.
- See L(the podman documentation,
https://docs.podman.io/en/latest/markdown/podman-network-prune.1.html#filter)
for more information on possible filters.
type: dict
system:
description:
- Whether to prune unused pods, containers, image, networks and volume data
type: bool
default: false
system_all:
description:
- Whether to prune all unused images, not only dangling images.
type: bool
default: false
system_volumes:
description:
- Whether to prune volumes currently unused by any container.
type: bool
default: false
volume:
description:
- Whether to prune volumes.
type: bool
default: false
volume_filters:
description:
- A dictionary of filter values used for selecting volumes to delete.
- See L(the podman documentation,
https://docs.podman.io/en/latest/markdown/podman-volume-prune.1.html#filter)
for more information on possible filters.
type: dict
"""
EXAMPLES = r"""
- name: Prune containers older than 24h
containers.podman.podman_prune:
containers: true
containers_filters:
# only consider containers created more than 24 hours ago
until: 24h
- name: Prune everything
containers.podman.podman_prune:
system: true
- name: Prune everything (including non-dangling images)
containers.podman.podman_prune:
system: true
system_all: true
system_volumes: true
"""
RETURN = r"""
# containers
containers:
description:
- List of IDs of deleted containers.
returned: I(containers) is C(true)
type: list
elements: str
sample: []
# images
images:
description:
- List of IDs of deleted images.
returned: I(images) is C(true)
type: list
elements: str
sample: []
# networks
networks:
description:
- List of IDs of deleted networks.
returned: I(networks) is C(true)
type: list
elements: str
sample: []
# volumes
volumes:
description:
- List of IDs of deleted volumes.
returned: I(volumes) is C(true)
type: list
elements: str
sample: []
# system
system:
description:
- List of ID of deleted containers, volumes, images, network and total reclaimed space
returned: I(system) is C(true)
type: list
elements: str
sample: []
"""
from ansible.module_utils.basic import AnsibleModule
def filtersPrepare(target, filters):
filter_out = []
if target == "system":
for system_filter in filters:
filter_out.append(filters[system_filter])
else:
for common_filter in filters:
if isinstance(filters[common_filter], dict):
dict_filters = filters[common_filter]
for single_filter in dict_filters:
filter_out.append(
"--filter={label}={key}={value}".format(
label=common_filter,
key=single_filter,
value=dict_filters[single_filter],
)
)
else:
if target == "image" and (common_filter in ("dangling_only", "external")):
if common_filter == "dangling_only" and not filters["dangling_only"]:
filter_out.append("-a")
if common_filter == "external" and filters["external"]:
filter_out.append("--external")
else:
filter_out.append(
"--filter={label}={value}".format(label=common_filter, value=filters[common_filter])
)
return filter_out
def podmanExec(module, target, filters, executable):
command = [executable, target, "prune", "--force"]
if filters is not None:
command.extend(filtersPrepare(target, filters))
rc, out, err = module.run_command(command)
changed = bool(out)
if rc != 0:
module.fail_json(msg="Error executing prune on {target}: {err}".format(target=target, err=err))
return {
"changed": changed,
target: list(filter(None, out.split("\n"))),
"errors": err,
}
def main():
results = dict()
module_args = dict(
container=dict(type="bool", default=False),
container_filters=dict(type="dict"),
image=dict(type="bool", default=False),
image_filters=dict(type="dict"),
network=dict(type="bool", default=False),
network_filters=dict(type="dict"),
volume=dict(type="bool", default=False),
volume_filters=dict(type="dict"),
system=dict(type="bool", default=False),
system_all=dict(type="bool", default=False),
system_volumes=dict(type="bool", default=False),
executable=dict(type="str", default="podman"),
)
module = AnsibleModule(argument_spec=module_args)
executable = module.get_bin_path(module.params["executable"], required=True)
for target, filters in (
("container", "container_filters"),
("image", "image_filters"),
("network", "network_filters"),
("volume", "volume_filters"),
):
if module.params[target]:
results[target] = podmanExec(module, target, module.params[filters], executable)
if module.params["system"]:
target = "system"
system_filters = {}
if module.params["system_all"]:
system_filters["system_all"] = "--all"
if module.params["system_volumes"]:
system_filters["system_volumes"] = "--volumes"
results[target] = podmanExec(module, target, system_filters, executable)
# Calculate global changed status from all targets
changed = any(res.get("changed", False) for res in results.values())
module.exit_json(changed=changed, **results)
if __name__ == "__main__":
main()