#!/usr/bin/env bash set -euo pipefail # init_db_manager.sh # Purpose: # - Build and deploy the prole-db-manager Node.js REST endpoint # - Provides /backup//full to trigger barman full backups into Garage # - Deploys to the prole-db namespace; accessible via Kong endpoint /backup # - Deploys to the current cluster (k3d or k3s) based on PROLE_MODE from conf/prole.cfg # # Usage: # ./init_db_manager.sh [--mode MODE] SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) # 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 ACTION=${1:-start} NAMESPACE="${PROLE_NAMESPACE}" PROLE_HOME=${PROLE_HOME:-$(cd "$SCRIPT_DIR/.." && pwd)} DB_MANAGER_IMAGE=${DB_MANAGER_IMAGE:-prole-db-manager:latest} DB_MANAGER_NAME=${DB_MANAGER_NAME:-prole-db-manager} DB_MANAGER_PORT=${DB_MANAGER_PORT:-80} DB_MANAGER_SRC=${DB_MANAGER_SRC:-$PROLE_HOME/src/db-manager} REGISTRY=${REGISTRY:-} usage() { cat < Actions: start Build image and deploy db-manager to current cluster (k3d/k3s) stop Remove db-manager deployment status Show db-manager pod/service status restart Restart db-manager pods build Build the container image only USAGE exit 1 } ensure_tools() { for t in kubectl docker; do command -v "$t" >/dev/null || { echo "Missing required tool: $t" >&2; exit 1; } done } ensure_namespace() { if ! kubectl get namespace "$NAMESPACE" >/dev/null 2>&1; then echo "Creating namespace '$NAMESPACE' ..." kubectl create namespace "$NAMESPACE" >/dev/null 2>&1 || true fi } build_image() { echo "Building $DB_MANAGER_IMAGE from $DB_MANAGER_SRC ..." docker build -t "$DB_MANAGER_IMAGE" "$DB_MANAGER_SRC" if [[ -n "$REGISTRY" ]]; then local remote_tag="${REGISTRY}/${DB_MANAGER_IMAGE}" echo "Pushing $remote_tag ..." docker tag "$DB_MANAGER_IMAGE" "$remote_tag" docker push "$remote_tag" fi } import_image_k3d() { if ! command -v k3d >/dev/null 2>&1; then echo "WARN: k3d not available; skipping k3d image import." >&2 return 0 fi local cluster_name="${K3D_CLUSTER_NAME:-prole-dev-cluster}" echo "Importing $DB_MANAGER_IMAGE into k3d cluster '$cluster_name' ..." k3d image import "$DB_MANAGER_IMAGE" -c "$cluster_name" >/dev/null 2>&1 || true echo "Image imported to k3d cluster successfully." } import_image_k3s() { if ! command -v ansible >/dev/null 2>&1; then echo "WARN: ansible not available; skipping k3s image import (image must already exist on nodes)." >&2 return 0 fi local export_dir="${DOCKER_IMPORT_DIR:-/tmp}" local safe_name safe_name=$(echo "$DB_MANAGER_IMAGE" | sed 's/\//_/g; s/:/_/g') local tar_path="${export_dir%/}/${safe_name}.tar" local ansible_cfg="$PROLE_HOME/ansible.cfg" local vault_file="${ANSIBLE_VAULT_PASSWORD_FILE:-}" local dest="/tmp/$(basename "$tar_path")" local ansible_args=("ansible" "k3s_hosts") mkdir -p "$export_dir" echo "Exporting $DB_MANAGER_IMAGE to $tar_path ..." docker save -o "$tar_path" "$DB_MANAGER_IMAGE" if [[ -z "$vault_file" && -f "$PROLE_HOME/.vault_pass" ]]; then vault_file="$PROLE_HOME/.vault_pass" fi if [[ -n "$vault_file" ]]; then ansible_args+=("--vault-password-file" "$vault_file") fi echo "Importing $DB_MANAGER_IMAGE into k3s nodes ..." if [[ -f "$ansible_cfg" ]]; then ANSIBLE_CONFIG="$ansible_cfg" "${ansible_args[@]}" -m copy -a "src=$tar_path dest=$dest mode=0644" || { echo "ERROR: Failed to copy image to k3s nodes." >&2; return 1; } ANSIBLE_CONFIG="$ansible_cfg" "${ansible_args[@]}" -m shell -a "ctr -n k8s.io -a /run/k3s/containerd/containerd.sock images import --no-unpack $dest" || { echo "ERROR: Failed to import image into k3s nodes." >&2; return 1; } else "${ansible_args[@]}" -m copy -a "src=$tar_path dest=$dest mode=0644" || { echo "ERROR: Failed to copy image to k3s nodes." >&2; return 1; } "${ansible_args[@]}" -m shell -a "ctr -n k8s.io -a /run/k3s/containerd/containerd.sock images import --no-unpack $dest" || { echo "ERROR: Failed to import image into k3s nodes." >&2; return 1; } fi echo "Image imported to k3s nodes successfully." } deploy() { echo "Deploying $DB_MANAGER_NAME to namespace '$NAMESPACE' ..." local manifests_dir="$PROLE_HOME/deploy/opentofu/k3s/manifests/prole" # Only deploy db-manager resources — the full kustomization includes services # (garage, openbao, prole, etc.) that belong in the service namespace and would # create duplicates if applied here. kubectl apply -f "$manifests_dir/db-manager-deployment.yaml" -n "$NAMESPACE" kubectl apply -f "$manifests_dir/db-manager-service.yaml" -n "$NAMESPACE" # Apply cross-namespace ingresses separately (they have their own namespace metadata) # Only apply if the target namespace already exists to avoid errors if [[ -f "$manifests_dir/dashboard-ingress.yaml" ]] && kubectl get namespace kubernetes-dashboard >/dev/null 2>&1; then kubectl apply -f "$manifests_dir/dashboard-ingress.yaml" || true fi if [[ -f "$manifests_dir/supabase-ingress.yaml" ]] && kubectl get namespace supabase >/dev/null 2>&1; then kubectl apply -f "$manifests_dir/supabase-ingress.yaml" || true fi echo "Waiting for $DB_MANAGER_NAME rollout ..." kubectl rollout status deployment/"$DB_MANAGER_NAME" -n "$NAMESPACE" --timeout=120s echo "$DB_MANAGER_NAME deployed successfully." } stop() { echo "Removing $DB_MANAGER_NAME from namespace '$NAMESPACE' ..." kubectl delete deployment "$DB_MANAGER_NAME" -n "$NAMESPACE" --ignore-not-found=true kubectl delete service "$DB_MANAGER_NAME" -n "$NAMESPACE" --ignore-not-found=true echo "$DB_MANAGER_NAME removed." } status() { echo "=== $DB_MANAGER_NAME pods ===" kubectl get pods -n "$NAMESPACE" -l app="$DB_MANAGER_NAME" 2>/dev/null || echo "No pods found" echo "" echo "=== $DB_MANAGER_NAME service ===" kubectl get svc "$DB_MANAGER_NAME" -n "$NAMESPACE" 2>/dev/null || echo "No service found" } restart() { echo "Restarting $DB_MANAGER_NAME ..." kubectl rollout restart deployment/"$DB_MANAGER_NAME" -n "$NAMESPACE" kubectl rollout status deployment/"$DB_MANAGER_NAME" -n "$NAMESPACE" --timeout=120s echo "$DB_MANAGER_NAME restarted." } case "$ACTION" in start) ensure_tools ensure_namespace build_image case "${PROLE_MODE:-k3d}" in k3d) import_image_k3d ;; k3s) import_image_k3s ;; *) echo "WARN: Unknown mode '${PROLE_MODE:-}'; skipping image import." >&2 ;; esac deploy ;; stop) ensure_tools stop ;; status) ensure_tools status ;; restart) ensure_tools restart ;; build) ensure_tools build_image ;; *) usage ;; esac