prole/mock_val/preflight_kubecontext.sh
chrisfu 3943d1b298 feat(mock_val): add diagnostics, utilities, and misc operational scripts
Diagnostics:
  diag_gitlab_boot.sh, diag_gitlab_webservice_oom.sh, diag_gke_storage.sh

Utilities:
  ensure_default_storage_class.sh — set/verify default StorageClass
  preflight_kubecontext.sh        — validate kubecontext before ops
  onboard_engineer.sh             — new engineer onboarding script
  gen_oidc_signing_key.sh         — generate OIDC signing key
  fetch_prole_secrets.sh          — pull secrets from vault
  set-k3s-token-1password.sh      — store k3s token in 1Password
  sync_cnpg_grafana_dashboard.py  — sync CNPG dashboard to Grafana

Config/certs:
  krb5.local.conf, knoe-db-ca.crt

Updated: build-a-bao.sh, hostprobe-*.yaml, hosts.txt, knoe-db-passwwd.sh,
         repair_pipeline.sh, status.sh, status_common_services.sh
Co-authored-by: Junie <junie@jetbrains.com>
2026-05-23 21:31:40 -07:00

135 lines
4.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# preflight_kubecontext.sh
#
# Shared helper to detect the "wrong shell context for the install mode"
# class of bug. Sourced by install.sh and deploy.sh.
#
# Exposes two functions:
#
# verify_kubecontext_matches_config <config-path>
# Strict gate. Reads APP_CLUSTER_KUBECONTEXT from the config's [Global]
# section and refuses to proceed if `kubectl config current-context`
# doesn't match. Used by deploy.sh (unattended path: silent mismatches
# are dangerous).
#
# Returns 0 on match (or when the config has no APP_CLUSTER_KUBECONTEXT,
# e.g. fresh k3d setup). Exits 1 with a clear error on mismatch.
# Set KNOE_SKIP_KUBECONTEXT_GUARD=true to bypass (escape hatch for
# deliberate cross-cluster maintenance).
#
# print_kubecontext_notice
# Informational. Prints the current kubectl context (or "(none)") so
# the user sees what install.sh is about to inherit before the TUI
# launches. Never exits or fails. Used by install.sh.
#
# History: this guard was filed in response to the 2026-04-28 14:00 UTC
# outage. An install.sh run in k3d mode with the shell pointed at GKE
# overwrote the GKE-cluster ObjectStore + ScheduledBackup with k3d-mode
# defaults, and CNPG backups silently failed for hours until the next
# manual check. See CLAUDE.md §"Env-contamination warning" and
# docs/TODO.md queue item #1 (drift R4).
# Read APP_CLUSTER_KUBECONTEXT from the [Global] section of an INI-style
# config. Empty string if absent. Quote-stripping is best-effort.
_kubectx_from_config() {
local cfg="$1"
[[ -f "$cfg" ]] || { echo ""; return 0; }
# awk: print value when we're in [Global] and key matches.
# Strips surrounding whitespace and quotes.
awk '
/^\[/{section=$0; next}
section=="[Global]" && /^[[:space:]]*APP_CLUSTER_KUBECONTEXT[[:space:]]*=/ {
sub(/^[^=]*=[[:space:]]*/, "", $0)
sub(/^"/, "", $0); sub(/"$/, "", $0)
sub(/^'\''/, "", $0); sub(/'\''$/, "", $0)
print $0
exit
}
' "$cfg"
}
# Read the live current-context, or empty if kubectl/config unavailable.
_kubectx_current() {
command -v kubectl >/dev/null 2>&1 || { echo ""; return 0; }
kubectl config current-context 2>/dev/null || true
}
# verify_kubecontext_matches_config <config-path>
# Strict gate. Exits 1 on mismatch unless KNOE_SKIP_KUBECONTEXT_GUARD=true.
verify_kubecontext_matches_config() {
local cfg_path="${1:-}"
if [[ -z "$cfg_path" ]]; then
echo "preflight_kubecontext: usage: verify_kubecontext_matches_config <config-path>" >&2
return 2
fi
if [[ "${KNOE_SKIP_KUBECONTEXT_GUARD:-false}" == "true" ]]; then
echo "preflight_kubecontext: KNOE_SKIP_KUBECONTEXT_GUARD=true — skipping check (escape hatch)." >&2
return 0
fi
local expected
expected="$(_kubectx_from_config "$cfg_path")"
# No baked context in the config (e.g. fresh k3d.cfg) → nothing to check.
if [[ -z "$expected" ]]; then
return 0
fi
local actual
actual="$(_kubectx_current)"
# No live current-context → user hasn't selected one; the config is
# authoritative and downstream code will pass --context explicitly.
if [[ -z "$actual" ]]; then
return 0
fi
if [[ "$expected" == "$actual" ]]; then
return 0
fi
cat >&2 <<EOF
==============================================================================
ABORTING: kubectl context mismatch
==============================================================================
Config: $cfg_path
Expected: APP_CLUSTER_KUBECONTEXT = $expected
Actual: kubectl config current-context = $actual
These don't match. The installer would dispatch kubectl operations
against the WRONG cluster, which has caused real outages in the past
(see CLAUDE.md §"Env-contamination warning"). Refusing to proceed.
To fix:
1) Switch context to the expected cluster:
kubectl config use-context $expected
Re-run this command afterward.
2) Or, if you really need to deploy against the active context, edit
\`$cfg_path\` and update [Global] APP_CLUSTER_KUBECONTEXT to match.
3) Override (only when you know what you're doing):
KNOE_SKIP_KUBECONTEXT_GUARD=true ./deploy.sh
==============================================================================
EOF
return 1
}
# print_kubecontext_notice
# Informational. Never fails; just shows the user what's about to be
# inherited so they can abort before the TUI launches if it looks wrong.
print_kubecontext_notice() {
local actual
actual="$(_kubectx_current)"
if [[ -z "$actual" ]]; then
echo "==> kubectl current-context: (none set)"
else
echo "==> kubectl current-context: $actual"
fi
echo " The mode you select must target this cluster, OR you must switch"
echo " context (kubectl config use-context …) before proceeding."
}