#!/usr/bin/env bash set -euo pipefail # init_redis.sh # Purpose: # - Deploy Redis as a shared common service via Bitnami Helm chart # - Provides a pub/sub-capable Redis instance for knoe CLI, desktop, and GitLab # - Runs in knoe-system (or SERVICE_NAMESPACE) so all services can reach it # - Service endpoint: redis-master..svc.cluster.local:6379 SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) # Shared option parsing for common core scripts # shellcheck disable=SC1090 source "$SCRIPT_DIR/common_core_lib.sh" # Inject default config if not provided _has_config=0 for _arg in "$@"; do [[ "$_arg" == "-c" || "$_arg" == "--config" || "$_arg" == -c=* || "$_arg" == --config=* ]] && _has_config=1 done if [[ $_has_config -eq 0 ]]; then _default_cfg="$(common_core_default_config_path "$SCRIPT_DIR" || true)" if [[ -n "$_default_cfg" ]]; then set -- "-c" "$_default_cfg" "$@" fi fi unset _has_config _arg _default_cfg common_core_preparse_config "$@" # shellcheck disable=SC1090 source "$SCRIPT_DIR/prole_cfg.sh" set -- "${COMMON_CORE_ARGS[@]}" common_core_parse_args "$@" if [[ -z "${PROLE_MODE:-}" ]]; then export PROLE_MODE="k3s" fi if [[ "${COMMON_CORE_HELP:-0}" == 1 ]]; then common_core_usage "$0" exit 0 fi if [[ -n "${COMMON_CORE_PARSE_ERROR:-}" ]]; then echo "ERROR: ${COMMON_CORE_PARSE_ERROR}" >&2 common_core_usage "$0" exit 2 fi ACTION="$COMMON_CORE_ACTION" NAMESPACE="$(common_core_resolve_namespace "${SERVICE_NAMESPACE:-knoe-system}")" common_core_apply_namespace "$NAMESPACE" REDIS_RELEASE="${REDIS_RELEASE:-redis}" REDIS_REPO_NAME="bitnami" REDIS_REPO_URL="https://charts.bitnami.com/bitnami" REDIS_CHART="bitnami/redis" REDIS_CHART_VERSION="${REDIS_CHART_VERSION:-}" REDIS_PORT="${REDIS_PORT:-6379}" REDIS_PVC_SIZE="${REDIS_PVC_SIZE:-1Gi}" # No dynamic provisioner is available in the service cluster; persistence disabled by default # (Redis is used as a pub/sub broker — durable storage is not required) REDIS_STORAGE_CLASS="${REDIS_STORAGE_CLASS:-${STORAGE_CLASS:-}}" REDIS_PERSISTENCE_ENABLED="${REDIS_PERSISTENCE_ENABLED:-false}" # Image registry override — set to "registry.bitnami.com" if docker.io is unreachable # Bitnami OCI registry works as an alternative when Docker Hub times out on constrained networks. REDIS_IMAGE_REGISTRY="${REDIS_IMAGE_REGISTRY:-}" # Helm timeout — increase for slow image pulls on constrained network links (e.g. Pi cluster) REDIS_HELM_TIMEOUT="${REDIS_HELM_TIMEOUT:-8m}" log() { echo "[INFO] $*"; } warn() { echo "[WARN] $*" >&2; } die() { echo "[ERROR] $*" >&2; exit 1; } command -v helm >/dev/null 2>&1 || die "helm not found" command -v kubectl >/dev/null 2>&1 || die "kubectl not found" # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- redis_service_host() { printf '%s-master.%s.svc.cluster.local' "$REDIS_RELEASE" "$NAMESPACE" } redis_is_running() { kubectl -n "$NAMESPACE" get deployment "${REDIS_RELEASE}-master" >/dev/null 2>&1 || \ kubectl -n "$NAMESPACE" get statefulset "${REDIS_RELEASE}-master" >/dev/null 2>&1 } # --------------------------------------------------------------------------- # Deploy # --------------------------------------------------------------------------- deploy_redis() { # If Redis is already running and REDIS_FORCE_UPGRADE is not set, skip the # helm upgrade to avoid Docker Hub / OCI registry timeouts on constrained # networks (e.g. Pi cluster where registry-1.docker.io may be unreachable). # Set REDIS_FORCE_UPGRADE=1 to force a chart upgrade regardless. if [[ "${REDIS_FORCE_UPGRADE:-0}" != "1" ]] && redis_is_running; then log "Redis already running in '${NAMESPACE}'; skipping upgrade." log "Set REDIS_FORCE_UPGRADE=1 to force a helm upgrade." return 0 fi log "Adding/updating Bitnami Helm repo..." helm repo add "$REDIS_REPO_NAME" "$REDIS_REPO_URL" 2>&1 || true helm repo update "$REDIS_REPO_NAME" 2>&1 || warn "helm repo update returned non-zero; continuing..." kubectl get namespace "$NAMESPACE" >/dev/null 2>&1 || kubectl create namespace "$NAMESPACE" >/dev/null local helm_args=( upgrade --install "$REDIS_RELEASE" "$REDIS_CHART" --namespace "$NAMESPACE" --create-namespace --timeout "$REDIS_HELM_TIMEOUT" --wait --set architecture=standalone --set auth.enabled=false --set master.persistence.enabled="${REDIS_PERSISTENCE_ENABLED}" --set master.persistence.size="$REDIS_PVC_SIZE" --set master.resources.requests.memory=128Mi --set master.resources.requests.cpu=50m --set master.resources.limits.memory=512Mi --set master.resources.limits.cpu=500m ) if [[ -n "$REDIS_CHART_VERSION" ]]; then helm_args+=(--version "$REDIS_CHART_VERSION") fi if [[ -n "$REDIS_STORAGE_CLASS" ]]; then helm_args+=(--set master.persistence.storageClass="$REDIS_STORAGE_CLASS") fi if [[ -n "$REDIS_IMAGE_REGISTRY" ]]; then log "Using image registry override: ${REDIS_IMAGE_REGISTRY}" helm_args+=(--set global.imageRegistry="$REDIS_IMAGE_REGISTRY") fi log "Deploying Redis (release=${REDIS_RELEASE}, ns=${NAMESPACE})..." helm "${helm_args[@]}" log "Redis ready. Endpoint: $(redis_service_host):${REDIS_PORT}" log "Pub/sub: redis-cli -h $(redis_service_host) -p ${REDIS_PORT} subscribe " } # --------------------------------------------------------------------------- # Action dispatch # --------------------------------------------------------------------------- case "$ACTION" in start|update|reload|initialize|restart) deploy_redis ;; stop) log "Removing Redis (${REDIS_RELEASE}) from namespace ${NAMESPACE}..." helm -n "$NAMESPACE" uninstall "$REDIS_RELEASE" 2>/dev/null || warn "Redis release not found." ;; status) log "Redis status in namespace ${NAMESPACE}:" kubectl -n "$NAMESPACE" get pods -l "app.kubernetes.io/name=redis" 2>/dev/null || \ echo " No Redis pods found." kubectl -n "$NAMESPACE" get svc -l "app.kubernetes.io/name=redis" 2>/dev/null || true ;; *) die "Unknown action: $ACTION" ;; esac