Set-OPS-Public/roles/serveur_web_dorsal/templates/sonde-apps-servies.sh.j2
Daniel Allaire aac74f6043 supervision : les huit derniers roles, et deux defauts que l epreuve a trouves
Les 33 roles serveur_* declarent maintenant une sonde. Les huit qui manquaient
sont ceux dont la verite ne ressemble pas a « ce service repond-il ».

Quatre marqueurs du site : ce que tasks/main.yml verifie UNE FOIS au deploiement
cesse d etre vrai sans que rien ne tombe. La racine du cache se retrouve chainee,
la forge du genome repond en n ayant plus rien dedans, un locataire n est plus
admis a resoudre, l isolation d un depot glisse.

serveur_ops_site ne sert rien : il detient un pouvoir. La sonde verifie que la
carte est la, que la voute du site est chiffree et que sa cle est en 0600 — sans
lire le contenu d aucun des trois.

serveur_icingaweb2 surveille la vitrine de la supervision elle-meme : si la
console meurt, tout reste vert et l exploitant est aveugle.

DEFAUT 1 — quatre gabarits qu Ansible aurait refuse de rendre. Jinja lit le
{# de ${#tableau[@]} comme un debut de commentaire. Le depot connaissait le
remede et l appliquait la ou quelqu un s etait fait prendre, nulle part ailleurs.
P76 rend desormais chaque gabarit de role, avec les delimiteurs qu Ansible en
tirerait — pas une recherche de motif.

DEFAUT 2 — la doctrine promettait 54 greffons et citait check_pgsql. La flotte a
monitoring-plugins-basic : 53, sans check_pgsql ni check_dns ni check_ldap. Le
paquet qui les porte traine samba et snmp sur chaque machine. Un greffon absent
sort en 127, qui n est pas un code Nagios.

21 controles negatifs sur les machines reelles du site. ansible-lint production
0/91, harnais 75 OK.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-14 15:43:52 -04:00

68 lines
3 KiB
Django/Jinja

#jinja2: comment_start_string:'{=#', comment_end_string:'#=}'
#!/bin/bash
# (Le gabarit redefinit le delimiteur de commentaire Jinja : `${#tableau[@]}` contient
# la sequence `{#`, que Jinja lirait comme un debut de commentaire. Le shell en a
# besoin ; c'est donc Jinja qui cede. Meme geste que `client_sante/setops-sante.sh.j2`
# et `serveur_nginx/sonde-edge.sh.j2`.)
# GENERE par Set-OPS (role serveur_web_dorsal). Ne pas editer a la main.
#
# SONDE « apps-servies » — chacune des webapps declarees repond-elle encore ?
#
# UNE BOUCLE AUTOUR D'UN GREFFON. Chaque app est mesuree par `check_http` ; ce que la
# boucle ajoute est la LISTE des apps que cet hebergeur doit servir, qui vient du plan.
#
# DEUX LECTURES PAR APP, ET ELLES NE DISENT PAS LA MEME CHOSE :
# - l'unite systemd est-elle active ? -> l'app a-t-elle ete lancee
# - son port repond-il ? -> l'app fait-elle encore son travail
# La seconde est celle qui compte, et c'est justement celle qu'aucun rapport d'unites en
# echec ne fera jamais. La premiere reste utile pour NOMMER la cause : « pas demarree »
# et « demarree mais coincee » n'appellent pas le meme geste.
set -uo pipefail
noms=({% for a in serveur_web_dorsal_apps | default([]) %}'{{ a.nom }}' {% endfor %})
ports=({% for a in serveur_web_dorsal_apps | default([]) %}'{{ a.port }}' {% endfor %})
if (( ${#noms[@]} == 0 )); then
# PAS UN VERT MUET : un hebergeur sans app declaree est un etat legitime, et le dire
# vaut mieux qu'un succes qui laisserait croire qu'on a verifie quelque chose.
echo "Aucune webapp declaree sur cet hebergeur : rien a servir, rien a verifier."
exit 0
fi
fautives=()
for i in "${!noms[@]}"; do
nom=${noms[$i]}
port=${ports[$i]}
etat=$(systemctl is-active "${nom}.service" 2>/dev/null || true)
if [[ "${etat}" != "active" ]]; then
fautives+=("${nom} : unite ${etat:-introuvable}")
continue
fi
# LE CODE ATTENDU N'EST PAS 200. Une webapp peut parfaitement rendre 302 (redirection
# vers une page de connexion), 401 ou 403 a la racine sans etre en panne. Ce qu'on
# exclut, ce sont les 5xx et l'absence de reponse — c'est-a-dire l'app coincee ou morte.
sortie=$(/usr/lib/nagios/plugins/check_http -H 127.0.0.1 -p "${port}" -u / \
-e '{{ serveur_web_dorsal_sonde_codes }}' -t 10 2>&1)
code=$?
# LE GREFFON REND PARFOIS DEUX LIGNES — la cause, puis son verdict. Icinga ne
# garde que la premiere pour resume : sans repliage, la moitie du message
# disparait de la vue qu'on regarde en premier.
resume=${sortie%%|*}
resume=${resume//$'\n'/ }
if (( code != 0 )); then
# LE MESSAGE DU GREFFON EST CONSERVE : c'est lui qui distingue « socket ferme » de
# « delai depasse » — l'app morte de l'app coincee, et le geste n'est pas le meme.
fautives+=("${nom} : active mais ${resume}")
fi
done
if (( ${#fautives[@]} > 0 )); then
liste=$(printf '%s; ' "${fautives[@]}"); liste=${liste%; }
echo "Webapp(s) qui ne repondent plus — ${liste}"
exit 2
fi
echo "Webapps : ${#noms[@]} servie(s) — ${noms[*]}."
exit 0