#! /usr/bin/env bash # Example invokation # sudo SCALE_POOL_ROOT=$SCALE_POOL_ROOT $SCALE_POOL_ROOT/jailmaker/test/test-jlmkr docker set -e #### Global variables if [[ -z "$JLMKR_PATH" && -n "$SCALE_POOL_ROOT" ]]; then SCALE_POOL_ROOT=${SCALE_POOL_ROOT:?must be exported before you can run test suite} JLMKR_PATH=${SCALE_POOL_ROOT}/jailmaker elif [[ -z "$JLMKR_PATH" ]]; then JLMKR_PATH=${PWD:-.} fi if [[ ! -r "$JLMKR_PATH/jlmkr.py" ]]; then >&2 printf "%s\n" \ "couldn't find jlmkr.py. Are you running from the jailmaker directory?" \ "If not, setup either JLMKR_PATH or SCALE_POOL_ROOT" \ "" >&2 printf "\tPWD: %s\n\tJLMKR_PATH: %s\n\tSCALE_POOL_ROOT: %s\n" \ "$PWD" "$JLMKR_PATH" "$SCALE_POOL_ROOT" >&2 printf "\n" exit 2 fi JAIL_TYPE="${1}" if [ -n "${JAIL_TYPE}" ]; then if [ -r "${JAIL_TYPE}" ]; then JAIL_CONFIG="$JAIL_TYPE" JAIL_TYPE= # Can't perform full test with config path FULL_TEST=0 else JAIL_CONFIG="$JLMKR_PATH/templates/$JAIL_TYPE/config" # Full test is an option when using JAIL_TYPE FULL_TEST=${FULL_TEST:-0} fi if [ ! -r "${JAIL_CONFIG}" ]; then >&2 printf "Must supply a valid jail type or config path\n" exit 2 fi fi # shellcheck disable=SC2034 # JAIL is used inside perform_test_suite JAIL="${2:-${JAIL_TYPE:-default}-test}" # STOP=0 - (default) perform all tests, in non-blocking mode # STOP=l - only list and images, nothing else # STOP=i - interactive test, includ console-blocking waiting for input tests (edit and shell) STOP=${STOP:-0} REPORT=(create edit exec images list log remove restart shell start status stop) WAIT_FOR_JAIL=${WAIT_FOR_JAIL:-4s} #### Functions jlmkr () { /usr/bin/env python3 "$JLMKR_PATH/jlmkr.py" "${@:---help}" } iterate () { # shellcheck disable=SC2206 # $1 will pass multiple values, we want splitting here local SET=($1) DO=("${@:2}") local x j _x x_STATUS for j in "${SET[@]}"; do for _x in "${DO[@]}"; do x="${_x//\(Jv)/JLMKR_"$j"}" # echo "$x" >&2 ${NO_EVAL:+:} eval "echo \$JLMKR_${j} \"$x\"" x_STATUS=✅ ${NO_EVAL:+:} eval "JLMKR_$j=$x_STATUS" ${NO_EVAL:+:} eval "JLMKR_${j}_x=\"${x//\"/\'}\"" if [[ -n "$DELAY" ]]; then printf "Waiting %s seconds before test...\n" "${DELAY}" sleep "${DELAY}" fi set +e eval "$x" || x_STATUS=$? set -e if [[ "$x_STATUS" != "✅" ]]; then ${NO_EVAL:+:} eval "JLMKR_${j}_x=\"($x_STATUS) ${x//\"/\'}\"" ${NO_EVAL:+:} eval "JLMKR_$j=❌" STOP=E:$x_STATUS return fi done done } perform_test_suite() { # shellcheck disable=SC2016 # function relies heavily on single quotes preventing expansion if [[ "$STOP" =~ ^(0|l|i)$ ]]; then # Initialize REPORT with empty checkboxes - NO_EVAL=1 is important here, otherwise Status will be evaluated NO_EVAL=1 iterate "${REPORT[*]}" '(Jv)="🔳"' TESTS=(list images) iterate "${TESTS[*]}" 'jlmkr $j' [[ "$STOP" =~ ^(0|i)$ ]] && TESTS=(create) \ && iterate "${TESTS[*]}" 'jlmkr $j ${JAIL_CONFIG:+--config} $JAIL_CONFIG $JAIL' [[ "$STOP" =~ ^(0|i)$ ]] && TESTS=(start) \ && iterate "${TESTS[*]}" 'jlmkr $j $JAIL' [[ "$STOP" =~ ^(0|i)$ ]] && TESTS=(restart) \ && DELAY=$WAIT_FOR_JAIL iterate "${TESTS[*]}" 'jlmkr $j $JAIL' # If this is an interactive test, edit and shell will wait for input [[ "$STOP" == "i" ]] && TESTS=(edit shell) \ && DELAY=$WAIT_FOR_JAIL iterate "${TESTS[*]}" 'jlmkr $j $JAIL' # This is the non-interactive test for edit [[ "$STOP" == "0" ]] && TESTS=(edit) \ && DELAY=$WAIT_FOR_JAIL iterate "${TESTS[*]}" 'EDITOR=cat jlmkr $j $JAIL' # This is the non-interactive test for shell [[ "$STOP" == "0" ]] && TESTS=(shell) \ && DELAY=$WAIT_FOR_JAIL iterate "${TESTS[*]}" 'jlmkr $j $JAIL /bin/sh -c "echo shell called successful"' [[ "$STOP" =~ ^(0|i)$ ]] && TESTS=(exec) \ && DELAY=$WAIT_FOR_JAIL iterate "${TESTS[*]}" 'jlmkr $j $JAIL /bin/sh -c "echo exec called successful"' [[ "$STOP" =~ ^(0|i)$ ]] && TESTS=(status) \ && iterate "${TESTS[*]}" 'jlmkr $j $JAIL --no-pager' [[ "$STOP" =~ ^(0|i)$ ]] && TESTS=(log) \ && iterate "${TESTS[*]}" 'jlmkr $j $JAIL -n 10' [[ "$STOP" =~ ^(0|l|i)$ ]] || >&2 printf "Had an Error. Cleanup up and stopping.\n" # Always perform these cleanup steps, even if something failed [[ "$STOP" != l ]] \ && TESTS=(stop) \ && iterate "${TESTS[*]}" 'jlmkr $j $JAIL' \ [[ "$STOP" != l ]] \ && TESTS=(remove) \ && iterate "${TESTS[*]}" 'jlmkr $j $JAIL <<<"$JAIL" ' fi printf '\n\nReport for:\n\tCWD: %s\t\tJAIL_CONFIG: %s\n\n' "$(pwd)" "${JAIL_CONFIG}" # shellcheck disable=SC2016 NO_EVAL=1 iterate "${REPORT[*]}" 'echo "$(Jv) ${(Jv)_x:-$j}"' } #### Execution starts here perform_test_suite if [[ "$STOP" =~ ^(0|i)$ ]]; then [[ "$FULL_TEST" == 1 ]] || STOP="Single Test" fi if [[ "$STOP" =~ ^(0|i)$ ]]; then pushd "$JLMKR_PATH" > /dev/null || STOP=pushd STOP=0 # The following test suite should only be run non-interactivley JAIL_CONFIG="./templates/$JAIL_TYPE/config" perform_test_suite JAIL_CONFIG="templates/$JAIL_TYPE/config" perform_test_suite JAIL_CONFIG="$JLMKR_PATH/$JAIL_CONFIG" perform_test_suite cd ~ perform_test_suite TMP_JAIL_CFG=$(mktemp) \ && cp "$JAIL_CONFIG" "$TMP_JAIL_CFG" \ && JAIL_CONFIG="${TMP_JAIL_CFG}" perform_test_suite \ && rm "$TMP_JAIL_CFG" \ || STOP=E:temp_file popd > /dev/null || STOP=popd fi if [[ "$STOP" = 0 ]]; then printf "All tests completed\n" else printf "Stopped: %s\n" "$STOP" [[ "$STOP" = "Single Test" ]] || exit 1 fi