sonde genome-a-jour : la forge du site porte-t-elle ce que le poste a publie ?
Filet sous make publier : compare la forge du site a eregion (repere seulement, depots lisibles sans identifiant), tolere l ecart d une publication en cours. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
91dc90f22b
commit
5c638675cb
4 changed files with 105 additions and 0 deletions
|
|
@ -77,3 +77,14 @@ serveur_ops_site_conformite_horaire: "hourly"
|
||||||
# Au-dela, le constat est PERIME et la sonde passe au rouge : un minuteur mort ne doit pas
|
# Au-dela, le constat est PERIME et la sonde passe au rouge : un minuteur mort ne doit pas
|
||||||
# laisser la derniere bonne nouvelle au vert.
|
# laisser la derniere bonne nouvelle au vert.
|
||||||
serveur_ops_site_conformite_age_max_h: 3
|
serveur_ops_site_conformite_age_max_h: 3
|
||||||
|
|
||||||
|
# LE FILET DU GENOME (2026-09-28) — voir `templates/sonde-genome-a-jour.sh.j2`.
|
||||||
|
# Les depots qu'eregion laisse lire SANS IDENTIFIANT, et leur adresse. Les depots prives n'y
|
||||||
|
# sont pas : donner au site un jeton sur une forge heritee l'y lierait. La sonde les NOMME
|
||||||
|
# comme non compares.
|
||||||
|
serveur_ops_site_genome_repere:
|
||||||
|
set-ops-public: "https://forge.alliance-boreale.ca/Alliance-Boreale/Set-OPS-Public.git"
|
||||||
|
# `make publier` pousse eregion une minute avant la forge du site : un ecart plus jeune que
|
||||||
|
# ceci n'est pas un retard.
|
||||||
|
serveur_ops_site_genome_tolerance_min: 60
|
||||||
|
serveur_ops_site_genome_etat: "/var/lib/setops/genome-ecarts.json"
|
||||||
|
|
|
||||||
|
|
@ -40,3 +40,9 @@ sondes:
|
||||||
Le pare-feu Proxmox, le SDN, la frontiere et les acces WireGuard disent-ils encore ce
|
Le pare-feu Proxmox, le SDN, la frontiere et les acces WireGuard disent-ils encore ce
|
||||||
que le plan dit ? Le 2026-09-28, aucune VM des locataires n'avait son pare-feu actif
|
que le plan dit ? Le 2026-09-28, aucune VM des locataires n'avait son pare-feu actif
|
||||||
et rien ne le signalait ; les plans existaient, personne ne les jouait sans raison.
|
et rien ne le signalait ; les plans existaient, personne ne les jouait sans raison.
|
||||||
|
- nom: genome-a-jour
|
||||||
|
ttl: 5400
|
||||||
|
raison: >-
|
||||||
|
La forge du site porte-t-elle ce que le poste a publie ? Elle fait autorite, mais un
|
||||||
|
`git push` seul, ou un runner injoignable au moment de publier, la laisse en retard
|
||||||
|
sans rien dire — le 2026-08-26, quatre commits dont un correctif du pare-feu.
|
||||||
|
|
|
||||||
|
|
@ -196,3 +196,12 @@
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
mode: "0750"
|
mode: "0750"
|
||||||
|
|
||||||
|
# LE FILET DU GENOME (2026-09-28) : la forge du site porte-t-elle ce qu'eregion porte ?
|
||||||
|
- name: Deposer la sonde « genome-a-jour »
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: sonde-genome-a-jour.sh.j2
|
||||||
|
dest: /usr/local/lib/setops/sondes/genome-a-jour.sh
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0750"
|
||||||
|
|
|
||||||
79
roles/serveur_ops_site/templates/sonde-genome-a-jour.sh.j2
Normal file
79
roles/serveur_ops_site/templates/sonde-genome-a-jour.sh.j2
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# GENERE par Set-OPS (role serveur_ops_site). Ne pas editer a la main.
|
||||||
|
#
|
||||||
|
# SONDE « genome-a-jour » — la forge du site porte-t-elle ce que le poste a publie ?
|
||||||
|
#
|
||||||
|
# Contrat : docs/supervision-conception.md — une ligne, 0/1/3.
|
||||||
|
#
|
||||||
|
# POURQUOI UN FILET (2026-09-28). La forge du site fait autorite (D-81) ; les commits naissent
|
||||||
|
# sur le poste. `make publier` pousse sur eregion PUIS sur la forge du site — mais un
|
||||||
|
# `git push` fait a la main, ou un runner injoignable au moment de publier, la laisse en
|
||||||
|
# retard sans rien dire. Le 2026-08-26 : quatre commits, dont un correctif du pare-feu.
|
||||||
|
#
|
||||||
|
# LE REPERE EST EREGION, OU CHAQUE COMMIT ARRIVE EN PREMIER — comme repere seulement : eregion
|
||||||
|
# reste hors du chemin du genome. On ne compare que les depots qu'eregion laisse LIRE SANS
|
||||||
|
# IDENTIFIANT (`serveur_ops_site_genome_repere`) : donner au site un jeton pour les depots
|
||||||
|
# prives le lierait a une forge heritee. Les autres sont NOMMES comme non compares.
|
||||||
|
#
|
||||||
|
# UN ECART NEUF N'EST PAS UN RETARD : `make publier` pousse eregion une minute avant la forge
|
||||||
|
# du site. On retient depuis quand chaque ecart dure, et on ne parle qu'au-dela de
|
||||||
|
# `serveur_ops_site_genome_tolerance_min`.
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
python3 - <<'EOF'
|
||||||
|
import json, subprocess, time, os
|
||||||
|
FORGE = "https://forge.{{ domaine_interne }}/{{ serveur_ops_forge_organisation | default('genome') }}"
|
||||||
|
DEPOTS = {{ serveur_ops_depots | default([]) | to_json }}
|
||||||
|
REPERE = {{ serveur_ops_site_genome_repere | to_json }}
|
||||||
|
TOLERANCE = {{ serveur_ops_site_genome_tolerance_min }} * 60
|
||||||
|
ETAT = "{{ serveur_ops_site_genome_etat }}"
|
||||||
|
|
||||||
|
def tete(url, branche):
|
||||||
|
r = subprocess.run(["git", "ls-remote", url, f"refs/heads/{branche}"], capture_output=True,
|
||||||
|
text=True, timeout=8, env=dict(os.environ, GIT_TERMINAL_PROMPT="0"))
|
||||||
|
return r.stdout.split()[0] if r.returncode == 0 and r.stdout.strip() else None
|
||||||
|
|
||||||
|
try:
|
||||||
|
vus = json.load(open(ETAT))
|
||||||
|
except (OSError, ValueError):
|
||||||
|
vus = {}
|
||||||
|
maintenant = time.time()
|
||||||
|
en_retard, illisibles, a_jour, non_compares, neufs = [], [], [], [], []
|
||||||
|
for d in DEPOTS:
|
||||||
|
nom, branche = d["depot"], d.get("branche", "main")
|
||||||
|
if nom not in REPERE:
|
||||||
|
non_compares.append(nom)
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
site, ref = tete(f"{FORGE}/{nom}.git", branche), tete(REPERE[nom], branche)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
site = ref = None
|
||||||
|
if not site or not ref:
|
||||||
|
illisibles.append(nom + (" (forge du site)" if not site else " (repere)"))
|
||||||
|
continue
|
||||||
|
if site == ref:
|
||||||
|
a_jour.append(nom)
|
||||||
|
vus.pop(nom, None)
|
||||||
|
continue
|
||||||
|
depuis = vus.setdefault(nom, {"depuis": maintenant, "site": site, "repere": ref})["depuis"]
|
||||||
|
minutes = int((maintenant - depuis) / 60)
|
||||||
|
(en_retard if maintenant - depuis > TOLERANCE else neufs).append(
|
||||||
|
f"{nom} (forge {site[:7]}, repere {ref[:7]}, depuis {minutes} min)")
|
||||||
|
|
||||||
|
with open(ETAT + ".tmp", "w") as f:
|
||||||
|
json.dump(vus, f)
|
||||||
|
os.replace(ETAT + ".tmp", ETAT)
|
||||||
|
|
||||||
|
nc = f" Non compares (prives sur le repere) : {', '.join(non_compares)}." if non_compares else ""
|
||||||
|
perf = f"| a_jour={len(a_jour)} en_retard={len(en_retard)} non_compares={len(non_compares)}"
|
||||||
|
if en_retard:
|
||||||
|
print(f"FORGE DU SITE EN RETARD : {'; '.join(en_retard)}. `make publier`.{nc} {perf}")
|
||||||
|
raise SystemExit(1)
|
||||||
|
if illisibles and not a_jour:
|
||||||
|
print(f"Rien de comparable : {', '.join(illisibles)} illisible(s).{nc} {perf}")
|
||||||
|
raise SystemExit(3)
|
||||||
|
suite = f" Ecart recent, dans la tolerance : {'; '.join(neufs)}." if neufs else ""
|
||||||
|
ill = f" Illisible(s) : {', '.join(illisibles)}." if illisibles else ""
|
||||||
|
print(f"Forge du site a jour : {', '.join(a_jour) or 'aucun depot compare'}.{suite}{ill}{nc} {perf}")
|
||||||
|
raise SystemExit(0)
|
||||||
|
EOF
|
||||||
Loading…
Reference in a new issue