robosats/scripts/traditional/regtest-services
2024-12-27 20:03:06 +01:00

373 lines
10 KiB
Bash
Executable File

#!/bin/sh
_command_exist() {
if command -v "$1" >/dev/null 2>&1; then
return 0
else
echo "error: $1 command not found" >&2
return 1
fi
}
_create_dir() {
if [ ! -e "$1" ]; then
mkdir -p "$1" || return "$?"
if [ "$#" -ge 2 ]; then
if ! chmod "$2" "$1"; then
echo "error: setting chmod $2 of $1" >&2
return 1
fi
fi
elif [ ! -d "$1" ]; then
echo "error: $1 is not a directory" >&2
return 1
fi
}
_get_env_var() {
if ! env_var="$(dotenv -f ".env" get "$1" 2>/dev/null)"; then
echo "error: getting $1 from .env" >&2
return 1
fi
printf "%s\n" "$env_var"
return 0
}
# transform relative path into absolute and remove trailing slashes
_get_env_var_path() {
env_var="$(_get_env_var "$1")" || return "$?"
real_path="$(realpath -m "$env_var")" || return "$?"
printf "%s\n" "$real_path"
return 0
}
_services_environment_set() {
# docker-compose.yml
CELERY_WORKER_COMMAND="celery -A robosats worker --loglevel=INFO --concurrency 4 --max-tasks-per-child=4 --max-memory-per-child=200000"
CELERY_BEAT_COMMAND="celery -A robosats beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler"
REGTEST_SERVICES_DIR="$(_get_env_var_path "REGTEST_SERVICES_DIR")" || return "$?"
REGTEST_LOGS_DIR="$(_get_env_var_path "REGTEST_LOGS_DIR")" || return "$?"
_create_dir "$REGTEST_SERVICES_DIR" || return "$?"
_create_dir "$REGTEST_LOGS_DIR" || return "$?"
POSTGRES_DIR="$REGTEST_SERVICES_DIR/postgres"
REDIS_DIR="$REGTEST_SERVICES_DIR/redis"
GNUPG_DIR="$(_get_env_var_path "GNUPG_DIR")" || return "$?"
POSTGRES_DB="$(_get_env_var "POSTGRES_DB")" || return "$?"
POSTGRES_USER="$(_get_env_var "POSTGRES_USER")" || return "$?"
POSTGRES_PASS="$(_get_env_var "POSTGRES_PASSWORD")" || return "$?"
POSTGRES_PORT="$(_get_env_var "POSTGRES_PORT")" || return "$?"
REDIS_PORT="$(_get_env_var "REDIS_PORT")" || return "$?"
# defaults
POSTGRES_DB="${POSTGRES_DB:-postgres}"
POSTGRES_USER="${POSTGRES_USER:-postgres}"
POSTGRES_PASS="${POSTGRES_PASS:-example}"
POSTGRES_PORT="${POSTGRES_PORT:-5432}"
REDIS_PORT="${REDIS_REGTEST_PORT:-6379}"
}
postgres_action() {
if [ "$#" -lt 1 ]; then
echo "error: insert postgres action" >&2
return 1
fi
action="$1"
shift 1
case "$action" in
setup|database) ;;
*)
echo "error: wrong action" >&2
return 1
;;
esac
if ! _command_exist postgres; then
return 1
fi
if ! _command_exist initdb; then
return 1
fi
if ! _command_exist psql; then
return 1
fi
case "$action" in
setup)
if [ -e "$POSTGRES_DIR" ]; then
echo "postgres directory $POSTGRES_DIR already exists"
return 0
fi
_create_dir "$POSTGRES_DIR" "0700" || return "$?"
if ! initdb -D "$POSTGRES_DIR"; then
echo "error: running initdb" >&2
return 1
fi
cat << EOF > "$POSTGRES_DIR/postgresql.conf"
port = $POSTGRES_PORT
unix_socket_directories = '$POSTGRES_DIR'
EOF
;;
database)
if [ ! -d "$POSTGRES_DIR" ]; then
printf "%s%s\n" \
"error: $POSTGRES_DIR is not a directory, " \
"should run postgres-setup" \
>&2
return 1
fi
;;
esac
postgres_setup_log_file="$REGTEST_LOGS_DIR/postgres-setup-log"
echo "starting postgres, setup log file is $postgres_setup_log_file"
postgres -D "$POSTGRES_DIR" >>"$postgres_setup_log_file" 2>&1 &
postgres_pid="$!"
_postgres_shut_down() {
echo "shutting down postgres"
if ! kill "$postgres_pid"; then
echo "error: shutting down postgres" >&2
return 1
fi
}
sleep 5
case "$action" in
setup)
echo "setting up postgres user $POSTGRES_USER"
psql_stdin=$(cat << EOF
CREATE ROLE $POSTGRES_USER WITH LOGIN PASSWORD '$POSTGRES_PASS';
ALTER ROLE $POSTGRES_USER CREATEDB;
EOF
)
;;
database)
psql_stdin=$(cat << EOF
CREATE DATABASE $POSTGRES_DB OWNER $POSTGRES_USER;
EOF
)
;;
esac
printf "%s\n" "$psql_stdin" |
psql -h localhost -p "$POSTGRES_PORT" -U "$USER" -d postgres
sleep 5
case "$action" in
database)
if ! DJANGO_SUPERUSER_USERNAME="$(_get_env_var "ESCROW_USERNAME")"; then
_postgres_shut_down || return "$?"
return 1
fi
# shellcheck disable=SC2034
DJANGO_SUPERUSER_PASSWORD="password"
DJANGO_SUPERUSER_EMAIL="superuser@email.com"
if ! python3 manage.py migrate; then
_postgres_shut_down || return "$?"
return 1
fi
if ! python3 manage.py createsuperuser \
--noinput \
--username "$DJANGO_SUPERUSER_USERNAME" \
--email "$DJANGO_SUPERUSER_EMAIL"
then
_postgres_shut_down || return "$?"
return 1
fi
;;
esac
_postgres_shut_down || return "$?"
return 0
}
cleanup_signal() {
printf "\n"
printf "%s\n" "Caught $1 signal, sending it to services..."
pkill -"$2" -f "$CELERY_BEAT_COMMAND"
pkill -"$2" -f "$CELERY_WORKER_COMMAND"
pkill -"$2" -f "python3 manage.py follow_invoices"
pkill -"$2" -f "python3 manage.py clean_orders"
pkill -"$2" -f "python3 manage.py runserver 0.0.0.0:8000"
pkill -"$2" -f "redis-server \*:${REDIS_PORT}"
pkill -"$2" -f "postgres -D $POSTGRES_DIR"
exit 0
}
cleanup_int() {
printf "\n"
printf "%s\n" "Caught INT signal, shutting down services..."
pkill -INT -f "$CELERY_BEAT_COMMAND"
pkill -INT -f "$CELERY_WORKER_COMMAND"
pkill -TERM -f "python3 manage.py follow_invoices"
pkill -TERM -f "python3 manage.py clean_orders"
pkill -TERM -f "python3 manage.py runserver 0.0.0.0:8000"
# pkill -INT -f "python3 manage.py follow_invoices"
# pkill -INT -f "python3 manage.py clean_orders"
# pkill -INT -f "python3 manage.py runserver 0.0.0.0:8000"
pkill -INT -f "redis-server \*:${REDIS_PORT}"
pkill -INT -f "postgres -D $POSTGRES_DIR"
exit 0
}
main_loop() {
if [ "$#" -lt 1 ]; then
echo "error: insert main loop action" >&2
return 1
fi
case "$1" in
test)
is_test=true
;;
server)
is_test=false
;;
*)
echo "error: $1 is invalid" >&2
return 1
;;
esac
shift 1
if ! _command_exist postgres; then
return 1
fi
if ! _command_exist redis-server; then
return 1
fi
if ! _command_exist celery; then
return 1
fi
if [ ! -d "$POSTGRES_DIR" ]; then
printf "%s%s\n" \
"error: $POSTGRES_DIR is not a directory, " \
"should run postgres-setup and postgres-database" \
>&2
return 1
fi
if ! pgrep -a bitcoind >/dev/null 2>&1 || {
! pgrep -a lightningd >/dev/null 2>&1 &&
! pgrep -a lnd >/dev/null 2>&1
}; then
printf "%s%s\n" \
"error: bitcoin or lightning not running, " \
"make sure to run this script after running regtest-nodes" \
>&2
return 1
fi
_create_dir "$REDIS_DIR" || return "$?"
_create_dir "$GNUPG_DIR" "0700" || return "$?"
trap "cleanup_signal HUP" HUP
trap "cleanup_signal QUIT" QUIT
trap "cleanup_signal TERM" TERM
trap "cleanup_int" INT
while true; do
if ! pgrep -f "postgres -D $POSTGRES_DIR" >/dev/null; then
echo "starting postgres"
postgres -D "$POSTGRES_DIR" >> "$REGTEST_LOGS_DIR/postgres" 2>&1 &
fi
if ! pgrep -f "redis-server \*:${REDIS_PORT}" >/dev/null; then
echo "starting redis"
printf "%s\n%s\n%s\n" \
"dir $REDIS_DIR" \
"port $REDIS_PORT" \
"maxclients 1024" |
redis-server - >> "$REGTEST_LOGS_DIR/redis" 2>&1 &
fi
if [ "$is_test" = false ]; then
if ! pgrep -f "python3 manage.py runserver 0.0.0.0:8000" >/dev/null; then
echo "starting runserver"
python3 manage.py runserver 0.0.0.0:8000 \
>> "$REGTEST_LOGS_DIR/runserver" 2>&1 &
fi
if ! pgrep -f "python3 manage.py clean_orders" >/dev/null; then
echo "starting clean-orders"
python3 manage.py clean_orders \
>> "$REGTEST_LOGS_DIR/clean-orders" 2>&1 &
fi
if ! pgrep -f "python3 manage.py follow_invoices" >/dev/null; then
echo "starting follow-invoices"
python3 manage.py follow_invoices \
>> "$REGTEST_LOGS_DIR/follow-invoices" 2>&1 &
fi
if ! pgrep -f "$CELERY_WORKER_COMMAND" >/dev/null; then
echo "starting celery worker"
$CELERY_WORKER_COMMAND >> "$REGTEST_LOGS_DIR/celery-worker" 2>&1 &
fi
if ! pgrep -f "$CELERY_BEAT_COMMAND" >/dev/null; then
echo "starting celery beat"
$CELERY_BEAT_COMMAND >> "$REGTEST_LOGS_DIR/celery-beat" 2>&1 &
fi
fi
sleep 2
done
}
_services_main() {
if [ "$#" -lt 1 ]; then
echo "error: insert action" >&2
return 1
fi
action="$1"
shift 1
case "$action" in
-h|--help)
cat << EOF
regtest-services postgres-setup|postgres-database|server|test
EOF
return 0
;;
esac
_services_environment_set || return "$?"
case "$action" in
postgres-setup)
postgres_action "setup"
;;
postgres-database)
postgres_action "database"
;;
server|test)
main_loop "$action"
;;
*)
echo "error: action $action not recognized" >&2
return 1
;;
esac
}
_services_main "$@"