308 lines
8.5 KiB
Bash
308 lines
8.5 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# Podman and Toolbox commands to run
|
|
PODMAN=${PODMAN:-podman}
|
|
TOOLBOX=${TOOLBOX:-toolbox}
|
|
|
|
# Helpful globals
|
|
LATEST_FEDORA_VERSION=${LATEST_FEDORA_VERSION:-"32"}
|
|
DEFAULT_FEDORA_VERSION=${DEFAULT_FEDORA_VERSION:-"f31"}
|
|
REGISTRY_URL=${REGISTRY_URL:-"registry.fedoraproject.org"}
|
|
TOOLBOX_DEFAULT_IMAGE=${TOOLBOX_DEFAULT_IMAGE:-"registry.fedoraproject.org/f31/fedora-toolbox:31"}
|
|
TOOLBOX_TIMEOUT=${TOOLBOX_TIMEOUT:-100}
|
|
PODMAN_TIMEOUT=${PODMAN_TIMEOUT:-100}
|
|
|
|
|
|
################
|
|
# run_podman # Invoke $PODMAN, with timeout, using BATS 'run'
|
|
################
|
|
#
|
|
# This is the preferred mechanism for invoking podman: first, it
|
|
# invokes $PODMAN, which may be 'podman-remote' or '/some/path/podman'.
|
|
#
|
|
# Second, we log the command run and its output. This doesn't normally
|
|
# appear in BATS output, but it will if there's an error.
|
|
#
|
|
# Next, we check exit status. Since the normal desired code is 0,
|
|
# that's the default; but the first argument can override:
|
|
#
|
|
# run_podman 125 nonexistent-subcommand
|
|
# run_podman '?' some-other-command # let our caller check status
|
|
#
|
|
# Since we use the BATS 'run' mechanism, $output and $status will be
|
|
# defined for our caller.
|
|
#
|
|
function run_podman() {
|
|
# Number as first argument = expected exit code; default 0
|
|
expected_rc=0
|
|
case "$1" in
|
|
[0-9]) expected_rc=$1; shift;;
|
|
[1-9][0-9]) expected_rc=$1; shift;;
|
|
[12][0-9][0-9]) expected_rc=$1; shift;;
|
|
'?') expected_rc= ; shift;; # ignore exit code
|
|
esac
|
|
|
|
# stdout is only emitted upon error; this echo is to help a debugger
|
|
echo "\$ $PODMAN $*"
|
|
run timeout --foreground -v --kill=10 $PODMAN_TIMEOUT $PODMAN "$@" 3>/dev/null
|
|
# without "quotes", multiple lines are glommed together into one
|
|
if [ -n "$output" ]; then
|
|
echo "$output"
|
|
fi
|
|
if [ "$status" -ne 0 ]; then
|
|
echo -n "[ rc=$status ";
|
|
if [ -n "$expected_rc" ]; then
|
|
if [ "$status" -eq "$expected_rc" ]; then
|
|
echo -n "(expected) ";
|
|
else
|
|
echo -n "(** EXPECTED $expected_rc **) ";
|
|
fi
|
|
fi
|
|
echo "]"
|
|
fi
|
|
|
|
if [ -n "$expected_rc" ]; then
|
|
if [ "$status" -ne "$expected_rc" ]; then
|
|
die "exit code is $status; expected $expected_rc"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function run_toolbox() {
|
|
# Number as first argument = expected exit code; default 0
|
|
expected_rc=0
|
|
case "$1" in
|
|
[0-9]) expected_rc=$1; shift;;
|
|
[1-9][0-9]) expected_rc=$1; shift;;
|
|
[12][0-9][0-9]) expected_rc=$1; shift;;
|
|
'?') expected_rc= ; shift;; # ignore exit code
|
|
esac
|
|
|
|
# stdout is only emitted upon error; this echo is to help a debugger
|
|
echo "\$ $TOOLBOX $*"
|
|
run timeout --foreground -v --kill=10 $TOOLBOX_TIMEOUT $TOOLBOX "$@" 3>/dev/null
|
|
# without "quotes", multiple lines are glommed together into one
|
|
if [ -n "$output" ]; then
|
|
echo "$output"
|
|
fi
|
|
if [ "$status" -ne 0 ]; then
|
|
echo -n "[ rc=$status ";
|
|
if [ -n "$expected_rc" ]; then
|
|
if [ "$status" -eq "$expected_rc" ]; then
|
|
echo -n "(expected) ";
|
|
else
|
|
echo -n "(** EXPECTED $expected_rc **) ";
|
|
fi
|
|
fi
|
|
echo "]"
|
|
fi
|
|
|
|
if [ -n "$expected_rc" ]; then
|
|
if [ "$status" -ne "$expected_rc" ]; then
|
|
die "exit code is $status; expected $expected_rc"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Toolbox helper functions
|
|
|
|
function is_toolbox_ready() {
|
|
toolbox_container="$1"
|
|
expected_string="Listening to file system and ticker events"
|
|
num_of_tries=5
|
|
timeout=2
|
|
|
|
run_podman logs $toolbox_container
|
|
|
|
for ((i = 0; i < $num_of_tries; i++)); do
|
|
if [[ "$output" =~ .*"$expected_string".* ]]; then
|
|
return
|
|
fi
|
|
|
|
sleep $timeout
|
|
run_podman logs $toolbox_container
|
|
done
|
|
|
|
echo "Output of 'podman logs $toolbox_container':"
|
|
echo "$output"
|
|
echo ""
|
|
|
|
die "container $toolbox_container was not ready in time"
|
|
}
|
|
|
|
# Functions to prepare environment
|
|
|
|
|
|
function create_toolbox() {
|
|
echo "# [create_toolbox]"
|
|
|
|
local numberof="$1"
|
|
local naming="$2"
|
|
local image="$3"
|
|
|
|
if [ "$numberof" = "" ]; then
|
|
numberof=${numberof:-1}
|
|
fi
|
|
|
|
if [ "$image" = "" ]; then
|
|
image=$TOOLBOX_DEFAULT_IMAGE
|
|
fi
|
|
|
|
for i in $(seq "$numberof"); do
|
|
if [ "$naming" = "" ]; then
|
|
run_toolbox '?' -y create -i "$image"
|
|
else
|
|
run_toolbox '?' -y create -c "$naming-$i" -i "$image"
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
function get_images() {
|
|
echo "# [get_images]"
|
|
|
|
local numberof="$1"
|
|
local image=""
|
|
|
|
if [ "$numberof" = "" ]; then
|
|
numberof=${numberof:-1}
|
|
fi
|
|
|
|
for i in $(seq $numberof); do
|
|
local version=$[$LATEST_FEDORA_VERSION-$i]
|
|
image="$REGISTRY_URL/f$version/fedora-toolbox:$version"
|
|
run_podman pull "$image" || echo "Podman couldn't pull the image."
|
|
done
|
|
}
|
|
|
|
|
|
function remove_all_images() {
|
|
echo "# [remove_all_images]"
|
|
run_podman images --all --format '{{.Repository}}:{{.Tag}} {{.ID}}'
|
|
for line in "${lines[@]}"; do
|
|
set $line
|
|
run_podman rmi --force "$1" >/dev/null 2>&1 || true
|
|
run_podman rmi --force "$2" >/dev/null 2>&1 || true
|
|
done
|
|
}
|
|
|
|
function remove_all_images_but_default() {
|
|
echo "# [remove_all_images_but_default]"
|
|
found_needed_image=1
|
|
run_podman images --all --format '{{.Repository}}:{{.Tag}} {{.ID}}'
|
|
for line in "${lines[@]}"; do
|
|
set $line
|
|
if [ "$1" == "$TOOLBOX_DEFAULT_IMAGE" ]; then
|
|
found_needed_image=1
|
|
else
|
|
run_podman rmi --force "$1" >/dev/null 2>&1 || true
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
function get_image_name() {
|
|
echo "# [get_image_name]"
|
|
local type="$1"
|
|
local version="$2"
|
|
|
|
if [ -z "$type" ]; then
|
|
type=${type:-fedora}
|
|
fi
|
|
|
|
if [ -z "$version" ]; then
|
|
version=${version:-$DEFAULT_FEDORA_VERSION}
|
|
fi
|
|
|
|
case "$type" in
|
|
fedora)
|
|
echo "$REGISTRY_URL/f$version/fedora-toolbox:$version"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
function remove_all_containers() {
|
|
echo "# [remove_all_containers]"
|
|
run_toolbox '?' rm --all --force
|
|
}
|
|
|
|
|
|
# BATS specific functions
|
|
|
|
#########
|
|
# die # Abort with helpful message
|
|
#########
|
|
function die() {
|
|
echo "#/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" >&2
|
|
echo "#| FAIL: $*" >&2
|
|
echo "#\\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" >&2
|
|
false
|
|
}
|
|
|
|
|
|
########
|
|
# is # Compare actual vs expected string; fail w/diagnostic if mismatch
|
|
########
|
|
#
|
|
# Compares given string against expectations, using 'expr' to allow patterns.
|
|
#
|
|
# Examples:failed to inspect
|
|
#
|
|
# is "$actual" "$expected" "descriptive test name"
|
|
# is "apple" "orange" "name of a test that will fail in most universes"
|
|
# is "apple" "[a-z]\+" "this time it should pass"
|
|
#
|
|
function is() {
|
|
local actual="$1"
|
|
local expect="$2"
|
|
local testname="${3:-FIXME}"
|
|
|
|
if [ -z "$expect" ]; then
|
|
if [ -z "$actual" ]; then
|
|
return
|
|
fi
|
|
expect='[no output]'
|
|
elif expr "$actual" : "$expect" >/dev/null; then
|
|
return
|
|
fi
|
|
|
|
# This is a multi-line message, which may in turn contain multi-line
|
|
# output, so let's format it ourself, readably
|
|
local -a actual_split
|
|
readarray -t actual_split <<<"$actual"
|
|
printf "#/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n" >&2
|
|
printf "#| FAIL: $testname\n" >&2
|
|
printf "#| expected: '%s'\n" "$expect" >&2
|
|
printf "#| actual: '%s'\n" "${actual_split[0]}" >&2
|
|
local line
|
|
for line in "${actual_split[@]:1}"; do
|
|
printf "#| > '%s'\n" "$line" >&2
|
|
done
|
|
printf "#\\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" >&2
|
|
false
|
|
}
|
|
|
|
#################
|
|
# parse_table # Split a table on '|' delimiters; return space-separated
|
|
#################
|
|
#
|
|
# See sample .bats scripts for examples. The idea is to list a set of
|
|
# tests in a table, then use simple logic to iterate over each test.
|
|
# Columns are separated using '|' (pipe character) because sometimes
|
|
# we need spaces in our fields.
|
|
#
|
|
function parse_table() {
|
|
while read line; do
|
|
test -z "$line" && continue
|
|
|
|
declare -a row=()
|
|
while read col; do
|
|
dprint "col=<<$col>>"
|
|
row+=("$col")
|
|
done < <(echo "$line" | tr '|' '\012' | sed -e 's/^ *//' -e 's/\\/\\\\/g')
|
|
|
|
printf "%q " "${row[@]}"
|
|
printf "\n"
|
|
done <<<"$1"
|
|
}
|