commit 6d4437efb62aa86d96c217298f41aeaf6f1f39d7 Author: Benjamin Renard Date: Sun Mar 3 17:18:20 2024 +0100 Initial version diff --git a/README.md b/README.md new file mode 100644 index 0000000..4fde042 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# Check container upgrade + +Monitoring plugin to check if containers are upgradable. By default all running container are checked. + +Check are done by running Icinga/Nagios compatible check plugin inside containers. + +## Installation + +``` +git clone https://gitea.zionetrix.net/bn8/check_container_upgrade.git /usr/local/src/check_container_upgrade +mkdir -p /usr/local/lib/nagios/plugins +ln -s /usr/local/src/check_container_upgrade/check_container_upgrade /usr/local/lib/nagios/plugins/ +echo "nagios ALL=NOPASSWD: /usr/local/lib/nagios/plugins/check_container_upgrade" > /etc/sudoers.d/nagios-containers +chmod 0400 /etc/sudoers.d/nagios-containers +echo "command[check_container_upgrade]=sudo /usr/local/lib/nagios/plugins/check_container_upgrade" > /etc/nagios/nrpe.d/containers.cfg +service nagios-nrpe-server reload +``` + +## Usage + +``` +Usage : check_container_upgrade [-d] [-E /path/to/engine] [container1,...] + -E [path] Force a specific engine (possible values: auto docker podman, default: auto) + -x [container] Exclude specified container (could be repeat) + -d Debug mode + -X Enable bash tracing (=set -x) + -h Show this message +``` + +## Copyright + +Copyright (c) 2024 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_container_upgrade b/check_container_upgrade new file mode 100755 index 0000000..5457415 --- /dev/null +++ b/check_container_upgrade @@ -0,0 +1,202 @@ +#!/bin/bash +# Monitoring plugin to check if running containers are upgradable +# +# Author: Benjamin Renard +# Date: Sun, 03 Mar 2024 16:40:19 +0100 +# Source: https://gitea.zionetrix.net/bn8/check_container_upgrade +# + +ENGINE="auto" +POSSIBLE_ENGINES=( "auto" "docker" "podman" ) +DEBUG=0 +EXCLUDED_CONTAINERS=( buildx_buildkit_default ) +declare -rA CHECK_PLUGINS=( + ["/usr/lib/nagios/plugins/check_apt"]="/usr/lib/nagios/plugins/check_apt -u -U -t 60 -l" + ["/usr/lib/nagios/plugins/check_apk"]="/usr/lib/nagios/plugins/check_apk" +) + +function debug() { + if [ $DEBUG -eq 1 ] + then + >&2 echo -e "[DEBUG] $1" + fi +} + +function is_empty() { + [ $# -gt 0 ] && return 1 + return 0 +} + +function in_array() { + param=$1; + shift; + for elem in "$@"; + do + [[ "$param" = "$elem" ]] && return 0; + done; + return 1 +} + +function usage() { + error="$1" + [ -n "$error" ] && echo "$error" + cat << EOF +Usage : $0 [-d] [-E /path/to/engine] [container1,...] + -E [path] Force a specific engine (possible values: ${POSSIBLE_ENGINES[@]}, default: $ENGINE) + -x [container] Exclude specified container (could be repeat) + -d Debug mode + -X Enable bash tracing (=set -x) + -h Show this message +EOF + [ -n "$error" ] && exit 1 + exit 0 +} + +while getopts "hdXE:x:" OPTION +do + case $OPTION in + d) + DEBUG=1 + ;; + h) + usage + ;; + E) + ENGINE=$OPTARG + if [ ! -x "$ENGINE" ] + then + in_array $ENGINE $POSSIBLE_ENGINES || usage "Invalid engine $ENGINE" + fi + ;; + x) + EXCLUDED_CONTAINERS+=( $OPTARG ) + ;; + X) + set -x + ;; + *) + usage "Unknown option $OPTION" + ;; + esac +done +ONLY_CONTAINERS=( "${@:$OPTIND}" ) +! is_empty $ONLY_CONTAINERS && debug "Only containers: ${ONLY_CONTAINERS[@]}" + +if [ "$ENGINE" == "auto" ] +then + debug "Auto-detect engine..." + for engine in ${POSSIBLE_ENGINES[@]} + do + [ "$engine" == "auto" ] && continue + which "$engine" > /dev/null 2>&1 + if [ $? -ne 0 ] + then + debug "$engine not found" + continue + fi + ENGINE="$engine" + break + done + if [ -z "$ENGINE" ] + then + echo "UNKNOWN - Fail to auto-detect engine" + exit 3 + fi + debug "Auto-detected engine: $ENGINE" +fi + +EXIT_CODE=0 +declare -A UPTODATE +declare -A ERRORS +CHECKED_CONTAINERS=( ) + +debug "List running containers..." +RUNNING_CONTAINERS=$($ENGINE ps --format '{{.Names}}' | tr '\n' ' ') +debug "Running containers: $RUNNING_CONTAINERS" + +for container in $RUNNING_CONTAINERS +do + if ! is_empty $ONLY_CONTAINERS && ! in_array $container $ONLY_CONTAINERS + then + debug "$container - Ignored" + continue + fi + if in_array $container $EXCLUDED_CONTAINERS + then + debug "$container - Excluded" + continue + fi + CHECKED_CONTAINERS+=( "$container" ) + STATUS="" + for check_plugin in ${CHECK_PLUGINS[@]} + do + $ENGINE exec $container test -e $check_plugin > /dev/null 2>&1 + if [ $? -ne 0 ] + then + debug "$container - Plugin $check_plugin not found" + continue + fi + debug "$container - Plugin $check_plugin found, use it" + STATUS="$($ENGINE exec $container ${CHECK_PLUGINS[${check_plugin}]} 2>&1)" + ex=$? + debug "$container - Plugin output: $STATUS" + debug "$container - Plugin exit code: $ex" + break + done + if [ -z "$STATUS" ] + then + debug "$container - No check plugin found" + STATUS="UNKNOWN - No check plugin available" + ex=3 + fi + if [ $ex -eq 0 ] + then + UPTODATE+=( ["$container"]=$STATUS ) + else + ERRORS+=( ["$container"]=$STATUS ) + fi + [ $EXIT_CODE -ge $ex ] && continue + [ $ex -gt 3 ] && ex=3 + EXIT_CODE=$ex +done + +if ! is_empty $ONLY_CONTAINERS +then + for container in ${ONLY_CONTAINERS[@]} + do + if ! in_array $container $CHECKED_CONTAINERS + then + debug "$container - Not found" + ERRORS+=( ["$container"]="Not found" ) + EXIT_CODE=3 + fi + done +fi + +debug "Final exit code: $EXIT_CODE" + +case $EXIT_CODE in + 0) + echo "OK - All containers are uptodate" + ;; + 1) + echo "WARNING - some containers need to be updated" + ;; + 2) + echo "CRITICAL - some containers need to be updated" + ;; + *) + echo "UNKNOWN - fail to retrieve status of some containers" + ;; +esac +for container in ${!ERRORS[@]} +do + echo ${container} - ${ERRORS[${container}]} +done + +for container in ${!UPTODATE[@]} +do + echo ${container} - ${UPTODATE[${container}]} +done + +exit $EXIT_CODE