diff --git a/changelogs/fragments/podman_image_facts-no-fail-on-invalid-image.yaml b/changelogs/fragments/podman_image_facts-no-fail-on-invalid-image.yaml new file mode 100644 index 00000000000..b63a35c3bbb --- /dev/null +++ b/changelogs/fragments/podman_image_facts-no-fail-on-invalid-image.yaml @@ -0,0 +1,2 @@ +bugfixes: + - podman_image_facts - do not fail if invalid or non-existant image name is provided (https://github.com/ansible/ansible/issues/57899) diff --git a/lib/ansible/modules/cloud/podman/podman_image_info.py b/lib/ansible/modules/cloud/podman/podman_image_info.py index 071a1cbbfc0..f57869d495e 100644 --- a/lib/ansible/modules/cloud/podman/podman_image_info.py +++ b/lib/ansible/modules/cloud/podman/podman_image_info.py @@ -154,20 +154,49 @@ import json from ansible.module_utils.basic import AnsibleModule -def get_image_info(module, executable, name): - +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): - name = [name] + names = [name] - command = [executable, 'image', 'inspect'] - command.extend(name) + for name in names: + if image_exists(module, executable, name): + valid_names.append(name) - rc, out, err = module.run_command(command) + return valid_names - if rc != 0: - module.fail_json(msg="Unable to gather info for '{0}': {1}".format(', '.join(name), err)) - return out +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): @@ -193,7 +222,8 @@ def main(): executable = module.get_bin_path(executable, required=True) if name: - results = json.loads(get_image_info(module, executable, 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)) diff --git a/test/integration/targets/podman_image_info/tasks/main.yml b/test/integration/targets/podman_image_info/tasks/main.yml index 84a5bf97599..259fc11f1ff 100644 --- a/test/integration/targets/podman_image_info/tasks/main.yml +++ b/test/integration/targets/podman_image_info/tasks/main.yml @@ -24,3 +24,30 @@ - all_image_result.images | length > 0 - named_image_result.images | length == 1 - "'dnsmasq' in named_image_result.images[0]['RepoTags'][0]" + + - name: Get info on single image that does not exist + podman_image_info: + name: nope + register: single_nonexistant + + - name: Get info on multiple images that do not exist + podman_image_info: + name: + - nope + - reallynope + register: multiple_nonexistant + + - name: Get info with one image that does not exist + podman_image_info: + name: + - dnsmasq + - nope + - etcd + register: mixed_nonexistant + + - name: Ensure image info was returned when non-existant image info was requisted + assert: + that: + - single_nonexistant.images | length == 0 + - multiple_nonexistant.images | length == 0 + - mixed_nonexistant.images | length == 2