commit 91f949b6a21618e7c592d18f15183aefcff8c312 Author: Benjamin Renard Date: Sat Oct 8 10:09:21 2022 +0200 First version diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c5f88a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*~ +.*.swp diff --git a/README.md b/README.md new file mode 100644 index 0000000..6944b25 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# Monitoring plugin to check if pip upgrades is available + +This Icinga/Nagios check plugin permit to check if pip upgrades is available. + +## Installation + +``` +apt install git +git clone https://gitea.zionetrix.net/bn8/check_pip_upgrade.git /usr/local/src/check_pip_upgrade +mkdir -p /usr/local/lib/nagios/plugins +ln -s /usr/local/src/check_pip_upgrade/check_pip_upgrade /usr/local/lib/nagios/plugins/ +echo "command[check_pip_upgrade]=/usr/local/lib/nagios/plugins/check_pip_upgrade" > /etc/nagios/nrpe.d/pip.cfg +service nagios-nrpe-server reload +``` + +## Usage + +``` +usage: check_pip_upgrade [-h] [-d] [-b BIN] [packages ...] + +positional arguments: + packages Python package(s) to check. By default, all installed packages are checkesd. + +optional arguments: + -h, --help show this help message and exit + -d, --debug + -b BIN, --bin BIN Python binary path +``` + +## Copyright + +Copyright (c) 2022 Benjamin Renard + +## License + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation. + +This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + diff --git a/check_pip_upgrade b/check_pip_upgrade new file mode 100755 index 0000000..530b88c --- /dev/null +++ b/check_pip_upgrade @@ -0,0 +1,114 @@ +#!/usr/bin/env python +""" +Icinga/Nagios plugin to check if pip upgrade is available + +Copyright (c) 2022 Benjamin Renard + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 3 +as published by the Free Software Foundation. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +""" + +import sys +import subprocess +import argparse +import json +import os +import logging +import traceback + + +# nagios exit code +STATUS = { + 'OK': 0, + 'WARNING': 1, + 'CRITICAL': 2, + 'UNKNOWN': 3 +} + +parser = argparse.ArgumentParser() +parser.add_argument( + '-d', '--debug', + action="store_true", + dest="debug", + default=False +) + +parser.add_argument( + '-b', '--bin', + action="store", + dest="bin", + help="Python binary path", + type=str +) + +parser.add_argument( + action="store", + dest="packages", + help=( + "Python package(s) to check. By default, all installed" + "packages are checked." + ), + nargs='*', + default=[] +) + +options = parser.parse_args() + +logging.basicConfig( + level=logging.DEBUG if options.debug else logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s') + +if options.bin and not os.path.exists(options.bin): + print(f'UNKNOWN - python executable "{options.bin}" not found') + sys.exit(STATUS['UNKNOWN']) + +cmd = [ + options.bin if options.bin else sys.executable, '-m', 'pip', 'list', + '--format', 'json', '--outdated' +] +logging.debug('Execute external command: %s', ' '.join(cmd)) +output = subprocess.check_output(cmd) +logging.debug('Output:\n%s', output) + +try: + outdated_packages = dict( + (package['name'], package) + for package in json.loads(output) + if not options.packages or package['name'] in options.packages + ) +except Exception as exc: + print('UNKNOWN - Exception occured parsing pip output') + traceback.print_exc(exc) + sys.exit(STATUS['UNKNOWN']) + +if outdated_packages: + if len(outdated_packages) > 1: + print(f'WARNING - {len(outdated_packages)} upgrades available') + print('\n'.join([ + f' - {name} ({p["version"]} => {p["latest_version"]})' + for name, p in outdated_packages.items() + ])) + else: + name = next(iter(outdated_packages)) + p = outdated_packages[name] + print( + f'WARNING - available upgrade for {name} ' + f'({p["version"]} => {p["latest_version"]})' + ) + sys.exit(STATUS['WARNING']) + +if options.packages and len(options.packages) == 1: + print(f'OK - {options.packages[0]} is uptodate') +else: + print('OK - all packages is uptodate') +sys.exit(STATUS['OK'])