test: add podman/docker dbtest tool for postgres, mssql and mysql
This commit is contained in:
Executable
+130
@@ -0,0 +1,130 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user