Skip to content
Browse Docs

Deep Dives

AI: Claude and Codex patterns

ConfigHub: Deploy and manage

Docs
Configs
Stacks
Apps
Plugins
Guides

Live walk: testing an entry's plain objects with kubectl, 2026-10-11

This log records one walk. The site now ships a second test script for an entry, try-objects.sh. It tests the entry's retained objects themselves, the one file a reader holds when they take the published bundle. It fetches that file, checks its SHA-256 against the entry's listing, and applies it with kubectl. It uses curl, shasum, awk and kubectl. It needs no cub CLI and no account. This walk ran seven of those scripts on two throwaway local clusters. You can also view this as a markdown file.

UNOFFICIAL/EXPERIMENTAL

This is a dated record of one walk. It is not a Guide. Every line that starts with $ is a command that was run, and the text under it is the output it printed. Times are UTC. A line longer than 220 characters is cut and ends with ....

Versions and setting

  • kind v0.31.0 with a node at Kubernetes v1.35.0, kubectl client v1.36.0, Docker 29.4.0, on macOS.
  • Every script ran under /bin/bash, which is GNU bash 3.2.57 on this machine.
  • The home directory held no ConfigHub credentials. No cub command ran and no account was used.
  • Each cluster had one node and no GPUs. The clusters had their own kubeconfig file, so the machine's default kubeconfig was not touched.
  • The scratch directory is written <work>. $SITE is the site/ directory of a checkout of this repository at the commit that added the scripts. The scripts ran from the checkout because the site had not published them yet.
  • Each script fetched its retained file from this repository's main branch on GitHub, as a reader's copy would.

The answer in brief

EntryWhat the script didWhat the walk saw afterwards
nvidia/gpu-operator v26.3.3, base default. Its verdict is flatten-with-routes, and it has no other test script.It created the namespace, applied the 5 CRDs and waited for each, then applied the other 19 objects. It exited 0.The operator and the three node-feature-discovery workloads rolled out. The ClusterPolicy reported ready.
The same entry, run again on the same clusterIt found the 5 CRDs present and matching, left them alone, and applied the other 19 objects again. It exited 0.The same four Pods were still running and the ClusterPolicy still reported ready.
nvidia/gpu-operator v25.10.1, base default, on the cluster that held v26.3.3It found CRDs that differ from its file and stopped. It exited 1.The operator image was still v26.3.3.
prometheus-community/prometheus-blackbox-exporter 11.18.0, base default. Its verdict is safe-to-flatten.It created the monitoring namespace and applied 4 objects. It exited 0.The Deployment rolled out and one Pod ran.
valkey/valkey 0.11.0, base default. Its verdict is safe-to-flatten, and its 4 objects name no namespace.It applied the 4 objects into default, the namespace the entry was built for. It exited 0.The Deployment rolled out and one Pod ran.
argo-cd/argo-cd 10.1.3, base default. Its plan says a Secret must exist before apply.It stopped before it applied anything and printed the step. It exited 1.The cluster held no argocd namespace, no Argo CD CRD and no Argo CD ClusterRole.
The same entry, after the walk created the Secret, with REQUIREMENTS_READY=1It applied the 3 CRDs and the other 52 objects. It exited 0.Six Deployments and one StatefulSet rolled out, and seven Pods ran.
k8s-ephemeral-storage-metrics 1.19.2, base default. Its file holds a ServiceMonitor and does not define that kind.It stopped before it applied anything, because the cluster did not serve the kind. It exited 1.No object of the entry was on the cluster.
prometheus-community/prometheus-operator-crds 28.0.1, base default, then k8s-ephemeral-storage-metrics againThe first applied its 10 CRDs. The second then passed its check and applied its 6 objects. Both exited 0.The walk did not check these workloads further.

No run failed because of a fault in a generated script.

Run 1. The GPU Operator v26.3.3, which has no other test script

The cluster was new.

$ kind create cluster --name cwtest-1011-obj-1 --kubeconfig ./kubeconfig --wait 120s 2>&1 | tail -2; kubectl get nodes

Thanks for using kind! ๐Ÿ˜Š
NAME                              STATUS   ROLES           AGE   VERSION
cwtest-1011-obj-1-control-plane   Ready    control-plane   46s   v1.35.0
[exit 0 at 07:33:45Z]

$ /bin/bash "$SITE/sh/nvidia-gpu-operator-v26-3-3/default/try-objects.sh"

>> Fetch the retained objects into ./nvidia-gpu-operator-v26-3-3-default-objects/objects.yaml

