Evidence · How close AWS is
corpus-quickpizza
grafana/quickpizza deployments/terraform (tag v0.15.28), Grafana Labs’ QuickPizza demo application’s own Kubernetes deployment root: a namespace, seven Deployments with their Services, a Postgres StatefulSet, ConfigMaps, Secrets, a ServiceAccount and a ClusterRoleBinding; the kubernetes lane’s first published estate
Source: https://github.com/grafana/quickpizza.git at v0.15.28.
Set: growing. Lane: kubernetes.
Clear. Every headline stage passes.
| Stage | Verdict | Duration | Detail |
|---|---|---|---|
| Cold deploy | pass | 2m25s | 26 objects (namespace, 7 Deployments, 8 Services, a StatefulSet, 2 ConfigMaps, 3 Secrets, a ServiceAccount, a ClusterRoleBinding) from plain terraform on the unmodified published root plus its deltas (kubeconfig lines dropped, placeholder Grafana Cloud values, Alloy’s rollout not awaited), against kind v1.36.1; a real terraform.tfstate with 26 instances, zero tofu-estate labels, 9 pod(s) Running (Alloy errors on the placeholder Grafana Cloud token, by design); the identical root cold-deployed by stock on a second cluster as every later stage’s oracle |
| Migrate | pass | 7s | 26 of 26 stamped, 0 skipped, from the stock state file; every object carries tofu-estate=corpus-quickpizza, read back with kubectl across the estate’s eight kinds |
| Replan from nothing | pass | 6s | the plan with no state file is empty; a representative set of identities (the namespace, two Deployments, the StatefulSet, a Service, a ConfigMap, a Secret, the ServiceAccount, the ClusterRoleBinding) confirmed present by NAMESPACE/NAME with kubectl |
| No-op apply | pass | 6s | no-op apply (0 added, 0 changed, 0 destroyed); objects carrying tofu-estate=corpus-quickpizza unchanged at 26 across eight kinds, counted with kubectl |
| Drift and reconverge | pass | 12s | the alloy-config ConfigMap tampered with kubectl patch; choudoufu proposed exactly kubernetes_config_map_v1.alloy_config (0 add, 1 change, 0 destroy), matching stock’s own plan on the oracle cluster for the same tamper; apply changed 1 and the config reads back as the file the root ships. BREAK=1 tampers postgres-init-script too and the single-object assertion correctly fails |
| Rename | pass | 13s | moved block: kubernetes_service_account_v1.alloy -> .collector, with the ClusterRoleBinding’s subject and the Deployment’s service_account_name references following, zero churn (no add, no change, no destroy); the live object untouched and still labelled; stock’s plan for the same moved block on the oracle cluster is also zero churn. The moved-block half only: live-mv has no Kubernetes leg (#1066). BREAK=1 renames the object’s own metadata.name and the zero-churn assertion correctly fails |
| Remove a block | pass | 18s | deleting kubernetes_cluster_role_binding_v1.alloy’s block proposed exactly one destroy (0 add, 0 change, 1 destroy) at the sweep’s orphan address kubernetes_cluster_role_binding_v1.orphan_alloy - a cluster-scoped object found by its label, which carries no address - applied cleanly, the object gone (kubectl get clusterrolebinding: NotFound), the next plan empty; stock’s plan for the same removal on the oracle cluster is also exactly one destroy; the Deployments’ ReplicaSets and Pods and the StatefulSet’s Pod and PVC, which carry no estate label, were never proposed. BREAK_REMOVE=1 keeps the block and no destroy is proposed |
| Change count | pass | 36s | a two-instance count ConfigMap added beside the published root (the estate’s own shape has no count block): scaling 2 to 1 destroyed exactly shard-1, planned at the sweep’s orphan address kubernetes_config_map_v1.orphan_quickpizza_shard-1 since the label carries no index (shard-0 untouched, both read with kubectl); back to 2 created exactly kubernetes_config_map_v1.shard[1] under the same name; the next plan is empty; stock’s plans for the same two changes on the oracle cluster have the identical shape. BREAK_COUNT=1 asserts the lower index was destroyed and correctly fails |
| Replace with create_before_destroy | n/a | A Kubernetes name is unique within its namespace, so nothing can be created before the object it replaces is destroyed; a forced replacement is destroy-then-create, which this stage does not measure. | |
| Crash between create and destroy | n/a | The create-before-destroy window this stage interrupts does not exist on Kubernetes (see day2_replace). | |
| Teardown | pass | 32s | apply -destroy removed exactly the 27 remaining objects in one apply, in an order the API server accepted (the namespace last), the namespace gone and no object of any of the estate’s eight kinds carrying tofu-estate=corpus-quickpizza (kubectl, every namespace); stock’s destroy of the same estate on the oracle cluster also removed exactly the 27 its state held |
| Plan, review, apply | pass | 17s | plan -out wrote one update (the namespace gains reviewed=yes); the world then moved out of band (a stray label on the catalog Service, kubectl, never choudoufu) and apply of the saved plan refused with “The approved plan no longer matches the live system” at exit 3, nothing applied; with the label removed the identical file applied, 0 added, 1 changed, 0 destroyed, and reviewed=yes reads back; stock’s own planfile applied on the oracle cluster in the unchanged case. BREAK_APPROVAL=1 expects success after the move and correctly fails |
| Greenfield apply | pass | 34s | the published root applied fresh with a live block and no terraform.tfstate: 26 objects, every one labelled tofu-estate=corpus-quickpizza (kubectl, eight kinds); the record store held 24 file(s); replanned empty with and without the cache; the cluster’s inventory (ConfigMap and Secret keys, every Service’s ports and selector, every Deployment’s replicas, containers and service account, the StatefulSet’s containers and claim, the ClusterRoleBinding’s role and subjects, the namespace) matches stock’s cold deploy on the same cluster object by object, labels never compared. BREAK=1 drops the StatefulSet from the expected inventory and the match correctly fails |
| Strict profile (not a headline stage) | pass | 20s | every strict toggle on (secrets = refuse, no_source_create = refuse, marker_repair = never with a markers “record” selection naming kubernetes_config_map_v1) against a scratch estate carrying random_password.db: exactly one refusal, Logical resource is not admitted under strict { secrets = “refuse” }; the other two toggles are on and silent. BREAK_STRICT=1 turns secrets back to “store” and the refusal disappears |
Last run at commit 79697017b6 on 2026-09-12T23:34:50Z, exit code 0, against emulator image ghcr.io/lex00/floci@sha256:0bbeb43075c9df9c7e06311cd4eec99a354594d304faa4fe5899b494a009d23d. Total run time 5m47.1s.
Oracle: stock terraform 1.15.8, stock tofu 1.12.5. Stale: the current pin is terraform 1.16.1, tofu 1.12.6.
Reproduce it
go run ./tools/gauntlet run corpus-quickpizza
Needs Docker (the emulator is pulled at the pinned digest), the AWS CLI, and a
stock terraform or tofu binary on PATH for the cold deploy. The script is
live/e2e/corpus-quickpizza/run.sh; BREAK=1 corrupts its assertions to show they are load-bearing.