#!/usr/bin/env bash # Regression test: init_cloudnative_pg.sh should bootstrap-generate CNPG admin keys # when OpenBao is unavailable and no local admin key files exist. set -euo pipefail SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) KNOE_HOME=$(cd "$SCRIPT_DIR/../.." && pwd) ETC_DIR="$KNOE_HOME/etc" SCRIPT_UNDER_TEST="$ETC_DIR/init_cloudnative_pg.sh" TMP_DIR=$(mktemp -d) trap 'rm -rf "$TMP_DIR"' EXIT export TMP_DIR BIN_DIR="$TMP_DIR/bin" mkdir -p "$BIN_DIR" mock_tool() { cat <"$BIN_DIR/$1" #!/usr/bin/env bash echo "Mocked $1 called with \$@" >>"$TMP_DIR/mock_calls.log" exit 0 M_EOF chmod +x "$BIN_DIR/$1" } # Custom kubectl mock: return minimal outputs so initialize() doesn't hang. cat <<'K_EOF' >"$BIN_DIR/kubectl" #!/usr/bin/env bash _log_file="${TMP_DIR}/mock_calls.log" echo "Mocked kubectl called with $@" >>"${_log_file}" args="$*" # API server readiness probes used by wait_for_apiserver_ready() if [[ "${args}" == *"get --raw=/readyz"* || "${args}" == *"get --raw='/readyz'"* || "${args}" == *"get --raw=\"/readyz\""* ]]; then echo "ok" exit 0 fi if [[ "${args}" == *"version --short"* ]]; then echo "Client Version: v0.0.0" echo "Server Version: v0.0.0" exit 0 fi # Simulate kubectl-cnpg plugin being present, but psql connectivity not yet ready. if [[ "${args}" == *"cnpg"*"version"* ]]; then exit 0 fi if [[ "${args}" == *"cnpg"*"psql"* ]]; then exit 1 fi # Pretend required secrets exist (DB user + TLS artifacts) if [[ "${args}" == *"get secret"*"knoe-db-user"* ]]; then exit 0 fi if [[ "${args}" == *"get secret"*"knoe-db-tls"* || "${args}" == *"get secret"*"knoe-db-ca"* ]]; then exit 0 fi # CNPG webhook wait: return an endpoint IP so wait passes quickly. if [[ "${args}" == *"get endpoints"*"cnpg-webhook-service"* ]]; then echo "10.42.0.10" exit 0 fi # Avoid barman plugin waits (strict readiness now includes service registration) if [[ "${args}" == *"get crd"*"objectstores.barmancloud.cnpg.io"* ]]; then exit 0 fi if [[ "${args}" == *"-n cnpg-system"*"get secret"*"barman-cloud-client-tls"* ]]; then exit 0 fi if [[ "${args}" == *"-n cnpg-system"*"get secret"*"barman-cloud-server-tls"* ]]; then exit 0 fi if [[ "${args}" == *"-n cnpg-system"*"get deploy"*"barman-cloud"* ]]; then exit 0 fi if [[ "${args}" == *"-n cnpg-system"*"rollout status"*"deploy/barman-cloud"* ]]; then exit 0 fi if [[ "${args}" == *"-n cnpg-system"*"get svc"*"-l cnpg.io/pluginName=barman-cloud.cloudnative-pg.io"*"-o jsonpath="*"metadata.name"* ]]; then echo "barman-cloud" exit 0 fi if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"-o jsonpath="*"metadata.name"* ]]; then echo "barman-cloud" exit 0 fi if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginClientSecret"* ]]; then echo "barman-cloud-client-tls" exit 0 fi if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginServerSecret"* ]]; then echo "barman-cloud-server-tls" exit 0 fi if [[ "${args}" == *"-n cnpg-system"*"get svc barman-cloud"*"pluginPort"* ]]; then echo "9090" exit 0 fi if [[ "${args}" == *"-n cnpg-system"*"get endpoints barman-cloud"* ]]; then echo "10.42.0.11" exit 0 fi # CNPG pods listing and readiness queries if [[ "${args}" == *"get pods"* && "${args}" == *"cnpg.io/cluster="* ]]; then if [[ "${args}" == *"--no-headers"* ]]; then echo "knoe-db-1 1/1 Running 0 1m" echo "knoe-db-2 1/1 Running 0 1m" echo "knoe-db-3 1/1 Running 0 1m" exit 0 fi if [[ "${args}" == *"-o jsonpath="* ]]; then printf "True\nTrue\nTrue\n" exit 0 fi fi # Cluster instances if [[ "${args}" == *"get cluster"*"jsonpath="*".spec.instances"* ]]; then echo "3" exit 0 fi # For kubectl create secret --dry-run=client -o yaml, emit a minimal YAML so pipes look realistic. if [[ "${args}" == *"create secret"*"--dry-run=client"*"-o yaml"* ]]; then echo "apiVersion: v1" echo "kind: Secret" exit 0 fi exit 0 K_EOF chmod +x "$BIN_DIR/kubectl" # Other tool mocks mock_tool curl mock_tool docker mock_tool k3d mock_tool skopeo mock_tool jq # Mock knoe.cfg: point KNOE_SERVICE at a non-writable dir so the script must fallback to HOME mkdir -p "$TMP_DIR/conf" mkdir -p "$TMP_DIR/service" chmod 0500 "$TMP_DIR/service" || true TMP_HOME="$TMP_DIR/home" mkdir -p "$TMP_HOME" cat <"$TMP_DIR/conf/knoe.cfg" [User] NAMESPACE = test-ns SERVICE_NAMESPACE = test-system KNOE_HOME = $KNOE_HOME KNOE_SERVICE = $TMP_DIR/service [Global] DEPLOYMENT_MODE = k3d KUBECONTEXT = test [Docker Build] LOCAL_REGISTRY = localhost:5000 LOCAL_REGISTRY_INTERNAL = k3d-knoe-registry.localhost:5000 C_EOF export PATH="$BIN_DIR:$PATH" export HOME="$TMP_HOME" export KNOE_HOME="$KNOE_HOME" export KNOE_CONF="$TMP_DIR/conf" export PROLE_PASSWD="test-password" export KNOE_SERVICE="$TMP_DIR/service" export CNPG_WAIT_TIMEOUT=5 set +e bash "$SCRIPT_UNDER_TEST" --mode k3d initialize >"$TMP_DIR/stdout" 2>"$TMP_DIR/stderr" RC=$? set -e if [[ $RC -ne 0 ]]; then echo "FAILURE: init_cloudnative_pg.sh initialize returned rc=$RC" echo "--- stdout ---" sed -n '1,200p' "$TMP_DIR/stdout" || true echo "--- stderr ---" sed -n '1,200p' "$TMP_DIR/stderr" || true exit 1 fi SECRETS_DIR_FALLBACK="$TMP_HOME/.knoe/etc/secrets" if [[ ! -f "$SECRETS_DIR_FALLBACK/admin.key" || ! -f "$SECRETS_DIR_FALLBACK/admin.pub" ]]; then echo "FAILURE: expected bootstrap-generated admin.key/admin.pub in fallback secrets dir: $SECRETS_DIR_FALLBACK" ls -la "$SECRETS_DIR_FALLBACK" 2>/dev/null || true exit 1 fi if [[ ! -f "$SECRETS_DIR_FALLBACK/admin_ed25519.key" || ! -f "$SECRETS_DIR_FALLBACK/admin_ed25519.pub" ]]; then echo "FAILURE: expected legacy-mirrored admin_ed25519.key/.pub in fallback secrets dir: $SECRETS_DIR_FALLBACK" ls -la "$SECRETS_DIR_FALLBACK" 2>/dev/null || true exit 1 fi echo "SUCCESS"