From 47af0afbd15b074561d98a117be353301a354e85 Mon Sep 17 00:00:00 2001 From: Ed Santiago Date: Wed, 2 Dec 2020 13:59:42 -0700 Subject: WIP: test docker-compose git-fetch a set of docker-compose examples Add a mechanism for 'curl'ing to verify that service is up. For each docker-compose directory: 1) test that it comes up 2) use 'curl' to confirm that the service is up 3) bring it back down Signed-off-by: Ed Santiago --- .../elasticsearch-logstash-kibana.curl | 3 + test/docker-compose/flask.curl | 1 + test/docker-compose/gitea-postgres.curl | 1 + test/docker-compose/react-rust-postgres.skip | 1 + test/docker-compose/test-docker-compose | 441 +++++++++++++++++++++ 5 files changed, 447 insertions(+) create mode 100644 test/docker-compose/elasticsearch-logstash-kibana.curl create mode 100644 test/docker-compose/flask.curl create mode 100644 test/docker-compose/gitea-postgres.curl create mode 100644 test/docker-compose/react-rust-postgres.skip create mode 100755 test/docker-compose/test-docker-compose (limited to 'test') diff --git a/test/docker-compose/elasticsearch-logstash-kibana.curl b/test/docker-compose/elasticsearch-logstash-kibana.curl new file mode 100644 index 000000000..9a94bd65c --- /dev/null +++ b/test/docker-compose/elasticsearch-logstash-kibana.curl @@ -0,0 +1,3 @@ +9200 elasticsearch +9600 logstash +5601 kibana diff --git a/test/docker-compose/flask.curl b/test/docker-compose/flask.curl new file mode 100644 index 000000000..b50ddbf1d --- /dev/null +++ b/test/docker-compose/flask.curl @@ -0,0 +1 @@ +5000 Hello World! diff --git a/test/docker-compose/gitea-postgres.curl b/test/docker-compose/gitea-postgres.curl new file mode 100644 index 000000000..a0a58b3fd --- /dev/null +++ b/test/docker-compose/gitea-postgres.curl @@ -0,0 +1 @@ +3000 .* Gitea: Git with a cup of tea diff --git a/test/docker-compose/react-rust-postgres.skip b/test/docker-compose/react-rust-postgres.skip new file mode 100644 index 000000000..57f89ed17 --- /dev/null +++ b/test/docker-compose/react-rust-postgres.skip @@ -0,0 +1 @@ +broken diff --git a/test/docker-compose/test-docker-compose b/test/docker-compose/test-docker-compose new file mode 100755 index 000000000..d37caa12a --- /dev/null +++ b/test/docker-compose/test-docker-compose @@ -0,0 +1,441 @@ +#!/usr/bin/env bash +# +# Usage: test-docker-compose [testname] +# +# DEVELOPER NOTE: you almost certainly don't need to play in here. See README. +# +ME=$(basename $0) + +############################################################################### +# BEGIN stuff you can but probably shouldn't customize + +# Directory where this script (and extra test configs) live +TEST_ROOTDIR=$(realpath $(dirname $0)) + +# Podman executable +PODMAN_BIN=$(realpath bin)/podman + +# Github repo containing sample docker-compose setups +# FIXME: we should probably version this +AWESOME_COMPOSE=https://github.com/docker/awesome-compose + +# Local path to docker socket +DOCKER_SOCK=/var/run/docker.sock + +# END stuff you can but probably shouldn't customize +############################################################################### +# BEGIN setup + +TMPDIR=${TMPDIR:-/var/tmp} +WORKDIR=$(mktemp --tmpdir -d $ME.tmp.XXXXXX) + +# Log of all HTTP requests and responses; always make '.log' point to latest +LOGBASE=${TMPDIR}/$ME.log +LOG=${LOGBASE}.$(date +'%Y%m%dT%H%M%S') +ln -sf $LOG $LOGBASE + +# Keep track of test count and failures in files, not variables, because +# variables don't carry back up from subshells. +testcounter_file=$WORKDIR/.testcounter +failures_file=$WORKDIR/.failures + +echo 0 >$testcounter_file +echo 0 >$failures_file + +# END setup +############################################################################### +# BEGIN infrastructure code - the helper functions used in tests themselves + +######### +# die # Exit error with a message to stderr +######### +function die() { + echo "$ME: $*" >&2 + exit 1 +} + +######## +# is # Simple comparison +######## +function is() { + local actual=$1 + local expect=$2 + local testname=$3 + + if [[ $actual = $expect ]]; then + # On success, include expected value; this helps readers understand + _show_ok 1 "$testname=$expect" + return + fi + _show_ok 0 "$testname" "$expect" "$actual" +} + +########## +# like # Compare, but allowing patterns +########## +function like() { + local actual=$1 + local expect=$2 + local testname=$3 + + # "is" (equality) is a subset of "like", but one that expr fails on if + # the expected result has shell-special characters like '['. Treat it + # as a special case. + if [[ $actual = $expect ]]; then + _show_ok 1 "$testname=$expect" + return + fi + + if expr "$actual" : "$expect" &>/dev/null; then + # On success, include expected value; this helps readers understand + _show_ok 1 "$testname ('$actual') ~ $expect" + return + fi + _show_ok 0 "$testname" "~ $expect" "$actual" +} + +############## +# _show_ok # Helper for is() and like(): displays 'ok' or 'not ok' +############## +function _show_ok() { + local ok=$1 + local testname=$2 + + # If output is a tty, colorize pass/fail + local red= + local green= + local reset= + local bold= + if [ -t 1 ]; then + red='\e[31m' + green='\e[32m' + reset='\e[0m' + bold='\e[1m' + fi + + _bump $testcounter_file + count=$(<$testcounter_file) + + # "skip" is a special case of "ok". Assume that our caller has included + # the magical '# skip - reason" comment string. + if [[ $ok == "skip" ]]; then + # colon-plus: replace green with yellow, but only if green is non-null + green="${green:+\e[33m}" + ok=1 + fi + if [ $ok -eq 1 ]; then + echo -e "${green}ok $count $testname${reset}" + echo "ok $count $testname" >>$LOG + return + fi + + # Failed + local expect=$3 + local actual=$4 + echo -e "${red}not ok $count $testname${reset}" + echo -e "${red}# expected: $expect${reset}" + echo -e "${red}# actual: ${bold}$actual${reset}" + + echo "not ok $count $testname" >>$LOG + echo " expected: $expect" >>$LOG + + _bump $failures_file +} + +########### +# _bump # Increment a counter in a file +########### +function _bump() { + local file=$1 + + count=$(<$file) + echo $(( $count + 1 )) >| $file +} + +############# +# jsonify # convert 'foo=bar,x=y' to json {"foo":"bar","x":"y"} +############# +function jsonify() { + # split by comma + local -a settings_in + read -ra settings_in <<<"$1" + + # convert each to double-quoted form + local -a settings_out + for i in ${settings_in[*]}; do + settings_out+=$(sed -e 's/\(.*\)=\(.*\)/"\1":"\2"/' <<<$i) + done + + # ...and wrap inside braces. + # FIXME: handle commas + echo "{${settings_out[*]}}" +} + +####### +# t # Main test helper +####### +function t() { + local method=$1; shift + local path=$1; shift + local curl_args + + local testname="$method $path" + # POST requests require an extra params arg + if [[ $method = "POST" ]]; then + curl_args="-d $(jsonify $1)" + testname="$testname [$curl_args]" + shift + fi + + # entrypoint path can include a descriptive comment; strip it off + path=${path%% *} + + # curl -X HEAD but without --head seems to wait for output anyway + if [[ $method == "HEAD" ]]; then + curl_args="--head" + fi + local expected_code=$1; shift + + # If given path begins with /, use it as-is; otherwise prepend /version/ + local url=http://$HOST:$PORT + if expr "$path" : "/" >/dev/null; then + url="$url$path" + else + url="$url/v1.40/$path" + fi + + # Log every action we do + echo "-------------------------------------------------------------" >>$LOG + echo "\$ $testname" >>$LOG + rm -f $WORKDIR/curl.* + # -s = silent, but --write-out 'format' gives us important response data + response=$(curl -s -X $method ${curl_args} \ + -H 'Content-type: application/json' \ + --dump-header $WORKDIR/curl.headers.out \ + --write-out '%{http_code}^%{content_type}^%{time_total}' \ + -o $WORKDIR/curl.result.out "$url") + + # Any error from curl is instant bad news, from which we can't recover + rc=$? + if [[ $rc -ne 0 ]]; then + echo "FATAL: curl failure ($rc) on $url - cannot continue" >&2 + exit 1 + fi + + # Show returned headers (without trailing ^M or empty lines) in log file. + # Sometimes -- I can't remember why! -- we don't get headers. + if [[ -e $WORKDIR/curl.headers.out ]]; then + tr -d '\015' < $WORKDIR/curl.headers.out | egrep '.' >>$LOG + fi + + IFS='^' read actual_code content_type time_total <<<"$response" + printf "X-Response-Time: ${time_total}s\n\n" >>$LOG + + # Log results, if text. If JSON, filter through jq for readability. + if [[ $content_type =~ /octet ]]; then + output="[$(file --brief $WORKDIR/curl.result.out)]" + echo "$output" >>$LOG + else + output=$(< $WORKDIR/curl.result.out) + + if [[ $content_type =~ application/json ]]; then + jq . <<<"$output" >>$LOG + else + echo "$output" >>$LOG + fi + fi + + # Test return code + is "$actual_code" "$expected_code" "$testname : status" + + # Special case: 204/304, by definition, MUST NOT return content (rfc2616) + if [[ $expected_code = 204 || $expected_code = 304 ]]; then + if [ -n "$*" ]; then + die "Internal error: ${expected_code} status returns no output; fix your test." + fi + if [ -n "$output" ]; then + _show_ok 0 "$testname: ${expected_code} status returns no output" "''" "$output" + fi + return + fi + + local i + + # Special case: if response code does not match, dump the response body + # and skip all further subtests. + if [[ $actual_code != $expected_code ]]; then + echo -e "# response: $output" + for i; do + _show_ok skip "$testname: $i # skip - wrong return code" + done + return + fi + + for i; do + if expr "$i" : "[^=~]\+=.*" >/dev/null; then + # Exact match on json field + json_field=$(expr "$i" : "\([^=]*\)=") + expect=$(expr "$i" : '[^=]*=\(.*\)') + actual=$(jq -r "$json_field" <<<"$output") + is "$actual" "$expect" "$testname : $json_field" + elif expr "$i" : "[^=~]\+~.*" >/dev/null; then + # regex match on json field + json_field=$(expr "$i" : "\([^~]*\)~") + expect=$(expr "$i" : '[^~]*~\(.*\)') + actual=$(jq -r "$json_field" <<<"$output") + like "$actual" "$expect" "$testname : $json_field" + else + # Direct string comparison + is "$output" "$i" "$testname : output" + fi + done +} + +################### +# start_service # Run the socket listener +################### +service_pid= +function start_service() { + test -x $PODMAN_BIN || die "Not found: $PODMAN_BIN" + + rm -rf $WORKDIR/{root,runroot,cni} + mkdir $WORKDIR/cni + cp /etc/cni/net.d/*podman*conflist $WORKDIR/cni/ + + $PODMAN_BIN \ + --root $WORKDIR/root \ + --runroot $WORKDIR/runroot \ + --cgroup-manager=systemd \ + --cni-config-dir $WORKDIR/cni \ + system service \ + --time 0 unix:/$DOCKER_SOCK \ + &> $WORKDIR/server.log & + service_pid=$! + + # Wait (FIXME: how do we test the socket?) + local _timeout=5 + while [ $_timeout -gt 0 ]; do + # FIXME: should we actually try a read or write? + test -S $DOCKER_SOCK && return + sleep 1 + _timeout=$(( $_timeout - 1 )) + done + cat $WORKDIR/server.log + die "Timed out waiting for service" +} + +############ +# podman # Needed by some test scripts to invoke the actual podman binary +############ +function podman() { + echo "\$ $PODMAN_BIN $*" >>$WORKDIR/output.log + $PODMAN_BIN --root $WORKDIR "$@" >>$WORKDIR/output.log 2>&1 +} + +# END infrastructure code +############################################################################### +# BEGIN sanity checks + +for tool in curl docker-compose; do + type $tool &>/dev/null || die "$ME: Required tool '$tool' not found" +done + +# END sanity checks +############################################################################### +# BEGIN entry handler (subtest invoker) + +TESTS_DIR=$WORKDIR/awesome-compose + +git clone $AWESOME_COMPOSE $TESTS_DIR + +# Identify the tests to run. If called with args, use those as globs. +tests_to_run=() +if [ -n "$*" ]; then + shopt -s nullglob + for i; do + match=(${TEST_ROOTDIR}/*${i}*.curl) + if [ ${#match} -eq 0 ]; then + die "No match for $TEST_ROOTDIR/*$i*.curl" + fi + tests_to_run+=("${match[@]}") + done + shopt -u nullglob +else + tests_to_run=(${TEST_ROOTDIR}/*.curl) +fi + +# Test count: each of those tests might have a local set of subtests +n_tests=$((2 * ${#tests_to_run[*]})) +for t in ${tests_to_run[@]}; do + n_curls=$(wc -l $t | awk '{print $1}') + n_tests=$(( n_tests + n_curls )) +done + + +echo "1..$n_tests" + +for t in ${tests_to_run[@]}; do + testname="$(basename $t .curl)" + + start_service + + logfile=$WORKDIR/$testname.log + ( + cd $TESTS_DIR/$testname || die "Cannot cd $TESTS_DIR/$testname" + docker-compose up -d &> $logfile + if [[ $? -ne 0 ]]; then + _show_ok 0 "$testname - up" "[ok]" "$(< $logfile)" + # FIXME: cat log + docker-compose down >>$logfile 2>&1 # No status check here + exit 1 + fi + _show_ok 1 "$testname - up" + + # FIXME: run tests, e.g. curl + curls=$TEST_ROOTDIR/$testname.curl + if [[ -e $curls ]]; then + while read port expect; do + actual=$(curl --retry 5 --retry-connrefused -s http://127.0.0.1:$port/) + curl_rc=$? + if [ $curl_rc -ne 0 ]; then + _show_ok 0 "$testname - curl failed with status $curl_rc" + docker-compose down >>$logfile 2>&1 + exit 1 + fi + echo "got here: $actual" + like "$actual" "$expect" "$testname : port $port" + done < $curls + fi + + echo "OK, press ENTER to stop" + read x + + docker-compose down &> $logfile + if [[ $? -eq 0 ]]; then + _show_ok 1 "$testname - down" + else + _show_ok 0 "$testname - down" "[ok]" "$(< $logfile)" + # FIXME: show error + fi + ) + + kill $service_pid + wait $service_pid + + # FIXME: otherwise we get EBUSY + umount $WORKDIR/root/overlay &>/dev/null +done + +# END entry handler +############################################################################### + +# Clean up + +test_count=$(<$testcounter_file) +failure_count=$(<$failures_file) + +#if [ -z "$PODMAN_TESTS_KEEP_WORKDIR" ]; then +# rm -rf $WORKDIR +#fi + +exit $failure_count -- cgit v1.2.3-54-g00ecf From 82d7b9f2e21c93cfb12c8f199284c38f3e858280 Mon Sep 17 00:00:00 2001 From: baude Date: Wed, 2 Dec 2020 08:45:08 -0600 Subject: add compose regression to ci to prevent any regressions, we should be running regression tests using compose. Signed-off-by: baude --- .cirrus.yml | 18 +- contrib/cirrus/runner.sh | 4 + contrib/cirrus/setup_environment.sh | 1 + test/compose/elasticsearch-logstash-kibana.curl | 3 + test/compose/env_and_volume/docker-compose.yml | 18 + test/compose/env_and_volume/read/Dockerfile | 5 + test/compose/env_and_volume/read/app.py | 10 + test/compose/env_and_volume/write/Dockerfile | 5 + test/compose/env_and_volume/write/app.py | 13 + test/compose/flask.curl | 1 + test/compose/gitea-postgres.curl | 1 + test/compose/mount_and_label/docker-compose.yml | 10 + test/compose/mount_and_label/frontend/Dockerfile | 5 + test/compose/mount_and_label/frontend/app.py | 10 + test/compose/mount_and_label/readme.txt | 5 + test/compose/port_map_diff_port/docker-compose.yml | 6 + .../compose/port_map_diff_port/frontend/Dockerfile | 5 + test/compose/port_map_diff_port/frontend/app.py | 9 + test/compose/react-rust-postgres.skip | 1 + test/compose/simple_port_map/docker-compose.yml | 6 + test/compose/simple_port_map/frontend/Dockerfile | 6 + test/compose/simple_port_map/frontend/app.py | 9 + test/compose/test-compose | 439 ++++++++++++++++++++ .../elasticsearch-logstash-kibana.curl | 3 - test/docker-compose/flask.curl | 1 - test/docker-compose/gitea-postgres.curl | 1 - test/docker-compose/react-rust-postgres.skip | 1 - test/docker-compose/test-docker-compose | 441 --------------------- 28 files changed, 589 insertions(+), 448 deletions(-) create mode 100644 test/compose/elasticsearch-logstash-kibana.curl create mode 100644 test/compose/env_and_volume/docker-compose.yml create mode 100644 test/compose/env_and_volume/read/Dockerfile create mode 100644 test/compose/env_and_volume/read/app.py create mode 100644 test/compose/env_and_volume/write/Dockerfile create mode 100644 test/compose/env_and_volume/write/app.py create mode 100644 test/compose/flask.curl create mode 100644 test/compose/gitea-postgres.curl create mode 100644 test/compose/mount_and_label/docker-compose.yml create mode 100644 test/compose/mount_and_label/frontend/Dockerfile create mode 100644 test/compose/mount_and_label/frontend/app.py create mode 100644 test/compose/mount_and_label/readme.txt create mode 100644 test/compose/port_map_diff_port/docker-compose.yml create mode 100644 test/compose/port_map_diff_port/frontend/Dockerfile create mode 100644 test/compose/port_map_diff_port/frontend/app.py create mode 100644 test/compose/react-rust-postgres.skip create mode 100644 test/compose/simple_port_map/docker-compose.yml create mode 100644 test/compose/simple_port_map/frontend/Dockerfile create mode 100644 test/compose/simple_port_map/frontend/app.py create mode 100755 test/compose/test-compose delete mode 100644 test/docker-compose/elasticsearch-logstash-kibana.curl delete mode 100644 test/docker-compose/flask.curl delete mode 100644 test/docker-compose/gitea-postgres.curl delete mode 100644 test/docker-compose/react-rust-postgres.skip delete mode 100755 test/docker-compose/test-docker-compose (limited to 'test') diff --git a/.cirrus.yml b/.cirrus.yml index 0fa51be63..8507aa3d2 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -30,7 +30,7 @@ env: PRIOR_UBUNTU_NAME: "ubuntu-19" # Google-cloud VM Images - IMAGE_SUFFIX: "c5402398833246208" + IMAGE_SUFFIX: "c4704091098054656" FEDORA_CACHE_IMAGE_NAME: "fedora-${IMAGE_SUFFIX}" PRIOR_FEDORA_CACHE_IMAGE_NAME: "prior-fedora-${IMAGE_SUFFIX}" UBUNTU_CACHE_IMAGE_NAME: "ubuntu-${IMAGE_SUFFIX}" @@ -434,6 +434,21 @@ apiv2_test_task: podman_system_info_script: '$SCRIPT_BASE/logcollector.sh podman' time_script: '$SCRIPT_BASE/logcollector.sh time' +compose_test_task: + name: "compose test on $DISTRO_NV" + alias: compose_test + depends_on: + - validate + gce_instance: *standardvm + env: + <<: *stdenvars + TEST_FLAVOR: compose + clone_script: *noop # Comes from cache + gopath_cache: *ro_gopath_cache + setup_script: *setup + main_script: *main + always: *logs_artifacts + # Execute the podman integration tests on all primary platforms and release # versions, as root, without involving the podman-remote client. @@ -619,6 +634,7 @@ success_task: - docker-py_test - unit_test - apiv2_test + - compose_test - local_integration_test - remote_integration_test - rootless_integration_test diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh index fa921f3e4..cc6d155f9 100755 --- a/contrib/cirrus/runner.sh +++ b/contrib/cirrus/runner.sh @@ -73,6 +73,10 @@ function _run_apiv2() { make localapiv2 |& logformatter } +function _run_compose() { + ./test/compose/test-compose |& logformatter +} + function _run_int() { dotest integration } diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index c32b45a4f..a3c0f9a13 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -195,6 +195,7 @@ case "$TEST_FLAVOR" in build) make clean ;; unit) ;; apiv2) ;& # use next item + compose) ;& int) ;& sys) ;& bindings) ;& diff --git a/test/compose/elasticsearch-logstash-kibana.curl b/test/compose/elasticsearch-logstash-kibana.curl new file mode 100644 index 000000000..ddb7a96b0 --- /dev/null +++ b/test/compose/elasticsearch-logstash-kibana.curl @@ -0,0 +1,3 @@ +9200 You Know, for Search +9600 "status":"green" +5601 Kibana diff --git a/test/compose/env_and_volume/docker-compose.yml b/test/compose/env_and_volume/docker-compose.yml new file mode 100644 index 000000000..df906e170 --- /dev/null +++ b/test/compose/env_and_volume/docker-compose.yml @@ -0,0 +1,18 @@ +version: '3' +services: + writer: + environment: + - PODMAN_MSG=podman_rulez + build: write + ports: + - '5000:5000' + volumes: + - data:/data + reader: + build: read + ports: + - '5001:5000' + volumes: + - data:/data +volumes: + data: diff --git a/test/compose/env_and_volume/read/Dockerfile b/test/compose/env_and_volume/read/Dockerfile new file mode 100644 index 000000000..a393a0dcb --- /dev/null +++ b/test/compose/env_and_volume/read/Dockerfile @@ -0,0 +1,5 @@ +FROM podman_python +WORKDIR /app +COPY . /app +ENTRYPOINT ["python3"] +CMD ["app.py"] diff --git a/test/compose/env_and_volume/read/app.py b/test/compose/env_and_volume/read/app.py new file mode 100644 index 000000000..71fbbb26a --- /dev/null +++ b/test/compose/env_and_volume/read/app.py @@ -0,0 +1,10 @@ +from flask import Flask +app = Flask(__name__) + +@app.route('/') +def hello(): + f = open("/data/message", "r") + return f.read() + +if __name__ == '__main__': + app.run(host='0.0.0.0') diff --git a/test/compose/env_and_volume/write/Dockerfile b/test/compose/env_and_volume/write/Dockerfile new file mode 100644 index 000000000..a393a0dcb --- /dev/null +++ b/test/compose/env_and_volume/write/Dockerfile @@ -0,0 +1,5 @@ +FROM podman_python +WORKDIR /app +COPY . /app +ENTRYPOINT ["python3"] +CMD ["app.py"] diff --git a/test/compose/env_and_volume/write/app.py b/test/compose/env_and_volume/write/app.py new file mode 100644 index 000000000..b6ad6fe63 --- /dev/null +++ b/test/compose/env_and_volume/write/app.py @@ -0,0 +1,13 @@ +from flask import Flask +import os +app = Flask(__name__) + +@app.route('/') +def hello(): + f = open("/data/message", "w") + f.write(os.getenv("PODMAN_MSG")) + f.close() + return "done" + +if __name__ == '__main__': + app.run(host='0.0.0.0') diff --git a/test/compose/flask.curl b/test/compose/flask.curl new file mode 100644 index 000000000..b50ddbf1d --- /dev/null +++ b/test/compose/flask.curl @@ -0,0 +1 @@ +5000 Hello World! diff --git a/test/compose/gitea-postgres.curl b/test/compose/gitea-postgres.curl new file mode 100644 index 000000000..a0a58b3fd --- /dev/null +++ b/test/compose/gitea-postgres.curl @@ -0,0 +1 @@ +3000 .* Gitea: Git with a cup of tea diff --git a/test/compose/mount_and_label/docker-compose.yml b/test/compose/mount_and_label/docker-compose.yml new file mode 100644 index 000000000..6487067e3 --- /dev/null +++ b/test/compose/mount_and_label/docker-compose.yml @@ -0,0 +1,10 @@ +version: '3' +services: + web: + build: frontend + ports: + - '5000:5000' + volumes: + - /tmp/mount:/data:ro + labels: + - "io.podman=the_best" diff --git a/test/compose/mount_and_label/frontend/Dockerfile b/test/compose/mount_and_label/frontend/Dockerfile new file mode 100644 index 000000000..a393a0dcb --- /dev/null +++ b/test/compose/mount_and_label/frontend/Dockerfile @@ -0,0 +1,5 @@ +FROM podman_python +WORKDIR /app +COPY . /app +ENTRYPOINT ["python3"] +CMD ["app.py"] diff --git a/test/compose/mount_and_label/frontend/app.py b/test/compose/mount_and_label/frontend/app.py new file mode 100644 index 000000000..bd2794d94 --- /dev/null +++ b/test/compose/mount_and_label/frontend/app.py @@ -0,0 +1,10 @@ +from flask import Flask +app = Flask(__name__) + +@app.route('/') +def hello(): + f = open("/data/message") + return f.read() + +if __name__ == '__main__': + app.run(host='0.0.0.0') diff --git a/test/compose/mount_and_label/readme.txt b/test/compose/mount_and_label/readme.txt new file mode 100644 index 000000000..bba769c51 --- /dev/null +++ b/test/compose/mount_and_label/readme.txt @@ -0,0 +1,5 @@ +this test creates a container with a mount (not volume) and also adds a label to the container. + +validate by curl http://localhost:5000 and message should be same message as piped into the mount message. + +also verify the label with podman ps and a filter that only catches that container diff --git a/test/compose/port_map_diff_port/docker-compose.yml b/test/compose/port_map_diff_port/docker-compose.yml new file mode 100644 index 000000000..3003c52f4 --- /dev/null +++ b/test/compose/port_map_diff_port/docker-compose.yml @@ -0,0 +1,6 @@ +version: '3' +services: + web: + build: frontend + ports: + - '5001:5000' diff --git a/test/compose/port_map_diff_port/frontend/Dockerfile b/test/compose/port_map_diff_port/frontend/Dockerfile new file mode 100644 index 000000000..a393a0dcb --- /dev/null +++ b/test/compose/port_map_diff_port/frontend/Dockerfile @@ -0,0 +1,5 @@ +FROM podman_python +WORKDIR /app +COPY . /app +ENTRYPOINT ["python3"] +CMD ["app.py"] diff --git a/test/compose/port_map_diff_port/frontend/app.py b/test/compose/port_map_diff_port/frontend/app.py new file mode 100644 index 000000000..895556a89 --- /dev/null +++ b/test/compose/port_map_diff_port/frontend/app.py @@ -0,0 +1,9 @@ +from flask import Flask +app = Flask(__name__) + +@app.route('/') +def hello(): + return "Podman rulez!" + +if __name__ == '__main__': + app.run(host='0.0.0.0') diff --git a/test/compose/react-rust-postgres.skip b/test/compose/react-rust-postgres.skip new file mode 100644 index 000000000..57f89ed17 --- /dev/null +++ b/test/compose/react-rust-postgres.skip @@ -0,0 +1 @@ +broken diff --git a/test/compose/simple_port_map/docker-compose.yml b/test/compose/simple_port_map/docker-compose.yml new file mode 100644 index 000000000..e7eab1047 --- /dev/null +++ b/test/compose/simple_port_map/docker-compose.yml @@ -0,0 +1,6 @@ +version: '3' +services: + web: + build: frontend + ports: + - '5000:5000' diff --git a/test/compose/simple_port_map/frontend/Dockerfile b/test/compose/simple_port_map/frontend/Dockerfile new file mode 100644 index 000000000..2595828ff --- /dev/null +++ b/test/compose/simple_port_map/frontend/Dockerfile @@ -0,0 +1,6 @@ +FROM alpine +WORKDIR /app +RUN apk update && apk add py3-pip && pip3 install flask +COPY . /app +ENTRYPOINT ["python3"] +CMD ["app.py"] diff --git a/test/compose/simple_port_map/frontend/app.py b/test/compose/simple_port_map/frontend/app.py new file mode 100644 index 000000000..895556a89 --- /dev/null +++ b/test/compose/simple_port_map/frontend/app.py @@ -0,0 +1,9 @@ +from flask import Flask +app = Flask(__name__) + +@app.route('/') +def hello(): + return "Podman rulez!" + +if __name__ == '__main__': + app.run(host='0.0.0.0') diff --git a/test/compose/test-compose b/test/compose/test-compose new file mode 100755 index 000000000..f7643b078 --- /dev/null +++ b/test/compose/test-compose @@ -0,0 +1,439 @@ +#!/usr/bin/env bash +# +# Usage: test-docker-compose [testname] +# +# DEVELOPER NOTE: you almost certainly don't need to play in here. See README. +# +ME=$(basename $0) + +############################################################################### +# BEGIN stuff you can but probably shouldn't customize + +# Directory where this script (and extra test configs) live +TEST_ROOTDIR=$(realpath $(dirname $0)) + +# Podman executable +PODMAN_BIN=$(realpath bin)/podman + +# Github repo containing sample docker-compose setups +# FIXME: we should probably version this +AWESOME_COMPOSE=https://github.com/docker/awesome-compose + +# Local path to docker socket +DOCKER_SOCK=/var/run/docker.sock + +# END stuff you can but probably shouldn't customize +############################################################################### +# BEGIN setup + +TMPDIR=${TMPDIR:-/var/tmp} +WORKDIR=$(mktemp --tmpdir -d $ME.tmp.XXXXXX) + +# Log of all HTTP requests and responses; always make '.log' point to latest +LOGBASE=${TMPDIR}/$ME.log +LOG=${LOGBASE}.$(date +'%Y%m%dT%H%M%S') +ln -sf $LOG $LOGBASE + +# Keep track of test count and failures in files, not variables, because +# variables don't carry back up from subshells. +testcounter_file=$WORKDIR/.testcounter +failures_file=$WORKDIR/.failures + +echo 0 >$testcounter_file +echo 0 >$failures_file + +# END setup +############################################################################### +# BEGIN infrastructure code - the helper functions used in tests themselves + +######### +# die # Exit error with a message to stderr +######### +function die() { + echo "$ME: $*" >&2 + exit 1 +} + +######## +# is # Simple comparison +######## +function is() { + local actual=$1 + local expect=$2 + local testname=$3 + + if [[ $actual = $expect ]]; then + # On success, include expected value; this helps readers understand + _show_ok 1 "$testname=$expect" + return + fi + _show_ok 0 "$testname" "$expect" "$actual" +} + +########## +# like # Compare, but allowing patterns +########## +function like() { + local actual=$1 + local expect=$2 + local testname=$3 + + # "is" (equality) is a subset of "like", but one that expr fails on if + # the expected result has shell-special characters like '['. Treat it + # as a special case. + + if [[ "$actual" = "$expect" ]]; then + _show_ok 1 "$testname=$expect" + return + fi + + if expr "$actual" : ".*$expect" &>/dev/null; then + # On success, include expected value; this helps readers understand + _show_ok 1 "$testname ('$actual') ~ $expect" + return + fi + _show_ok 0 "$testname" "~ $expect" "$actual" +} + +############## +# _show_ok # Helper for is() and like(): displays 'ok' or 'not ok' +############## +function _show_ok() { + local ok=$1 + local testname=$2 + + # If output is a tty, colorize pass/fail + local red= + local green= + local reset= + local bold= + if [ -t 1 ]; then + red='\e[31m' + green='\e[32m' + reset='\e[0m' + bold='\e[1m' + fi + + _bump $testcounter_file + count=$(<$testcounter_file) + + # "skip" is a special case of "ok". Assume that our caller has included + # the magical '# skip - reason" comment string. + if [[ $ok == "skip" ]]; then + # colon-plus: replace green with yellow, but only if green is non-null + green="${green:+\e[33m}" + ok=1 + fi + if [ $ok -eq 1 ]; then + echo -e "${green}ok $count $testname${reset}" + echo "ok $count $testname" >>$LOG + return + fi + + # Failed + local expect=$3 + local actual=$4 + printf "${red}not ok $count $testname${reset}\n" + printf "${red}# expected: %s${reset}\n" "$expect" + printf "${red}# actual: ${bold}%s${reset}\n" "$actual" + + echo "not ok $count $testname" >>$LOG + echo " expected: $expect" >>$LOG + + _bump $failures_file +} + +########### +# _bump # Increment a counter in a file +########### +function _bump() { + local file=$1 + + count=$(<$file) + echo $(( $count + 1 )) >| $file +} + +############# +# jsonify # convert 'foo=bar,x=y' to json {"foo":"bar","x":"y"} +############# +function jsonify() { + # split by comma + local -a settings_in + read -ra settings_in <<<"$1" + + # convert each to double-quoted form + local -a settings_out + for i in ${settings_in[*]}; do + settings_out+=$(sed -e 's/\(.*\)=\(.*\)/"\1":"\2"/' <<<$i) + done + + # ...and wrap inside braces. + # FIXME: handle commas + echo "{${settings_out[*]}}" +} + +####### +# t # Main test helper +####### +function t() { + local method=$1; shift + local path=$1; shift + local curl_args + + local testname="$method $path" + # POST requests require an extra params arg + if [[ $method = "POST" ]]; then + curl_args="-d $(jsonify $1)" + testname="$testname [$curl_args]" + shift + fi + + # entrypoint path can include a descriptive comment; strip it off + path=${path%% *} + + # curl -X HEAD but without --head seems to wait for output anyway + if [[ $method == "HEAD" ]]; then + curl_args="--head" + fi + local expected_code=$1; shift + + # If given path begins with /, use it as-is; otherwise prepend /version/ + local url=http://$HOST:$PORT + if expr "$path" : "/" >/dev/null; then + url="$url$path" + else + url="$url/v1.40/$path" + fi + + # Log every action we do + echo "-------------------------------------------------------------" >>$LOG + echo "\$ $testname" >>$LOG + rm -f $WORKDIR/curl.* + # -s = silent, but --write-out 'format' gives us important response data + response=$(curl -s -X $method ${curl_args} \ + -H 'Content-type: application/json' \ + --dump-header $WORKDIR/curl.headers.out \ + --write-out '%{http_code}^%{content_type}^%{time_total}' \ + -o $WORKDIR/curl.result.out "$url") + + # Any error from curl is instant bad news, from which we can't recover + rc=$? + if [[ $rc -ne 0 ]]; then + echo "FATAL: curl failure ($rc) on $url - cannot continue" >&2 + exit 1 + fi + + # Show returned headers (without trailing ^M or empty lines) in log file. + # Sometimes -- I can't remember why! -- we don't get headers. + if [[ -e $WORKDIR/curl.headers.out ]]; then + tr -d '\015' < $WORKDIR/curl.headers.out | egrep '.' >>$LOG + fi + + IFS='^' read actual_code content_type time_total <<<"$response" + printf "X-Response-Time: ${time_total}s\n\n" >>$LOG + + # Log results, if text. If JSON, filter through jq for readability. + if [[ $content_type =~ /octet ]]; then + output="[$(file --brief $WORKDIR/curl.result.out)]" + echo "$output" >>$LOG + else + output=$(< $WORKDIR/curl.result.out) + + if [[ $content_type =~ application/json ]]; then + jq . <<<"$output" >>$LOG + else + echo "$output" >>$LOG + fi + fi + + # Test return code + is "$actual_code" "$expected_code" "$testname : status" + + # Special case: 204/304, by definition, MUST NOT return content (rfc2616) + if [[ $expected_code = 204 || $expected_code = 304 ]]; then + if [ -n "$*" ]; then + die "Internal error: ${expected_code} status returns no output; fix your test." + fi + if [ -n "$output" ]; then + _show_ok 0 "$testname: ${expected_code} status returns no output" "''" "$output" + fi + return + fi + + local i + + # Special case: if response code does not match, dump the response body + # and skip all further subtests. + if [[ $actual_code != $expected_code ]]; then + echo -e "# response: $output" + for i; do + _show_ok skip "$testname: $i # skip - wrong return code" + done + return + fi + + for i; do + if expr "$i" : "[^=~]\+=.*" >/dev/null; then + # Exact match on json field + json_field=$(expr "$i" : "\([^=]*\)=") + expect=$(expr "$i" : '[^=]*=\(.*\)') + actual=$(jq -r "$json_field" <<<"$output") + is "$actual" "$expect" "$testname : $json_field" + elif expr "$i" : "[^=~]\+~.*" >/dev/null; then + # regex match on json field + json_field=$(expr "$i" : "\([^~]*\)~") + expect=$(expr "$i" : '[^~]*~\(.*\)') + actual=$(jq -r "$json_field" <<<"$output") + like "$actual" "$expect" "$testname : $json_field" + else + # Direct string comparison + is "$output" "$i" "$testname : output" + fi + done +} + +################### +# start_service # Run the socket listener +################### +service_pid= +function start_service() { + test -x $PODMAN_BIN || die "Not found: $PODMAN_BIN" + + rm -rf $WORKDIR/{root,runroot,cni} + mkdir $WORKDIR/cni + cp /etc/cni/net.d/*podman*conflist $WORKDIR/cni/ + + $PODMAN_BIN \ + --root $WORKDIR/root \ + --runroot $WORKDIR/runroot \ + --cgroup-manager=systemd \ + --cni-config-dir $WORKDIR/cni \ + system service \ + --time 0 unix:/$DOCKER_SOCK \ + &> $WORKDIR/server.log & + service_pid=$! + + # Wait (FIXME: how do we test the socket?) + local _timeout=5 + while [ $_timeout -gt 0 ]; do + # FIXME: should we actually try a read or write? + test -S $DOCKER_SOCK && return + sleep 1 + _timeout=$(( $_timeout - 1 )) + done + cat $WORKDIR/server.log + die "Timed out waiting for service" +} + +############ +# podman # Needed by some test scripts to invoke the actual podman binary +############ +function podman() { + echo "\$ $PODMAN_BIN $*" >>$WORKDIR/output.log + $PODMAN_BIN --root $WORKDIR "$@" >>$WORKDIR/output.log 2>&1 +} + +# END infrastructure code +############################################################################### +# BEGIN sanity checks + +for tool in curl docker-compose; do + type $tool &>/dev/null || die "$ME: Required tool '$tool' not found" +done + +# END sanity checks +############################################################################### +# BEGIN entry handler (subtest invoker) + +TESTS_DIR=$WORKDIR/awesome-compose + +git clone $AWESOME_COMPOSE $TESTS_DIR +git -C $TESTS_DIR checkout -q a3c38822277bcca04abbadf34120dcff808db3ec + +# Identify the tests to run. If called with args, use those as globs. +tests_to_run=() +if [ -n "$*" ]; then + shopt -s nullglob + for i; do + match=(${TEST_ROOTDIR}/*${i}*.curl) + if [ ${#match} -eq 0 ]; then + die "No match for $TEST_ROOTDIR/*$i*.curl" + fi + tests_to_run+=("${match[@]}") + done + shopt -u nullglob +else + tests_to_run=(${TEST_ROOTDIR}/*.curl) +fi + +# Test count: each of those tests might have a local set of subtests +n_tests=$((2 * ${#tests_to_run[*]})) +for t in ${tests_to_run[@]}; do + n_curls=$(wc -l $t | awk '{print $1}') + n_tests=$(( n_tests + n_curls )) +done + + +echo "1..$n_tests" + +for t in ${tests_to_run[@]}; do + testname="$(basename $t .curl)" + + start_service + + logfile=$WORKDIR/$testname.log + ( + cd $TESTS_DIR/$testname || die "Cannot cd $TESTS_DIR/$testname" + docker-compose up -d &> $logfile + if [[ $? -ne 0 ]]; then + _show_ok 0 "$testname - up" "[ok]" "$(< $logfile)" + # FIXME: cat log + docker-compose down >>$logfile 2>&1 # No status check here + exit 1 + fi + _show_ok 1 "$testname - up" + + # FIXME: run tests, e.g. curl + curls=$TEST_ROOTDIR/$testname.curl + if [[ -e $curls ]]; then + while read port expect; do + actual=$(curl --retry 5 --retry-connrefused -s http://127.0.0.1:$port/) + curl_rc=$? + if [ $curl_rc -ne 0 ]; then + _show_ok 0 "$testname - curl failed with status $curl_rc" + docker-compose down >>$logfile 2>&1 + exit 1 + fi + like "$actual" "$expect" "$testname : port $port" + done < $curls + fi + + docker-compose down &> $logfile + if [[ $? -eq 0 ]]; then + _show_ok 1 "$testname - down" + else + _show_ok 0 "$testname - down" "[ok]" "$(< $logfile)" + # FIXME: show error + fi + ) + + kill $service_pid + wait $service_pid + + # FIXME: otherwise we get EBUSY + umount $WORKDIR/root/overlay &>/dev/null +done + +# END entry handler +############################################################################### + +# Clean up + +test_count=$(<$testcounter_file) +failure_count=$(<$failures_file) + +if [ -z "$PODMAN_TESTS_KEEP_WORKDIR" ]; then + rm -rf $WORKDIR +fi + +exit $failure_count diff --git a/test/docker-compose/elasticsearch-logstash-kibana.curl b/test/docker-compose/elasticsearch-logstash-kibana.curl deleted file mode 100644 index 9a94bd65c..000000000 --- a/test/docker-compose/elasticsearch-logstash-kibana.curl +++ /dev/null @@ -1,3 +0,0 @@ -9200 elasticsearch -9600 logstash -5601 kibana diff --git a/test/docker-compose/flask.curl b/test/docker-compose/flask.curl deleted file mode 100644 index b50ddbf1d..000000000 --- a/test/docker-compose/flask.curl +++ /dev/null @@ -1 +0,0 @@ -5000 Hello World! diff --git a/test/docker-compose/gitea-postgres.curl b/test/docker-compose/gitea-postgres.curl deleted file mode 100644 index a0a58b3fd..000000000 --- a/test/docker-compose/gitea-postgres.curl +++ /dev/null @@ -1 +0,0 @@ -3000 .* Gitea: Git with a cup of tea diff --git a/test/docker-compose/react-rust-postgres.skip b/test/docker-compose/react-rust-postgres.skip deleted file mode 100644 index 57f89ed17..000000000 --- a/test/docker-compose/react-rust-postgres.skip +++ /dev/null @@ -1 +0,0 @@ -broken diff --git a/test/docker-compose/test-docker-compose b/test/docker-compose/test-docker-compose deleted file mode 100755 index d37caa12a..000000000 --- a/test/docker-compose/test-docker-compose +++ /dev/null @@ -1,441 +0,0 @@ -#!/usr/bin/env bash -# -# Usage: test-docker-compose [testname] -# -# DEVELOPER NOTE: you almost certainly don't need to play in here. See README. -# -ME=$(basename $0) - -############################################################################### -# BEGIN stuff you can but probably shouldn't customize - -# Directory where this script (and extra test configs) live -TEST_ROOTDIR=$(realpath $(dirname $0)) - -# Podman executable -PODMAN_BIN=$(realpath bin)/podman - -# Github repo containing sample docker-compose setups -# FIXME: we should probably version this -AWESOME_COMPOSE=https://github.com/docker/awesome-compose - -# Local path to docker socket -DOCKER_SOCK=/var/run/docker.sock - -# END stuff you can but probably shouldn't customize -############################################################################### -# BEGIN setup - -TMPDIR=${TMPDIR:-/var/tmp} -WORKDIR=$(mktemp --tmpdir -d $ME.tmp.XXXXXX) - -# Log of all HTTP requests and responses; always make '.log' point to latest -LOGBASE=${TMPDIR}/$ME.log -LOG=${LOGBASE}.$(date +'%Y%m%dT%H%M%S') -ln -sf $LOG $LOGBASE - -# Keep track of test count and failures in files, not variables, because -# variables don't carry back up from subshells. -testcounter_file=$WORKDIR/.testcounter -failures_file=$WORKDIR/.failures - -echo 0 >$testcounter_file -echo 0 >$failures_file - -# END setup -############################################################################### -# BEGIN infrastructure code - the helper functions used in tests themselves - -######### -# die # Exit error with a message to stderr -######### -function die() { - echo "$ME: $*" >&2 - exit 1 -} - -######## -# is # Simple comparison -######## -function is() { - local actual=$1 - local expect=$2 - local testname=$3 - - if [[ $actual = $expect ]]; then - # On success, include expected value; this helps readers understand - _show_ok 1 "$testname=$expect" - return - fi - _show_ok 0 "$testname" "$expect" "$actual" -} - -########## -# like # Compare, but allowing patterns -########## -function like() { - local actual=$1 - local expect=$2 - local testname=$3 - - # "is" (equality) is a subset of "like", but one that expr fails on if - # the expected result has shell-special characters like '['. Treat it - # as a special case. - if [[ $actual = $expect ]]; then - _show_ok 1 "$testname=$expect" - return - fi - - if expr "$actual" : "$expect" &>/dev/null; then - # On success, include expected value; this helps readers understand - _show_ok 1 "$testname ('$actual') ~ $expect" - return - fi - _show_ok 0 "$testname" "~ $expect" "$actual" -} - -############## -# _show_ok # Helper for is() and like(): displays 'ok' or 'not ok' -############## -function _show_ok() { - local ok=$1 - local testname=$2 - - # If output is a tty, colorize pass/fail - local red= - local green= - local reset= - local bold= - if [ -t 1 ]; then - red='\e[31m' - green='\e[32m' - reset='\e[0m' - bold='\e[1m' - fi - - _bump $testcounter_file - count=$(<$testcounter_file) - - # "skip" is a special case of "ok". Assume that our caller has included - # the magical '# skip - reason" comment string. - if [[ $ok == "skip" ]]; then - # colon-plus: replace green with yellow, but only if green is non-null - green="${green:+\e[33m}" - ok=1 - fi - if [ $ok -eq 1 ]; then - echo -e "${green}ok $count $testname${reset}" - echo "ok $count $testname" >>$LOG - return - fi - - # Failed - local expect=$3 - local actual=$4 - echo -e "${red}not ok $count $testname${reset}" - echo -e "${red}# expected: $expect${reset}" - echo -e "${red}# actual: ${bold}$actual${reset}" - - echo "not ok $count $testname" >>$LOG - echo " expected: $expect" >>$LOG - - _bump $failures_file -} - -########### -# _bump # Increment a counter in a file -########### -function _bump() { - local file=$1 - - count=$(<$file) - echo $(( $count + 1 )) >| $file -} - -############# -# jsonify # convert 'foo=bar,x=y' to json {"foo":"bar","x":"y"} -############# -function jsonify() { - # split by comma - local -a settings_in - read -ra settings_in <<<"$1" - - # convert each to double-quoted form - local -a settings_out - for i in ${settings_in[*]}; do - settings_out+=$(sed -e 's/\(.*\)=\(.*\)/"\1":"\2"/' <<<$i) - done - - # ...and wrap inside braces. - # FIXME: handle commas - echo "{${settings_out[*]}}" -} - -####### -# t # Main test helper -####### -function t() { - local method=$1; shift - local path=$1; shift - local curl_args - - local testname="$method $path" - # POST requests require an extra params arg - if [[ $method = "POST" ]]; then - curl_args="-d $(jsonify $1)" - testname="$testname [$curl_args]" - shift - fi - - # entrypoint path can include a descriptive comment; strip it off - path=${path%% *} - - # curl -X HEAD but without --head seems to wait for output anyway - if [[ $method == "HEAD" ]]; then - curl_args="--head" - fi - local expected_code=$1; shift - - # If given path begins with /, use it as-is; otherwise prepend /version/ - local url=http://$HOST:$PORT - if expr "$path" : "/" >/dev/null; then - url="$url$path" - else - url="$url/v1.40/$path" - fi - - # Log every action we do - echo "-------------------------------------------------------------" >>$LOG - echo "\$ $testname" >>$LOG - rm -f $WORKDIR/curl.* - # -s = silent, but --write-out 'format' gives us important response data - response=$(curl -s -X $method ${curl_args} \ - -H 'Content-type: application/json' \ - --dump-header $WORKDIR/curl.headers.out \ - --write-out '%{http_code}^%{content_type}^%{time_total}' \ - -o $WORKDIR/curl.result.out "$url") - - # Any error from curl is instant bad news, from which we can't recover - rc=$? - if [[ $rc -ne 0 ]]; then - echo "FATAL: curl failure ($rc) on $url - cannot continue" >&2 - exit 1 - fi - - # Show returned headers (without trailing ^M or empty lines) in log file. - # Sometimes -- I can't remember why! -- we don't get headers. - if [[ -e $WORKDIR/curl.headers.out ]]; then - tr -d '\015' < $WORKDIR/curl.headers.out | egrep '.' >>$LOG - fi - - IFS='^' read actual_code content_type time_total <<<"$response" - printf "X-Response-Time: ${time_total}s\n\n" >>$LOG - - # Log results, if text. If JSON, filter through jq for readability. - if [[ $content_type =~ /octet ]]; then - output="[$(file --brief $WORKDIR/curl.result.out)]" - echo "$output" >>$LOG - else - output=$(< $WORKDIR/curl.result.out) - - if [[ $content_type =~ application/json ]]; then - jq . <<<"$output" >>$LOG - else - echo "$output" >>$LOG - fi - fi - - # Test return code - is "$actual_code" "$expected_code" "$testname : status" - - # Special case: 204/304, by definition, MUST NOT return content (rfc2616) - if [[ $expected_code = 204 || $expected_code = 304 ]]; then - if [ -n "$*" ]; then - die "Internal error: ${expected_code} status returns no output; fix your test." - fi - if [ -n "$output" ]; then - _show_ok 0 "$testname: ${expected_code} status returns no output" "''" "$output" - fi - return - fi - - local i - - # Special case: if response code does not match, dump the response body - # and skip all further subtests. - if [[ $actual_code != $expected_code ]]; then - echo -e "# response: $output" - for i; do - _show_ok skip "$testname: $i # skip - wrong return code" - done - return - fi - - for i; do - if expr "$i" : "[^=~]\+=.*" >/dev/null; then - # Exact match on json field - json_field=$(expr "$i" : "\([^=]*\)=") - expect=$(expr "$i" : '[^=]*=\(.*\)') - actual=$(jq -r "$json_field" <<<"$output") - is "$actual" "$expect" "$testname : $json_field" - elif expr "$i" : "[^=~]\+~.*" >/dev/null; then - # regex match on json field - json_field=$(expr "$i" : "\([^~]*\)~") - expect=$(expr "$i" : '[^~]*~\(.*\)') - actual=$(jq -r "$json_field" <<<"$output") - like "$actual" "$expect" "$testname : $json_field" - else - # Direct string comparison - is "$output" "$i" "$testname : output" - fi - done -} - -################### -# start_service # Run the socket listener -################### -service_pid= -function start_service() { - test -x $PODMAN_BIN || die "Not found: $PODMAN_BIN" - - rm -rf $WORKDIR/{root,runroot,cni} - mkdir $WORKDIR/cni - cp /etc/cni/net.d/*podman*conflist $WORKDIR/cni/ - - $PODMAN_BIN \ - --root $WORKDIR/root \ - --runroot $WORKDIR/runroot \ - --cgroup-manager=systemd \ - --cni-config-dir $WORKDIR/cni \ - system service \ - --time 0 unix:/$DOCKER_SOCK \ - &> $WORKDIR/server.log & - service_pid=$! - - # Wait (FIXME: how do we test the socket?) - local _timeout=5 - while [ $_timeout -gt 0 ]; do - # FIXME: should we actually try a read or write? - test -S $DOCKER_SOCK && return - sleep 1 - _timeout=$(( $_timeout - 1 )) - done - cat $WORKDIR/server.log - die "Timed out waiting for service" -} - -############ -# podman # Needed by some test scripts to invoke the actual podman binary -############ -function podman() { - echo "\$ $PODMAN_BIN $*" >>$WORKDIR/output.log - $PODMAN_BIN --root $WORKDIR "$@" >>$WORKDIR/output.log 2>&1 -} - -# END infrastructure code -############################################################################### -# BEGIN sanity checks - -for tool in curl docker-compose; do - type $tool &>/dev/null || die "$ME: Required tool '$tool' not found" -done - -# END sanity checks -############################################################################### -# BEGIN entry handler (subtest invoker) - -TESTS_DIR=$WORKDIR/awesome-compose - -git clone $AWESOME_COMPOSE $TESTS_DIR - -# Identify the tests to run. If called with args, use those as globs. -tests_to_run=() -if [ -n "$*" ]; then - shopt -s nullglob - for i; do - match=(${TEST_ROOTDIR}/*${i}*.curl) - if [ ${#match} -eq 0 ]; then - die "No match for $TEST_ROOTDIR/*$i*.curl" - fi - tests_to_run+=("${match[@]}") - done - shopt -u nullglob -else - tests_to_run=(${TEST_ROOTDIR}/*.curl) -fi - -# Test count: each of those tests might have a local set of subtests -n_tests=$((2 * ${#tests_to_run[*]})) -for t in ${tests_to_run[@]}; do - n_curls=$(wc -l $t | awk '{print $1}') - n_tests=$(( n_tests + n_curls )) -done - - -echo "1..$n_tests" - -for t in ${tests_to_run[@]}; do - testname="$(basename $t .curl)" - - start_service - - logfile=$WORKDIR/$testname.log - ( - cd $TESTS_DIR/$testname || die "Cannot cd $TESTS_DIR/$testname" - docker-compose up -d &> $logfile - if [[ $? -ne 0 ]]; then - _show_ok 0 "$testname - up" "[ok]" "$(< $logfile)" - # FIXME: cat log - docker-compose down >>$logfile 2>&1 # No status check here - exit 1 - fi - _show_ok 1 "$testname - up" - - # FIXME: run tests, e.g. curl - curls=$TEST_ROOTDIR/$testname.curl - if [[ -e $curls ]]; then - while read port expect; do - actual=$(curl --retry 5 --retry-connrefused -s http://127.0.0.1:$port/) - curl_rc=$? - if [ $curl_rc -ne 0 ]; then - _show_ok 0 "$testname - curl failed with status $curl_rc" - docker-compose down >>$logfile 2>&1 - exit 1 - fi - echo "got here: $actual" - like "$actual" "$expect" "$testname : port $port" - done < $curls - fi - - echo "OK, press ENTER to stop" - read x - - docker-compose down &> $logfile - if [[ $? -eq 0 ]]; then - _show_ok 1 "$testname - down" - else - _show_ok 0 "$testname - down" "[ok]" "$(< $logfile)" - # FIXME: show error - fi - ) - - kill $service_pid - wait $service_pid - - # FIXME: otherwise we get EBUSY - umount $WORKDIR/root/overlay &>/dev/null -done - -# END entry handler -############################################################################### - -# Clean up - -test_count=$(<$testcounter_file) -failure_count=$(<$failures_file) - -#if [ -z "$PODMAN_TESTS_KEEP_WORKDIR" ]; then -# rm -rf $WORKDIR -#fi - -exit $failure_count -- cgit v1.2.3-54-g00ecf From f3e69d7300e3b4d6c5bb676c1dae27b10c3a4d56 Mon Sep 17 00:00:00 2001 From: Ed Santiago Date: Thu, 10 Dec 2020 14:34:21 -0700 Subject: test-compose: rewrite to new subdir form ...in which we use all-local tests Signed-off-by: Ed Santiago --- test/compose/README.md | 47 ++++ test/compose/elasticsearch-logstash-kibana.curl | 3 - test/compose/flask.curl | 1 - test/compose/gitea-postgres.curl | 1 - test/compose/react-rust-postgres.skip | 1 - test/compose/simple_port_map/frontend/app.py | 10 +- test/compose/simple_port_map/setup.sh | 3 + test/compose/simple_port_map/teardown.sh | 4 + test/compose/simple_port_map/tests.sh | 3 + test/compose/test-compose | 284 ++++++++---------------- 10 files changed, 160 insertions(+), 197 deletions(-) create mode 100644 test/compose/README.md delete mode 100644 test/compose/elasticsearch-logstash-kibana.curl delete mode 100644 test/compose/flask.curl delete mode 100644 test/compose/gitea-postgres.curl delete mode 100644 test/compose/react-rust-postgres.skip create mode 100644 test/compose/simple_port_map/setup.sh create mode 100644 test/compose/simple_port_map/teardown.sh create mode 100644 test/compose/simple_port_map/tests.sh (limited to 'test') diff --git a/test/compose/README.md b/test/compose/README.md new file mode 100644 index 000000000..863decf2c --- /dev/null +++ b/test/compose/README.md @@ -0,0 +1,47 @@ +Tests for docker-compose +======================== + +This directory contains tests for docker-compose under podman. + +Each subdirectory must contain one docker-compose.yml file along with +all necessary infrastructure for it (e.g. Containerfile, any files +to be copied into the container, and so on. + +The `test-compose` script will, for each test subdirectory: + +* set up a fresh podman root under an empty working directory; +* run a podman server rooted therein; +* cd to the test subdirectory, and run `docker-compose up -d`; +* source `tests.sh`; +* run `docker-compose down`. + +As a special case, `setup.sh` and `teardown.sh` in the test directory +will contain commands to be executed prior to `docker-compose up` and +after `docker-compose down` respectively. + +tests.sh will probably contain commands of the form + + test_port 12345 = 'hello there' + +Where 12345 is the port to curl to; '=' checks equality, '~' uses `expr` +to check substrings; and 'hello there' is a string to look for in +the curl results. + +Usage: + + $ sudo test/compose/test-compose [pattern] + +By default, all subdirs will be run. If given a pattern, only those +subdirectories matching 'pattern' will be run. + +If `$COMPOSE_WAIT` is set, `test-compose` will pause before running +`docker-compose down`. This can be helpful for you to debug failing tests: + + $ env COMPOSE_WAIT=1 sudo --preserve-env=COMPOSE_WAIT test/compose/test-compose + +Then, in another window, + + # ls -lt /var/tmp/ + # X=/var/tmp/test-compose.tmp.XXXXXX <--- most recent results of above + # podman --root $X/root --runroot $X/runroot ps -a + # podman --root $X/root --runroot $X/runroot logs -l diff --git a/test/compose/elasticsearch-logstash-kibana.curl b/test/compose/elasticsearch-logstash-kibana.curl deleted file mode 100644 index ddb7a96b0..000000000 --- a/test/compose/elasticsearch-logstash-kibana.curl +++ /dev/null @@ -1,3 +0,0 @@ -9200 You Know, for Search -9600 "status":"green" -5601 Kibana diff --git a/test/compose/flask.curl b/test/compose/flask.curl deleted file mode 100644 index b50ddbf1d..000000000 --- a/test/compose/flask.curl +++ /dev/null @@ -1 +0,0 @@ -5000 Hello World! diff --git a/test/compose/gitea-postgres.curl b/test/compose/gitea-postgres.curl deleted file mode 100644 index a0a58b3fd..000000000 --- a/test/compose/gitea-postgres.curl +++ /dev/null @@ -1 +0,0 @@ -3000 .* Gitea: Git with a cup of tea diff --git a/test/compose/react-rust-postgres.skip b/test/compose/react-rust-postgres.skip deleted file mode 100644 index 57f89ed17..000000000 --- a/test/compose/react-rust-postgres.skip +++ /dev/null @@ -1 +0,0 @@ -broken diff --git a/test/compose/simple_port_map/frontend/app.py b/test/compose/simple_port_map/frontend/app.py index 895556a89..97b17c440 100644 --- a/test/compose/simple_port_map/frontend/app.py +++ b/test/compose/simple_port_map/frontend/app.py @@ -1,9 +1,15 @@ from flask import Flask +import os app = Flask(__name__) @app.route('/') def hello(): - return "Podman rulez!" + passthru = "ERROR: Could not get $ENV_PASSTHRU envariable" + try: + passthru = os.getenv("ENV_PASSTHRU") + except Exception as e: + passthru = passthru + ": " + str(e) + return "Podman rulez!--" + passthru + "--!" if __name__ == '__main__': - app.run(host='0.0.0.0') + app.run(host='0.0.0.0') diff --git a/test/compose/simple_port_map/setup.sh b/test/compose/simple_port_map/setup.sh new file mode 100644 index 000000000..9004b1e76 --- /dev/null +++ b/test/compose/simple_port_map/setup.sh @@ -0,0 +1,3 @@ +# -*- bash -*- + +export ENV_PASSTHRU=$(random_string 20) diff --git a/test/compose/simple_port_map/teardown.sh b/test/compose/simple_port_map/teardown.sh new file mode 100644 index 000000000..3f8153fa0 --- /dev/null +++ b/test/compose/simple_port_map/teardown.sh @@ -0,0 +1,4 @@ +# -*- bash -*- + +# FIXME: this is completely unnecessary; it's just an example of a teardown +unset ENV_PASSTHRU diff --git a/test/compose/simple_port_map/tests.sh b/test/compose/simple_port_map/tests.sh new file mode 100644 index 000000000..959b429d6 --- /dev/null +++ b/test/compose/simple_port_map/tests.sh @@ -0,0 +1,3 @@ +# -*- bash -*- + +test_port 5000 = "Podman rulez!--$ENV_PASSTHRU--!" diff --git a/test/compose/test-compose b/test/compose/test-compose index f7643b078..9558fbf58 100755 --- a/test/compose/test-compose +++ b/test/compose/test-compose @@ -1,32 +1,26 @@ #!/usr/bin/env bash # -# Usage: test-docker-compose [testname] -# -# DEVELOPER NOTE: you almost certainly don't need to play in here. See README. +# Usage: test-compose [testname] # ME=$(basename $0) ############################################################################### # BEGIN stuff you can but probably shouldn't customize -# Directory where this script (and extra test configs) live +# Directory where this script and all subtests live TEST_ROOTDIR=$(realpath $(dirname $0)) # Podman executable -PODMAN_BIN=$(realpath bin)/podman - -# Github repo containing sample docker-compose setups -# FIXME: we should probably version this -AWESOME_COMPOSE=https://github.com/docker/awesome-compose +PODMAN_BIN=$(realpath $TEST_ROOTDIR/../../bin)/podman -# Local path to docker socket +# Local path to docker socket (we will add the unix:/ prefix when we need it) DOCKER_SOCK=/var/run/docker.sock # END stuff you can but probably shouldn't customize ############################################################################### # BEGIN setup -TMPDIR=${TMPDIR:-/var/tmp} +export TMPDIR=${TMPDIR:-/var/tmp} WORKDIR=$(mktemp --tmpdir -d $ME.tmp.XXXXXX) # Log of all HTTP requests and responses; always make '.log' point to latest @@ -153,145 +147,30 @@ function _bump() { echo $(( $count + 1 )) >| $file } -############# -# jsonify # convert 'foo=bar,x=y' to json {"foo":"bar","x":"y"} -############# -function jsonify() { - # split by comma - local -a settings_in - read -ra settings_in <<<"$1" - - # convert each to double-quoted form - local -a settings_out - for i in ${settings_in[*]}; do - settings_out+=$(sed -e 's/\(.*\)=\(.*\)/"\1":"\2"/' <<<$i) - done - - # ...and wrap inside braces. - # FIXME: handle commas - echo "{${settings_out[*]}}" -} - -####### -# t # Main test helper -####### -function t() { - local method=$1; shift - local path=$1; shift - local curl_args - - local testname="$method $path" - # POST requests require an extra params arg - if [[ $method = "POST" ]]; then - curl_args="-d $(jsonify $1)" - testname="$testname [$curl_args]" - shift - fi - - # entrypoint path can include a descriptive comment; strip it off - path=${path%% *} - - # curl -X HEAD but without --head seems to wait for output anyway - if [[ $method == "HEAD" ]]; then - curl_args="--head" - fi - local expected_code=$1; shift - - # If given path begins with /, use it as-is; otherwise prepend /version/ - local url=http://$HOST:$PORT - if expr "$path" : "/" >/dev/null; then - url="$url$path" - else - url="$url/v1.40/$path" - fi - - # Log every action we do - echo "-------------------------------------------------------------" >>$LOG - echo "\$ $testname" >>$LOG - rm -f $WORKDIR/curl.* - # -s = silent, but --write-out 'format' gives us important response data - response=$(curl -s -X $method ${curl_args} \ - -H 'Content-type: application/json' \ - --dump-header $WORKDIR/curl.headers.out \ - --write-out '%{http_code}^%{content_type}^%{time_total}' \ - -o $WORKDIR/curl.result.out "$url") - - # Any error from curl is instant bad news, from which we can't recover - rc=$? - if [[ $rc -ne 0 ]]; then - echo "FATAL: curl failure ($rc) on $url - cannot continue" >&2 - exit 1 - fi - - # Show returned headers (without trailing ^M or empty lines) in log file. - # Sometimes -- I can't remember why! -- we don't get headers. - if [[ -e $WORKDIR/curl.headers.out ]]; then - tr -d '\015' < $WORKDIR/curl.headers.out | egrep '.' >>$LOG - fi - - IFS='^' read actual_code content_type time_total <<<"$response" - printf "X-Response-Time: ${time_total}s\n\n" >>$LOG - - # Log results, if text. If JSON, filter through jq for readability. - if [[ $content_type =~ /octet ]]; then - output="[$(file --brief $WORKDIR/curl.result.out)]" - echo "$output" >>$LOG - else - output=$(< $WORKDIR/curl.result.out) - - if [[ $content_type =~ application/json ]]; then - jq . <<<"$output" >>$LOG - else - echo "$output" >>$LOG - fi - fi - - # Test return code - is "$actual_code" "$expected_code" "$testname : status" - - # Special case: 204/304, by definition, MUST NOT return content (rfc2616) - if [[ $expected_code = 204 || $expected_code = 304 ]]; then - if [ -n "$*" ]; then - die "Internal error: ${expected_code} status returns no output; fix your test." - fi - if [ -n "$output" ]; then - _show_ok 0 "$testname: ${expected_code} status returns no output" "''" "$output" - fi - return - fi - - local i - - # Special case: if response code does not match, dump the response body - # and skip all further subtests. - if [[ $actual_code != $expected_code ]]; then - echo -e "# response: $output" - for i; do - _show_ok skip "$testname: $i # skip - wrong return code" - done - return +############### +# test_port # Run curl against a port, check results against expectation +############### +function test_port() { + local port="$1" # e.g. 5000 + local op="$2" # '=' or '~' + local expect="$3" # what to expect from curl output + + local actual=$(curl --retry 5 --retry-connrefused -s http://127.0.0.1:$port/) + local curl_rc=$? + if [ $curl_rc -ne 0 ]; then + _show_ok 0 "$testname - curl failed with status $curl_rc" +### docker-compose down >>$logfile 2>&1 +### exit 1 fi - for i; do - if expr "$i" : "[^=~]\+=.*" >/dev/null; then - # Exact match on json field - json_field=$(expr "$i" : "\([^=]*\)=") - expect=$(expr "$i" : '[^=]*=\(.*\)') - actual=$(jq -r "$json_field" <<<"$output") - is "$actual" "$expect" "$testname : $json_field" - elif expr "$i" : "[^=~]\+~.*" >/dev/null; then - # regex match on json field - json_field=$(expr "$i" : "\([^~]*\)~") - expect=$(expr "$i" : '[^~]*~\(.*\)') - actual=$(jq -r "$json_field" <<<"$output") - like "$actual" "$expect" "$testname : $json_field" - else - # Direct string comparison - is "$output" "$i" "$testname : output" - fi - done + case "$op" in + '=') is "$actual" "$expect" "$testname : port $port" ;; + '~') like "$actual" "$expect" "$testname : port $port" ;; + *) die "Invalid operator '$op'" ;; + esac } + ################### # start_service # Run the socket listener ################### @@ -299,8 +178,10 @@ service_pid= function start_service() { test -x $PODMAN_BIN || die "Not found: $PODMAN_BIN" - rm -rf $WORKDIR/{root,runroot,cni} - mkdir $WORKDIR/cni + # FIXME: use ${testname} subdir but we can't: 50-char limit in runroot + rm -rf $WORKDIR/{root,runroot,cni} + mkdir --mode 0755 $WORKDIR/{root,runroot,cni} + chcon --reference=/var/lib/containers $WORKDIR/root cp /etc/cni/net.d/*podman*conflist $WORKDIR/cni/ $PODMAN_BIN \ @@ -329,8 +210,21 @@ function start_service() { # podman # Needed by some test scripts to invoke the actual podman binary ############ function podman() { - echo "\$ $PODMAN_BIN $*" >>$WORKDIR/output.log - $PODMAN_BIN --root $WORKDIR "$@" >>$WORKDIR/output.log 2>&1 + echo "\$ podman $*" >>$WORKDIR/output.log + $PODMAN_BIN \ + --root $WORKDIR/root \ + --runroot $WORKDIR/runroot \ + "$@" >>$WORKDIR/output.log 2>&1 +} + +################### +# random_string # Returns a pseudorandom human-readable string +################### +function random_string() { + # Numeric argument, if present, is desired length of string + local length=${1:-10} + + head /dev/urandom | tr -dc a-zA-Z0-9 | head -c$length } # END infrastructure code @@ -345,17 +239,12 @@ done ############################################################################### # BEGIN entry handler (subtest invoker) -TESTS_DIR=$WORKDIR/awesome-compose - -git clone $AWESOME_COMPOSE $TESTS_DIR -git -C $TESTS_DIR checkout -q a3c38822277bcca04abbadf34120dcff808db3ec - # Identify the tests to run. If called with args, use those as globs. tests_to_run=() if [ -n "$*" ]; then shopt -s nullglob for i; do - match=(${TEST_ROOTDIR}/*${i}*.curl) + match=(${TEST_ROOTDIR}/*${i}*/docker-compose.yml) if [ ${#match} -eq 0 ]; then die "No match for $TEST_ROOTDIR/*$i*.curl" fi @@ -363,56 +252,68 @@ if [ -n "$*" ]; then done shopt -u nullglob else - tests_to_run=(${TEST_ROOTDIR}/*.curl) + tests_to_run=(${TEST_ROOTDIR}/*/docker-compose.yml) fi -# Test count: each of those tests might have a local set of subtests -n_tests=$((2 * ${#tests_to_run[*]})) +# Too hard to precompute the number of tests; just spit it out at the end. +n_tests=0 for t in ${tests_to_run[@]}; do - n_curls=$(wc -l $t | awk '{print $1}') - n_tests=$(( n_tests + n_curls )) -done + testdir="$(dirname $t)" + testname="$(basename $testdir)" - -echo "1..$n_tests" - -for t in ${tests_to_run[@]}; do - testname="$(basename $t .curl)" + if [ -e $test_dir/SKIP ]; then + local reason="$(<$test_dir/SKIP)" + if [ -n "$reason" ]; then + reason=" - $reason" + fi + _show_ok skip "$testname # skip$reason" + continue + fi start_service logfile=$WORKDIR/$testname.log ( - cd $TESTS_DIR/$testname || die "Cannot cd $TESTS_DIR/$testname" + cd $testdir || die "Cannot cd $testdir" + + # setup file may be used for creating temporary directories/files. + # We source it so that envariables defined in it will get back to us. + if [ -e setup.sh ]; then + . setup.sh + fi + if [ -e teardown.sh ]; then + trap '. teardown.sh' 0 + fi + docker-compose up -d &> $logfile - if [[ $? -ne 0 ]]; then - _show_ok 0 "$testname - up" "[ok]" "$(< $logfile)" - # FIXME: cat log + docker_compose_rc=$? + if [[ $docker_compose_rc -ne 0 ]]; then + _show_ok 0 "$testname - up" "[ok]" "status=$docker_compose_rc" + sed -e 's/^/# /' <$logfile docker-compose down >>$logfile 2>&1 # No status check here exit 1 fi _show_ok 1 "$testname - up" - # FIXME: run tests, e.g. curl - curls=$TEST_ROOTDIR/$testname.curl - if [[ -e $curls ]]; then - while read port expect; do - actual=$(curl --retry 5 --retry-connrefused -s http://127.0.0.1:$port/) - curl_rc=$? - if [ $curl_rc -ne 0 ]; then - _show_ok 0 "$testname - curl failed with status $curl_rc" - docker-compose down >>$logfile 2>&1 - exit 1 - fi - like "$actual" "$expect" "$testname : port $port" - done < $curls + # Run tests. This is likely to be a series of 'test_port' checks + # but may also include podman commands to inspect labels, state + if [ -e tests.sh ]; then + . tests.sh + fi + # FIXME: if any tests fail, try 'podman logs' on container? + + if [ -n "$COMPOSE_WAIT" ]; then + echo -n "Pausing due to \$COMPOSE_WAIT. Press ENTER to continue: " + read keepgoing fi + # Done. Clean up. docker-compose down &> $logfile - if [[ $? -eq 0 ]]; then + rc=$? + if [[ $rc -eq 0 ]]; then _show_ok 1 "$testname - down" else - _show_ok 0 "$testname - down" "[ok]" "$(< $logfile)" + _show_ok 0 "$testname - down" "[ok]" "rc=$rc" # FIXME: show error fi ) @@ -422,6 +323,9 @@ for t in ${tests_to_run[@]}; do # FIXME: otherwise we get EBUSY umount $WORKDIR/root/overlay &>/dev/null + + # FIXME: run 'podman ps'? +# rm -rf $WORKDIR/${testname} done # END entry handler @@ -432,8 +336,10 @@ done test_count=$(<$testcounter_file) failure_count=$(<$failures_file) -if [ -z "$PODMAN_TESTS_KEEP_WORKDIR" ]; then - rm -rf $WORKDIR -fi +#if [ -z "$PODMAN_TESTS_KEEP_WORKDIR" ]; then +# rm -rf $WORKDIR +#fi + +echo "1..${test_count}" exit $failure_count -- cgit v1.2.3-54-g00ecf From cb91bf96e02de8a6a7e50f83b4b69b9c47b84cc5 Mon Sep 17 00:00:00 2001 From: baude Date: Fri, 11 Dec 2020 09:17:45 -0600 Subject: add compose test descriptions adding compose test descriptions and validations. Signed-off-by: baude --- test/compose/env_and_volume/README.md | 12 ++++++++++++ test/compose/env_and_volume/read/Dockerfile | 2 +- test/compose/env_and_volume/tests.sh | 4 ++++ test/compose/env_and_volume/write/Dockerfile | 2 +- test/compose/images/README.md | 5 +++++ test/compose/images/podman-python/Containerfile | 3 +++ test/compose/mount_and_label/README.md | 9 +++++++++ test/compose/mount_and_label/docker-compose.yml | 2 +- test/compose/mount_and_label/frontend/Dockerfile | 2 +- test/compose/mount_and_label/readme.txt | 5 ----- test/compose/mount_and_label/setup.sh | 2 ++ test/compose/mount_and_label/teardown.sh | 1 + test/compose/mount_and_label/tests.sh | 4 ++++ test/compose/port_map_diff_port/README.md | 9 +++++++++ test/compose/port_map_diff_port/frontend/Dockerfile | 2 +- test/compose/port_map_diff_port/tests.sh | 3 +++ test/compose/setup.sh.example | 3 +++ test/compose/simple_port_map/README.md | 9 +++++++++ test/compose/simple_port_map/frontend/app.py | 7 +------ test/compose/simple_port_map/setup.sh | 3 --- test/compose/simple_port_map/teardown.sh | 4 ---- test/compose/simple_port_map/tests.sh | 2 +- test/compose/teardown.sh.example | 4 ++++ 23 files changed, 75 insertions(+), 24 deletions(-) create mode 100644 test/compose/env_and_volume/README.md create mode 100644 test/compose/env_and_volume/tests.sh create mode 100644 test/compose/images/README.md create mode 100644 test/compose/images/podman-python/Containerfile create mode 100644 test/compose/mount_and_label/README.md delete mode 100644 test/compose/mount_and_label/readme.txt create mode 100644 test/compose/mount_and_label/setup.sh create mode 100644 test/compose/mount_and_label/teardown.sh create mode 100644 test/compose/mount_and_label/tests.sh create mode 100644 test/compose/port_map_diff_port/README.md create mode 100644 test/compose/port_map_diff_port/tests.sh create mode 100644 test/compose/setup.sh.example create mode 100644 test/compose/simple_port_map/README.md delete mode 100644 test/compose/simple_port_map/setup.sh delete mode 100644 test/compose/simple_port_map/teardown.sh create mode 100644 test/compose/teardown.sh.example (limited to 'test') diff --git a/test/compose/env_and_volume/README.md b/test/compose/env_and_volume/README.md new file mode 100644 index 000000000..e7d74976b --- /dev/null +++ b/test/compose/env_and_volume/README.md @@ -0,0 +1,12 @@ +environment variable and volume +=============== + +This test creates two containers both of which are running flask. The first container has +an environment variable called PODMAN_MSG. That container pipes the contents of PODMAN_MSG +to a file on a shared volume between the containers. The second container then reads the +file are returns the PODMAN_MSG value via flask (http). + +Validation +------------ +* curl http://localhost:5000 and verify message +* curl http://localhost:5001 and verify message diff --git a/test/compose/env_and_volume/read/Dockerfile b/test/compose/env_and_volume/read/Dockerfile index a393a0dcb..8d5c45401 100644 --- a/test/compose/env_and_volume/read/Dockerfile +++ b/test/compose/env_and_volume/read/Dockerfile @@ -1,4 +1,4 @@ -FROM podman_python +FROM quay.io/libpod/podman_python WORKDIR /app COPY . /app ENTRYPOINT ["python3"] diff --git a/test/compose/env_and_volume/tests.sh b/test/compose/env_and_volume/tests.sh new file mode 100644 index 000000000..a4c8bed30 --- /dev/null +++ b/test/compose/env_and_volume/tests.sh @@ -0,0 +1,4 @@ +# -*- bash -*- + +test_port 5000 = "done" +test_port 5001 = "podman_rulez" diff --git a/test/compose/env_and_volume/write/Dockerfile b/test/compose/env_and_volume/write/Dockerfile index a393a0dcb..8d5c45401 100644 --- a/test/compose/env_and_volume/write/Dockerfile +++ b/test/compose/env_and_volume/write/Dockerfile @@ -1,4 +1,4 @@ -FROM podman_python +FROM quay.io/libpod/podman_python WORKDIR /app COPY . /app ENTRYPOINT ["python3"] diff --git a/test/compose/images/README.md b/test/compose/images/README.md new file mode 100644 index 000000000..f25fbdc24 --- /dev/null +++ b/test/compose/images/README.md @@ -0,0 +1,5 @@ +images +====== + +Use these directories for images that are needed for the compose testing. These +images should be then pushed to `quay.io/libpod` for consumption. diff --git a/test/compose/images/podman-python/Containerfile b/test/compose/images/podman-python/Containerfile new file mode 100644 index 000000000..47f90afaa --- /dev/null +++ b/test/compose/images/podman-python/Containerfile @@ -0,0 +1,3 @@ +FROM alpine +WORKDIR /app +RUN apk update && apk add py3-pip && pip3 install flask && rm -fr /var/cache/apk/* diff --git a/test/compose/mount_and_label/README.md b/test/compose/mount_and_label/README.md new file mode 100644 index 000000000..623b38cac --- /dev/null +++ b/test/compose/mount_and_label/README.md @@ -0,0 +1,9 @@ +mount and label +=============== + +This test creates a container with a mount (not volume) and also adds a label to the container. + +Validation +------------ +* curl http://localhost:5000 and verify message +* inspect the container to make the label exists on it diff --git a/test/compose/mount_and_label/docker-compose.yml b/test/compose/mount_and_label/docker-compose.yml index 6487067e3..112d7e134 100644 --- a/test/compose/mount_and_label/docker-compose.yml +++ b/test/compose/mount_and_label/docker-compose.yml @@ -5,6 +5,6 @@ services: ports: - '5000:5000' volumes: - - /tmp/mount:/data:ro + - /tmp/data:/data:ro labels: - "io.podman=the_best" diff --git a/test/compose/mount_and_label/frontend/Dockerfile b/test/compose/mount_and_label/frontend/Dockerfile index a393a0dcb..8d5c45401 100644 --- a/test/compose/mount_and_label/frontend/Dockerfile +++ b/test/compose/mount_and_label/frontend/Dockerfile @@ -1,4 +1,4 @@ -FROM podman_python +FROM quay.io/libpod/podman_python WORKDIR /app COPY . /app ENTRYPOINT ["python3"] diff --git a/test/compose/mount_and_label/readme.txt b/test/compose/mount_and_label/readme.txt deleted file mode 100644 index bba769c51..000000000 --- a/test/compose/mount_and_label/readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -this test creates a container with a mount (not volume) and also adds a label to the container. - -validate by curl http://localhost:5000 and message should be same message as piped into the mount message. - -also verify the label with podman ps and a filter that only catches that container diff --git a/test/compose/mount_and_label/setup.sh b/test/compose/mount_and_label/setup.sh new file mode 100644 index 000000000..8633d65d5 --- /dev/null +++ b/test/compose/mount_and_label/setup.sh @@ -0,0 +1,2 @@ +mkdir -p /tmp/data +echo "Podman rulez!" > /tmp/data/message diff --git a/test/compose/mount_and_label/teardown.sh b/test/compose/mount_and_label/teardown.sh new file mode 100644 index 000000000..57867c28a --- /dev/null +++ b/test/compose/mount_and_label/teardown.sh @@ -0,0 +1 @@ +rm /tmp/data/message diff --git a/test/compose/mount_and_label/tests.sh b/test/compose/mount_and_label/tests.sh new file mode 100644 index 000000000..07ff089b5 --- /dev/null +++ b/test/compose/mount_and_label/tests.sh @@ -0,0 +1,4 @@ +# -*- bash -*- + +test_port 5000 = "Podman rulez!" +podman container inspect -l --format '{{.Config.Labels}}' | grep "the_best" diff --git a/test/compose/port_map_diff_port/README.md b/test/compose/port_map_diff_port/README.md new file mode 100644 index 000000000..13ece72ad --- /dev/null +++ b/test/compose/port_map_diff_port/README.md @@ -0,0 +1,9 @@ +port map on different port +=============== + +This test creates a container that runs flask on different ports for the container +and the host + +Validation +------------ +* curl http://localhost:5001 and verify message diff --git a/test/compose/port_map_diff_port/frontend/Dockerfile b/test/compose/port_map_diff_port/frontend/Dockerfile index a393a0dcb..8d5c45401 100644 --- a/test/compose/port_map_diff_port/frontend/Dockerfile +++ b/test/compose/port_map_diff_port/frontend/Dockerfile @@ -1,4 +1,4 @@ -FROM podman_python +FROM quay.io/libpod/podman_python WORKDIR /app COPY . /app ENTRYPOINT ["python3"] diff --git a/test/compose/port_map_diff_port/tests.sh b/test/compose/port_map_diff_port/tests.sh new file mode 100644 index 000000000..5a468aadc --- /dev/null +++ b/test/compose/port_map_diff_port/tests.sh @@ -0,0 +1,3 @@ +# -*- bash -*- + +test_port 5001 = "Podman rulez!" diff --git a/test/compose/setup.sh.example b/test/compose/setup.sh.example new file mode 100644 index 000000000..9004b1e76 --- /dev/null +++ b/test/compose/setup.sh.example @@ -0,0 +1,3 @@ +# -*- bash -*- + +export ENV_PASSTHRU=$(random_string 20) diff --git a/test/compose/simple_port_map/README.md b/test/compose/simple_port_map/README.md new file mode 100644 index 000000000..f28d71c3e --- /dev/null +++ b/test/compose/simple_port_map/README.md @@ -0,0 +1,9 @@ +simple port map to host +=============== + +This test creates a container that runs flask on and maps to the same +host port + +Validation +------------ +* curl http://localhost:5000 and verify message diff --git a/test/compose/simple_port_map/frontend/app.py b/test/compose/simple_port_map/frontend/app.py index 97b17c440..e4f84068c 100644 --- a/test/compose/simple_port_map/frontend/app.py +++ b/test/compose/simple_port_map/frontend/app.py @@ -4,12 +4,7 @@ app = Flask(__name__) @app.route('/') def hello(): - passthru = "ERROR: Could not get $ENV_PASSTHRU envariable" - try: - passthru = os.getenv("ENV_PASSTHRU") - except Exception as e: - passthru = passthru + ": " + str(e) - return "Podman rulez!--" + passthru + "--!" + return "Podman rulez!" if __name__ == '__main__': app.run(host='0.0.0.0') diff --git a/test/compose/simple_port_map/setup.sh b/test/compose/simple_port_map/setup.sh deleted file mode 100644 index 9004b1e76..000000000 --- a/test/compose/simple_port_map/setup.sh +++ /dev/null @@ -1,3 +0,0 @@ -# -*- bash -*- - -export ENV_PASSTHRU=$(random_string 20) diff --git a/test/compose/simple_port_map/teardown.sh b/test/compose/simple_port_map/teardown.sh deleted file mode 100644 index 3f8153fa0..000000000 --- a/test/compose/simple_port_map/teardown.sh +++ /dev/null @@ -1,4 +0,0 @@ -# -*- bash -*- - -# FIXME: this is completely unnecessary; it's just an example of a teardown -unset ENV_PASSTHRU diff --git a/test/compose/simple_port_map/tests.sh b/test/compose/simple_port_map/tests.sh index 959b429d6..ccb2b6a3d 100644 --- a/test/compose/simple_port_map/tests.sh +++ b/test/compose/simple_port_map/tests.sh @@ -1,3 +1,3 @@ # -*- bash -*- -test_port 5000 = "Podman rulez!--$ENV_PASSTHRU--!" +test_port 5000 = "Podman rulez!" diff --git a/test/compose/teardown.sh.example b/test/compose/teardown.sh.example new file mode 100644 index 000000000..3f8153fa0 --- /dev/null +++ b/test/compose/teardown.sh.example @@ -0,0 +1,4 @@ +# -*- bash -*- + +# FIXME: this is completely unnecessary; it's just an example of a teardown +unset ENV_PASSTHRU -- cgit v1.2.3-54-g00ecf