AkurAI Build
Menu

Public repository / 9c0f98ff6f19b1986884b04e14b9fc9e24c11912

AkurAI-EC2 / bin/akurai-mariadbctl

Latest change 2b11dd5386e6d27f84b7d17ac9b1e47bd4dfdf96 - Add akurai-mariadbctl; delegate 'akurai-ec2 mariadb' to the docker stack by Ólafur Búi Ólafsson

#!/bin/sh
# akurai-mariadbctl — operate the local /opt/akurai-mariadb docker compose
# MariaDB stack (mariadb-prod :3306, mariadb-dev :3307). Same layout on Titan
# and the AkurAI EC2 host; on EC2 drive it remotely via
# `akurai-ec2 mariadb <command...>`.
#
# Secret handling: passwords never travel via argv. create-user reads the
# password from stdin (pipe it from a 0400 secret file or PassVault-derived
# material); root credentials stay inside the containers' /run/secrets files.
set -eu

ROOT=/opt/akurai-mariadb
SUDO=""
[ "$(id -u)" -ne 0 ] && ! docker info >/dev/null 2>&1 && SUDO="sudo"

usage() {
    cat <<'EOF'
usage: akurai-mariadbctl <command> [args]

  status                       compose state, memory, databases per instance
  health                       healthcheck verdict (exit 1 unless both healthy)
  up | down | restart          compose lifecycle for the whole stack
  root-shell [prod|dev]        interactive root SQL shell
  sql <prod|dev> [database]    execute SQL from stdin as root
  create-db <name> [prod|dev]  CREATE DATABASE IF NOT EXISTS (utf8mb4)
  create-user <user> <db> [prod|dev]
                               create user + scoped grant; password on stdin
  dump <database> [prod|dev]   mariadb-dump to stdout (pipe to a file)
  logs [prod|dev] [lines]      container logs (default 50 lines)
EOF
    exit "${1:-0}"
}

container() {
    case "${1:-prod}" in
        prod) echo mariadb-prod ;;
        dev) echo mariadb-dev ;;
        *) echo "unknown instance: $1 (use prod|dev)" >&2; exit 2 ;;
    esac
}

root_sql() { # $1 container; SQL on stdin
    $SUDO docker exec -i "$1" sh -c 'exec mariadb -uroot -p"$(cat /run/secrets/root.pass)" --batch'
}

cmd="${1:-}"; [ $# -gt 0 ] && shift
case "$cmd" in
    status)
        (cd "$ROOT" && $SUDO docker compose ps)
        $SUDO docker stats --no-stream --format '{{.Name}} mem={{.MemUsage}} cpu={{.CPUPerc}}' mariadb-prod mariadb-dev 2>/dev/null || true
        for instance in prod dev; do
            c=$(container $instance)
            printf '%s databases: ' "$instance"
            echo 'SHOW DATABASES' | root_sql "$c" 2>/dev/null | grep -vE '^(Database|information_schema|performance_schema|mysql|sys)$' | tr '\n' ' '
            echo
        done
        ;;
    health)
        ok=0
        for c in mariadb-prod mariadb-dev; do
            state=$($SUDO docker inspect -f '{{.State.Health.Status}}' "$c" 2>/dev/null || echo missing)
            echo "$c: $state"
            [ "$state" = healthy ] || ok=1
        done
        exit $ok
        ;;
    up) (cd "$ROOT" && $SUDO docker compose up -d) ;;
    down) (cd "$ROOT" && $SUDO docker compose down) ;;
    restart) (cd "$ROOT" && $SUDO docker compose restart) ;;
    root-shell)
        c=$(container "${1:-prod}")
        exec $SUDO docker exec -it "$c" sh -c 'exec mariadb -uroot -p"$(cat /run/secrets/root.pass)"'
        ;;
    sql)
        [ $# -ge 1 ] || usage 2
        c=$(container "$1")
        if [ $# -ge 2 ]; then
            $SUDO docker exec -i "$c" sh -c 'exec mariadb -uroot -p"$(cat /run/secrets/root.pass)" --batch "$1"' sh "$2"
        else
            root_sql "$c"
        fi
        ;;
    create-db)
        [ $# -ge 1 ] || usage 2
        c=$(container "${2:-prod}")
        printf 'CREATE DATABASE IF NOT EXISTS `%s` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n' "$1" | root_sql "$c"
        echo "created: $1 on ${2:-prod}"
        ;;
    create-user)
        [ $# -ge 2 ] || usage 2
        user="$1"; db="$2"; c=$(container "${3:-prod}")
        password=$(cat)
        [ -n "$password" ] || { echo "empty password on stdin" >&2; exit 2; }
        printf "CREATE USER IF NOT EXISTS '%s'@'%%' IDENTIFIED BY '%s';\nGRANT ALL PRIVILEGES ON \`%s\`.* TO '%s'@'%%';\nFLUSH PRIVILEGES;\n" \
            "$user" "$password" "$db" "$user" | root_sql "$c"
        echo "created: $user -> $db on ${3:-prod}"
        ;;
    dump)
        [ $# -ge 1 ] || usage 2
        c=$(container "${2:-prod}")
        $SUDO docker exec -i "$c" sh -c 'exec mariadb-dump -uroot -p"$(cat /run/secrets/root.pass)" --single-transaction "$1"' sh "$1"
        ;;
    logs)
        c=$(container "${1:-prod}")
        $SUDO docker logs --tail "${2:-50}" "$c"
        ;;
    ''|-h|--help|help) usage ;;
    *) echo "unknown command: $cmd" >&2; usage 2 ;;
esac