#!/usr/bin/python # Copyright (c) 2019 Ansible Project # 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 DOCUMENTATION = r""" module: podman_image_info author: - Sam Doran (@samdoran) short_description: Gather info about images using podman notes: - Podman may required elevated privileges in order to run properly. description: - Gather info about images using C(podman) options: executable: description: - Path to C(podman) executable if it is not in the C($PATH) on the machine running C(podman) default: 'podman' type: str name: description: - List of tags or UID to gather info about. If no name is given return info about all images. type: list elements: str """ EXAMPLES = r""" - name: Gather info for all images containers.podman.podman_image_info: - name: Gather info on a specific image containers.podman.podman_image_info: name: nginx - name: Gather info on several images containers.podman.podman_image_info: name: - redis - quay.io/bitnami/wildfly """ RETURN = r""" images: description: info from all or specified images returned: always type: list sample: [ { "Id": "029bed813f07be84fae0344cbf8076ced5ea3c929d5f064ba617ac7d8c610a4b", "Digest": "sha256:3362f865019db5f14ac5154cb0db2c3741ad1cce0416045be422ad4de441b081", "RepoTags": [ "docker.io/library/alpine:3.15", "quay.io/podman/alpine:3.15", "quay.io/podman/alpine:3.15" ], "RepoDigests": [ "docker.io/library/alpine@sha256:3362f865019db5f14ac5154cb0db2c3741ad1cce0416045be422ad4de441b081", "docker.io/library/alpine@sha256:c58a2fce65cb3487f965d2fb08eec4843384dbe29264f427b665421db1aabef2", "quay.io/podman/alpine@sha256:3362f865019db5f14ac5154cb0db2c3741ad1cce0416045be422ad4de441b081", "quay.io/podman/alpine@sha256:c58a2fce65cb3487f965d2fb08eec4843384dbe29264f427b665421db1aabef2", "quay.io/podman/alpine@sha256:3362f865019db5f14ac5154cb0db2c3741ad1cce0416045be422ad4de441b081", "quay.io/podman/alpine@sha256:c58a2fce65cb3487f965d2fb08eec4843384dbe29264f427b665421db1aabef2" ], "Parent": "", "Comment": "", "Created": "2023-06-14T20:42:13.993588153Z", "Config": { "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh" ] }, "Version": "20.10.23", "Author": "", "Architecture": "amd64", "Os": "linux", "Size": 11745350, "VirtualSize": 11745350, "GraphDriver": { "Name": "overlay", "Data": { "UpperDir": "/home/podman/.local/share/containers/storage/overlay/579b.../diff", "WorkDir": "/home/podman/.local/share/containers/storage/overlay/579b.../work" } }, "RootFS": { "Type": "layers", "Layers": [ "sha256:579b..." ] }, "Labels": null, "Annotations": {}, "ManifestType": "application/vnd.docker.distribution.manifest.v2+json", "User": "", "History": [ { "created": "2023-06-14T20:42:13.893052319Z", "created_by": "/bin/sh -c #(nop) ADD file:234234234 in / " }, { "created": "2023-06-14T20:42:13.993588153Z", "created_by": "/bin/sh -c #(nop) CMD [\"/bin/sh\"]", "empty_layer": true } ], "NamesHistory": [ "quay.io/podman/alpine:3.15", "quay.io/podman/alpine:3.15", "docker.io/library/alpine:3.15" ] } ] """ import json from ansible.module_utils.basic import AnsibleModule def image_exists(module, executable, name): command = [executable, "image", "exists", name] rc, out, err = module.run_command(command) if rc == 1: return False elif 'Command "exists" not found' in err: # The 'exists' test is available in podman >= 0.12.1 command = [executable, "image", "ls", "-q", name] rc2, out2, err2 = module.run_command(command) if rc2 != 0: return False return True def filter_invalid_names(module, executable, name): valid_names = [] names = name if not isinstance(name, list): names = [name] for name in names: if image_exists(module, executable, name): valid_names.append(name) return valid_names def get_image_info(module, executable, name): names = name if not isinstance(name, list): names = [name] if len(names) > 0: command = [executable, "image", "inspect"] command.extend(names) rc, out, err = module.run_command(command) if rc != 0: module.fail_json(msg="Unable to gather info for '{0}': {1}".format(", ".join(names), err)) return out else: return json.dumps([]) def get_all_image_info(module, executable): command = [executable, "image", "ls", "-q"] rc, out, err = module.run_command(command) out = out.strip() if out: name = out.split("\n") res = get_image_info(module, executable, name) return res return json.dumps([]) def main(): module = AnsibleModule( argument_spec=dict( executable=dict(type="str", default="podman"), name=dict(type="list", elements="str"), ), supports_check_mode=True, ) executable = module.params["executable"] name = module.params.get("name") executable = module.get_bin_path(executable, required=True) if name: valid_names = filter_invalid_names(module, executable, name) results = json.loads(get_image_info(module, executable, valid_names)) else: results = json.loads(get_all_image_info(module, executable)) results = dict(changed=False, images=results) module.exit_json(**results) if __name__ == "__main__": main()