>> Check the file against the SHA-256 in the listing
The file matches: sha256 73ebb5f6de3d1f010330d266db11b99b508be84dfc92b9d5deb01a39b66fee7c

>> Split the file into its 24 objects. The cluster is untouched so far
./nvidia-gpu-operator-v26-3-3-default-objects/crds:
doc-0002.yaml
doc-0004.yaml
doc-0006.yaml
doc-0007.yaml
doc-0008.yaml

./nvidia-gpu-operator-v26-3-3-default-objects/rest:
doc-0009.yaml
doc-0010.yaml
doc-0011.yaml
doc-0012.yaml
doc-0013.yaml
doc-0014.yaml
doc-0015.yaml
doc-0016.yaml
doc-0017.yaml
doc-0018.yaml
doc-0019.yaml
doc-0020.yaml
doc-0021.yaml
doc-0022.yaml
doc-0023.yaml
doc-0024.yaml
doc-0025.yaml
doc-0026.yaml
doc-0027.yaml

>> Check that kubectl reaches a cluster
kind-cwtest-1011-obj-1

>> Create the gpu-operator namespace if it does not exist
namespace/gpu-operator created

>> Check the 5 CRDs this file holds

>> A CRD is missing, so apply the file's CRDs first
customresourcedefinition.apiextensions.k8s.io/clusterpolicies.nvidia.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/nvidiadrivers.nvidia.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/nodefeatures.nfd.k8s-sigs.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/nodefeaturegroups.nfd.k8s-sigs.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/nodefeaturerules.nfd.k8s-sigs.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/clusterpolicies.nvidia.com condition met
customresourcedefinition.apiextensions.k8s.io/nvidiadrivers.nvidia.com condition met
customresourcedefinition.apiextensions.k8s.io/nodefeatures.nfd.k8s-sigs.io condition met
customresourcedefinition.apiextensions.k8s.io/nodefeaturegroups.nfd.k8s-sigs.io condition met
customresourcedefinition.apiextensions.k8s.io/nodefeaturerules.nfd.k8s-sigs.io condition met

>> Apply the other 19 objects
serviceaccount/node-feature-discovery created
serviceaccount/gpu-operator created
configmap/gpu-operator-node-feature-discovery-master-conf created
configmap/gpu-operator-node-feature-discovery-worker-conf created
clusterrole.rbac.authorization.k8s.io/gpu-operator-node-feature-discovery created
clusterrole.rbac.authorization.k8s.io/gpu-operator-node-feature-discovery-gc created
clusterrole.rbac.authorization.k8s.io/gpu-operator created
clusterrolebinding.rbac.authorization.k8s.io/gpu-operator-node-feature-discovery created
clusterrolebinding.rbac.authorization.k8s.io/gpu-operator-node-feature-discovery-gc created
clusterrolebinding.rbac.authorization.k8s.io/gpu-operator created
role.rbac.authorization.k8s.io/gpu-operator-node-feature-discovery-worker created
role.rbac.authorization.k8s.io/gpu-operator created
rolebinding.rbac.authorization.k8s.io/gpu-operator-node-feature-discovery-worker created
rolebinding.rbac.authorization.k8s.io/gpu-operator created
daemonset.apps/gpu-operator-node-feature-discovery-worker created
deployment.apps/gpu-operator-node-feature-discovery-master created
deployment.apps/gpu-operator-node-feature-discovery-gc created
deployment.apps/gpu-operator created
clusterpolicy.nvidia.com/cluster-policy created

>> Done. The 5 CRDs were applied first. kubectl applied the other 19 objects of this entry's retained file.

>> The script stops here. It did not wait for any workload to start

>> Not run by this script: 2 steps of this entry's plan. The entry page says who runs each one.
   - Before an upgrade, move the CRDs to the new version. Helm does not upgrade CRDs from a chart's crds directory, so the chart ships this Job. The listing gives the rest.
   - After deleting, prune node-feature-discovery labels from the nodes. The Job runs nfd-master -prune, which removes node-feature-discovery labels, annotations and taints from every node, with its own ServiceAccoun ...
[exit 0 at 07:34:10Z]

The script does not wait for workloads. The walk checked them by hand.

$ kubectl -n gpu-operator rollout status deployment/gpu-operator --timeout=300s | tail -1; kubectl -n gpu-operator rollout status deployment/gpu-operator-node-feature-discovery-master --timeout=300s | tail -1; kubect ...
deployment "gpu-operator" successfully rolled out
deployment "gpu-operator-node-feature-discovery-master" successfully rolled out
daemon set "gpu-operator-node-feature-discovery-worker" successfully rolled out
[exit 0 at 07:35:20Z]

