#!/usr/bin/env bash
# Legt die zweite Redis-Maschine an und macht sie zur Replik von REDIS-SRV-1.
#
#   redis-replik-anlegen.sh pruefen            # zeigt nur, was waere
#   redis-replik-anlegen.sh anlegen [--ja]     # legt an und richtet ein
#
# Warum ein frischer Server und kein Abbild der laufenden Maschine (anders als
# bei frontend-aufnehmen.sh): auf einem Frontend steckt der ganze Shop, den
# will man genau so kopiert haben. Redis dagegen ist eine Zeile apt-get und
# eine Konfigurationsdatei - und die wird hier WOERTLICH vom laufenden Master
# uebernommen, samt ACL-Benutzern und Passwoertern. Dafuer muss der Master
# nicht angefasst werden, und es kommt kein zweites Datenverzeichnis mit,
# das man hinterher wegwerfen muesste.
#
# Die Maschine bekommt bewusst KEINE oeffentliche Adresse. Sie ist nur im
# internen Netz erreichbar, genau wie REDIS-SRV-1.
set -uo pipefail

BEFEHL="${1:-pruefen}"
JA="${2:-}"

NAME=REDIS-SRV-2
IP=10.0.2.2
MASTER_IP=10.0.2.1
TYP=cpx22
ABBILD=ubuntu-24.04
STANDORT=nbg1
NETZ=11975902
PLATZGRUPPE=1473568          # "REDIS Server", Typ spread - anderer Wirt
SCHLUESSEL=riccardo-deploy

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

hcloud_get()  { curl -s -H "Authorization: Bearer $T" "https://api.hetzner.cloud/v1/$1"; }
hcloud_post() { curl -s -X POST -H "Authorization: Bearer $T" -H 'Content-Type: application/json' -d "$2" "https://api.hetzner.cloud/v1/$1"; }

echo "== Lage =="
VORHANDEN=$(hcloud_get "servers?name=$NAME" | python3 -c 'import json,sys; s=json.load(sys.stdin)["servers"]; print(s[0]["id"] if s else "")')
if [ -n "$VORHANDEN" ]; then
    echo "   $NAME gibt es schon (id $VORHANDEN) - es wird nichts neu angelegt."
else
    echo "   $NAME gibt es noch nicht."
fi
echo "   Master $MASTER_IP:"
rz_ssh "$MASTER_IP" "redis-server --version | cut -d' ' -f1-3 | sed 's/^/     /'" 2>/dev/null

if [ "$BEFEHL" != anlegen ]; then
    echo
    echo "Nur geprueft. Zum Anlegen: $0 anlegen --ja"
    exit 0
fi
[ "$JA" = "--ja" ] || { echo "Das legt einen kostenpflichtigen Server an. Mit --ja bestaetigen."; exit 1; }

# ------------------------------------------------------------------ anlegen
if [ -z "$VORHANDEN" ]; then
    echo "== Server anlegen =="
    ANTWORT=$(hcloud_post servers "$(python3 -c "
import json
print(json.dumps({
    'name': '$NAME', 'server_type': '$TYP', 'image': '$ABBILD', 'location': '$STANDORT',
    'placement_group': $PLATZGRUPPE,
    'ssh_keys': ['$SCHLUESSEL'],
    'labels': {'Redis': '', 'Riccardo-Onlineshop': ''},
    'public_net': {'enable_ipv4': False, 'enable_ipv6': False},
    'networks': [$NETZ],
    'start_after_create': True,
}))")")
    NEU=$(printf '%s' "$ANTWORT" | python3 -c 'import json,sys; a=json.load(sys.stdin); print(a["server"]["id"] if a.get("server") else "FEHLER " + json.dumps(a.get("error", a)))')
    case "$NEU" in FEHLER*) echo "   $NEU"; exit 1;; esac
    echo "   angelegt, id $NEU"

    # Hetzner vergibt im Netz eine freie Adresse - wir wollen aber genau die
    # 10.0.2.2, damit die Konfiguration vorhersagbar bleibt.
    IST=$(hcloud_get "servers/$NEU" | python3 -c 'import json,sys; n=json.load(sys.stdin)["server"]["private_net"]; print(n[0]["ip"] if n else "")')
    if [ "$IST" != "$IP" ]; then
        echo "   Adresse ist $IST, gewuenscht $IP - wird umgehaengt"
        hcloud_post "servers/$NEU/actions/detach_from_network" "{\"network\": $NETZ}" > /dev/null
        sleep 5
        hcloud_post "servers/$NEU/actions/attach_to_network" "{\"network\": $NETZ, \"ip\": \"$IP\"}" > /dev/null
        sleep 5
        hcloud_post "servers/$NEU/actions/reboot" '{}' > /dev/null
    fi
else
    NEU="$VORHANDEN"
fi

echo "== Warten, bis die Maschine antwortet =="
for i in $(seq 1 60); do
    rz_ssh "$IP" "true" 2>/dev/null && { echo "   erreichbar nach ${i}0 s"; break; }
    sleep 10
    [ "$i" = 60 ] && { echo "   kommt nicht hoch - abgebrochen"; exit 1; }
done

echo "== Redis einrichten =="
rz_ssh "$IP" "
    export DEBIAN_FRONTEND=noninteractive
    apt-get update -qq
    apt-get install -y -qq redis-server >/dev/null
    redis-server --version | cut -d' ' -f1-3 | sed 's/^/   /'
"

echo "== Konfiguration vom Master uebernehmen =="
# Woertlich, damit ACL-Benutzer, Passwoerter, maxmemory und Verdraengung
# uebereinstimmen. Danach nur die drei Zeilen, die maschinenspezifisch sind.
rz_ssh "$MASTER_IP" "cat /etc/redis/redis.conf" \
  | rz_ssh_stdin "$IP" "cat > /etc/redis/redis.conf.neu"
rz_ssh "$IP" "
    set -e
    cp /etc/redis/redis.conf /etc/redis/redis.conf.ubuntu-vorgabe
    mv /etc/redis/redis.conf.neu /etc/redis/redis.conf
    chown redis:redis /etc/redis/redis.conf; chmod 640 /etc/redis/redis.conf
    sed -i 's/^bind .*/bind 127.0.0.1 $IP/' /etc/redis/redis.conf
    grep -q '^replica-read-only' /etc/redis/redis.conf || echo 'replica-read-only yes' >> /etc/redis/redis.conf
    echo 'vm.overcommit_memory = 1' > /etc/sysctl.d/99-redis.conf
    sysctl -q -p /etc/sysctl.d/99-redis.conf
    systemctl enable -q redis-server
    systemctl restart redis-server
    sleep 2
    systemctl is-active redis-server | sed 's/^/   redis-server: /'
    grep -E '^(bind|maxmemory|maxmemory-policy|appendonly|replica-read-only)' /etc/redis/redis.conf | sed 's/^/   /'
"

echo "== Replikation herstellen =="
# Anmeldung am Master ueber den ACL-Benutzer "default": der Benutzer
# "shopware" hat resetchannels und darf kein Pub/Sub - Replikation und
# Sentinel brauchen das aber.
./redis-zugang.sh "$IP" "$MASTER_IP" || exit 1

echo "== Stand =="
./redis-zugang.sh --lage "$MASTER_IP" "$IP"
