Automated validation tool for testing DevWorkspace instances on OpenShift clusters. Tests container image compatibility with devfiles across three editor scenarios: SSHD, JetBrains IDEA, and VSCode.
# Basic validation (uses small numbers of entries - 3 images, 5 devfiles)
./dw-auto-validate.sh
# Verbose mode - shows detailed output
./dw-auto-validate.sh -v
# Full test matrix (uses all entries from -full.txt files - all images, all devfiles. Takes significant time to complete!)
./dw-auto-validate.sh -f
# Debug mode - verbose + runs only first test + no cleanup
./dw-auto-validate.sh -d
# Help
./dw-auto-validate.sh -h# Check all images in images-full.txt are accessible via skopeo
./verify_images.shoc- OpenShift CLIjq- JSON processorcurl- HTTP client (for fetching devfiles)skopeo- Container image inspector (for verify_images.sh only)
- Prerequisites Check: Validates
ocandjqinstallation, checks cluster login (prompts for web login if needed) - Scenario Selection: Interactive prompt to choose scenario (1=sshd, 2=jetbrains, 3=vscode)
- Settings Loading: Sources
settings/settings-<SCENARIO>.envto load configuration and validation function - Test Execution:
- Starts timer
- Iterates through devfiles × images matrix
- For each combination: creates DevWorkspace, waits for Running state, validates, records results
- Cleanup: Deletes DevWorkspace and temporary files (skipped in debug mode)
- Summary Report: Shows test counts, success/failure, elapsed time, and lists failed tests
-v: Verbose mode - enableslog()output, shows detailed progress-f: Full mode - usesimages/images-full.txtanddevfiles/devfiles-full.txtinstead of their default counterparts-d: Debug mode - enables verbose + debug output, runs only first test, skips cleanup-h: Help - displays usage information
Debug mode specifics: Sets DEBUG=1, FULL=0, VERBOSE=1, runs only the first test iteration ([[ ${DEBUG} -eq 1 && ${total_count} == 1 ]] && continue), skips cleanup to allow resource inspection.
Each scenario in settings/settings-<SCENARIO>.env exports:
TIMEOUT: Seconds to wait for DevWorkspace to reach 'Running' stateDEVWORKSPACE_NAME: Name for the DevWorkspace instance (e.g., 'sshd-test', 'jetbrains-idea-test', 'vscode-test')PROJECT_URL: Git repository URL (must include surrounding double quotes)EDITOR_DEFINITION: URL to the editor definition YAMLvalidate_devworkspace(): Function that validates the running DevWorkspace
sshd (settings-sshd.env):
- Timeout: 60s
- Checks
/tmp/sshd.logfor "Server listening on" - Verifies SSHD server started successfully
jetbrains (settings-jetbrains.env):
- Timeout: 120s
- Port-forwards to 3400, curls
127.0.0.1:3400 - Validates HTTP 200 response from JetBrains landing page
- On failure, outputs
/idea-server/std.outfor debugging
vscode (settings-vscode.env):
- Timeout: 60s
- Checks
/checode/entrypoint-logs.txtfor "Extension host agent listening on 3100" - Verifies VSCode extension host is listening
Uses devworkspace-template.yaml as base, performs sed substitutions in two stages:
Stage 1 - Metadata and devfile injection:
cat devworkspace-template.yaml | sed \
-e "/DEVFILE/r ${TMP_DEVFILE}" \ # Inject devfile content
-e '/DEVFILE/ d' \ # Remove DEVFILE placeholder
-e "s|DEVWORKSPACE_NAME|...|" \
-e "s|DEVWORKSPACE_NS|...|" \
-e "s|EDITOR_DEFINITION|...|" \
-e "s|PROJECT_URL|...|"Stage 2 - Image override:
eval "sed \"s|image: .*|image: ${image}|\" > ${TMP_DEVWORKSPACE}"The two-stage approach ensures devfile content is injected before image replacement.
log(): Outputs only whenVERBOSE=1(set by-vor-dflags)debug(): Outputs only whenDEBUG=1(set by-dflag)${QUIET}: Set to&>/dev/nullin non-verbose mode, empty string otherwise- Used with
evalto conditionally suppressoccommand output:eval "oc apply -f ${TMP_DEVWORKSPACE} ${QUIET}"
- Used with
Tracks test execution time using bash's $SECONDS variable:
START_TIME=$SECONDScaptured before test loopELAPSED_TIME=$((SECONDS - START_TIME))calculated after cleanup- Displayed in purple in summary as
Xm YsorXh Ym Zswhen duration exceeds 1 hour
settings/
settings-sshd.env # SSHD scenario: timeout=60s, validates /tmp/sshd.log
settings-jetbrains.env # JetBrains scenario: timeout=120s, validates port 3400
settings-vscode.env # VSCode scenario: timeout=60s, validates /checode/entrypoint-logs.txt
images/
images.txt # Quick test list (3 UDI images: ubi8, ubi9, ubi10)
images-full.txt # Complete test matrix (UDI + base-developer-image variants)
devfiles/
devfiles.txt # Quick test list (nodejs, go, python, php-laravel and java-quarkus devfile)
devfiles-full.txt # Complete devfile list (32 devfiles from devfile registry)
samples/
samples.txt # Sample project URLs (currently unused)
samples-full.txt # Extended sample project list (currently unused)
devworkspace-template.yaml # Base template with placeholders
dw-auto-validate.sh # Main validation orchestrator
verify_images.sh # Skopeo-based image accessibility checker
All validate_devworkspace() functions follow this pattern:
validate_devworkspace() {
devfile_url=$1 # Receives devfile URL as first argument
# Find pod matching ${DEVWORKSPACE_NAME}
podNameAndDWName=$(oc get pods -o 'jsonpath={...}')
podName=$(echo ${podNameAndDWName} | grep ${DEVWORKSPACE_NAME} | cut -d, -f1)
# Get main container name
mainContainerName=$(oc get devworkspace ${DEVWORKSPACE_NAME} -o 'jsonpath={.spec.template.components[0].name}')
# Validate pod and container exist
if [ -z "${podName}" ] || [ -z "${mainContainerName}" ]; then
return 1
fi
# Scenario-specific validation logic here
# Return 0 for pass, 1 for fail
}Critical details:
- Has access to
${DEVWORKSPACE_NS},${DEVWORKSPACE_NAME},log(),debug() - Must return 0 for success, 1 for failure
- Should use
&>/dev/nullon oc exec commands meant only for exit code checking - Use
debug()to output diagnostic information visible only in debug mode
PROJECT_URL must include its own quotes: export PROJECT_URL='"https://..."'
This is because the sed substitution inserts the value directly into YAML:
git:
remotes:
origin: PROJECT_URL # becomes: origin: "https://..."Waiting for Running state:
state=""
count=0
while [ "${state}" != "Running" ] && [ ${count} -lt ${TIMEOUT} ]; do
state=$(oc get dw ${DEVWORKSPACE_NAME} -o 'jsonpath={.status.phase}')
sleep 1s
count=$[${count}+1]
doneFinding pod by DevWorkspace label:
podNameAndDWName=$(oc get pods -o 'jsonpath={range .items[*]}{.metadata.name}{","}{.metadata.labels.controller\.devfile\.io/devworkspace_name}{end}')
podName=$(echo ${podNameAndDWName} | grep ${DEVWORKSPACE_NAME} | cut -d, -f1)Getting main container name:
mainContainerName=$(oc get devworkspace ${DEVWORKSPACE_NAME} -o 'jsonpath={.spec.template.components[0].name}')- Create
settings/settings-<name>.env - Export required variables:
TIMEOUT,DEVWORKSPACE_NAME,PROJECT_URL,EDITOR_DEFINITION - Implement
validate_devworkspace()function that returns 0/1 - Update scenario selection in dw-auto-validate.sh (add option, update prompts)