#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" SERVER_DIR="${ROOT_DIR}/deploy/server" SERVER_ENV_FILE="${SERVER_DIR}/.env" SERVER_COMPOSE_FILE="${SERVER_DIR}/docker-compose.tcp.yml" COMPOSE_PROJECT="${RPKI_RTR_COMPOSE_PROJECT:-rpki-rtr}" FORCE=0 usage() { cat <<'EOF' Usage: scripts/04_cleanup.sh [options] Remove server generated directories: logs, reports, and RTR database. Options: --force Clean even if the server container appears to be running. -h, --help Show this help. EOF } log() { printf '[04_cleanup] %s\n' "$*" >&2 } stage() { printf '\n====== %s ======\n' "$*" >&2 } die() { printf '[04_cleanup] ERROR: %s\n' "$*" >&2 exit 1 } env_value() { local key="$1" local default_value="$2" local line line="$(grep -E "^[[:space:]]*${key}=" "${SERVER_ENV_FILE}" | tail -n 1 || true)" if [ -n "${line}" ]; then printf '%s\n' "${line#*=}" else printf '%s\n' "${default_value}" fi } resolve_host_path() { local raw_path="$1" case "${raw_path}" in /*|[A-Za-z]:/*|[A-Za-z]:\\*) printf '%s\n' "${raw_path}" ;; *) (cd "${SERVER_DIR}" && cd "${raw_path}" 2>/dev/null && pwd -P) || printf '%s/%s\n' "${SERVER_DIR}" "${raw_path}" ;; esac } compose_available() { if docker compose version >/dev/null 2>&1; then COMPOSE_BIN=(docker compose) return 0 fi if command -v docker-compose >/dev/null 2>&1 && docker-compose version >/dev/null 2>&1; then COMPOSE_BIN=(docker-compose) return 0 fi return 1 } server_running() { local cid state [ -f "${SERVER_COMPOSE_FILE}" ] || return 1 compose_available || return 1 cid="$("${COMPOSE_BIN[@]}" --env-file "${SERVER_ENV_FILE}" -p "${COMPOSE_PROJECT}" -f "${SERVER_COMPOSE_FILE}" ps -q rpki-rtr 2>/dev/null || true)" [ -n "${cid}" ] || return 1 state="$(docker inspect -f '{{.State.Running}}' "${cid}" 2>/dev/null || true)" [ "${state}" = "true" ] } clean_dir() { local label="$1" local path="$2" local root_with_slash if [ ! -d "${path}" ]; then log "${label}: ${path} not found, skip" return 0 fi root_with_slash="${ROOT_DIR}/" case "${path}/" in "${root_with_slash}"*) ;; *) log "ERROR: ${label} path is outside repo root, refuse to remove: ${path}" return 1 ;; esac log "${label}: removing ${path}" if ! rm -rf "${path}"; then log "ERROR: failed to remove ${label}: ${path}" return 1 fi } while [ "$#" -gt 0 ]; do case "$1" in --force) FORCE=1 shift ;; -h|--help) usage exit 0 ;; *) die "unknown option: $1" ;; esac done stage "Checking Server" [ -f "${SERVER_ENV_FILE}" ] || die "server env file not found: ${SERVER_ENV_FILE}" if [ "${FORCE}" -ne 1 ] && command -v docker >/dev/null 2>&1 && server_running; then die "rpki-rtr is still running, run scripts/03_shutdown.sh first or use --force" fi LOG_DIR="${ROOT_DIR}/logs" REPORT_DIR="$(resolve_host_path "$(env_value RPKI_RTR_REPORT_HOST_DIR '../../report')")" DB_DIR="$(resolve_host_path "$(env_value RPKI_RTR_DB_HOST_DIR '../../rtr-db')")" stage "Removing Server Files" failed_count=0 clean_dir "logs" "${LOG_DIR}" || failed_count=$((failed_count + 1)) clean_dir "report" "${REPORT_DIR}" || failed_count=$((failed_count + 1)) clean_dir "rtr-db" "${DB_DIR}" || failed_count=$((failed_count + 1)) if [ "${failed_count}" -gt 0 ]; then die "${failed_count} cleanup item(s) failed" fi stage "Cleanup Finished"