#!/usr/bin/env bash set -euo pipefail # init_supabase_ports.sh # Purpose: # - Ensure the supabase namespace front-door (svc/db on port 5432) # points to knoe-db-rw in the provided namespace. # - Ensure the Supabase reference Postgres service is on port 15432 # and not host-exposed. PROG="init_supabase_ports" SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) # Load environment and config via prole_cfg.sh # shellcheck disable=SC1090 source "$SCRIPT_DIR/prole_cfg.sh" if [[ "${1:-}" == "--mode" || "${1:-}" == "-m" ]]; then prole_set_mode "${2:-}" shift 2 elif [[ "${1:-}" == --mode=* || "${1:-}" == -m=* ]]; then prole_set_mode "${1#*=}" shift fi SUPABASE_NAMESPACE="${SUPABASE_NAMESPACE:-supabase}" KNOE_DB_SERVICE="${KNOE_DB_SERVICE:-knoe-db-rw}" SUPABASE_DB_SERVICE="${SUPABASE_DB_SERVICE:-db}" SUPABASE_POSTGRES_SERVICE="${SUPABASE_POSTGRES_SERVICE:-supabase-postgres}" SUPABASE_POSTGRES_PORT="${SUPABASE_POSTGRES_PORT:-15432}" DB_PORT="${DB_PORT:-5432}" RESTART_ON_CHANGE=1 usage() { cat < [options] Required: -n, --namespace Namespace that contains svc/$KNOE_DB_SERVICE Options: --supabase-namespace Supabase namespace (default: $SUPABASE_NAMESPACE) --no-restart Do not restart Supabase services on change -h, --help Show this help Notes: - This script creates/updates svc/$SUPABASE_DB_SERVICE in the Supabase namespace as an ExternalName pointing to $KNOE_DB_SERVICE..svc.cluster.local:5432. - When the target namespace changes, Supabase services are restarted automatically. EOF } log() { printf '%s\n' "$*"; } warn() { printf '[warn] %s\n' "$*"; } err() { printf '[error] %s\n' "$*" >&2; } TARGET_NAMESPACE="" while [[ $# -gt 0 ]]; do case "$1" in -n|--namespace) TARGET_NAMESPACE="${2:-}" shift 2 ;; --supabase-namespace) SUPABASE_NAMESPACE="${2:-}" shift 2 ;; --no-restart) RESTART_ON_CHANGE=0 shift ;; -h|--help) usage exit 0 ;; *) err "Unknown argument: $1" usage exit 2 ;; esac done if [[ -z "$TARGET_NAMESPACE" ]]; then err "-n|--namespace is required" usage exit 1 fi ensure_tools() { for t in kubectl; do command -v "$t" >/dev/null || { err "Missing required tool: $t"; exit 1; } done } ensure_namespace() { if ! kubectl get namespace "$SUPABASE_NAMESPACE" >/dev/null 2>&1; then log "Creating namespace '$SUPABASE_NAMESPACE' ..." kubectl create namespace "$SUPABASE_NAMESPACE" >/dev/null 2>&1 || true fi } selector_pairs_to_yaml() { local selector="$1" local out="" local pair key val IFS=',' read -ra pairs <<<"$selector" for pair in "${pairs[@]}"; do pair="$(printf '%s' "$pair" | xargs)" [[ -z "$pair" ]] && continue key="${pair%%=*}" val="${pair#*=}" [[ -z "$key" || -z "$val" ]] && continue out+=" ${key}: ${val}\n" done printf '%b' "$out" } get_selector_pairs() { local out out=$(kubectl -n "$SUPABASE_NAMESPACE" get svc "$1" \ -o jsonpath='{range $k,$v := .spec.selector}{$k}={$v},{end}' 2>/dev/null || true) printf '%s' "$out" | sed 's/,$//' } restart_supabase() { log "Restarting Supabase workloads in namespace '$SUPABASE_NAMESPACE' ..." local restarted=0 if kubectl -n "$SUPABASE_NAMESPACE" get deploy >/dev/null 2>&1; then if kubectl -n "$SUPABASE_NAMESPACE" rollout restart deploy --all >/dev/null 2>&1; then restarted=1 fi fi if kubectl -n "$SUPABASE_NAMESPACE" get sts >/dev/null 2>&1; then if kubectl -n "$SUPABASE_NAMESPACE" rollout restart statefulset --all >/dev/null 2>&1; then restarted=1 fi fi if [[ "$restarted" -eq 0 ]]; then warn "Rollout restart not supported; deleting Supabase pods instead." kubectl -n "$SUPABASE_NAMESPACE" delete pod --all --ignore-not-found >/dev/null 2>&1 || true fi } ensure_tools ensure_namespace if ! kubectl -n "$TARGET_NAMESPACE" get svc "$KNOE_DB_SERVICE" >/dev/null 2>&1; then warn "Service not found: $KNOE_DB_SERVICE in namespace $TARGET_NAMESPACE" fi DESIRED_EXTERNAL="${KNOE_DB_SERVICE}.${TARGET_NAMESPACE}.svc.cluster.local" service_exists=0 current_type="" current_external="" current_selector="" if kubectl -n "$SUPABASE_NAMESPACE" get svc "$SUPABASE_DB_SERVICE" >/dev/null 2>&1; then service_exists=1 current_type=$(kubectl -n "$SUPABASE_NAMESPACE" get svc "$SUPABASE_DB_SERVICE" -o jsonpath='{.spec.type}' 2>/dev/null || true) current_external=$(kubectl -n "$SUPABASE_NAMESPACE" get svc "$SUPABASE_DB_SERVICE" -o jsonpath='{.spec.externalName}' 2>/dev/null || true) current_selector=$(get_selector_pairs "$SUPABASE_DB_SERVICE") fi namespace_changed=1 if [[ "$service_exists" -eq 1 && "$current_type" == "ExternalName" && "$current_external" == "$DESIRED_EXTERNAL" ]]; then namespace_changed=0 fi # Preserve selectors from the previous db service for the reference Postgres service. DB_SELECTOR="$current_selector" if [[ -z "$DB_SELECTOR" ]]; then DB_SELECTOR="${SUPABASE_DB_SELECTOR:-io.kompose.service=db}" fi if [[ "$service_exists" -eq 1 && "$current_type" != "ExternalName" ]]; then log "Replacing service $SUPABASE_NAMESPACE/$SUPABASE_DB_SERVICE with ExternalName -> $DESIRED_EXTERNAL" kubectl -n "$SUPABASE_NAMESPACE" delete svc "$SUPABASE_DB_SERVICE" --ignore-not-found >/dev/null 2>&1 || true fi log "Ensuring $SUPABASE_NAMESPACE/$SUPABASE_DB_SERVICE points to $DESIRED_EXTERNAL:$DB_PORT" cat </dev/null 2>&1; then supabase_pg_exists=1 supabase_pg_type=$(kubectl -n "$SUPABASE_NAMESPACE" get svc "$SUPABASE_POSTGRES_SERVICE" -o jsonpath='{.spec.type}' 2>/dev/null || true) fi if [[ "$supabase_pg_exists" -eq 1 && "$supabase_pg_type" != "ExternalName" ]]; then log "Replacing service $SUPABASE_NAMESPACE/$SUPABASE_POSTGRES_SERVICE with ExternalName on ${SUPABASE_POSTGRES_PORT}" kubectl -n "$SUPABASE_NAMESPACE" delete svc "$SUPABASE_POSTGRES_SERVICE" --ignore-not-found >/dev/null 2>&1 || true supabase_pg_exists=0 fi log "Ensuring $SUPABASE_NAMESPACE/$SUPABASE_POSTGRES_SERVICE uses port ${SUPABASE_POSTGRES_PORT}" cat <