The operator, recorded
15 sessions, recorded at the terminal against a four-node kind cluster with the operator installed from its chart. Each one is checked while it runs: a recording is published only if every condition it claims held on the live cluster. Open one to read the session in full; Play types it out where it stands.
- Kubernetes1.37.0
- Operatorc08fc73ebbae
- Ptahf6e562c
- Executorsha256:137662e6db45
- Recorded2026-09-28
- Checks held178
- Runs15
These sessions were recorded against Ptah f6e562c. The supported executor is now v0.13.0, so read them as evidence about the operator's behavior rather than as a check that these commands still run unchanged today.
A replay of a verified run, not a live cluster. Nothing on this page talks to anything.
# The lab is one cluster, built from the versions this repository declares.$ demo/bin/lab versionskubernetes 1.37.0kind v0.33.0operator c08fc73ebbae4214f244f1b0d90f4359f0d5ef0aexecutor e2e-registry.demo.svc.cluster.local:5000/ptah-executor@sha256:137662e6db45b7fa5e9aa1f4d188fff8db74d913a13a2f1d426b4dd2b0a4702fptah f6e562c # 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 8m15sptah-operator 2/2 2 2 8m15s # 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:01f5f72a848666b45f2cc2f6df1e16453b94a7f2c54dbb794c6ef5e0c3d69a6be2e-registry.demo.svc.cluster.local:5000/ptah-operator@sha256:01f5f72a848666b45f2cc2f6df1e16453b94a7f2c54dbb794c6ef5e0c3d69a6b # 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 7m56ssecret/demo-database-broken Opaque 1 100ssecret/demo-mysql-database Opaque 5 7m54ssecret/demo-registry Opaque 4 7m57ssecret/demo-registry-pull kubernetes.io/dockerconfigjson 1 7m56ssecret/demo-shadow-database Opaque 2 7m36s NAME DATA AGEconfigmap/demo-migration-verification-policy 1 7m31sconfigmap/demo-verification-policy 1 7m31sconfigmap/e2e-verification-policy 1 8m24sconfigmap/kube-root-ca.crt 1 8m24s
- Stand up the labLabA four-node kind cluster, the chart from a package, and every image pinned by digest.$ demo/bin/lab versions
- Adopt a database that already has a schemaLifecycleRecord the history a database already earned, and let the operator carry on from there.$ kubectl -n "$NAMESPACE" exec deploy/demo-psql -- psql -c "SELECT * FROM shipments ORDER BY id"
- Start a new database from a checkpointLifecycleA fresh database runs the snapshot and what came after it, and ends up where the long way ends.$ ls demo/migrations-checkpoint | grep -v down
- Apply a schemaLifecyclePublish a schema as an artifact, point the operator at it, and watch it converge.$ cat demo/schemas/v1.sql
- Manage reference dataLifecycleRows declared beside the tables that hold them, reconciled through the same plan.$ sed -n '/ptah:schema:table name="regions"/,/^}/p' demo/reference/v1/catalog.go
- Change the schemaLifecycleA second revision, a new digest, and the difference applied as one plan.$ kubectl -n "$NAMESPACE" exec deploy/demo-psql -- psql -c "\dt"
- Ship a second release onto rows that already existLifecycleA backfill that runs against real data, and a history that says it ran once.$ APPLY=Always demo/bin/lab manifest shipments "$(cat demo/.lab/release-1-digest)" | kubectl apply -f -
- Run a prepared migration sequenceLifecycleNumbered SQL files in an artifact, matched against the database's own record of what has run.$ ls demo/migrations
- Refuse a destructive changeSafetyThe third revision drops a column. The policy says no, and says so before anything runs.$ kubectl -n "$NAMESPACE" exec deploy/demo-psql -- psql -c "INSERT INTO customers (id, email) VALUES (1, 'a@example.test') RETURNING id, email"
- Approve a planSafetyWith apply set to OnApproval, nothing runs until a person approves that exact plan.$ APPLY=OnApproval demo/bin/lab manifest storefront "$(cat demo/.lab/digest)" | tee demo/.lab/storefront.yaml
- Retire a used approvalSafetyAn approval describes one plan against one observed state. Applying it moves that state.$ kubectl -n "$NAMESPACE" get ptahschema storefront -o jsonpath='{.status.phase}{"\n"}{.status.plan.fingerprint}{"\n"}'
- Close the driftOperationsSomeone changes the database by hand. The operator notices and puts it back.$ kubectl -n "$NAMESPACE" get ptahschema storefront -o json
- Fail, then recoverOperationsPoint it at a database that is not there. It says so, keeps trying, and converges when it is.$ APPLY=Always demo/bin/lab manifest storefront "$(cat demo/.lab/digest)"
- Recover a MySQL migration that stopped halfwayOperationsDDL that committed, a run nobody can retry, and a repair decided by what the database holds.$ APPLY=Always demo/bin/lab manifest deliveries "$(cat demo/.lab/deliveries-1-digest)" | kubectl apply -f -
- Suspend and resumeOperationsOne field stops reconciliation without deleting anything, and resuming picks up where it stopped.$ kubectl -n "$NAMESPACE" get ptahschema storefront -o json