#!/usr/bin/env bash
# Hält die Varnish-Löschliste aller Frontends auf dem aktuellen Stand.
#
#   varnish-knoten.sh pruefen <zugangsordner>    # nur vergleichen, ändert nichts
#   varnish-knoten.sh setzen  <zugangsordner>    # Liste auf allen Knoten schreiben
#
# Hintergrund: Shopware schickt Löschaufträge an eine Liste von Varnish-Knoten
# (config/packages/varnish.yaml). Steht ein Knoten nicht darin, liefert er nach
# jeder Änderung veraltete Seiten aus – ohne Fehlermeldung. Der Shop läuft, ein
# Teil der Besucher sieht alte Preise.
#
# Die Liste wird aus dem Hetzner-Label "Webserver" abgeleitet – derselben
# Quelle, aus der auch Firewall und Load Balancer ihre Knoten ziehen.
#
# Warum eine erzeugte Datei und keine Umgebungsvariable: Symfony lässt für
# diesen Knoten keinen dynamischen Wert zu ("A dynamic value is not compatible
# with a PrototypedArrayNode"). Am 23.09.2026 ausprobiert und verworfen.
#
# Warum die YAML in Python entsteht und nicht in der Shell: der erste Versuch
# baute sie per $(printf …) zusammen. Die Befehlssubstitution schluckt den
# letzten Zeilenumbruch, dadurch landete der nächste Schlüssel hinter dem
# letzten Listeneintrag – kaputte YAML, und Shopware startet auf dem Knoten
# nicht mehr. Deshalb außerdem: erst sichern, dann schreiben, und bei einem
# Fehler automatisch zurück.
set -uo pipefail

BEFEHL="${1:-pruefen}"
# Der Zugangsordner wird nicht mehr gebraucht; ein zweites Argument wird der
# alten Aufrufform zuliebe stillschweigend geschluckt.
ACCESS="${2:-}"
ZIEL=/var/www/riccardo/config/packages/varnish.yaml

source "$(dirname "$0")/lib-knoten.sh"
rz_pruefe_schluessel || exit 1

# Wrapper in der Form, die dieses Skript nutzt: erstes Argument ist root@ip.
rz_ssh_roh() { ssh -n -i "$RZ_SCHLUESSEL" "${RZ_SSHO[@]}" "$@"; }

mapfile -t KNOTEN < <(rz_knoten | awk '{print $2}') || exit 1
echo "Knoten laut Label: ${KNOTEN[*]}"

ENTWURF=$(mktemp)
trap 'rm -f "$ENTWURF"' EXIT
python3 - "$ENTWURF" "${KNOTEN[@]}" <<'PY'
import sys, datetime
ziel, knoten = sys.argv[1], sys.argv[2:]
zeilen = "\n".join(f'        - "http://{k}"' for k in knoten)
open(ziel, "w").write(f"""# Shopware gibt den Seiten-Cache an Varnish ab und schickt gezielte
# Loeschauftraege an ALLE Frontends - sonst haette ein Knoten nach einer
# Aenderung noch den alten Stand.
#
# ERZEUGT von dev/deploy/varnish-knoten.sh aus dem Hetzner-Label "Webserver".
# Nicht von Hand aendern: beim naechsten Lauf wird die Datei ueberschrieben.
# Stand: {datetime.datetime.now():%Y-%m-%d %H:%M}
shopware:
  http_cache:
    reverse_proxy:
      enabled: true
      use_varnish_xkey: true
      hosts:
{zeilen}
      max_parallel_invalidations: 3
      purge_all:
        ban_method: "BAN"
        urls:
          - "/"
""")
PY
python3 -c 'import sys,yaml; yaml.safe_load(open(sys.argv[1]))' "$ENTWURF" 2>/dev/null \
    || { echo "Der Entwurf ist keine gueltige YAML - abgebrochen, nichts angefasst."; exit 1; }

fehler=0
for ip in "${KNOTEN[@]}"; do
    kurz="fe${ip##*.}"
    

    IST=$(rz_ssh_roh "root@$ip" \
        "grep -oP '\"http://\K[0-9.]+' $ZIEL 2>/dev/null | sort -V | tr '\n' ' '")
    SOLL="$(printf '%s ' "${KNOTEN[@]}")"

    if [ "$IST" = "$SOLL" ]; then
        echo "  $ip: Liste stimmt ($IST)"
        continue
    fi

    echo "  $ip: ABWEICHUNG – ist: ${IST:-leer} | soll: $SOLL"
    fehler=1
    [ "$BEFEHL" = "setzen" ] || continue

    SICHERUNG="/tmp/varnish.yaml.vor-$(date +%Y%m%d-%H%M%S)"
    rz_ssh_roh "root@$ip" "cp $ZIEL $SICHERUNG 2>/dev/null || true"
    ssh -i "$RZ_SCHLUESSEL" "${RZ_SSHO[@]}" \
        -o LogLevel=ERROR "root@$ip" "cat > $ZIEL && chown www-data:www-data $ZIEL" < "$ENTWURF"

    if rz_ssh_roh "root@$ip" \
        "cd /var/www/riccardo && sudo -u www-data /usr/bin/php8.5 bin/console cache:clear -q >/dev/null 2>&1"
    then
        rz_ssh_roh "root@$ip" "systemctl reload php8.5-fpm"
        echo "    -> geschrieben, Cache geleert"
    else
        echo "    -> cache:clear fehlgeschlagen, Sicherung wird zurueckgespielt"
        rz_ssh_roh "root@$ip" \
            "cp $SICHERUNG $ZIEL && cd /var/www/riccardo && sudo -u www-data /usr/bin/php8.5 bin/console cache:clear -q; systemctl reload php8.5-fpm"
        echo "    -> alter Stand wiederhergestellt"
        exit 1
    fi
done

if [ "$BEFEHL" = "setzen" ]; then
    echo "Gegenprobe (was Shopware auf jedem Knoten wirklich sieht):"
    for ip in "${KNOTEN[@]}"; do
        kurz="fe${ip##*.}"
        
        GESEHEN=$(rz_ssh_roh "root@$ip" \
            "cd /var/www/riccardo && sudo -u www-data /usr/bin/php8.5 bin/console debug:config shopware http_cache 2>/dev/null | grep -oP 'http://[0-9.]+' | tr '\n' ' '")
        STATUS=$(rz_ssh_roh "root@$ip" \
            "curl -s -o /dev/null -w '%{http_code}' -H 'Host: shop.riccardo-zigarette.de' http://127.0.0.1/")
        echo "  $ip sieht: ${GESEHEN:-nichts} | Shop antwortet: $STATUS"
    done
    exit 0
fi

exit $fehler
