#!/usr/bin/env bash
# Nächtliche Sicherung der Shop-Datenbank.
#
# Läuft auf Frontend 1 und sichert über das Netz von DB-SRV-3: auf diesen
# Knoten schreibt kein Frontend, der Dump belastet den Betrieb also am
# wenigsten, und Galera hält alle drei Knoten identisch.
#
# Warum nicht direkt auf dem Datenbankknoten? Die DB-Server haben keinen
# Internetzugang (keine Namensauflösung), können also nicht in den Object
# Storage schreiben. Die Frontends können beides.
#
# Ablage: lokal unter /var/backups/riccardo-db (14 Tage) und zusätzlich im
# privaten Object-Storage-Bucket (30 Tage) – eine Kopie auf derselben Maschine
# ist keine Sicherung.
set -euo pipefail

ZIEL=/var/backups/riccardo-db
BEHALTEN_TAGE=14
BEHALTEN_TAGE_FERN=30
DATENBANKEN=(riccardo_shop)
STAMP="$(date +%Y%m%d-%H%M)"

[ -f /etc/riccardo-backup.env ] && . /etc/riccardo-backup.env

: "${DB_HOST:=10.0.3.3}"
: "${DB_USER:?DB_USER fehlt in /etc/riccardo-backup.env}"
: "${DB_PASS:?DB_PASS fehlt in /etc/riccardo-backup.env}"
DB=(-h "$DB_HOST" -u "$DB_USER" "-p$DB_PASS")

mkdir -p "$ZIEL"

host="${S3_ENDPOINT#https://}"

# Legt eine Datei im privaten Bucket ab – mit awscli oder s3cmd, je nachdem
# was auf der Maschine vorhanden ist.
fern_kopieren() {
    local datei="$1"
    local ziel="datenbank-sicherungen/$(basename "$datei")"
    [ -n "${S3_KEY:-}" ] || return 0

    if command -v aws >/dev/null; then
        AWS_ACCESS_KEY_ID="$S3_KEY" AWS_SECRET_ACCESS_KEY="$S3_SECRET" \
        aws --endpoint-url "$S3_ENDPOINT" --region "${S3_REGION:-nbg1}" \
            s3 cp "$datei" "s3://${S3_BUCKET_PRIVATE}/$ziel" --only-show-errors
    elif command -v s3cmd >/dev/null; then
        s3cmd --access_key="$S3_KEY" --secret_key="$S3_SECRET" \
              --host="$host" --host-bucket="%(bucket)s.$host" \
              --quiet put "$datei" "s3://${S3_BUCKET_PRIVATE}/$ziel"
    else
        echo "Kein S3-Werkzeug vorhanden – Sicherung liegt nur lokal" >&2
    fi
}

# Räumt alte Sicherungen im Bucket auf
fern_aufraeumen() {
    local grenze="$1" liste
    [ -n "${S3_KEY:-}" ] || return 0

    if command -v aws >/dev/null; then
        liste=$(AWS_ACCESS_KEY_ID="$S3_KEY" AWS_SECRET_ACCESS_KEY="$S3_SECRET" \
            aws --endpoint-url "$S3_ENDPOINT" --region "${S3_REGION:-nbg1}" \
                s3 ls "s3://${S3_BUCKET_PRIVATE}/datenbank-sicherungen/")
        while read -r datum _ _ name; do
            [ -n "$name" ] && [[ "$datum" < "$grenze" ]] && \
            AWS_ACCESS_KEY_ID="$S3_KEY" AWS_SECRET_ACCESS_KEY="$S3_SECRET" \
            aws --endpoint-url "$S3_ENDPOINT" --region "${S3_REGION:-nbg1}" \
                s3 rm "s3://${S3_BUCKET_PRIVATE}/datenbank-sicherungen/$name" --only-show-errors
        done <<< "$liste"
    elif command -v s3cmd >/dev/null; then
        liste=$(s3cmd --access_key="$S3_KEY" --secret_key="$S3_SECRET" \
              --host="$host" --host-bucket="%(bucket)s.$host" \
              ls "s3://${S3_BUCKET_PRIVATE}/datenbank-sicherungen/")
        while read -r datum _ _ pfad; do
            [ -n "$pfad" ] && [[ "$datum" < "$grenze" ]] && \
            s3cmd --access_key="$S3_KEY" --secret_key="$S3_SECRET" \
                  --host="$host" --host-bucket="%(bucket)s.$host" \
                  --quiet del "$pfad"
        done <<< "$liste"
    fi
}

# Nur sichern, wenn der Knoten synchron ist – sonst wäre der Stand unklar
zustand="$(mariadb "${DB[@]}" -N -e 'show status like "wsrep_local_state_comment"' | cut -f2)"
if [ "$zustand" != "Synced" ]; then
    echo "Knoten ist nicht synchron ($zustand) – Sicherung abgebrochen" >&2
    exit 1
fi

for db in "${DATENBANKEN[@]}"; do
    datei="$ZIEL/$db-$STAMP.sql.gz"
    mariadb-dump "${DB[@]}" --single-transaction --quick --routines --triggers --events \
        --default-character-set=utf8mb4 --databases "$db" | gzip -6 > "$datei"

    # Plausibilität: eine Sicherung unter 5 MB ist für diesen Shop verdächtig
    groesse=$(stat -c %s "$datei")
    if [ "$groesse" -lt 5000000 ]; then
        echo "Sicherung $datei ist nur $groesse Bytes groß – bitte prüfen" >&2
    fi

    # Kopie in den privaten Bucket. Auf den Datenbankknoten gibt es kein
    # awscli im Paketangebot, dort übernimmt s3cmd.
    fern_kopieren "$datei"
done

# Alte Sicherungen aufräumen, lokal und im Bucket
find "$ZIEL" -name '*.sql.gz' -mtime +$BEHALTEN_TAGE -delete
fern_aufraeumen "$(date -d "-$BEHALTEN_TAGE_FERN days" +%Y-%m-%d)"


echo "$(date '+%Y-%m-%d %H:%M') Sicherung fertig: $(ls -1 "$ZIEL"/*.sql.gz | wc -l) Dateien lokal"
