Suspend and resume
One field stops reconciliation without deleting anything, and resuming picks up where it stopped.
What it shows. How to take a database out of the operator's hands during an incident, and give it back.
A replay of a verified run, not a live cluster. 10 checks held while it was recorded. Play types it out in the frame below; the transcript is the same session, already there.
# Converged, and reconciliation is active.$ kubectl -n "$NAMESPACE" get ptahschema storefront -o json \ | jq -r '.status.conditions[] | select(.type == "Suspended") | "\(.type)\t\(.status)\t\(.reason)"'Suspended False Active # Suspend it. One boolean, and the resource stays exactly where it is.$ kubectl -n "$NAMESPACE" patch ptahschema storefront --type=merge -p '{"spec":{"suspend":true}}'ptahschema.operator.ptah.run/storefront patched # The operator says it is suspended, with the reason on the condition.$ kubectl -n "$NAMESPACE" get ptahschema storefront -o jsonpath='{.status.phase}{"\n"}'Suspended # Now publish a change it would otherwise pick up, and point the resource at it.$ eval "$(demo/bin/lab credentials)"export PTAH_OCI_USERNAME PTAH_OCI_PASSWORD PTAH_OCI_REGISTRYDIGEST=$(ptah schema push "oci://$PTAH_OCI_REGISTRY/schemas/demo:v2-$$" \ --schema-file demo/schemas/v2.sql --dialect postgres --plain-http \ | sed -n 's/^Digest: //p')kubectl -n "$NAMESPACE" patch ptahschema storefront --type=merge \ -p "{\"spec\":{\"desired\":{\"ociRef\":\"oci://$REGISTRY_IN_CLUSTER/schemas/demo@$DIGEST\"}}}"ptahschema.operator.ptah.run/storefront patched # Nothing happens, which is the point. The database is untouched.$ kubectl -n "$NAMESPACE" exec deploy/demo-psql -- psql -c "\dt" List of relations Schema | Name | Type | Owner--------+-----------+-------+--------------- public | customers | table | ptah_external(1 row) # Resume, and it starts from what is actually there rather than from what it remembered.$ kubectl -n "$NAMESPACE" patch ptahschema storefront --type=merge -p '{"spec":{"suspend":false}}'ptahschema.operator.ptah.run/storefront patched # It plans against the live database and converges on the revision it was given.$ kubectl -n "$NAMESPACE" exec deploy/demo-psql -- psql -c "\dt" List of relations Schema | Name | Type | Owner--------+-----------+-------+--------------- public | customers | table | ptah_external public | orders | table | ptah_external(2 rows)
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.
| Step | Claim | Held |
|---|---|---|
| 1 | exits 0, prints "Suspended", prints "False", prints "Active" | yes |
| 2 | exits 0, prints "patched" | yes |
| 3 | ptahschema/storefront: Suspended=True (Requested) | yes |
| 3 | exits 0, prints "Suspended" | yes |
| 4 | exits 0, prints "patched" | yes |
| 5 | exits 0, never prints "orders" | yes |
| 5 | ptahschema/storefront: Suspended=True (Requested) | yes |
| 6 | exits 0, prints "patched" | yes |
| 7 | ptahschema/storefront: InSync=True (ScopedConverged) | yes |
| 7 | exits 0, prints "customers", prints "orders" | yes |
What it ran against
- Kubernetes1.37.0
- Operator8c7fe187707f
- Ptahv0.6.0
- Executorsha256:91ec0a6fa27f
- Recorded2026-09-17
- Scenarios at8c7fe187707f
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.
The scenario is demo/scenarios/suspend-resume.yaml, and make demo replays the whole set against a lab of your own. All recorded runs.