From 1d342f6952b4b20d07d3c94637a9e297e63466d5 Mon Sep 17 00:00:00 2001 From: Jeremy Lecour Date: Thu, 2 May 2024 16:21:13 +0200 Subject: [PATCH] apt: add list-upgradable-held-packages.sh --- CHANGELOG.md | 2 + apt/defaults/main.yml | 3 + apt/files/list-upgradable-held-packages.sh | 124 +++++++++++++++++++++ apt/tasks/hold_packages.yml | 23 +++- 4 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 apt/files/list-upgradable-held-packages.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 854ffa94..a111b6e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ The **patch** part is incremented if multiple releases happen the same month ### Added +* apt: add list-upgradable-held-packages.sh + ### Changed * evobackup-client: upstream release 24.05 diff --git a/apt/defaults/main.yml b/apt/defaults/main.yml index 772a8fb9..95ca8883 100644 --- a/apt/defaults/main.yml +++ b/apt/defaults/main.yml @@ -29,4 +29,7 @@ apt_check_hold_cron_weekday: "*" apt_check_hold_cron_day: "*" apt_check_hold_cron_month: "*" +apt_list_upgradable_held_enabled: False +apt_list_upgradable_held_special_time: "weekly" + apt_keyring_dir: "{{ ansible_distribution_major_version is version('12', '<') | ternary('/etc/apt/trusted.gpg.d', '/etc/apt/keyrings') }}" diff --git a/apt/files/list-upgradable-held-packages.sh b/apt/files/list-upgradable-held-packages.sh new file mode 100644 index 00000000..608fbf1e --- /dev/null +++ b/apt/files/list-upgradable-held-packages.sh @@ -0,0 +1,124 @@ +#!/bin/bash + +##### +# This script will send an email if some packages are on hold +# but have available updates. +##### + +# set all programs to C language (english) +export LC_ALL=C + +# If expansion is attempted on an unset variable or parameter, the shell prints an +# error message, and, if not interactive, exits with a non-zero status. +set -o nounset +# The pipeline's return status is the value of the last (rightmost) command +# to exit with a non-zero status, or zero if all commands exit successfully. +set -o pipefail +# Enable trace mode if called with environment variable TRACE=1 +if [[ "${TRACE-0}" == "1" ]]; then + set -o xtrace +fi + +# shellcheck disable=SC2155 +readonly PROGPATH=$(readlink -m "${0}") +# readonly PROGNAME=$(basename "${PROGPATH}") +# # shellcheck disable=SC2124 +# readonly ARGS=$@ + +# Fetch values from evomaintenance configuration +get_evomaintenance_mail() { + grep "EVOMAINTMAIL=" /etc/evomaintenance.cf | cut -d '=' -f2 +} +get_fqdn() { + hostname --fqdn +} +get_complete_hostname() { + REAL_HOSTNAME="$(get_fqdn)" + if [ "${HOSTNAME}" = "${REAL_HOSTNAME}" ]; then + echo "${HOSTNAME}" + else + echo "${HOSTNAME} (${REAL_HOSTNAME})" + fi +} + +format_mail() { + cat < +Content-Type: text/plain; charset=UTF-8 +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +X-Script: ${PROGPATH} +To: ${EMAIL_CLIENT:-alert5@evolix.fr} +Subject: Mise a jour manuelle disponible + +Bonjour, + +Un ou plusieurs paquets dont la mise à jour automatique a été +explicitement bloquée ont une nouvelle version disponible. + +Nom du serveur : +${HOSTNAME_TEXT} + +Liste des paquets : +${upgradable_held_packages} + +Pour que nous appliquions ces mises à jour vous devez +nous contacter explicitement, de préférence par ticket, +en mentionnant le serveur et les paquets concernés, +ainsi que les modalités de mise à jour (créneau horaire, +procédure technique…). + +Cordialement + +-- +Evolix +EOTEMPLATE +} + +main() { + held_packages=$(apt-mark showhold) + upgradable_packages=$(apt list --upgradable 2> /dev/null) + + if [ -z "${held_packages}" ]; then + # No packages are on hold + exit 0 + elif [ -z "${upgradable_packages}" ]; then + # No packages are upgradable + exit 0 + fi + + kept_back_output=$(LC_ALL=C apt-get upgrade --dry-run | grep -A 1 'The following packages have been kept back:') + if [ -z "${kept_back_output}" ]; then + # No packages are kept back + exit 0 + fi + + upgradable_held_packages=$(apt list --upgradable 2> /dev/null | grep -f <(echo "${kept_back_output}" | tail -1 | tr ' ' '\n' | sed -e '/^$/d')) + + if [ -z "${upgradable_held_packages}" ]; then + # No held packages are upgradable + exit 0 + fi + + HOSTNAME="$(get_fqdn)" + HOSTNAME_TEXT="$(get_complete_hostname)" + EMAIL_CLIENT="$(get_evomaintenance_mail)" + EMAIL_FROM="equipe@evolix.fr" + MAIL_CONTENT="$(format_mail)" + + SENDMAIL_BIN="$(command -v sendmail)" + + if [ -z "${SENDMAIL_BIN}" ]; then + >&2 echo "ERROR: No \`sendmail' command has been found, can't send mail." + exit 1 + fi + if [ ! -x "${SENDMAIL_BIN}" ]; then + >&2 echo "ERROR: \`${SENDMAIL_BIN}' is not executable, can't send mail." + exit 1 + fi + + echo "${MAIL_CONTENT}" | "${SENDMAIL_BIN}" -oi -t -f "equipe@evolix.fr" + exit 0 +} + +main diff --git a/apt/tasks/hold_packages.yml b/apt/tasks/hold_packages.yml index e92b7b44..f1848008 100644 --- a/apt/tasks/hold_packages.yml +++ b/apt/tasks/hold_packages.yml @@ -76,7 +76,16 @@ tags: - apt -- name: Check if Cron is installed +- name: List scripts is installed + ansible.builtin.copy: + src: list-upgradable-held-packages.sh + dest: /usr/share/scripts/list-upgradable-held-packages.sh + force: true + mode: "0755" + tags: + - apt + +- name: Check if cron is installed ansible.builtin.shell: cmd: "dpkg --list 'cron' 2>/dev/null | grep -q -E '^(i|h)i'" register: is_cron @@ -101,3 +110,15 @@ tags: - apt when: is_cron.rc == 0 + +- name: List upgradable held packages (script) + ansible.builtin.cron: + cron_file: apt-hold-packages + name: list-upgradable-held-packages + job: "/usr/share/scripts/list-upgradable-held-packages.sh" + user: root + special_time: "{{ apt_list_upgradable_held_special_time | mandatory }}" + state: "{{ apt_list_upgradable_held_enabled | bool | ternary('present', 'absent') }}" + tags: + - apt + when: is_cron.rc == 0