Skip to content
Snippets Groups Projects
Commit 1dbf8415 authored by ale's avatar ale
Browse files

Initial commit (import)

parents
Branches
No related tags found
No related merge requests found
Pipeline #57023 passed
include: "https://git.autistici.org/pipelines/containers/raw/master/common.yml"
FROM quay.io/podman/stable
# Include some tools that might be useful for testing purposes.
RUN dnf install -y netcat curl openssl
COPY with-container /usr/bin/with-container
COPY netcat-expect /usr/bin/netcat-expect
This container image is meant for testing other container images
(usually built via Gitlab CI) in a setup that mirrors what is used by
[float](https://git.autistici.org/ai3/float), i.e. a root-less,
read-only Podman environment.
The image itself is based on the official Podman stable image, and it
includes a wrapper script called *with-container*, that will start a
test container and then run a test script.
It can be used in your *.gitlab-ci.yml* file like this:
```yaml
- container_test:
stage: test
image: registry.git.autistici.org/ai3/docker/test/float-like-podman:master
script:
- with-container $IMAGE_TAG ./my-test-script.sh
```
The wrapper accepts Podman options, to customize the environment (like
*--env* or *--mount*) in order for the test to run properly. Note that
these options must be specified before the IMAGE_TAG, and must follow
the --VAR=VALUE syntax strictly (each must be a single argument to
with-container in order to be parsed correctly). E.g.:
```shell
with-container --env=FOO=bar --mount=type=bind,source=config.txt,destination=config.txt my-image ./test.sh
```
### Test script interface
The with-container wrapper takes care of running the test script
multiple times in case of transient errors, so you don't have to
add retry logic to your test script.
To distinguish permanent and transient errors, with-container looks
at the test script exit status code:
* 0: success
* 1: transient failure, retry
* anything else: permanent failure
### netcat-expect
An additional little tool is provided that can run request/response
matches against a target TCP server (using *netcat*). For each test,
create a directory with files named *request* and *response* that
should match the expected interaction, and run (e.g. with respect to
the above Gitlab CI example):
```yaml
script:
- with-container $IMAGE_TAG netcat-expect testdata/ping localhost 8080
```
#!/bin/sh
#
# Runs netcat against a target with a request payload, expecting a specific response.
# Both 'request' and 'response' should be files in the specified test directory.
#
# Any command-line options are passed through to netcat.
#
# Netcat arg parsing is a bit hacky, we have to handle the known
# options that take arguments specially.
netcat_args=
while [ $# -gt 0 ]; do
case "$1" in
-[IiMmOPpqsTVWwXx])
netcat_args="$netcat_args $1 $2"
shift 2
;;
-[IiMmOPpqsTVWwXx]*)
netcat_args="$netcat_args $1"
shift
;;
-*)
netcat_args="$netcat_args $1"
shift
;;
*)
break
;;
esac
done
if [ $# -lt 3 ]; then
echo "Usage: $0 [<netcat_options>] <testdir> <target_host> <target_port>"
exit 2
fi
testdir="$1"
testname=$(basename "$testdir")
target_host="$2"
target_port="$3"
target="${target_host}:${target_port}"
if [ ! -e "$testdir" ]; then
echo "Fatal: test directory $testdir does not exist" >&2
exit 1
fi
tmpdir=$(mktemp -d)
trap "rm -fr $tmpdir 2>/dev/null" EXIT
nc -vvvv -w 10 $netcat_args "$target_host" "$target_port" \
< "$testdir/request" \
> "$tmpdir/response"
if [ $? -gt 0 ]; then
echo "$testname: Fatal: connection to $target failed" >&2
exit 1
fi
if ! diff -u "$testdir/response" "$tmpdir/response"; then
echo "$testname: Fatal: response from $target does not match expectation" >&2
exit 1
fi
echo "$testname: Success: response from $target matches expectation" >&2
cat "$tmpdir/response"
exit 0
#!/bin/sh
die() {
echo "$*" >&2
exit 1
}
image=
podman_args=
script=
while [ $# -gt 0 ]; do
case "$1" in
-*)
podman_args="$podman_args $1"
;;
*)
if [ -z "$image" ]; then
image="$1"
else
script="$script $1"
fi
;;
esac
shift
done
if [ -z "$image" -o -z "$script" ]; then
die "Usage: $0 [<podman_args>...] <image> <script> [<script_args>...]"
fi
# The podman image is based on Fedora, which has a symlink tree in
# /etc/ssl/certs. Copy everything to a bind-mountable dir.
cp -rL /etc/ssl/certs /tmp/certs
case "$image" in
localhost/*) ;;
*)
podman pull $image \
|| die "error fetching image"
;;
esac
set -x
podman run \
--rm \
--name=test-container \
--pull=never \
--log-driver=none \
--no-healthcheck \
--network=host \
--user=1000:1000 \
--read-only \
--mount=type=tmpfs,destination=/run,tmpfs-mode=01777,tmpfs-size=16M,exec=true,notmpcopyup \
--mount=type=tmpfs,destination=/tmp,tmpfs-mode=01777,tmpfs-size=16M,notmpcopyup \
--mount=type=bind,source=/tmp/certs,destination=/etc/ssl/certs \
--security-opt=no-new-privileges \
--cap-drop=all \
$podman_args \
"$@" \
"$image" &
[ $? -gt 0 ] && die "Error starting container"
set +x
echo "started container"
trap "podman kill test-container >/dev/null 2>&1" EXIT
sleep 5
# The probe script protocol is simple: exit status 0 == success, exit
# status 1 == temporary failure, anything else = permanent failure.
n=0
ret=1
while [ $n -lt ${TIMEOUT:-30} ]; do
n=$(expr "$n" + 1)
echo "test attempt #$n" >&2
$script
rc=$?
case $rc in
0)
ret=0
break
;;
1)
;;
*)
echo "permanent failure of the test script" >&2
break
;;
esac
sleep 1
done
exit $ret
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment