diff --git a/.docker/run.sh b/.docker/run.sh new file mode 100755 index 0000000000..bd7bda65a2 --- /dev/null +++ b/.docker/run.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -ex + +if [ "${MAIN}" == "main_index" ]; then + PORT=5001 +else + MAIN="main" + PORT=5000 +fi + +uvicorn optimade.server.$MAIN:app --host 0.0.0.0 --port $PORT diff --git a/.github/workflows/deps_lint.yml b/.github/workflows/deps_lint.yml index fee4373190..7dd710e06b 100644 --- a/.github/workflows/deps_lint.yml +++ b/.github/workflows/deps_lint.yml @@ -94,7 +94,23 @@ jobs: - uses: actions/checkout@v1 - name: Build the Docker image - run: docker-compose -f ./docker-compose.yml build + run: docker-compose build + + - name: Test server + run: | + docker-compose up optimade & + .github/workflows/wait_for_it.sh localhost:3213 -t 120 + sleep 15 + curl http://localhost:3213/optimade/info > info.json + grep -F "http://example.com" info.json || exit 1 + + - name: Test index server + run: | + docker-compose up optimade-index & + .github/workflows/wait_for_it.sh localhost:3214 -t 120 + sleep 15 + curl http://localhost:3214/optimade/info > info.json + grep -F "http://example.com" info.json || exit 1 deps_static: runs-on: ubuntu-latest diff --git a/.github/workflows/wait_for_it.sh b/.github/workflows/wait_for_it.sh new file mode 100755 index 0000000000..eca6c3b9c8 --- /dev/null +++ b/.github/workflows/wait_for_it.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash +# Use this script to test if a given TCP host/port are available + +cmdname=$(basename $0) + +echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } + +usage() +{ + cat << USAGE >&2 +Usage: + $cmdname host:port [-s] [-t timeout] [-- command args] + -h HOST | --host=HOST Host or IP under test + -p PORT | --port=PORT TCP port under test + Alternatively, you specify the host and port as host:port + -s | --strict Only execute subcommand if the test succeeds + -q | --quiet Don't output any status messages + -t TIMEOUT | --timeout=TIMEOUT + Timeout in seconds, zero for no timeout + -- COMMAND ARGS Execute command with args after the test finishes +USAGE + exit 1 +} + +wait_for() +{ + if [[ $TIMEOUT -gt 0 ]]; then + echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT" + else + echoerr "$cmdname: waiting for $HOST:$PORT without a timeout" + fi + start_ts=$(date +%s) + while : + do + (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1 + result=$? + if [[ $result -eq 0 ]]; then + end_ts=$(date +%s) + echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds" + break + fi + sleep 1 + done + return $result +} + +wait_for_wrapper() +{ + # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 + if [[ $QUIET -eq 1 ]]; then + timeout $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & + else + timeout $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & + fi + PID=$! + trap "kill -INT -$PID" INT + wait $PID + RESULT=$? + if [[ $RESULT -ne 0 ]]; then + echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT" + fi + return $RESULT +} + +# process arguments +while [[ $# -gt 0 ]] +do + case "$1" in + *:* ) + hostport=(${1//:/ }) + HOST=${hostport[0]} + PORT=${hostport[1]} + shift 1 + ;; + --child) + CHILD=1 + shift 1 + ;; + -q | --quiet) + QUIET=1 + shift 1 + ;; + -s | --strict) + STRICT=1 + shift 1 + ;; + -h) + HOST="$2" + if [[ $HOST == "" ]]; then break; fi + shift 2 + ;; + --host=*) + HOST="${1#*=}" + shift 1 + ;; + -p) + PORT="$2" + if [[ $PORT == "" ]]; then break; fi + shift 2 + ;; + --port=*) + PORT="${1#*=}" + shift 1 + ;; + -t) + TIMEOUT="$2" + if [[ $TIMEOUT == "" ]]; then break; fi + shift 2 + ;; + --timeout=*) + TIMEOUT="${1#*=}" + shift 1 + ;; + --) + shift + CLI="$@" + break + ;; + --help) + usage + ;; + *) + echoerr "Unknown argument: $1" + usage + ;; + esac +done + +if [[ "$HOST" == "" || "$PORT" == "" ]]; then + echoerr "Error: you need to provide a host and port to test." + usage +fi + +TIMEOUT=${TIMEOUT:-15} +STRICT=${STRICT:-0} +CHILD=${CHILD:-0} +QUIET=${QUIET:-0} + +if [[ $CHILD -gt 0 ]]; then + wait_for + RESULT=$? + exit $RESULT +else + if [[ $TIMEOUT -gt 0 ]]; then + wait_for_wrapper + RESULT=$? + else + wait_for + RESULT=$? + fi +fi + +if [[ $CLI != "" ]]; then + if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then + echoerr "$cmdname: strict mode, refusing to execute subprocess" + exit $RESULT + fi + exec $CLI +else + exit $RESULT +fi diff --git a/Dockerfile b/Dockerfile index 126cc5f8d5..4dd36a1c6a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,8 +7,9 @@ COPY setup.py README.md ./ COPY optimade ./optimade RUN pip install -e .[server] -EXPOSE 80 +ARG PORT=5000 +EXPOSE ${PORT} -COPY run.sh ./ +COPY .docker/run.sh ./ -CMD ["/app/run.sh", "$MAIN"] +CMD ["/app/run.sh"] diff --git a/docker-compose.yml b/docker-compose.yml index 4d7b750fc5..7f0dfcf85e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,22 +2,26 @@ version: '2' services: - optimade-index: + optimade: restart: always build: context: . dockerfile: Dockerfile + args: + PORT: 5000 environment: - MAIN: main_index + MAIN: main ports: - - '3214:5001' + - '3213:5000' - optimade: + optimade-index: restart: always build: context: . dockerfile: Dockerfile + args: + PORT: 5001 environment: - MAIN: main + MAIN: main_index ports: - - '3213:5000' + - '3214:5001'