spb/ka-guardian
Public
1#!/bin/zsh2# ============================================3# KA Guardian — synchronisation du registre mld + sonde des runners (100 % zsh)4# Le registre des déploiements (M1M32:~/dispatch/registry.json) dit où tourne5# chaque app du Groupe Ka. mld le POUSSE déjà dans le spool à chaque sauvegarde ;6# ce service le TIRE en plus toutes les 2 min (ceinture et bretelles), puis7# sonde le runner :7791 de chaque nœud hébergeur pour que les orchestrateurs8# sachent, AVANT de dépêcher une mission, si le nœud est équipé.9# Chaîne launchd → zsh → /usr/bin/ssh : macOS 26 « Local Network Privacy »10# refuse le LAN aux descendants de python (homebrew) — jamais de python ici.11# ~/ka-guardian-spool/registry.json ← copie du registre (écriture atomique)12# ~/ka-guardian-spool/runners.json ← {"<ip>": {"ok":bool,"node":…,"busy":…,"ts":epoch}}13# ============================================14export PATH=/usr/bin:/bin:/usr/sbin:/sbin15SPOOL=$HOME/ka-guardian-spool16KEY=$HOME/.ssh/ka_guardian_ed2551917LOG=$SPOOL/registry-sync.log18INTERVAL=${KA_REGISTRY_INTERVAL:-120}19mkdir -p $SPOOL2021log() { print "$(date '+%F %T') $*" >> $LOG; }2223# JSON minimal sans python : extraire les IP uniques des apps du registre.24registry_ips() {25 # les entrées ont la forme "ip": "192.168.2.83"26 grep -o '"ip": *"[0-9.]*"' $SPOOL/registry.json 2>/dev/null | grep -o '[0-9.]*[0-9]' | sort -u27}2829while true; do30 # 1. tirer le registre (alias gitsrv = passerelle M1M32, clé ka_guardian autorisée)31 if /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=8 gitsrv 'cat ~/dispatch/registry.json' > $SPOOL/registry.json.pull 2>>$LOG \32 && grep -q '"apps"' $SPOOL/registry.json.pull; then33 if ! cmp -s $SPOOL/registry.json.pull $SPOOL/registry.json; then34 mv -f $SPOOL/registry.json.pull $SPOOL/registry.json35 log "registre mis à jour ($(grep -o '"updated": *"[^"]*"' $SPOOL/registry.json | head -1))"36 else37 rm -f $SPOOL/registry.json.pull38 fi39 else40 rm -f $SPOOL/registry.json.pull41 log "tirage du registre impossible (gitsrv injoignable) — copie précédente conservée"42 fi4344 # 2. sonder les runners des nœuds hébergeurs45 out="{"46 first=147 for ip in $(registry_ips); do48 resp=$(/usr/bin/ssh -i $KEY -o BatchMode=yes -o ConnectTimeout=6 -o StrictHostKeyChecking=accept-new \49 -o ControlMaster=auto -o ControlPath=/tmp/kg-cm-%h -o ControlPersist=120 \50 simon-pierreboucher@$ip "/usr/bin/curl -s -m 4 http://127.0.0.1:7791/health" 2>/dev/null)51 ts=$(date +%s)52 if [[ $resp == *'"ok":true'* ]]; then53 node=$(print -r -- $resp | grep -o '"node":"[^"]*"' | cut -d'"' -f4)54 busy=$([[ $resp == *'"busy":true'* ]] && echo true || echo false)55 row="\"$ip\":{\"ok\":true,\"node\":\"$node\",\"busy\":$busy,\"ts\":$ts}"56 else57 row="\"$ip\":{\"ok\":false,\"node\":null,\"busy\":false,\"ts\":$ts}"58 fi59 [[ $first -eq 1 ]] && first=0 || out+=","60 out+=$row61 done62 out+="}"63 print -r -- $out > $SPOOL/runners.json.tmp && mv -f $SPOOL/runners.json.tmp $SPOOL/runners.json6465 sleep $INTERVAL66done67