Skip to content

Stand up the lab

A four-node kind cluster, the chart from a package, and every image pinned by digest.

What it shows. What the other runs are against, and how to tell an install that finished from one that started.

A replay of a verified run, not a live cluster. 6 checks held while it was recorded. Play types it out in the frame below; the transcript is the same session, already there.

sh · lab-setup
# The lab is one cluster, built from the versions this repository declares.$ demo/bin/lab versionskubernetes  1.37.0kind        v0.33.0operator    b98f92bed240a4a34cde9c6bf5bc0cdc07da6d96executor    e2e-registry.demo.svc.cluster.local:5000/ptah-executor@sha256:f68968558f0634c1e388f2be3f8d9d0f7c5916631abe16c5bae55d21e8e909c0ptah        v0.13.0 # The operator runs in its own namespace, two replicas, one leader.$ kubectl -n "$OPERATOR_NAMESPACE" get deploymentNAME                                                           READY   UP-TO-DATE   AVAILABLE   AGEptah-operator-cert-rotator                                     1/1     1            1           10mptah-operator                                                  2/2     2            2           10m # Available means the install finished. The image is a digest, so one exact build runs.$ kubectl -n "$OPERATOR_NAMESPACE" get deployment -o json \  | jq -r '.items[].spec.template.spec.containers[].image'e2e-registry.demo.svc.cluster.local:5000/ptah-operator@sha256:18aafa202d6ebd9a5e65ffb026eb016cfad52eb14224ee8d8891f5eff55b63cde2e-registry.demo.svc.cluster.local:5000/ptah-operator@sha256:18aafa202d6ebd9a5e65ffb026eb016cfad52eb14224ee8d8891f5eff55b63cd # Three resources -- the desired state, the plan, and the decision that lets it run.$ kubectl get crd -o custom-columns=NAME:.metadata.name,ESTABLISHED:'.status.conditions[?(@.type=="Established")].status' \  ptahschemas.operator.ptah.run ptahschemaplans.operator.ptah.run ptahschemaapprovals.operator.ptah.runNAME                                    ESTABLISHEDptahschemas.operator.ptah.run           Trueptahschemaplans.operator.ptah.run       Trueptahschemaapprovals.operator.ptah.run   True # The namespace it works in. Credentials are Secrets; the policy cannot be edited.$ kubectl -n "$NAMESPACE" get secret,configmapNAME                          TYPE                             DATA   AGEsecret/demo-database          Opaque                           6      10msecret/demo-database-broken   Opaque                           1      3m1ssecret/demo-mysql-database    Opaque                           5      10msecret/demo-registry          Opaque                           4      10msecret/demo-registry-pull     kubernetes.io/dockerconfigjson   1      10msecret/demo-shadow-database   Opaque                           2      10m NAME                                               DATA   AGEconfigmap/demo-migration-verification-policy       1      10mconfigmap/demo-verification-policy                 1      10mconfigmap/e2e-verification-policy                  1      11mconfigmap/kube-root-ca.crt                         1      11mconfigmap/ptah-plan-664b0a2d1a26340c2113e29e-000   1      34s

What was checked

Every step states what has to hold before its output may be published. A condition is read as its type, status and reason on the live object, never as a phrase in a message.

StepClaimHeld
1exits 0, prints "kubernetes", prints "kind", prints "operator", prints "executor", prints "ptah"yes
2exits 0, prints "ptah"yes
3deployment/$CONTROLLER: Available=True (MinimumReplicasAvailable)yes
3exits 0, prints "@sha256:"yes
4exits 0, prints "ptahschemas", prints "ptahschemaplans", prints "ptahschemaapprovals"yes
5exits 0, prints "demo-database", prints "demo-registry", prints "demo-verification-policy", never prints "password"yes

What it ran against

  • Kubernetes1.37.0
  • Operatorb98f92bed240
  • Ptahv0.13.0
  • Executorsha256:f68968558f06
  • Recorded2026-10-10
  • Scenarios at0f7a06595d8b

What the commands read

A session is repeated, not admired, so every name in it is one your own environment can carry. There is nothing else: no helper of ours stands between a command and the cluster, and the recorder refuses a step that reads a name this list does not hold. The commands arekubectl, ptah and kubectl ptah, each of which you install once; the last one is the operator’s own read-only client.

  • KUBECONFIGthe cluster the commands run against
  • NAMESPACEthe namespace the schema and its database credentials live in
  • OPERATOR_NAMESPACEwhere the chart installed the operator
  • CONTROLLERthe controller Deployment’s name, from that release
  • REGISTRY_IN_CLUSTERthe registry address a Pod in the cluster resolves
  • PTAH_OCI_REGISTRYthe registry address the push goes to
  • PTAH_OCI_USERNAMEthe account that push uses
  • PTAH_OCI_PASSWORDits password, which no command prints

A session also uses demo/bin/lab in two places, and both are the lab handing over what it generated rather than doing the demonstration’s work:lab credentials prints the three registry values above, and lab manifestfills the published template with values the step states. Rundemo/acceptance/reproduce.sh to watch the same scenario repeated from a directory where neither exists, by an account that may not create a Job, with the plan approved by a second account that may create neither a schema nor a Job.

The scenario is demo/scenarios/lab-setup.yaml, and make demo replays the whole set against a lab of your own. All recorded runs.