#!/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 ' 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"