Creating Labs

Common Pitfalls

Common lab authoring mistakes to avoid in POV Demo labs.

Introduction

Note: These examples are authoring guidance. Test the behavior your lab depends on in its target environment.

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=60s

Correct

set -e                            # recommended explicit failure handling
kubectl apply -f solution.yaml
kubectl wait --for=condition=ready pod/my-app --timeout=60s

2. 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 -w

Correct

history -s "kubectl apply -f solution.yaml"
ensure_history_flushed

3. 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 lines

Correct (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/config

4. 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 fails

Correct

helm install my-release ./chart
sleep 10  # allow pods to start
kubectl wait --for=condition=ready pod -l app=my-app --timeout=120s

5. 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 running

Correct

systemctl stop myapp
cp /tmp/new-binary /usr/local/bin/myapp
systemctl start myapp

6. 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 unintentionally

Correct

# List what the glob matches before applying
ls rules/*.yml
kubectl apply -f rules/alerts.yml rules/recording.yml  # explicit files

7. 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 environments

Correct

set -e
kubectl auth can-i create pods || true   # ignore exit code
history -s "kubectl apply" || true       # safe history addition