$ for i in 1 2 3 4 5 6 7 8 9 10 11 12; do s="$(kubectl get clusterpolicy cluster-policy -o jsonpath="{.status.state}")"; [ "$s" = "ready" ] && break; sleep 10; done; kubectl get clusterpolicy cluster-policy -o jsonpa ...
ready
NAME                                                          READY   STATUS    RESTARTS   AGE
gpu-operator-6f4cbc9d8f-mzzt4                                 1/1     Running   0          71s
gpu-operator-node-feature-discovery-gc-585b876f9c-s7xq2       1/1     Running   0          71s
gpu-operator-node-feature-discovery-master-7f6684fb45-rjlfb   1/1     Running   0          71s
gpu-operator-node-feature-discovery-worker-rl5hj              1/1     Running   0          71s
[exit 0 at 07:35:20Z]

The same script a second time

The second run exercised the case where every CRD exists and matches the file. The script left the CRDs alone and applied the other objects again. kubectl printed configured for the four workloads and unchanged for the rest.

$ /bin/bash "$SITE/sh/nvidia-gpu-operator-v26-3-3/default/try-objects.sh" 2>&1 | sed -n "/Check the 5 CRDs/,\$p"
>> Check the 5 CRDs this file holds

>> The CRDs already exist and match this file. The script leaves them under their current owner
customresourcedefinition.apiextensions.k8s.io/clusterpolicies.nvidia.com condition met
customresourcedefinition.apiextensions.k8s.io/nvidiadrivers.nvidia.com condition met
customresourcedefinition.apiextensions.k8s.io/nodefeatures.nfd.k8s-sigs.io condition met
customresourcedefinition.apiextensions.k8s.io/nodefeaturegroups.nfd.k8s-sigs.io condition met
customresourcedefinition.apiextensions.k8s.io/nodefeaturerules.nfd.k8s-sigs.io condition met

>> Apply the other 19 objects
serviceaccount/node-feature-discovery unchanged
serviceaccount/gpu-operator unchanged
configmap/gpu-operator-node-feature-discovery-master-conf unchanged
configmap/gpu-operator-node-feature-discovery-worker-conf unchanged
clusterrole.rbac.authorization.k8s.io/gpu-operator-node-feature-discovery unchanged
clusterrole.rbac.authorization.k8s.io/gpu-operator-node-feature-discovery-gc unchanged
clusterrole.rbac.authorization.k8s.io/gpu-operator unchanged
clusterrolebinding.rbac.authorization.k8s.io/gpu-operator-node-feature-discovery unchanged
clusterrolebinding.rbac.authorization.k8s.io/gpu-operator-node-feature-discovery-gc unchanged
clusterrolebinding.rbac.authorization.k8s.io/gpu-operator unchanged
role.rbac.authorization.k8s.io/gpu-operator-node-feature-discovery-worker unchanged
role.rbac.authorization.k8s.io/gpu-operator unchanged
rolebinding.rbac.authorization.k8s.io/gpu-operator-node-feature-discovery-worker unchanged
rolebinding.rbac.authorization.k8s.io/gpu-operator unchanged
daemonset.apps/gpu-operator-node-feature-discovery-worker configured
deployment.apps/gpu-operator-node-feature-discovery-master configured
deployment.apps/gpu-operator-node-feature-discovery-gc configured
deployment.apps/gpu-operator configured
clusterpolicy.nvidia.com/cluster-policy unchanged

>> Done. The 5 CRDs already existed and matched, so the script left them alone. kubectl applied the other 19 objects of this entry's retained file.

>> The script stops here. It did not wait for any workload to start

>> Not run by this script: 2 steps of this entry's plan. The entry page says who runs each one.
   - Before an upgrade, move the CRDs to the new version. Helm does not upgrade CRDs from a chart's crds directory, so the chart ships this Job. The listing gives the rest.
   - After deleting, prune node-feature-discovery labels from the nodes. The Job runs nfd-master -prune, which removes node-feature-discovery labels, annotations and taints from every node, with its own ServiceAccoun ...
[exit 0 at 07:35:38Z]

That command pipes the script into sed, so the exit code under it is the pipeline's. A third run printed the script's own exit code.

