Skip to content

Commit

Permalink
Merge pull request #140 from CasperWA/add_docker_for_index_meta_db
Browse files Browse the repository at this point in the history
Add docker for the two servers.
The docker images are made as docker-compose services,
utilizing the same `Dockerfile`.

The index meta-database is now served at the same URL
as the regular server, but at a different port (5001 vs. 5000).

Both docker images are tested by being built and started
and then the validator has a go at them.
  • Loading branch information
CasperWA committed Feb 7, 2020
2 parents ea975a2 + 8d39011 commit 3712c9c
Show file tree
Hide file tree
Showing 11 changed files with 303 additions and 64 deletions.
11 changes: 11 additions & 0 deletions .docker/run.sh
Original file line number Diff line number Diff line change
@@ -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
23 changes: 23 additions & 0 deletions .github/workflows/deps_lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,29 @@ jobs:
.ci/openapi_diff.sh
.ci/index_openapi_diff.sh
docker-image:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1

- name: Build the Docker image
run: docker-compose build

- name: Test server
run: |
docker-compose up optimade &
.github/workflows/wait_for_it.sh localhost:3213 -t 120
sleep 15
docker exec optimade-python-tools_optimade_1 optimade_validator http://localhost:5000/optimade/v0
- name: Test index server
run: |
docker-compose up optimade-index &
.github/workflows/wait_for_it.sh localhost:3214 -t 120
sleep 15
docker exec optimade-python-tools_optimade-index_1 optimade_validator http://localhost:5001/optimade/v0 --index
deps_static:
runs-on: ubuntu-latest

Expand Down
161 changes: 161 additions & 0 deletions .github/workflows/wait_for_it.sh
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM python:3.7

WORKDIR /app

# copy repo contents
COPY setup.py README.md ./
COPY optimade ./optimade
RUN pip install -e .[server]

ARG PORT=5000
EXPOSE ${PORT}

COPY .docker/run.sh ./

CMD ["/app/run.sh"]
27 changes: 27 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
version: '2'

services:

optimade:
restart: always
build:
context: .
dockerfile: Dockerfile
args:
PORT: 5000
environment:
MAIN: main
ports:
- '3213:5000'

optimade-index:
restart: always
build:
context: .
dockerfile: Dockerfile
args:
PORT: 5001
environment:
MAIN: main_index
ports:
- '3214:5001'
12 changes: 6 additions & 6 deletions openapi/index_openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@
"version": "0.10.1"
},
"paths": {
"/index/optimade/v0/info": {
"/optimade/v0/info": {
"get": {
"tags": [
"Info"
],
"summary": "Get Info",
"operationId": "get_info_index_optimade_v0_info_get",
"operationId": "get_info_optimade_v0_info_get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {
"title": "Response Get Info Index Optimade V0 Info Get",
"title": "Response Get Info Optimade V0 Info Get",
"anyOf": [
{
"$ref": "#/components/schemas/IndexInfoResponse"
Expand All @@ -35,13 +35,13 @@
}
}
},
"/index/optimade/v0/links": {
"/optimade/v0/links": {
"get": {
"tags": [
"Links"
],
"summary": "Get Links",
"operationId": "get_links_index_optimade_v0_links_get",
"operationId": "get_links_optimade_v0_links_get",
"parameters": [
{
"description": "A filter string, in the format described in section [API Filtering Format Specification](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst#api-filtering-format-specification) of the [OPTiMaDe spec](https://github.com/Materials-Consortia/OPTiMaDe/blob/develop/optimade.rst).",
Expand Down Expand Up @@ -191,7 +191,7 @@
"content": {
"application/json": {
"schema": {
"title": "Response Get Links Index Optimade V0 Links Get",
"title": "Response Get Links Optimade V0 Links Get",
"anyOf": [
{
"$ref": "#/components/schemas/LinksResponse"
Expand Down
3 changes: 0 additions & 3 deletions optimade/server/index_links.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
[
{
"_id": {
"$oid": "746573745f73657276657263"
},
"id": "test_server",
"type": "child",
"name": "OPTiMaDe API",
Expand Down
26 changes: 11 additions & 15 deletions optimade/server/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
This specification is generated using [`optimade-python-tools`](https://github.com/Materials-Consortia/optimade-python-tools/tree/v{__version__}) v{__version__}."""
),
version=__api_version__,
docs_url=f"{BASE_URL_PREFIXES['regular']['major']}/extensions/docs",
redoc_url=f"{BASE_URL_PREFIXES['regular']['major']}/extensions/redoc",
openapi_url=f"{BASE_URL_PREFIXES['regular']['major']}/extensions/openapi.json",
docs_url=f"{BASE_URL_PREFIXES['major']}/extensions/docs",
redoc_url=f"{BASE_URL_PREFIXES['major']}/extensions/redoc",
openapi_url=f"{BASE_URL_PREFIXES['major']}/extensions/openapi.json",
)


Expand Down Expand Up @@ -77,10 +77,10 @@ def load_entries(endpoint_name: str, endpoint_collection: MongoCollection):


# Add various endpoints to `/optimade/vMAJOR`
app.include_router(info.router, prefix=BASE_URL_PREFIXES["regular"]["major"])
app.include_router(links.router, prefix=BASE_URL_PREFIXES["regular"]["major"])
app.include_router(references.router, prefix=BASE_URL_PREFIXES["regular"]["major"])
app.include_router(structures.router, prefix=BASE_URL_PREFIXES["regular"]["major"])
app.include_router(info.router, prefix=BASE_URL_PREFIXES["major"])
app.include_router(links.router, prefix=BASE_URL_PREFIXES["major"])
app.include_router(references.router, prefix=BASE_URL_PREFIXES["major"])
app.include_router(structures.router, prefix=BASE_URL_PREFIXES["major"])


def add_optional_versioned_base_urls(app: FastAPI):
Expand All @@ -91,14 +91,10 @@ def add_optional_versioned_base_urls(app: FastAPI):
```
"""
for version in ("minor", "patch"):
app.include_router(info.router, prefix=BASE_URL_PREFIXES["regular"][version])
app.include_router(links.router, prefix=BASE_URL_PREFIXES["regular"][version])
app.include_router(
references.router, prefix=BASE_URL_PREFIXES["regular"][version]
)
app.include_router(
structures.router, prefix=BASE_URL_PREFIXES["regular"][version]
)
app.include_router(info.router, prefix=BASE_URL_PREFIXES[version])
app.include_router(links.router, prefix=BASE_URL_PREFIXES[version])
app.include_router(references.router, prefix=BASE_URL_PREFIXES[version])
app.include_router(structures.router, prefix=BASE_URL_PREFIXES[version])


def update_schema(app: FastAPI):
Expand Down

0 comments on commit 3712c9c

Please sign in to comment.