Creating Labs
Scripting System
Learn how to write setup, check, solve, and cleanup scripts for POV Demo labs.
Script Types
Tasks support setup, check, and solve scripts. The executor runs each script type in parallel across the VMs that have a matching script.
| Type | When It Runs | Purpose |
|---|---|---|
setup | When a task is set up (the first task is set up as the session becomes ready) | Configure the VM, install tools, create initial state |
check | When the learner clicks "Check" | Validate the learner's work; exit 0 = pass, non-zero = fail |
solve | When the learner clicks "Solve" | Apply the solution |
lab_scripts/ use setup-{vm} and cleanup-{vm}. Setup runs during provisioning. Cleanup is run during teardown only for labs with AWS resources, and a cleanup failure does not stop teardown.Naming Convention
With virtual machines, scripts are discovered only with the matching {operation}-{vm-name} filename. With no VMs, task scripts are named setup, check, and solve; lab setup may be lab_scripts/setup.
| Script filename | VM name in config.yml |
|---|---|
setup-ubuntu-1 | ubuntu-1 |
check-nomad-server-1 | nomad-server-1 |
solve-kubernetes-control-1 | kubernetes-control-1 |
Setup Scripts
Setup scripts configure the environment before the learner begins. Non-check scripts run with bash -e; source a profile explicitly if the script needs profile-defined configuration.
# Non-check scripts are executed with bash -e
set -e
# Install required tools
apt-get update -q
apt-get install -y -q curl wget jq
# Create initial directory structure
mkdir -p /home/user/workspace
chown user:user /home/user/workspace
# Pre-populate a config file the learner will modify
cat > /home/user/workspace/config.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data: {}
EOF
# Add setup commands to bash history so learner can reference them
history -s "kubectl apply -f config.yaml"- Non-check scripts run with
bash -e, so their shebang is ignored. Source the required profile explicitly when a script needs it. - Use
set -eso the script fails fast on errors - Prefer idempotent scripts so reruns are safe.
- Use
history -s "command"to pre-populate terminal history (NOTset -o history)
Check Scripts
Check scripts validate the learner's work. Exit status controls the result: zero succeeds and non-zero fails. The executor sources /opt/tekanaid/scripts/check_template.sh when present and supplies fallback helpers.
#!/bin/bash
source /opt/tekanaid/scripts/check_template.sh
# Check that kubectl is configured correctly
check_command "kubectl cluster-info" "kubectl cluster-info should appear in shell history"
# Check that the deployment exists
check_command "kubectl get deployment my-app -n default" \
"kubectl get deployment should appear in shell history"
# Check specific content in a file
check_file_content "/home/user/workspace/config.yaml" \
"name: my-config" \
"ConfigMap name should be 'my-config'"
echo "All checks passed!"Solve Scripts
set -e for readable, portable scripts. The executor already invokes non-check scripts with bash -e; local validation does not require it on a specific line.# Non-check scripts are executed with bash -e
set -e
# Apply the solution
kubectl apply -f /home/user/workspace/solution.yaml
# Verify the solution worked
kubectl wait --for=condition=available deployment/my-app --timeout=60s- Prefer an idempotent solution so rerunning it is safe.
- Use
history -s "command"to show the solution commands in terminal history (NOTset -o history)
Helper Functions
The executor sources /opt/tekanaid/scripts/check_template.sh before each check script. Source that path explicitly only when running the script outside the executor.
| Function | Signature | Description |
|---|---|---|
check_command | check_command "pattern" "message" | Checks the root shell history for pattern; fails with message when absent. |
check_file_content | check_file_content "file" "pattern" "message" | Fails if pattern is not found in file. |
fail | fail "message" | Immediately fails the check with message. |
ensure_history_flushed | ensure_history_flushed | Flushes shell history before a history check. |
AI Gateway
An AI gateway is configured only when the session has a gateway key and the service has AI_GATEWAY_URL. When configured, the VM profile exports these client-compatible variables.
| Variable | Value |
|---|---|
OPENAI_API_BASE | Gateway base URL with /v1 |
OPENAI_API_KEY | Session gateway key |
ANTHROPIC_BASE_URL | Gateway base URL |
ANTHROPIC_API_KEY | Session gateway key |
LLM_API_BASE | Gateway base URL |
LLM_API_KEY | Session gateway key |