$ /bin/bash "$SITE/sh/nvidia-gpu-operator-v26-3-3/default/try-objects.sh" >/dev/null 2>&1; echo "the script exited $?"; kubectl get clusterpolicy cluster-policy -o jsonpath="{.status.state}{\"\n\"}"; kubectl -n gpu-o ...
the script exited 0
ready
NAME                                                          READY   STATUS    RESTARTS   AGE
gpu-operator-6f4cbc9d8f-mzzt4                                 1/1     Running   0          105s
gpu-operator-node-feature-discovery-gc-585b876f9c-s7xq2       1/1     Running   0          105s
gpu-operator-node-feature-discovery-master-7f6684fb45-rjlfb   1/1     Running   0          105s
gpu-operator-node-feature-discovery-worker-rl5hj              1/1     Running   0          105s
[exit 0 at 07:35:54Z]

An older version's script on the same cluster

The walk then ran the script for v25.10.1 against the cluster that held v26.3.3. Its CRD files differ from the ones on the cluster, so the script stopped before it applied any other object. It prints how to let it apply the file's CRDs. The walk did not do that.

$ /bin/bash "$SITE/sh/nvidia-gpu-operator-v25-10-1/default/try-objects.sh" > older.log 2>&1; echo "the script exited $?"; sed -n "/Check the .* CRDs/,\$p" older.log; kubectl -n gpu-operator get deployment gpu-operato ...
the script exited 1
>> Check the 5 CRDs this file holds

>> The CRDs already exist and differ from this file, or another tool owns them
This script does not change CRDs it did not just create.
If this is an upgrade, the objects that follow may need the newer CRDs.
To let this script apply the file's CRDs, re-run with:
  APPLY_CRDS=1 bash try-objects.sh
nvcr.io/nvidia/gpu-operator:v26.3.3
[exit 0 at 07:36:06Z]

The first cluster was then deleted.

$ kind delete cluster --name cwtest-1011-obj-1 --kubeconfig ./kubeconfig; kind get clusters | grep -c cwtest-1011-obj
Deleting cluster "cwtest-1011-obj-1" ...
Deleted nodes: ["cwtest-1011-obj-1-control-plane"]
0
[exit 1 at 07:36:21Z]

grep -c exits 1 when it counts nothing, which is why that line ends in exit 1. The count is 0.

Run 2. Two entries with the verdict safe-to-flatten

A second cluster was created. The first entry is the Prometheus blackbox exporter. Its image comes from quay.io and pulls with no sign-in.

$ kind create cluster --name cwtest-1011-obj-2 --kubeconfig ./kubeconfig --wait 120s 2>&1 | tail -2; kubectl get nodes

Have a nice day! ๐Ÿ‘‹
NAME                              STATUS   ROLES           AGE   VERSION
cwtest-1011-obj-2-control-plane   Ready    control-plane   26s   v1.35.0
[exit 0 at 07:37:38Z]

$ /bin/bash "$SITE/sh/prometheus-community-prometheus-blackbox-exporter-11-18-0/default/try-objects.sh"; echo "the script exited $?"

>> Fetch the retained objects into ./prometheus-community-prometheus-blackbox-exporter-11-18-0-default-objects/objects.yaml

>> Check the file against the SHA-256 in the listing
The file matches: sha256 f9a8cddd436d84f31bcb4903756d6a1e149e7f4197d33d18013e33b077195aa2

>> Split the file into its 4 objects. The cluster is untouched so far
doc-0001.yaml
doc-0002.yaml
doc-0003.yaml
doc-0004.yaml

>> Check that kubectl reaches a cluster
kind-cwtest-1011-obj-2

>> Create the monitoring namespace if it does not exist
namespace/monitoring created

>> Apply the 4 objects
serviceaccount/prometheus-blackbox-exporter created
configmap/prometheus-blackbox-exporter created
service/prometheus-blackbox-exporter created
deployment.apps/prometheus-blackbox-exporter created

>> Done. kubectl applied the 4 objects of this entry's retained file.

>> The script stops here. It did not wait for any workload to start
the script exited 0
[exit 0 at 07:37:38Z]

$ kubectl -n monitoring rollout status deployment --timeout=300s | tail -1; kubectl -n monitoring get pods,svc
deployment "prometheus-blackbox-exporter" successfully rolled out
NAME                                                READY   STATUS    RESTARTS   AGE
pod/prometheus-blackbox-exporter-576cfd6497-g9jj7   1/1     Running   0          7s

