#!/usr/bin/env bash set -euo pipefail # init_db_manager.sh # Purpose: # - Build and deploy the knoe-db-manager Node.js REST endpoint # - Provides /backup//full to trigger barman full backups into Garage # - Deploys to the knoe-db namespace; accessible via Kong endpoint /backup # - Deploys to the current cluster (k3d or k3s) based on KNOE_MODE from active config # # Usage: # ./init_db_manager.sh [--mode MODE] SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) # shellcheck disable=SC1090 source "$SCRIPT_DIR/knoe_cfg.sh" if [[ "${1:-}" == "--mode" || "${1:-}" == "-m" ]]; then knoe_set_mode "${2:-}" shift 2 elif [[ "${1:-}" == --mode=* || "${1:-}" == -m=* ]]; then knoe_set_mode "${1#*=}" shift fi ACTION=${1:-start} NAMESPACE="${PROLE_NAMESPACE}" KNOE_HOME=${KNOE_HOME:-$(cd "$SCRIPT_DIR/.." && pwd)} DB_MANAGER_IMAGE=${DB_MANAGER_IMAGE:-knoe-db-manager:latest} DB_MANAGER_NAME=${DB_MANAGER_NAME:-knoe-db-manager} DB_MANAGER_PORT=${DB_MANAGER_PORT:-80} DB_MANAGER_SRC=${DB_MANAGER_SRC:-$KNOE_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:-knoe-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() { # k3s: publish image to the shared registry and let nodes pull it. if [[ -z "${REGISTRY:-}" ]]; then local host host="$(_knoe_host_from_url "${PROLE_K3S_SERVER:-${K3S_SERVER_URL:-}}")" if [[ -n "${host:-}" ]]; then REGISTRY="${host}:5000" fi fi if [[ -z "${REGISTRY:-}" ]]; then echo "WARN: REGISTRY not set and PROLE_K3S_SERVER missing; cannot publish image for k3s." >&2 echo " Image must be available via a registry for k3s to pull." >&2 return 0 fi local remote_tag="${REGISTRY}/${DB_MANAGER_IMAGE}" echo "Publishing $remote_tag ..." docker tag "$DB_MANAGER_IMAGE" "$remote_tag" >/dev/null 2>&1 || true if ! docker push "$remote_tag"; then if command -v skopeo >/dev/null 2>&1; then echo "WARN: docker push failed; retrying with skopeo (insecure registry) ..." >&2 skopeo copy --dest-tls-verify=false "docker-daemon:${DB_MANAGER_IMAGE}" "docker://${remote_tag}" else echo "ERROR: docker push failed and skopeo is not available." >&2 return 1 fi fi } deploy() { echo "Deploying $DB_MANAGER_NAME to namespace '$NAMESPACE' ..." local manifests_dir="$KNOE_HOME/deploy/opentofu/k3s/manifests/knoe" # Only deploy db-manager resources — the full kustomization includes services # (garage, openbao, knoe, 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 "${KNOE_MODE:-k3d}" in k3d) import_image_k3d ;; k3s) import_image_k3s ;; *) echo "WARN: Unknown mode '${KNOE_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