#!/bin/sh # script/example-app: build the image, and on it the example app in # deploy/example-app, then run the app's container and check that the # health check passes, that a request is served through smallwebwaf, # that `sv stop` stops smallwebwaf in order, and that `docker stop` # stops the container without having to kill it. The container and both # images are removed however the script ends. Building the app needs # network access, for nixpkgs' binary cache. script/check does not run # this. set -eu SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)" ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)" # Named after this run, so that runs in other clones on the same host # never touch each other's. NAME="$("$SCRIPT_DIR/projectname")-example-$$" IMAGE="$NAME-base" APP_IMAGE="$NAME-app" CONTAINER="$NAME" cleanup() { docker rm --force "$CONTAINER" >/dev/null 2>&1 || true docker rmi --force "$APP_IMAGE" "$IMAGE" >/dev/null 2>&1 || true } fail() { echo "example-app: $*; the container's output:" >&2 docker logs "$CONTAINER" >&2 || true exit 1 } # wait_for ...: run the command every second until # it succeeds, for at most a minute. wait_for() { failure="$1" shift tries=0 until "$@"; do tries=$((tries + 1)) [ "$tries" -lt 60 ] || fail "$failure" sleep 1 done } healthy() { status="$(docker inspect --format '{{.State.Health.Status}}' "$CONTAINER")" [ "$status" = healthy ] } # logged : the container's output holds text. logged() { docker logs "$CONTAINER" 2>&1 | grep -qF "$1" } main() { cd "$ROOT" trap cleanup EXIT trap 'exit 1' HUP INT TERM docker build --no-cache -t "$IMAGE" . docker build --no-cache --build-arg SMALLWEBWAF_IMAGE="$IMAGE" \ -t "$APP_IMAGE" deploy/example-app docker run --detach --name "$CONTAINER" --publish 127.0.0.1::8080 \ "$APP_IMAGE" >/dev/null wait_for "the health check did not pass" healthy echo "example-app: the health check passes" address="$(docker port "$CONTAINER" 8080/tcp)" page="$(curl --fail --silent --show-error --max-time 10 "http://$address/")" || fail "no answer on port 8080" [ "$page" = "hello from the example app" ] || fail "port 8080 answered $page" wait_for "smallwebwaf logged no request it forwarded" logged '"action":"forward"' echo "example-app: smallwebwaf passes a request to the app and its answer back" docker exec "$CONTAINER" sv stop smallwebwaf >/dev/null || fail "sv stop smallwebwaf failed" wait_for "smallwebwaf did not stop in order" logged '"msg":"stopped"' echo "example-app: sv stop stops smallwebwaf in order" docker stop "$CONTAINER" >/dev/null status="$(docker inspect --format '{{.State.ExitCode}}' "$CONTAINER")" [ "$status" = 0 ] || fail "docker stop left exit status $status" echo "example-app: docker stop stops the container in order" } main "$@"