NAME                                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/prometheus-blackbox-exporter   ClusterIP   10.96.57.223   <none>        9115/TCP   7s
[exit 0 at 07:37:45Z]

The second entry is Valkey. Its four objects name no namespace, so kubectl would put them wherever the reader's context points. The script applies them into default, which is the namespace the listing records for the entry. Its image comes from Docker Hub and pulled with no sign-in.

$ /bin/bash "$SITE/sh/valkey-valkey-0-11-0/default/try-objects.sh" 2>&1 | sed -n "/Split the file/,\$p"
>> Split the file into its 4 objects. The cluster is untouched so far
doc-0001.yaml
doc-0002.yaml
doc-0003.yaml
doc-0004.yaml

>> Check that kubectl reaches a cluster
kind-cwtest-1011-obj-2

>> Create the default namespace if it does not exist

>> Apply 4 objects that name no namespace into default, the namespace this entry was built for
serviceaccount/valkey created
configmap/valkey-init-scripts created
service/valkey created
deployment.apps/valkey created

>> Done. kubectl applied the 4 objects of this entry's retained file.

>> The script stops here. It did not wait for any workload to start
[exit 0 at 07:37:51Z]

$ kubectl -n default rollout status deployment/valkey --timeout=300s | tail -1; kubectl -n default get pods,svc,sa,cm
deployment "valkey" successfully rolled out
NAME                         READY   STATUS    RESTARTS   AGE
pod/valkey-fc7549967-ldtpw   1/1     Running   0          21s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    58s
service/valkey       ClusterIP   10.96.142.129   <none>        6379/TCP   22s

NAME                     AGE
serviceaccount/default   51s
serviceaccount/valkey    22s

NAME                            DATA   AGE
configmap/kube-root-ca.crt      1      51s
configmap/valkey-init-scripts   1      22s
[exit 0 at 07:38:13Z]

The first command pipes the script into sed. A second run printed the script's own exit code.

$ /bin/bash "$SITE/sh/valkey-valkey-0-11-0/default/try-objects.sh" >/dev/null 2>&1; echo "the script exited $?"
the script exited 0
[exit 0 at 07:38:20Z]

Run 3. An entry whose plan has a step the script must stop for

The plan for Argo CD 10.1.3 says the Secret argocd/argocd-redis must exist before apply. Helm creates it with a hook, and plain objects carry no hook. The script cannot make that Secret for the reader, so it stops before it applies anything. The command leaves out the 55 file names the script lists.

$ /bin/bash "$SITE/sh/argo-cd-argo-cd-10-1-3/default/try-objects.sh" 2>&1 | grep -v "^doc-"; echo "the script exited ${PIPESTATUS[0]}"

>> Fetch the retained objects into ./argo-cd-argo-cd-10-1-3-default-objects/objects.yaml

>> Check the file against the SHA-256 in the listing
The file matches: sha256 b2cbe21e58abbf285edb7710df9df299c93bb288293eed091ef7e24f83f850b5

>> Split the file into its 55 objects. The cluster is untouched so far
./argo-cd-argo-cd-10-1-3-default-objects/crds:

./argo-cd-argo-cd-10-1-3-default-objects/rest:

>> Stop before applying anything. This entry's plan has 1 step that an install needs first
This script cannot carry out this step of the plan. It is yours to do, with your own values:
  - Secret argocd/argocd-redis must exist before apply. Redis auth Secret normally generated by the chart secret-init hook; config-only delivery lanes stage it explicitly.
Nothing was applied. Complete it before you apply the objects.
When it is done, re-run with:
  REQUIREMENTS_READY=1 bash try-objects.sh
the script exited 1
[exit 0 at 07:39:53Z]

$ kubectl get namespace argocd; kubectl get crd -o name | grep argoproj || echo "no argoproj CRD"; kubectl get clusterrole -o name | grep argocd || echo "no argocd ClusterRole"
Error from server (NotFound): namespaces "argocd" not found
no argoproj CRD
no argocd ClusterRole
[exit 0 at 07:39:54Z]

The walk then did the step by hand, with a random value that it did not print, and ran the script again with REQUIREMENTS_READY=1.

$ kubectl create namespace argocd; kubectl -n argocd create secret generic argocd-redis --from-literal=auth="$(openssl rand -hex 16)"
namespace/argocd created
secret/argocd-redis created
[exit 0 at 07:40:02Z]

