mirror of https://github.com/ansible/ansible.git
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>pull/33921/head
parent
d1cf9cfeb6
commit
6cb388a98a
@ -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()
|
@ -0,0 +1,3 @@
|
||||
posix/ci/group3
|
||||
skip/freebsd
|
||||
skip/osx
|
@ -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…
Reference in New Issue