mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-08-02 20:24:23 -07:00
New Module: package_facts (#33195)
* new package_facts module Signed-off-by: Adam Miller <maxamillion@fedoraproject.org> * remove package_facts pkg manager aliases, they are misleading Signed-off-by: Adam Miller <maxamillion@fedoraproject.org> * fix package_facts tests now that aliases are dropped Signed-off-by: Adam Miller <maxamillion@fedoraproject.org>
This commit is contained in:
parent
d1cf9cfeb6
commit
6cb388a98a
3 changed files with 315 additions and 0 deletions
237
lib/ansible/modules/packaging/os/package_facts.py
Normal file
237
lib/ansible/modules/packaging/os/package_facts.py
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# (c) 2017, Ansible Project
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
# most of it copied from AWX's scan_packages module
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||||
|
'status': ['preview'],
|
||||||
|
'supported_by': 'community'}
|
||||||
|
|
||||||
|
DOCUMENTATION = '''
|
||||||
|
module: package_facts
|
||||||
|
short_description: package information as facts
|
||||||
|
description:
|
||||||
|
- Return information about installed packages as facts
|
||||||
|
options:
|
||||||
|
manager:
|
||||||
|
description:
|
||||||
|
- The package manager used by the system so we can query the package information
|
||||||
|
default: auto
|
||||||
|
choices: ["auto", "rpm", "apt"]
|
||||||
|
required: False
|
||||||
|
version_added: "2.5"
|
||||||
|
author:
|
||||||
|
- Matthew Jones
|
||||||
|
- Brian Coca
|
||||||
|
- Adam Miller
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = '''
|
||||||
|
- name: get the rpm package facts
|
||||||
|
package_facts:
|
||||||
|
manager: "auto"
|
||||||
|
|
||||||
|
- name: show them
|
||||||
|
debug: var=ansible_facts.packages
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
RETURN = '''
|
||||||
|
ansible_facts:
|
||||||
|
description: facts to add to ansible_facts
|
||||||
|
returned: always
|
||||||
|
type: complex
|
||||||
|
contains:
|
||||||
|
packages:
|
||||||
|
description: list of dicts with package information
|
||||||
|
returned: when operating system level package manager is specified or auto detected manager
|
||||||
|
type: dict
|
||||||
|
sample_rpm:
|
||||||
|
{
|
||||||
|
"packages": {
|
||||||
|
"kernel": [
|
||||||
|
{
|
||||||
|
"arch": "x86_64",
|
||||||
|
"epoch": null,
|
||||||
|
"name": "kernel",
|
||||||
|
"release": "514.26.2.el7",
|
||||||
|
"source": "rpm",
|
||||||
|
"version": "3.10.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arch": "x86_64",
|
||||||
|
"epoch": null,
|
||||||
|
"name": "kernel",
|
||||||
|
"release": "514.16.1.el7",
|
||||||
|
"source": "rpm",
|
||||||
|
"version": "3.10.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arch": "x86_64",
|
||||||
|
"epoch": null,
|
||||||
|
"name": "kernel",
|
||||||
|
"release": "514.10.2.el7",
|
||||||
|
"source": "rpm",
|
||||||
|
"version": "3.10.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arch": "x86_64",
|
||||||
|
"epoch": null,
|
||||||
|
"name": "kernel",
|
||||||
|
"release": "514.21.1.el7",
|
||||||
|
"source": "rpm",
|
||||||
|
"version": "3.10.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"arch": "x86_64",
|
||||||
|
"epoch": null,
|
||||||
|
"name": "kernel",
|
||||||
|
"release": "693.2.2.el7",
|
||||||
|
"source": "rpm",
|
||||||
|
"version": "3.10.0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kernel-tools": [
|
||||||
|
{
|
||||||
|
"arch": "x86_64",
|
||||||
|
"epoch": null,
|
||||||
|
"name": "kernel-tools",
|
||||||
|
"release": "693.2.2.el7",
|
||||||
|
"source": "rpm",
|
||||||
|
"version": "3.10.0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kernel-tools-libs": [
|
||||||
|
{
|
||||||
|
"arch": "x86_64",
|
||||||
|
"epoch": null,
|
||||||
|
"name": "kernel-tools-libs",
|
||||||
|
"release": "693.2.2.el7",
|
||||||
|
"source": "rpm",
|
||||||
|
"version": "3.10.0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sample_deb:
|
||||||
|
{
|
||||||
|
"packages": {
|
||||||
|
"libbz2-1.0": [
|
||||||
|
{
|
||||||
|
"version": "1.0.6-5",
|
||||||
|
"source": "apt",
|
||||||
|
"arch": "amd64",
|
||||||
|
"name": "libbz2-1.0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"patch": [
|
||||||
|
{
|
||||||
|
"version": "2.7.1-4ubuntu1",
|
||||||
|
"source": "apt",
|
||||||
|
"arch": "amd64",
|
||||||
|
"name": "patch"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils._text import to_text
|
||||||
|
|
||||||
|
|
||||||
|
def rpm_package_list():
|
||||||
|
|
||||||
|
try:
|
||||||
|
import rpm
|
||||||
|
except ImportError:
|
||||||
|
module.fail_json('Unable to use the rpm python bindings, please ensure they are installed under the python the module runs under')
|
||||||
|
|
||||||
|
trans_set = rpm.TransactionSet()
|
||||||
|
installed_packages = {}
|
||||||
|
for package in trans_set.dbMatch():
|
||||||
|
package_details = dict(name=package[rpm.RPMTAG_NAME],
|
||||||
|
version=package[rpm.RPMTAG_VERSION],
|
||||||
|
release=package[rpm.RPMTAG_RELEASE],
|
||||||
|
epoch=package[rpm.RPMTAG_EPOCH],
|
||||||
|
arch=package[rpm.RPMTAG_ARCH],
|
||||||
|
source='rpm')
|
||||||
|
if package_details['name'] not in installed_packages:
|
||||||
|
installed_packages[package_details['name']] = [package_details]
|
||||||
|
else:
|
||||||
|
installed_packages[package_details['name']].append(package_details)
|
||||||
|
return installed_packages
|
||||||
|
|
||||||
|
|
||||||
|
def apt_package_list():
|
||||||
|
|
||||||
|
try:
|
||||||
|
import apt
|
||||||
|
except ImportError:
|
||||||
|
module.fail_json('Unable to use the apt python bindings, please ensure they are installed under the python the module runs under')
|
||||||
|
|
||||||
|
apt_cache = apt.Cache()
|
||||||
|
installed_packages = {}
|
||||||
|
apt_installed_packages = [pk for pk in apt_cache.keys() if apt_cache[pk].is_installed]
|
||||||
|
for package in apt_installed_packages:
|
||||||
|
ac_pkg = apt_cache[package].installed
|
||||||
|
package_details = dict(name=package, version=ac_pkg.version, arch=ac_pkg.architecture, source='apt')
|
||||||
|
if package_details['name'] not in installed_packages:
|
||||||
|
installed_packages[package_details['name']] = [package_details]
|
||||||
|
else:
|
||||||
|
installed_packages[package_details['name']].append(package_details)
|
||||||
|
return installed_packages
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: add more listing methods
|
||||||
|
def main():
|
||||||
|
global module
|
||||||
|
module = AnsibleModule(argument_spec=dict(manager=dict()))
|
||||||
|
manager = module.params['manager']
|
||||||
|
packages = {}
|
||||||
|
results = {}
|
||||||
|
|
||||||
|
if manager is None or manager == 'auto':
|
||||||
|
|
||||||
|
# detect!
|
||||||
|
for manager_lib in ('rpm', 'apt'):
|
||||||
|
try:
|
||||||
|
dummy = __import__(manager_lib)
|
||||||
|
manager = manager_lib
|
||||||
|
break
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# FIXME: add more detection methods
|
||||||
|
try:
|
||||||
|
if manager == "rpm":
|
||||||
|
packages = rpm_package_list()
|
||||||
|
elif manager == "apt":
|
||||||
|
packages = apt_package_list()
|
||||||
|
else:
|
||||||
|
if manager:
|
||||||
|
results['msg'] = 'Unsupported package manager: %s' % manager
|
||||||
|
results['skipped'] = True
|
||||||
|
else:
|
||||||
|
module.fail_json(msg='Could not detect supported package manager')
|
||||||
|
except Exception as e:
|
||||||
|
from traceback import format_tb
|
||||||
|
module.fail_json(msg='Failed to retrieve packages: %s' % to_text(e), exception=format_tb(sys.exc_info()[2]))
|
||||||
|
|
||||||
|
results['ansible_facts'] = {}
|
||||||
|
# Set the facts, this will override the facts in ansible_facts that might
|
||||||
|
# exist from previous runs when using operating system level or distribution
|
||||||
|
# package managers
|
||||||
|
results['ansible_facts']['packages'] = packages
|
||||||
|
|
||||||
|
module.exit_json(**results)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
3
test/integration/targets/package_facts/aliases
Normal file
3
test/integration/targets/package_facts/aliases
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
posix/ci/group3
|
||||||
|
skip/freebsd
|
||||||
|
skip/osx
|
75
test/integration/targets/package_facts/tasks/main.yml
Normal file
75
test/integration/targets/package_facts/tasks/main.yml
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
# Test playbook for the package_facts module
|
||||||
|
# (c) 2017, Adam Miller <admiller@redhat.com>
|
||||||
|
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
- name: Prep package_fact tests - Debian Family
|
||||||
|
block:
|
||||||
|
- name: install python apt bindings - python2
|
||||||
|
package: name="python-apt" state=installed
|
||||||
|
when: ansible_python.version.major|int == 2
|
||||||
|
|
||||||
|
- name: install python apt bindings - python3
|
||||||
|
package: name="python3-apt" state=installed
|
||||||
|
when: ansible_python.version.major|int == 3
|
||||||
|
|
||||||
|
- name: Gather package facts
|
||||||
|
package_facts:
|
||||||
|
manager: apt
|
||||||
|
|
||||||
|
- name: check for ansible_facts.packages exists
|
||||||
|
assert:
|
||||||
|
that: ansible_facts.packages is defined
|
||||||
|
when: ansible_os_family == "Debian"
|
||||||
|
|
||||||
|
- name: Run package_fact tests - Red Hat Family
|
||||||
|
block:
|
||||||
|
- name: Gather package facts
|
||||||
|
package_facts:
|
||||||
|
manager: rpm
|
||||||
|
|
||||||
|
- name: check for ansible_facts.packages exists
|
||||||
|
assert:
|
||||||
|
that: ansible_facts.packages is defined
|
||||||
|
when: (ansible_os_family == "RedHat")
|
||||||
|
|
||||||
|
- name: Run package_fact tests - SUSE/OpenSUSE Family
|
||||||
|
block:
|
||||||
|
- name: install python rpm bindings - python2
|
||||||
|
package: name="rpm-python" state=installed
|
||||||
|
when: ansible_python.version.major|int == 2
|
||||||
|
|
||||||
|
- name: install python rpm bindings - python3
|
||||||
|
package: name="python3-rpm" state=installed
|
||||||
|
when: ansible_python.version.major|int == 3
|
||||||
|
|
||||||
|
- name: Gather package facts
|
||||||
|
package_facts:
|
||||||
|
manager: rpm
|
||||||
|
|
||||||
|
- name: check for ansible_facts.packages exists
|
||||||
|
assert:
|
||||||
|
that: ansible_facts.packages is defined
|
||||||
|
when: (ansible_os_family == "openSUSE Leap") or (ansible_os_family == "Suse")
|
||||||
|
|
||||||
|
# Check that auto detection works also
|
||||||
|
- name: Gather package facts
|
||||||
|
package_facts:
|
||||||
|
manager: auto
|
||||||
|
|
||||||
|
- name: check for ansible_facts.packages exists
|
||||||
|
assert:
|
||||||
|
that: ansible_facts.packages is defined
|
Loading…
Add table
Add a link
Reference in a new issue