#!/usr/bin/env bash # Clusev image-source resolver — sourced by install.sh. Defines functions only; sourcing has no # side effects. Decides whether to PULL a digest-pinned promoted image or BUILD locally: # env — CLUSEV_IMAGE already set (staging/CI passed it) → respect it, pull. # pull — a public release-images.lock names valid image refs → pull exactly those digests. # build — no lock (dev/source tree) or an unusable lock → build locally (the tree ships Dockerfile). # The result is exposed via the global CLUSEV_RELEASE_MODE + exported CLUSEV_IMAGE/…/CLUSEV_PULL; # the caller persists the pin to .env. No file writes here (keeps it unit-testable without root). # # CLUSEV_RELEASE_MODE is a plain string flag (env|pull|build) read by the caller across the sourcing # boundary, so its literal assignments are deliberate and its "use" is external to this file: # shellcheck disable=SC2209,SC2034 # clusev_json_str FILE KEY -> value of a top-level "KEY": "VALUE" string. jq if present, else sed. # The lock is our own single-object JSON, so the sed fallback is sufficient + dependency-free. clusev_json_str() { local file="$1" key="$2" if command -v jq >/dev/null 2>&1; then jq -er --arg k "$key" '.[$k] // empty' "$file" 2>/dev/null || true else sed -n "s/.*\"${key}\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" "$file" 2>/dev/null | head -n1 fi } # _clusev_ref_ok REF -> true when REF is a plausible registry ref (non-empty, contains a "/" path). # Catches an empty/garbage lock so it falls back to a local build instead of a doomed `pull`. _clusev_ref_ok() { case "$1" in */*) [ -n "$1" ] ;; *) return 1 ;; esac; } # clusev_resolve_release_images [LOCK] [ENVFILE] -> sets CLUSEV_RELEASE_MODE (env|pull|build) and, # on pull/env, exports CLUSEV_PULL (and on pull, CLUSEV_IMAGE/CLUSEV_TERMINAL_IMAGE). ENVFILE is # accepted for signature symmetry with the caller but intentionally NOT written here. clusev_resolve_release_images() { local lock="${1:-release-images.lock}" CLUSEV_RELEASE_MODE=build # 1) staging/CI already pinned the image via the environment — never override it. if [ -n "${CLUSEV_IMAGE:-}" ]; then CLUSEV_RELEASE_MODE=env export CLUSEV_PULL="${CLUSEV_PULL:-1}" return 0 fi # 2) dev/source tree has no lock — build (unchanged). [ -f "$lock" ] || return 0 # 3/4) public tree: pull the exact promoted digests, or build if the lock is unusable. local appref termref appref="$(clusev_json_str "$lock" app)" termref="$(clusev_json_str "$lock" terminal)" if _clusev_ref_ok "$appref" && _clusev_ref_ok "$termref"; then export CLUSEV_IMAGE="$appref" CLUSEV_TERMINAL_IMAGE="$termref" CLUSEV_PULL=1 CLUSEV_RELEASE_MODE=pull fi return 0 }