Creating Labs
Common Pitfalls
Common lab authoring mistakes to avoid in POV Demo labs.
Introduction
Avoiding these mistakes makes scripts easier to understand and debug.
1. Missing set -e in Solve Scripts
Without set -e, a directly executed shell script can continue after a failed command. The POV Demo executor runs non-check scripts with bash -e, so this is guidance rather than a validation requirement.
Avoid
kubectl apply -f solution.yaml # if this fails, script continues
kubectl wait --for=condition=ready pod/my-app --timeout=60sCorrect
set -e # recommended explicit failure handling
kubectl apply -f solution.yaml
kubectl wait --for=condition=ready pod/my-app --timeout=60s2. Bash History with set -o history
Use history -s when adding individual commands to shell history. Test any broader history configuration in the shell environment used by your lab.
Avoid
set -o history
HISTFILE=~/.bash_history
history -wCorrect
history -s "kubectl apply -f solution.yaml"
ensure_history_flushed3. Non-Idempotent Commands
Prefer commands that can be safely rerun, especially when they create shared state.
Avoid (these fail if run twice)
kubectl run my-pod --image=nginx # fails: pod already exists
helm install my-release ./chart # fails: release already exists
kubectl create namespace my-ns # fails: namespace already exists
echo "line" >> /etc/config # appends duplicate linesCorrect (idempotent alternatives)
kubectl run my-pod --image=nginx --dry-run=client -o yaml | kubectl apply -f -
helm upgrade --install my-release ./chart
kubectl create namespace my-ns --dry-run=client -o yaml | kubectl apply -f -
grep -q "line" /etc/config || echo "line" >> /etc/config4. Race Conditions in Kubernetes Labs
Kubernetes resources take time to become ready. Use an appropriate readiness check and timeout after installation; an immediate check can race resource creation.
Avoid
helm install my-release ./chart
kubectl wait --for=condition=ready pod -l app=my-app --timeout=120s # often failsCorrect
helm install my-release ./chart
sleep 10 # allow pods to start
kubectl wait --for=condition=ready pod -l app=my-app --timeout=120s5. Binary Copy “Text File Busy” Error
Replacing a running executable can fail with “Text file busy”. Stop the service first when your platform requires it.
Avoid
cp /tmp/new-binary /usr/local/bin/myapp # fails if myapp is runningCorrect
systemctl stop myapp
cp /tmp/new-binary /usr/local/bin/myapp
systemctl start myapp6. Glob Patterns Matching Test Files
Glob patterns like rules/*.yml may match test fixture files (e.g. test_alerts.yml) that were not intended to be included. Inspect the matches before applying them.
Avoid
kubectl apply -f rules/*.yml # may apply test_alerts.yml unintentionallyCorrect
# List what the glob matches before applying
ls rules/*.yml
kubectl apply -f rules/alerts.yml rules/recording.yml # explicit files7. Commands Returning Non-Zero Under set -e
Some commands return non-zero exit codes even on success. Under set -e, these silently abort the script.
Avoid
set -e
kubectl auth can-i create pods # returns 1 if "no", aborting the script
history -s "kubectl apply" # may return non-zero in some environmentsCorrect
set -e
kubectl auth can-i create pods || true # ignore exit code
history -s "kubectl apply" || true # safe history addition