238 lines
7.0 KiB
Python
238 lines
7.0 KiB
Python
#!/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 (@matburt)
|
|
- Brian Coca (@bcoca)
|
|
- Adam Miller (@maxamillion)
|
|
'''
|
|
|
|
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(msg='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(msg='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()), supports_check_mode=True)
|
|
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()
|