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
102 lines
4.6 KiB
Bash
Executable File
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)"
|