185 lines
5.0 KiB
Bash
185 lines
5.0 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
|
|
SERVER_ENV_FILE="${ROOT_DIR}/deploy/server/.env"
|
|
CONSOLE_ENV_FILE="${ROOT_DIR}/deploy/console/.env"
|
|
SERVER_COMPOSE_FILE="${ROOT_DIR}/deploy/server/docker-compose.tcp.yml"
|
|
CONSOLE_COMPOSE_FILE="${ROOT_DIR}/deploy/console/docker-compose.yml"
|
|
SERVER_PROJECT="${RPKI_RTR_COMPOSE_PROJECT:-rpki-rtr}"
|
|
CONSOLE_PROJECT="${RPKI_CONSOLE_COMPOSE_PROJECT:-rpki-console}"
|
|
WAIT_SECS="${RPKI_SELF_CHECK_WAIT_SECS:-60}"
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: scripts/02_self_check.sh [options]
|
|
|
|
Check whether the RTR server and console started by scripts/01_start.sh are healthy.
|
|
|
|
Options:
|
|
--wait SECS Wait timeout for each check. Default: 60
|
|
-h, --help Show this help.
|
|
EOF
|
|
}
|
|
|
|
log() {
|
|
printf '[02_self_check] %s\n' "$*" >&2
|
|
}
|
|
|
|
stage() {
|
|
printf '\n====== %s ======\n' "$*" >&2
|
|
}
|
|
|
|
die() {
|
|
printf '[02_self_check] ERROR: %s\n' "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--wait)
|
|
[ "$#" -ge 2 ] || die "--wait requires a value"
|
|
WAIT_SECS="$2"
|
|
shift 2
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
die "unknown option: $1"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
command -v docker >/dev/null 2>&1 || die "docker command not found"
|
|
if docker compose version >/dev/null 2>&1; then
|
|
COMPOSE_BIN=(docker compose)
|
|
elif command -v docker-compose >/dev/null 2>&1 && docker-compose version >/dev/null 2>&1; then
|
|
COMPOSE_BIN=(docker-compose)
|
|
else
|
|
die "docker compose is not available"
|
|
fi
|
|
|
|
[ -f "${SERVER_ENV_FILE}" ] || die "server env file not found: ${SERVER_ENV_FILE}"
|
|
[ -f "${SERVER_COMPOSE_FILE}" ] || die "server compose file not found: ${SERVER_COMPOSE_FILE}"
|
|
[ -f "${CONSOLE_ENV_FILE}" ] || die "console env file not found: ${CONSOLE_ENV_FILE}"
|
|
[ -f "${CONSOLE_COMPOSE_FILE}" ] || die "console compose file not found: ${CONSOLE_COMPOSE_FILE}"
|
|
|
|
set -a
|
|
# shellcheck disable=SC1090
|
|
. "${SERVER_ENV_FILE}"
|
|
# shellcheck disable=SC1090
|
|
. "${CONSOLE_ENV_FILE}"
|
|
set +a
|
|
|
|
RTR_PORT="${RPKI_RTR_TCP_HOST_PORT:-323}"
|
|
ADMIN_PORT="${RPKI_RTR_ADMIN_ADDR##*:}"
|
|
ADMIN_PORT="${ADMIN_PORT:-8323}"
|
|
ADMIN_TOKEN="${RPKI_RTR_ADMIN_TOKEN:-}"
|
|
CONSOLE_PORT="${RPKI_CONSOLE_UI_PORT:-5173}"
|
|
|
|
server_compose() {
|
|
"${COMPOSE_BIN[@]}" --env-file "${SERVER_ENV_FILE}" -p "${SERVER_PROJECT}" -f "${SERVER_COMPOSE_FILE}" "$@"
|
|
}
|
|
|
|
console_compose() {
|
|
"${COMPOSE_BIN[@]}" --env-file "${CONSOLE_ENV_FILE}" -p "${CONSOLE_PROJECT}" -f "${CONSOLE_COMPOSE_FILE}" "$@"
|
|
}
|
|
|
|
container_running() {
|
|
local compose_kind="$1"
|
|
local service="$2"
|
|
local cid state
|
|
|
|
if [ "${compose_kind}" = "server" ]; then
|
|
cid="$(server_compose ps -q "${service}" 2>/dev/null || true)"
|
|
else
|
|
cid="$(console_compose ps -q "${service}" 2>/dev/null || true)"
|
|
fi
|
|
|
|
[ -n "${cid}" ] || return 1
|
|
state="$(docker inspect -f '{{.State.Running}}' "${cid}" 2>/dev/null || true)"
|
|
[ "${state}" = "true" ]
|
|
}
|
|
|
|
tcp_open() {
|
|
local host="$1"
|
|
local port="$2"
|
|
|
|
if command -v nc >/dev/null 2>&1; then
|
|
nc -z "${host}" "${port}" >/dev/null 2>&1
|
|
return
|
|
fi
|
|
|
|
(exec 3<>"/dev/tcp/${host}/${port}") >/dev/null 2>&1
|
|
}
|
|
|
|
http_get() {
|
|
local url="$1"
|
|
local token="${2:-}"
|
|
|
|
if command -v curl >/dev/null 2>&1; then
|
|
if [ -n "${token}" ]; then
|
|
curl -fsS -H "Authorization: Bearer ${token}" "${url}"
|
|
else
|
|
curl -fsS "${url}"
|
|
fi
|
|
return
|
|
fi
|
|
|
|
die "curl command is required for HTTP health checks"
|
|
}
|
|
|
|
wait_until() {
|
|
local label="$1"
|
|
shift
|
|
local deadline=$((SECONDS + WAIT_SECS))
|
|
|
|
while [ "${SECONDS}" -lt "${deadline}" ]; do
|
|
if "$@"; then
|
|
log "${label}: ok"
|
|
return 0
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
die "${label}: failed after ${WAIT_SECS}s"
|
|
}
|
|
|
|
show_command() {
|
|
printf '[02_self_check] check command: %s\n' "$*" >&2
|
|
}
|
|
|
|
check_admin_health() {
|
|
local body
|
|
body="$(http_get "http://127.0.0.1:${ADMIN_PORT}/admin/rtr/health" "${ADMIN_TOKEN}" 2>/dev/null || true)"
|
|
printf '%s' "${body}" | grep -q '"status"[[:space:]]*:[[:space:]]*"ok"'
|
|
}
|
|
|
|
check_console_http() {
|
|
http_get "http://127.0.0.1:${CONSOLE_PORT}/" >/dev/null 2>&1
|
|
}
|
|
|
|
stage "Checking Containers"
|
|
show_command "${COMPOSE_BIN[*]} --env-file ${SERVER_ENV_FILE} -p ${SERVER_PROJECT} -f ${SERVER_COMPOSE_FILE} ps -q rpki-rtr && docker inspect"
|
|
wait_until "server container" container_running server rpki-rtr
|
|
show_command "${COMPOSE_BIN[*]} --env-file ${CONSOLE_ENV_FILE} -p ${CONSOLE_PROJECT} -f ${CONSOLE_COMPOSE_FILE} ps -q rpki-console-ui && docker inspect"
|
|
wait_until "console container" container_running console rpki-console-ui
|
|
|
|
stage "Checking Server"
|
|
show_command "tcp connect 127.0.0.1:${RTR_PORT}"
|
|
wait_until "RTR port ${RTR_PORT}" tcp_open 127.0.0.1 "${RTR_PORT}"
|
|
show_command "curl -fsS -H 'Authorization: Bearer <token>' http://127.0.0.1:${ADMIN_PORT}/admin/rtr/health"
|
|
wait_until "Admin health" check_admin_health
|
|
|
|
stage "Checking Console"
|
|
show_command "tcp connect 127.0.0.1:${CONSOLE_PORT}"
|
|
wait_until "Console port ${CONSOLE_PORT}" tcp_open 127.0.0.1 "${CONSOLE_PORT}"
|
|
show_command "curl -fsS http://127.0.0.1:${CONSOLE_PORT}/"
|
|
wait_until "Console HTTP" check_console_http
|
|
|
|
stage "Self-Check Passed"
|