Set-OPS-Public/roles/serveur_grafana/templates/sonde-tableaux.sh.j2
Daniel Allaire b938897e17 sonde tableaux : la sante de chaque source de donnees de Grafana
Elle etait verte pendant que les tableaux etaient vides. Eprouvee avec une
source recreant le defaut du jour, puis retiree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 17:51:53 -04:00

63 lines
3.1 KiB
Django/Jinja

#!/bin/bash
# GENERE par Set-OPS (role serveur_grafana). Ne pas editer a la main.
#
# SONDE « tableaux » — Grafana repond, sa base tient, et ses SOURCES DE DONNEES aussi.
#
# Contrat : docs/supervision-conception.md (API des greffons Nagios) — une ligne, 0/1/2.
# Mise en defaut PAR PARAMETRE : `serveur_grafana_sonde_url` (port ferme).
#
# LES SOURCES, DEPUIS LE 2026-09-28. Cette sonde etait verte pendant que les tableaux des
# locataires n'affichaient RIEN : Grafana repondait, sa base tenait — mais sa source Loki
# parlait en clair a un Loki qui servait en HTTPS. Les tableaux tirent leur liste d'hotes de
# Loki : vide, aucun panneau ne se remplissait. « Grafana repond » n'etait pas la question ;
# « Grafana peut-il montrer quelque chose » l'est.
#
# LE MOT DE PASSE EST LU LA OU IL EST, pas recopie : dans le drop-in systemd de Grafana,
# en 0600 root. La sonde tourne en root ; rien d'autre ne le voit, et il n'est pas affiche.
set -uo pipefail
URL={{ serveur_grafana_sonde_url }}
DROPIN=/etc/systemd/system/grafana-server.service.d/setops.conf
s=$(curl -s --max-time 10 "${URL}/api/health" 2>/dev/null)
[[ -n "${s}" ]] || { echo "Grafana ne repond pas sur ${URL}."; exit 2; }
base=$(printf '%s' "${s}" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("database","?"))' 2>/dev/null)
ver=$(printf '%s' "${s}" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("version","?"))' 2>/dev/null)
[[ "${base}" == "ok" ]] || { echo "Grafana repond mais sa base est en defaut (${base:-illisible})."; exit 2; }
MDP=$(grep -hoP 'GF_SECURITY_ADMIN_PASSWORD=\K\S+' "${DROPIN}" 2>/dev/null | head -1)
if [[ -z "${MDP}" ]]; then
echo "Grafana ${ver} : base ok, mais sources NON verifiees (mot de passe illisible dans ${DROPIN})."
exit 1
fi
GRAFANA_MDP="${MDP}" python3 - "${URL}" "${ver}" <<'EOF'
import base64, json, os, sys, urllib.request
url, ver = sys.argv[1], sys.argv[2]
auth = "Basic " + base64.b64encode(f"admin:{os.environ['GRAFANA_MDP']}".encode()).decode()
def lire(chemin):
req = urllib.request.Request(url + chemin, headers={"Authorization": auth})
try:
with urllib.request.urlopen(req, timeout=8) as r:
return json.loads(r.read())
except urllib.error.HTTPError as e:
try:
return json.loads(e.read())
except ValueError:
return {"status": "ERROR", "message": f"HTTP {e.code}"}
except OSError as e:
return {"status": "ERROR", "message": str(e)[:80]}
sources = lire("/api/datasources")
if not isinstance(sources, list):
print(f"Grafana {ver} : base ok, mais la liste des sources est illisible ({str(sources)[:80]}).")
sys.exit(1)
ko, ok = [], []
for d in sources:
h = lire(f"/api/datasources/uid/{d['uid']}/health")
(ok if h.get("status") == "OK" else ko).append(f"{d['name']} ({str(h.get('message'))[:70]})" if h.get("status") != "OK" else d["name"])
perf = f"| sources_ok={len(ok)} sources_ko={len(ko)}"
if ko:
print(f"Grafana {ver} repond, mais source(s) EN DEFAUT : {'; '.join(ko)} — les tableaux restent vides. {perf}")
sys.exit(2)
print(f"Grafana {ver} : base ok, sources saines ({', '.join(ok) or 'aucune'}). {perf}")
EOF