131 lines
3.6 KiB
Bash
Executable File
131 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Reusable podman/docker test database tool for postgres, mssql and mysql.
|
|
# Usage: dbtest.sh <command> <db> [args]
|
|
set -euo pipefail
|
|
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ROOT="$(cd "$HERE/../.." && pwd)"
|
|
TIMEOUT="${DBTEST_TIMEOUT:-120}"
|
|
ALL_DBS=(postgres mssql mysql)
|
|
|
|
usage() {
|
|
cat <<USAGE
|
|
dbtest.sh <command> <db|all> [args]
|
|
|
|
commands:
|
|
up <db> start container, wait until ready, run init
|
|
down <db> stop and remove container
|
|
restart <db> down + up
|
|
status <db> running state and connection string
|
|
env <db> print 'export VAR=conn' (use: eval "\$(dbtest.sh env postgres)")
|
|
logs <db> container logs
|
|
shell <db> interactive client
|
|
exec <db> <file> run a SQL file against the database
|
|
test <db> [pkgs] up, run go tests with conn env set, down (keep with DBTEST_KEEP=1)
|
|
list supported databases
|
|
|
|
dbs: ${ALL_DBS[*]}
|
|
env: DBTEST_RUNTIME=podman|docker DBTEST_TIMEOUT=secs DBTEST_KEEP=1 DBTEST_GOFLAGS=...
|
|
USAGE
|
|
}
|
|
|
|
die() { echo "error: $*" >&2; exit 1; }
|
|
log() { echo "[dbtest] $*" >&2; }
|
|
|
|
detect_runtime() {
|
|
if [ -n "${DBTEST_RUNTIME:-}" ]; then echo "$DBTEST_RUNTIME"; return; fi
|
|
if command -v podman >/dev/null 2>&1; then echo podman
|
|
elif command -v docker >/dev/null 2>&1; then echo docker
|
|
else die "neither podman nor docker is installed"; fi
|
|
}
|
|
RUNTIME="$(detect_runtime)"
|
|
rt() { "$RUNTIME" "$@"; }
|
|
|
|
load_db() {
|
|
local f="$HERE/dbs/${1:-}.sh"
|
|
[ -f "$f" ] || die "unknown db '${1:-}' (supported: ${ALL_DBS[*]})"
|
|
# shellcheck disable=SC1090
|
|
source "$f"
|
|
}
|
|
|
|
is_running() { [ "$(rt inspect -f '{{.State.Running}}' "$DB_CONTAINER" 2>/dev/null || true)" = "true" ]; }
|
|
|
|
cmd_up() {
|
|
if is_running; then
|
|
log "$DB_NAME already running"
|
|
else
|
|
rt rm -f "$DB_CONTAINER" >/dev/null 2>&1 || true
|
|
log "starting $DB_NAME ($DB_IMAGE) on port $DB_PORT using $RUNTIME"
|
|
rt run -d --name "$DB_CONTAINER" "${DB_ENV[@]}" \
|
|
-p "$DB_PORT:$DB_INTERNAL_PORT" \
|
|
-v "$DB_INIT_MOUNT:ro,Z" "$DB_IMAGE" >/dev/null
|
|
fi
|
|
log "waiting for $DB_NAME (max ${TIMEOUT}s)"
|
|
local i=0
|
|
until db_ready; do
|
|
i=$((i + 1))
|
|
if [ "$i" -ge "$TIMEOUT" ]; then
|
|
rt logs --tail 50 "$DB_CONTAINER" >&2 || true
|
|
die "$DB_NAME did not become ready"
|
|
fi
|
|
sleep 1
|
|
done
|
|
db_post_init
|
|
log "$DB_NAME ready: $DB_CONN_VAR=$DB_CONN"
|
|
}
|
|
|
|
cmd_down() {
|
|
rt rm -f "$DB_CONTAINER" >/dev/null 2>&1 || true
|
|
log "$DB_NAME removed"
|
|
}
|
|
|
|
cmd_status() {
|
|
if is_running; then echo "$DB_NAME: running ($DB_CONTAINER, port $DB_PORT)"; else echo "$DB_NAME: stopped"; fi
|
|
echo "$DB_CONN_VAR=$DB_CONN"
|
|
}
|
|
|
|
cmd_test() {
|
|
local pkgs="${*:-$DB_DEFAULT_PKGS}"
|
|
[ -n "$pkgs" ] || die "no test packages for $DB_NAME; pass packages as arguments"
|
|
cmd_up
|
|
[ -n "${DBTEST_KEEP:-}" ] || trap cmd_down EXIT
|
|
export "$DB_CONN_VAR=$DB_CONN"
|
|
cd "$ROOT"
|
|
# shellcheck disable=SC2086
|
|
go test -count=1 ${DBTEST_GOFLAGS:-} $pkgs
|
|
}
|
|
|
|
cmd="${1:-}"
|
|
case "$cmd" in
|
|
""|-h|--help|help) usage; exit 0 ;;
|
|
list) printf '%s\n' "${ALL_DBS[@]}"; exit 0 ;;
|
|
esac
|
|
shift
|
|
target="${1:-}"
|
|
[ -n "$target" ] || die "missing <db>"
|
|
shift || true
|
|
|
|
run_one() {
|
|
load_db "$1"
|
|
shift
|
|
case "$cmd" in
|
|
up) cmd_up ;;
|
|
down) cmd_down ;;
|
|
restart) cmd_down; cmd_up ;;
|
|
status) cmd_status ;;
|
|
env) echo "export $DB_CONN_VAR='$DB_CONN'" ;;
|
|
logs) rt logs "$DB_CONTAINER" ;;
|
|
shell) db_shell "$@" ;;
|
|
exec) [ -f "${1:-}" ] || die "usage: exec <db> <file>"; db_exec_file "$1" ;;
|
|
test) cmd_test "$@" ;;
|
|
*) usage; die "unknown command '$cmd'" ;;
|
|
esac
|
|
}
|
|
|
|
if [ "$target" = "all" ]; then
|
|
case "$cmd" in up|down|restart|status|env) ;; *) die "'all' is only valid for up/down/restart/status/env" ;; esac
|
|
for d in "${ALL_DBS[@]}"; do (run_one "$d"); done
|
|
else
|
|
run_one "$target" "$@"
|
|
fi
|