k8s-layer
| Version | 2026.144.1443 |
| Repo | superproject |
harness-k8s-fixture — fake Kubernetes API surface for harness phase 5
Stands in for a real k3s cluster. Real k3s cannot run inside the
check-sandbox because the rootless user-namespace slice does not
delegate the cpuset cgroup controller — k3s aborts with
“failed to find cpuset cgroup (v2)” before kubelet starts.
Instead, this layer runs a minimal Python http.server that
replays just the GET endpoints the kube: check verb (client-go
dynamic, now in candy/plugin-kube)
reaches: nodes, services, storageclasses, ingressclasses, the
three k3s addons (traefik / local-path-provisioner /
svclb-traefik). Every list returns a single Ready object so the
harness’s wait-nodes / addons rollups exit 0. Listens on
0.0.0.0:6443 over plain HTTP — the matching kubeconfig sets
insecure-skip-tls-verify: true and uses an http:// server
URL, which client-go honors.
Services
Section titled “Services”harness-k8s-fixture
Acceptance plan
Section titled “Acceptance plan”This candy’s plan: — the runnable spec charly check executes against a live deployment. check: steps are idempotent probes; run: steps change state.
| Intent | Step |
|---|---|
run |
mkdir=/opt/harness-k8s |
run |
write=/opt/harness-k8s/fake_apiserver.py |
check |
the fake Kubernetes apiserver script is installed and executable at /opt/harness-k8s/fake_apiserver.py |
check |
a GET to /api/v1/nodes returns HTTP 200 carrying the Ready fixture node charly-fixture-k8s |
agent-check |
the harness kube: wait-nodes and addon rollups exit 0 against the fixture (nodes, storageclasses, ingressclasses, and the traefik / local-path-provisioner / svclb-traefik addons all report Ready) |
check |
file=/usr/bin/python3 |
check |
package=python3 |
check |
service=harness-k8s-fixture |
check |
port=6443 |
check |
http=http://127.0.0.1:${HOST_PORT:6443}/apis/storage.k8s.io/v1/storageclasses |
check |
http=http://127.0.0.1:${HOST_PORT:6443}/version |