#!/usr/bin/env bash
# Gemeinsame Grundlage der Ausroll-Skripte: Knoten finden und erreichen.
#
# Wird mit "source" eingebunden, nicht aufgerufen.
#
# Warum es das gibt: Die Knotenliste stand in jedem Skript einzeln und fest
# eingetragen (10.0.1.1 und 10.0.1.2). Ein dritter Knoten wäre beim Ausrollen
# STILL übersprungen worden – er liefe weiter mit altem Code, und niemand
# bekäme es mit. Seit dem 25.09.2026 fragt jedes Skript dieselbe Quelle:
# das Hetzner-Label "Webserver". Wer das Label trägt, bekommt die Änderung;
# wer es nicht trägt, hängt auch nicht am Load Balancer.
#
# Angemeldet wird mit dem Schlüssel, nicht mit Passwörtern. Das ist hier
# keine Stilfrage: ein frisch angelegter Knoten hat keine Passwortdatei im
# Zugangsordner, und ihn von Hand nachzutragen wäre genau die Handarbeit,
# die das automatische Aufnehmen abschaffen soll.

RZ_SCHLUESSEL="${RZ_SCHLUESSEL:-/root/.ssh/riccardo-prod}"
RZ_LABEL="${RZ_LABEL:-Webserver}"

RZ_SSHO=(-o BatchMode=yes
         -o PasswordAuthentication=no
         -o PreferredAuthentications=publickey
         -o StrictHostKeyChecking=no
         -o UserKnownHostsFile=/dev/null
         -o LogLevel=ERROR
         -o ConnectTimeout=15)

rz_token() {
    local t="${HCLOUD_TOKEN:-}"
    [ -n "$t" ] || t="$(cat ~/.hetzner-token 2>/dev/null || true)"
    [ -n "$t" ] || { echo "Kein Hetzner-Token (HCLOUD_TOKEN oder ~/.hetzner-token)." >&2; return 1; }
    printf '%s' "$t"
}

# Gibt je Zeile "name interne-ip" aus, nach Adresse sortiert.
#
# Bewusst KEIN Rückfall auf eine eingebaute Liste: eine veraltete Liste ist
# schlimmer als ein Abbruch, weil das Ausrollen dann scheinbar gelingt.
rz_knoten() {
    local token; token="$(rz_token)" || return 1
    local roh
    roh=$(curl -sS --fail-with-body -H "Authorization: Bearer $token" \
          "https://api.hetzner.cloud/v1/servers?label_selector=${RZ_LABEL}&per_page=50" 2>&1) \
        || { echo "Hetzner-API nicht erreichbar: $roh" >&2; return 1; }

    local liste
    liste=$(printf '%s' "$roh" | python3 -c '
import json, sys
d = json.load(sys.stdin)
if "error" in d:
    sys.stderr.write("Hetzner meldet: %s\n" % d["error"].get("message"))
    sys.exit(1)
zeilen = []
for s in d.get("servers", []):
    if s.get("status") != "running":
        sys.stderr.write("  übersprungen: %s ist %s\n" % (s["name"], s.get("status")))
        continue
    for netz in s.get("private_net", []):
        ip = netz.get("ip")
        if ip and ip.startswith("10.0.1."):
            zeilen.append((ip, s["name"]))
zeilen.sort(key=lambda z: [int(t) for t in z[0].split(".")])
for ip, name in zeilen:
    print(name, ip)
') || return 1

    [ -n "$liste" ] || { echo "Kein laufender Knoten mit Label \"$RZ_LABEL\" gefunden." >&2; return 1; }
    printf '%s\n' "$liste"
}

rz_ssh() {
    local ip="$1"; shift
    ssh -n -i "$RZ_SCHLUESSEL" "${RZ_SSHO[@]}" "root@$ip" "$@"
}

# Wie rz_ssh, aber mit offener Standardeingabe – für "bash -s" mit Skript.
rz_ssh_stdin() {
    local ip="$1"; shift
    ssh -i "$RZ_SCHLUESSEL" "${RZ_SSHO[@]}" "root@$ip" "$@"
}

rz_rsh() {
    printf 'ssh -i %s %s' "$RZ_SCHLUESSEL" "${RZ_SSHO[*]}"
}

# Bricht ab, wenn der Schlüssel fehlt – ohne ihn läuft gar nichts.
rz_pruefe_schluessel() {
    [ -r "$RZ_SCHLUESSEL" ] || {
        echo "Schlüssel $RZ_SCHLUESSEL nicht lesbar. Siehe dev/deploy/UMZUG.md, Abschnitt Zugangsdaten." >&2
        return 1
    }
}
