tripleo-validations/library/check_package_update.py

146 lines
4.0 KiB
Python
Executable File

#!/usr/bin/env python
# Copyright 2017 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
""" Check for available updates for a given package."""
import collections
import subprocess
from ansible.module_utils.basic import AnsibleModule
from yaml import safe_load as yaml_safe_load
DOCUMENTATION = '''
---
module: check_package_update
short_description: Check for available updates for a given package
description:
- Check for available updates for a given package
options:
package:
required: true
description:
- The name of the package you want to check
type: str
pkg_mgr:
required: true
description:
- Supported Package Manager, DNF or YUM
type: str
author: "Florian Fuchs"
'''
EXAMPLES = '''
- hosts: webservers
tasks:
- name: Get available updates for packages
check_package_update:
package: python-tripleoclient
pkg_mgr: "{{ ansible_pkg_mgr}}"
'''
SUPPORTED_PKG_MGRS = (
'yum',
'dnf',
)
PackageDetails = collections.namedtuple('PackageDetails',
['name', 'version', 'release', 'arch'])
def get_package_details(output):
if output:
return PackageDetails(
output.split('|')[0],
output.split('|')[1],
output.split('|')[2],
output.split('|')[3],
)
def _command(command):
# Return the result of a subprocess call
# as [stdout, stderr]
process = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
return process.communicate()
def check_update(module, package, pkg_mgr):
if pkg_mgr not in SUPPORTED_PKG_MGRS:
module.fail_json(
msg='Package manager "{}" is not supported.'.format(pkg_mgr))
return
installed_stdout, installed_stderr = _command(
['rpm', '-qa', '--qf',
'%{NAME}|%{VERSION}|%{RELEASE}|%{ARCH}',
package])
# Fail the module if for some reason we can't lookup the current package.
if installed_stderr != '':
module.fail_json(msg=installed_stderr)
return
elif not installed_stdout:
module.fail_json(
msg='"{}" is not an installed package.'.format(package))
return
installed = get_package_details(installed_stdout)
pkg_mgr_option = 'available'
if pkg_mgr == 'dnf':
pkg_mgr_option = '--available'
available_stdout, available_stderr = _command(
[pkg_mgr, '-q', 'list', pkg_mgr_option, installed.name])
if available_stdout:
new_pkg_info = available_stdout.split('\n')[1].rstrip().split()[:2]
new_ver, new_rel = new_pkg_info[1].split('-')
module.exit_json(
changed=False,
name=installed.name,
current_version=installed.version,
current_release=installed.release,
new_version=new_ver,
new_release=new_rel)
else:
module.exit_json(
changed=False,
name=installed.name,
current_version=installed.version,
current_release=installed.release,
new_version=None,
new_release=None)
def main():
module = AnsibleModule(
argument_spec=yaml_safe_load(DOCUMENTATION)['options']
)
check_update(module,
module.params.get('package'),
module.params.get('pkg_mgr'))
if __name__ == '__main__':
main()