cka-sim/setup.sh
vumast3r 43e2e1db2f refactor: renumber the CKA bank 1-102 with no gaps
Task ids used to jump 1-43 / 101-124 / 401-418 / 501-517. They now run
contiguously in the same order:

  1-43    unchanged (base and extra)
  44-67   hard pool          (was 101-124)
  68-85   Simulator Set C    (was 401-418)
  86-102  Simulator Set D    (was 501-517)

Every reference moved with its task: ids, solution keys, workspace paths
({WS}/qNN and the graders' hidden .qNN-* files), temp paths, the one
hardcoded id in code (Q56's derived canary weight), and Q-number
cross-references in the harness, README and the explainer. Each task's
paths were checked to carry only its own new number. History entries and
the local session state were remapped so past attempts stay attached to the
same tasks; retired set A/B ids keep their old numbers and match nothing.
weak-spots is regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mhxm4rsUfuE5HoytYbu2YW
2026-09-22 22:05:37 -06:00

102 lines
4.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# Bootstraps the cka-sim kind cluster (1 control-plane + 3 workers) on podman and preloads images.
# Override with CONTAINER_RUNTIME=docker if you ever want docker instead.
set -euo pipefail
cd "$(dirname "$0")"
RT="${CONTAINER_RUNTIME:-podman}"
need() {
command -v "$1" >/dev/null 2>&1 || { echo "ERROR: '$1' is not installed. $2"; exit 1; }
}
need "$RT" "https://podman.io/docs/installation"
need kind "https://kind.sigs.k8s.io/docs/user/quick-start/#installation"
need kubectl "https://kubernetes.io/docs/tasks/tools/"
need python3 ""
if [ "$RT" = podman ]; then
export KIND_EXPERIMENTAL_PROVIDER=podman
podman info >/dev/null 2>&1 || { echo "ERROR: podman is not working (try: podman info)."; exit 1; }
# kind needs cgroup v2 with controller delegation when podman is rootless.
if [ "$(id -u)" != 0 ] && [ "$(podman info --format '{{.Host.CgroupsVersion}}' 2>/dev/null)" != "v2" ]; then
echo "ERROR: rootless podman needs cgroup v2 for kind. Either enable cgroup v2 or run setup as root (sudo -E ./setup.sh)."
exit 1
fi
# inotify limits are the #1 cause of pods stuck in ContainerCreating on multi-node kind
for k in fs.inotify.max_user_watches:524288 fs.inotify.max_user_instances:512; do
key=${k%%:*}; want=${k##*:}; have=$(sysctl -n "$key" 2>/dev/null || echo 0)
[ "$have" -ge "$want" ] || echo "warn: $key=$have (recommend >= $want: sudo sysctl $key=$want)"
done
else
docker info >/dev/null 2>&1 || { echo "ERROR: docker daemon is not running/reachable."; exit 1; }
fi
if kind get clusters 2>/dev/null | grep -qx cka-sim; then
echo "==> kind cluster 'cka-sim' already exists, reusing it."
else
echo "==> Creating kind cluster 'cka-sim' on $RT (1 control-plane + 3 workers)..."
kind create cluster --config kind-config.yaml ${KIND_NODE_IMAGE:+--image "$KIND_NODE_IMAGE"} --wait 180s
fi
kubectl config use-context kind-cka-sim >/dev/null
echo "==> Waiting for nodes..."
kubectl wait --for=condition=Ready nodes --all --timeout=180s
echo "==> Preloading images into the cluster (non-fatal if a pull fails)..."
# `kind load docker-image` shells out to the docker CLI internally no matter which
# provider the cluster uses, so it can't see images that only exist in podman's
# store. Save to a tar and use `kind load image-archive` instead, which is
# runtime-agnostic.
for img in nginx:1.25 nginx:1.27 busybox:1.36 redis:7-alpine; do
if "$RT" pull -q "docker.io/library/$img" >/dev/null 2>&1; then
tarfile="$(mktemp)"
if "$RT" save -o "$tarfile" "docker.io/library/$img" >/dev/null 2>&1 \
&& kind load image-archive --name cka-sim "$tarfile" >/dev/null 2>&1; then
echo " loaded $img"
else
echo " warn: could not load $img"
fi
rm -f "$tarfile"
else
echo " warn: could not pull $img (tasks will pull at runtime)"
fi
done
echo "==> Making sure the exam workdir exists on the control-plane node..."
"$RT" exec cka-sim-control-plane mkdir -p /opt/cka
# The real exam gives you vim (and less/jq) on every node; the kind node image is minimal, so
# install them once here. Skip with CKA_SKIP_NODE_TOOLS=1.
if [ -z "${CKA_SKIP_NODE_TOOLS:-}" ]; then
echo "==> Installing editors and tools on the nodes (vim, nano, less, jq)..."
for n in $(kind get nodes --name cka-sim); do
if "$RT" exec "$n" sh -c 'command -v vim >/dev/null'; then
echo " $n already has vim"
continue
fi
if "$RT" exec "$n" sh -c 'DEBIAN_FRONTEND=noninteractive apt-get update -qq >/dev/null 2>&1 && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq vim nano less jq >/dev/null 2>&1'; then
"$RT" exec "$n" sh -c 'printf "set tabstop=2\nset expandtab\nset shiftwidth=2\n" > /root/.vimrc'
echo " $n ok"
else
echo " warn: could not install tools on $n (no outbound network?). Fall back to:"
echo " $RT cp $n:/path/file /tmp/f && \$EDITOR /tmp/f && $RT cp /tmp/f $n:/path/file"
fi
done
fi
# The exam expects etcdctl/etcdutl on the control-plane node, like the real one. They cannot be
# copied out of the running etcd pod (that image is distroless), so install them properly.
echo "==> Installing etcdctl/etcdutl on the control-plane node..."
printf ' '
CONTAINER_RUNTIME="$RT" bash ./etcd-tools.sh || echo " warn: no etcd client on the control-plane node; Q02/Q45 will say so when they seed"
# remember the runtime so the CLI uses the matching exec command
mkdir -p .state && echo "$RT" > .state/runtime
chmod +x exam
echo
echo "Cluster ready. Nodes:"
kubectl get nodes -o wide
echo
echo "Next: ./exam web (browser UI) or ./exam drill (5 tasks from your least-drilled domain)"