$ REQUIREMENTS_READY=1 /bin/bash "$SITE/sh/argo-cd-argo-cd-10-1-3/default/try-objects.sh" > ready.log 2>&1; echo "the script exited $?"; sed -n "/REQUIREMENTS_READY=1 is set/,\$p" ready.log | grep -v " created$\|cond ...
the script exited 0
>> REQUIREMENTS_READY=1 is set. The script takes your word for 1 step and does not check it

>> Check that kubectl reaches a cluster
kind-cwtest-1011-obj-2

>> Create the argocd namespace if it does not exist

>> Check the 3 CRDs this file holds

>> A CRD is missing, so apply the file's CRDs first
customresourcedefinition.apiextensions.k8s.io/applications.argoproj.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/applicationsets.argoproj.io serverside-applied
customresourcedefinition.apiextensions.k8s.io/appprojects.argoproj.io serverside-applied

>> Apply the other 52 objects
networkpolicy.networking.k8s.io/argo-cd-argocd-application-controller created
networkpolicy.networking.k8s.io/argo-cd-argocd-notifications-controller created
networkpolicy.networking.k8s.io/argo-cd-argocd-repo-server created
networkpolicy.networking.k8s.io/argo-cd-argocd-server created
networkpolicy.networking.k8s.io/argo-cd-argocd-dex-server created
networkpolicy.networking.k8s.io/argo-cd-argocd-redis created
serviceaccount/argocd-application-controller created
serviceaccount/argocd-applicationset-controller created
serviceaccount/argocd-notifications-controller created
serviceaccount/argo-cd-argocd-repo-server created
serviceaccount/argocd-server created
serviceaccount/argocd-dex-server created
secret/argocd-notifications-secret created
secret/argocd-secret created
configmap/argocd-cm created
configmap/argocd-cmd-params-cm created
configmap/argocd-gpg-keys-cm created
configmap/argocd-notifications-cm created
configmap/argocd-rbac-cm created
configmap/argocd-ssh-known-hosts-cm created
configmap/argocd-tls-certs-cm created
configmap/argo-cd-argocd-redis-health-configmap created
clusterrole.rbac.authorization.k8s.io/argo-cd-argocd-application-controller created
clusterrole.rbac.authorization.k8s.io/argo-cd-argocd-notifications-controller created
clusterrole.rbac.authorization.k8s.io/argo-cd-argocd-server created
clusterrolebinding.rbac.authorization.k8s.io/argo-cd-argocd-application-controller created
clusterrolebinding.rbac.authorization.k8s.io/argo-cd-argocd-notifications-controller created
clusterrolebinding.rbac.authorization.k8s.io/argo-cd-argocd-server created
role.rbac.authorization.k8s.io/argo-cd-argocd-application-controller created
role.rbac.authorization.k8s.io/argo-cd-argocd-applicationset-controller created
role.rbac.authorization.k8s.io/argo-cd-argocd-notifications-controller created
role.rbac.authorization.k8s.io/argo-cd-argocd-repo-server created
role.rbac.authorization.k8s.io/argo-cd-argocd-server created
role.rbac.authorization.k8s.io/argo-cd-argocd-dex-server created
rolebinding.rbac.authorization.k8s.io/argo-cd-argocd-application-controller created
rolebinding.rbac.authorization.k8s.io/argo-cd-argocd-applicationset-controller created
rolebinding.rbac.authorization.k8s.io/argo-cd-argocd-notifications-controller created
rolebinding.rbac.authorization.k8s.io/argo-cd-argocd-repo-server created
rolebinding.rbac.authorization.k8s.io/argo-cd-argocd-server created
rolebinding.rbac.authorization.k8s.io/argo-cd-argocd-dex-server created
service/argo-cd-argocd-applicationset-controller created
service/argo-cd-argocd-repo-server created
service/argo-cd-argocd-server created
service/argo-cd-argocd-dex-server created
service/argo-cd-argocd-redis created
deployment.apps/argo-cd-argocd-applicationset-controller created
deployment.apps/argo-cd-argocd-notifications-controller created
deployment.apps/argo-cd-argocd-repo-server created
deployment.apps/argo-cd-argocd-server created
deployment.apps/argo-cd-argocd-dex-server created
deployment.apps/argo-cd-argocd-redis created
statefulset.apps/argo-cd-argocd-application-controller created

>> Done. The 3 CRDs were applied first. kubectl applied the other 52 objects of this entry's retained file.

>> The script stops here. It did not wait for any workload to start

>> Not run by this script: 1 step of this entry's plan. The entry page says who runs it.
   - Secret argocd/argocd-redis must exist before apply. Redis auth Secret normally generated by the chart secret-init hook; config-only delivery lanes stage it explicitly.
