prole/tests/etc/test_k3s_cluster_rename.sh
chrisfu 7b242e88f5 Persist k3s context rename and scrub service config paths
Update conf/service/prole.cfg to persist the k3s kube context as knoe.dev.prole.org and replace host-specific absolute paths with $HOME-based paths for portability.

Include all pending project changes: local_user role package and screenrc provisioning updates, plus tools/k3s-cluster-rename.sh and tests/etc/test_k3s_cluster_rename.sh.

Co-authored-by: Junie <junie@jetbrains.com>
2026-03-28 11:23:19 -07:00

195 lines
5.0 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
PROLE_HOME=$(cd "$SCRIPT_DIR/../.." && pwd)
SCRIPT_UNDER_TEST="$PROLE_HOME/tools/k3s-cluster-rename.sh"
TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT
export TMP_DIR
BIN_DIR="$TMP_DIR/bin"
mkdir -p "$BIN_DIR"
cat <<'K_EOF' >"$BIN_DIR/kubectl"
#!/usr/bin/env bash
set -euo pipefail
cfg="${KUBECONFIG:?KUBECONFIG is required}"
if [[ "$*" == "config view --raw -o json" ]]; then
cat "$cfg"
exit 0
fi
if [[ "$*" == "config get-contexts -o name" ]]; then
python3 - "$cfg" <<'PY'
import json
import sys
with open(sys.argv[1], "r", encoding="utf-8") as fh:
data = json.load(fh)
for ctx in data.get("contexts", []):
name = ctx.get("name") if isinstance(ctx, dict) else None
if name:
print(name)
PY
exit 0
fi
echo "unsupported kubectl invocation: $*" >&2
exit 2
K_EOF
chmod +x "$BIN_DIR/kubectl"
cat <<'X_EOF' >"$BIN_DIR/kubectx"
#!/usr/bin/env bash
set -euo pipefail
echo "$*" >>"${TMP_DIR}/kubectx_calls.log"
exit 0
X_EOF
chmod +x "$BIN_DIR/kubectx"
assert_target_names() {
local cfg="$1"
python3 - "$cfg" <<'PY'
import json
import sys
target = "knoe.dev.prole.org"
with open(sys.argv[1], "r", encoding="utf-8") as fh:
data = json.load(fh)
context_names = [c.get("name") for c in data.get("contexts", []) if isinstance(c, dict)]
cluster_names = [c.get("name") for c in data.get("clusters", []) if isinstance(c, dict)]
user_names = [u.get("name") for u in data.get("users", []) if isinstance(u, dict)]
assert target in context_names, f"missing target context: {context_names}"
assert target in cluster_names, f"missing target cluster: {cluster_names}"
assert target in user_names, f"missing target user: {user_names}"
assert data.get("current-context") == target, f"unexpected current-context: {data.get('current-context')}"
for ctx in data.get("contexts", []):
if isinstance(ctx, dict) and ctx.get("name") == target:
body = ctx.get("context") or {}
assert body.get("cluster") == target, f"target context cluster mismatch: {body}"
assert body.get("user") == target, f"target context user mismatch: {body}"
break
else:
raise AssertionError("target context body not found")
PY
}
assert_has_kubectx_call() {
if ! [[ -f "$TMP_DIR/kubectx_calls.log" ]]; then
echo "FAILURE: expected kubectx to be called" >&2
exit 1
fi
if ! grep -q '^knoe.dev.prole.org$' "$TMP_DIR/kubectx_calls.log"; then
echo "FAILURE: expected kubectx to be called with knoe.dev.prole.org" >&2
cat "$TMP_DIR/kubectx_calls.log" >&2
exit 1
fi
}
create_single_context_cfg() {
local cfg="$1"
local name="$2"
cat >"$cfg" <<EOF
{
"apiVersion": "v1",
"kind": "Config",
"clusters": [
{
"name": "${name}",
"cluster": {
"server": "https://example:6443",
"insecure-skip-tls-verify": true
}
}
],
"users": [
{
"name": "${name}",
"user": {
"token": "test-token"
}
}
],
"contexts": [
{
"name": "${name}",
"context": {
"cluster": "${name}",
"user": "${name}",
"namespace": "default"
}
}
],
"current-context": "${name}"
}
EOF
}
export PATH="$BIN_DIR:$PATH"
# Core rename + idempotency
cfg_primary="$TMP_DIR/kubeconfig-primary.json"
create_single_context_cfg "$cfg_primary" "prole-k3s"
bash "$SCRIPT_UNDER_TEST" --kubeconfig "$cfg_primary" --no-backup
assert_target_names "$cfg_primary"
bash "$SCRIPT_UNDER_TEST" --kubeconfig "$cfg_primary" --no-backup
assert_target_names "$cfg_primary"
assert_has_kubectx_call
# Repair fallback when old name is absent but only one context exists
cfg_repair="$TMP_DIR/kubeconfig-repair.json"
create_single_context_cfg "$cfg_repair" "default"
bash "$SCRIPT_UNDER_TEST" --kubeconfig "$cfg_repair" --no-backup
assert_target_names "$cfg_repair"
# Default path behavior: active shell kubeconfig (~/.kube/config when KUBECONFIG unset)
home_dir="$TMP_DIR/home"
mkdir -p "$home_dir/.kube"
cfg_default="$home_dir/.kube/config"
create_single_context_cfg "$cfg_default" "prole-k3s"
unset KUBECONFIG || true
HOME="$home_dir" bash "$SCRIPT_UNDER_TEST" --no-backup
assert_target_names "$cfg_default"
# Negative path: ambiguous fallback must fail
cfg_ambiguous="$TMP_DIR/kubeconfig-ambiguous.json"
cat >"$cfg_ambiguous" <<'EOF'
{
"apiVersion": "v1",
"kind": "Config",
"clusters": [
{"name": "default", "cluster": {"server": "https://default:6443", "insecure-skip-tls-verify": true}},
{"name": "other", "cluster": {"server": "https://other:6443", "insecure-skip-tls-verify": true}}
],
"users": [
{"name": "default", "user": {"token": "t1"}},
{"name": "other", "user": {"token": "t2"}}
],
"contexts": [
{"name": "default", "context": {"cluster": "default", "user": "default"}},
{"name": "other", "context": {"cluster": "other", "user": "other"}}
],
"current-context": "default"
}
EOF
if bash "$SCRIPT_UNDER_TEST" --kubeconfig "$cfg_ambiguous" --no-backup >/dev/null 2>&1; then
echo "FAILURE: expected ambiguous rename to fail" >&2
exit 1
fi
echo "SUCCESS"