diff --git a/changelogs/fragments/package_facts_fix.yml b/changelogs/fragments/package_facts_fix.yml new file mode 100644 index 00000000000..f1ffbf4d641 --- /dev/null +++ b/changelogs/fragments/package_facts_fix.yml @@ -0,0 +1,2 @@ +bugfixes: + - package_facts module when using 'auto' will return the first package manager found that provides an output, instead of just the first one, as this can be foreign and not have any packages. diff --git a/lib/ansible/modules/package_facts.py b/lib/ansible/modules/package_facts.py index df10c4694db..e1dc026093a 100644 --- a/lib/ansible/modules/package_facts.py +++ b/lib/ansible/modules/package_facts.py @@ -460,7 +460,7 @@ def main(): # get supported pkg managers PKG_MANAGERS = get_all_pkg_managers() - PKG_MANAGER_NAMES = [x.lower() for x in PKG_MANAGERS.keys()] + PKG_MANAGER_NAMES = sorted([x.lower() for x in PKG_MANAGERS.keys()]) # add aliases PKG_MANAGER_NAMES.extend([alias for alist in ALIASES.values() for alias in alist]) @@ -510,12 +510,24 @@ def main(): manager = PKG_MANAGERS[pkgmgr]() try: + packages_found = {} if manager.is_available(handle_exceptions=False): - found += 1 try: - packages.update(manager.get_packages()) + packages_found = manager.get_packages() except Exception as e: module.warn('Failed to retrieve packages with %s: %s' % (pkgmgr, to_text(e))) + + # only consider 'found' if it results in something + if packages_found: + found += 1 + for k in packages_found.keys(): + if k in packages: + packages[k].extend(packages_found[k]) + else: + packages[k] = packages_found[k] + else: + module.warn('Found "%s" but no associated packages' % (pkgmgr)) + except Exception as e: if pkgmgr in module.params['manager']: module.warn('Requested package manager %s was not usable by this module: %s' % (pkgmgr, to_text(e))) diff --git a/test/integration/targets/package_facts/tasks/main.yml b/test/integration/targets/package_facts/tasks/main.yml index 144fa784f70..9309dca2aa9 100644 --- a/test/integration/targets/package_facts/tasks/main.yml +++ b/test/integration/targets/package_facts/tasks/main.yml @@ -18,6 +18,46 @@ - name: check for ansible_facts.packages exists assert: that: ansible_facts.packages is defined + + - name: Now try again but installing misleading rpm + block: + - name: install misleading rpm api + package: name="python3-rpm" state=present + + - name: prep outputdir + tempfile: path=~ state=directory + register: tempdir + + - name: install misleading rpm 'binary' file + file: dest="{{tempdir['path']}}/rpm" state=touch mode='0700' + + - name: Gather package facts, finding 'rpm' on debian fam (needed for latest version) + package_facts: + environment: + PATH: "${PATH}:{{tempdir['path']}}" + + - name: check we got packages + assert: + that: + - (ansible_facts.packages | length ) > 0 + + - name: Same again but this time forcing rpm first + package_facts: + manager: ['rpm', 'apt'] + environment: + PATH: "${PATH}:{{tempdir['path']}}" + + - name: check we got packages + assert: + that: + - (ansible_facts.packages | length ) > 0 + + always: + - package: name="python3-rpm" state=absent + - file: path="{{tempdir['path']}}/rpm" state=absent + - file: path="{{tempdir['path']}}" state=absent + + when: ansible_os_family == "Debian" - name: Run package_fact tests - Red Hat Family