52
[exit 0 at 07:40:12Z]

The filter in that command was meant to drop the created lines and did not. The output above is what it printed. The last line, 52, is the count of created lines.

$ kubectl -n argocd rollout status deployment --timeout=420s | grep -c "successfully rolled out"; kubectl -n argocd rollout status statefulset/argo-cd-argocd-application-controller --timeout=300s | tail -1; kubectl - ...
6
partitioned roll out complete: 1 new pods have been updated...
NAME                                                       READY   STATUS    RESTARTS   AGE
argo-cd-argocd-application-controller-0                    1/1     Running   0          56s
argo-cd-argocd-applicationset-controller-5fd5c8dc7-mmch8   1/1     Running   0          56s
argo-cd-argocd-dex-server-755bdbf66c-d8cbp                 1/1     Running   0          56s
argo-cd-argocd-notifications-controller-b6cf49795-znmjk    1/1     Running   0          56s
argo-cd-argocd-redis-75c4bd9966-zb7b7                      1/1     Running   0          56s
argo-cd-argocd-repo-server-69c4b456c5-xvn2v                1/1     Running   0          56s
argo-cd-argocd-server-966f64bd9-x4hps                      1/1     Running   0          56s
[exit 0 at 07:41:08Z]

The script's last lines still name the Secret step as not run by the script, which is true. The reader ran it.

Run 4. A file that uses a kind it does not define

The file for k8s-ephemeral-storage-metrics holds a ServiceMonitor. That kind belongs to the Prometheus Operator, and the file does not define it. The entry's plan has no step about it. On a cluster without the kind, kubectl apply would fail part of the way through. The script checks first and stops before it applies anything.

$ /bin/bash "$SITE/sh/k8s-ephemeral-storage-metrics-k8s-ephemeral-storage-metrics-1-19-2/default/try-objects.sh" > kinds.log 2>&1; echo "the script exited $?"; sed -n "/Split the file/,\$p" kinds.log; kubectl get all ...
the script exited 1
>> Split the file into its 6 objects. The cluster is untouched so far
doc-0001.yaml
doc-0002.yaml
doc-0003.yaml
doc-0004.yaml
doc-0005.yaml
doc-0006.yaml

>> Check that kubectl reaches a cluster
kind-cwtest-1011-obj-2

>> Check that the cluster serves the 1 kind this file uses and does not define
The cluster does not serve: ServiceMonitor.monitoring.coreos.com
This file uses these kinds and does not define them. Install what defines them, then re-run this script. Nothing was applied.
1
[exit 0 at 07:38:21Z]

The last line of that output is 1 because the search word also matches ephemeral-volume-controller, a ServiceAccount that every cluster has in kube-system. A narrower search found nothing from the entry.

$ kubectl get deployment,serviceaccount,servicemonitor -A 2>&1 | grep -c k8s-ephemeral-storage-metrics
0
[exit 1 at 07:39:39Z]

The walk then ran the script for the entry that holds those definitions, prometheus-community/prometheus-operator-crds 28.0.1, and ran the first script again. This time the check passed.

$ /bin/bash "$SITE/sh/prometheus-community-prometheus-operator-crds-28-0-1/default/try-objects.sh" > crds.log 2>&1; echo "the script exited $?"; sed -n "/Check the 10 CRDs/,\$p" crds.log | grep -v "condition met"
the script exited 0
>> Check the 10 CRDs this file holds

>> A CRD is missing, so apply the file's CRDs first
customresourcedefinition.apiextensions.k8s.io/alertmanagerconfigs.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/alertmanagers.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/podmonitors.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/probes.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/prometheusagents.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/prometheuses.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/prometheusrules.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/scrapeconfigs.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/servicemonitors.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/thanosrulers.monitoring.coreos.com serverside-applied

>> Done. The 10 CRDs of this entry's retained file were applied.

>> The script stops here. It did not wait for any workload to start
[exit 0 at 07:39:45Z]

$ /bin/bash "$SITE/sh/k8s-ephemeral-storage-metrics-k8s-ephemeral-storage-metrics-1-19-2/default/try-objects.sh" > kinds2.log 2>&1; echo "the script exited $?"; sed -n "/Check that the cluster serves/,\$p" kinds2.log
the script exited 0
>> Check that the cluster serves the 1 kind this file uses and does not define

>> Create the monitoring namespace if it does not exist

>> Apply the 6 objects
serviceaccount/k8s-ephemeral-storage-metrics created
clusterrole.rbac.authorization.k8s.io/k8s-ephemeral-storage-metrics created
clusterrolebinding.rbac.authorization.k8s.io/k8s-ephemeral-storage-metrics created
service/k8s-ephemeral-storage-metrics created
deployment.apps/k8s-ephemeral-storage-metrics created
servicemonitor.monitoring.coreos.com/k8s-ephemeral-storage-metrics created

>> Done. kubectl applied the 6 objects of this entry's retained file.

>> The script stops here. It did not wait for any workload to start
[exit 0 at 07:39:46Z]

What went wrong

  • No generated script failed. Two faults of wording were found by reading the scripts, and both were fixed in the generator. A script whose file holds only CRDs ended with "The 10 CRDs of this entry's retained file were applied first", and "first" meant nothing there. That was fixed before that script ran. A script whose file holds one CRD said "The 1 CRD were applied first". That was fixed after the walk, and no such script was run. After each fix the scripts that had already run were compared by SHA-256, and none had changed.
  • Two of the walk's own checks were wrong, and both are shown above. One search matched a ServiceAccount that Kubernetes ships. One filter did not drop the lines it was meant to drop.
  • Three commands pipe a script into sed or grep, so the exit code under them is the pipeline's. Each of those scripts has its own exit code in the same command or in the one after it.

What the walk did not cover

  • No GPU. No driver, toolkit or device-plugin workload ran.
  • One walk, on one machine, with one node per cluster.
  • Seven scripts ran, out of the 228 the site ships. The other 221 passed /bin/bash -n and were not run.
  • The scripts ran from a checkout. No script was fetched from the published site.
  • No script ran with APPLY_CRDS=1, so the case where the script replaces differing CRDs was not exercised.
  • No upgrade, delete or rollback step of any plan was run. Each script names those steps in its last lines and leaves them to the reader.
  • The walk checked that workloads started. It did not check that any of them did useful work. Valkey, Argo CD and the blackbox exporter were given no request.
  • Linux was not tested. The scripts fall back to sha256sum where shasum is missing. That branch did not run in this walk. The section below records a later run of it on macOS.

Added later the same day: the sha256sum branch

The scripts use shasum and fall back to sha256sum. This run gave one script a tool directory that holds sha256sum and no shasum, and no cluster. It used the metrics-server 3.14.0 default script from a checkout.

$ env -i HOME=<work> PATH=<work>/bin KUBECONFIG=<work>/no-such-kubeconfig bash -c 'command -v shasum || echo shasum-is-not-on-PATH; command -v sha256sum'
shasum-is-not-on-PATH
<work>/bin/sha256sum
[exit 0 at 10:28:38Z]

$ env -i HOME=<work> PATH=<work>/bin KUBECONFIG=<work>/no-such-kubeconfig bash ./try-objects.sh

>> Fetch the retained objects into ./metrics-server-metrics-server-3-14-0-default-objects/objects.yaml

>> Check the file against the SHA-256 in the listing
The file matches: sha256 6e0dc279447462b6ad2ca64f6af6e40c5fac2057c1d6498933d720ffd7d810b2

>> Split the file into its 9 objects. The cluster is untouched so far
doc-0001.yaml
doc-0002.yaml
doc-0003.yaml
doc-0004.yaml
doc-0005.yaml
doc-0006.yaml
doc-0007.yaml
doc-0008.yaml
doc-0009.yaml

>> Check that kubectl reaches a cluster
kubectl cannot reach a cluster. Point it at a throwaway cluster and re-run this script.
[exit 1 at 10:28:39Z]

The script took the fallback, matched the SHA-256 in the listing, split the file, and stopped because it had no cluster. The sha256sum here is the one macOS ships. A Linux machine was still not used.

Clean-up

Both clusters were deleted, and no cluster of this walk was left.

$ kind delete cluster --name cwtest-1011-obj-2 --kubeconfig ./kubeconfig; kind get clusters | grep cwtest-1011-obj || echo "no cwtest-1011-obj cluster is left"
Deleting cluster "cwtest-1011-obj-2" ...
Deleted nodes: ["cwtest-1011-obj-2-control-plane"]
no cwtest-1011-obj cluster is left
[exit 0 at 07:41:17Z]

The SHA-256 of the machine's default kubeconfig was the same before and after the walk.

Generated from the committed markdown file docs/user/live-walk-test-plain-objects-2026-10-11.md. The source file is the authoritative version.