15 changed files with 325 additions and 3 deletions
@ -0,0 +1,4 @@ |
|||||
|
**/__pycache__/ |
||||
|
build/ |
||||
|
dist/ |
||||
|
**/*.egg-info |
||||
@ -0,0 +1,25 @@ |
|||||
|
version: "2" |
||||
|
|
||||
|
services: |
||||
|
monsun_postgres: |
||||
|
image: postgres |
||||
|
container_name: monsun_postgres |
||||
|
restart: always |
||||
|
volumes: |
||||
|
- ./db-data:/var/lib/postgresql/data |
||||
|
env_file: dev.env |
||||
|
|
||||
|
monsun_backend: |
||||
|
build: . |
||||
|
container_name: monsun_backd |
||||
|
restart: always |
||||
|
ports: |
||||
|
- 80:80 |
||||
|
volumes: |
||||
|
- ./config:/var/config/ |
||||
|
depends_on: |
||||
|
- monsun_postgres |
||||
|
environment: |
||||
|
POSTGRES_HOST: monsun_postgres |
||||
|
env_file: dev.env |
||||
|
command: ["bash", "./wait-for-it.sh", "monsun_postgres:5432", "-t", "60", "--", "./docker-entrypoint.sh"] |
||||
@ -0,0 +1,6 @@ |
|||||
|
#!/usr/bin/env bash |
||||
|
source /opt/venv/bin/activate |
||||
|
flask db upgrade |
||||
|
|
||||
|
service nginx start |
||||
|
uwsgi --ini uwsgi.ini |
||||
@ -0,0 +1,3 @@ |
|||||
|
docker build -t monsun_backend . |
||||
|
docker tag monsun_backend:latest registry.berthoud.dev/monsun_backend |
||||
|
docker push registry.berthoud.dev/monsun_backend:latest |
||||
@ -0,0 +1,45 @@ |
|||||
|
# stage 1 |
||||
|
FROM python:3.8-slim-buster as backend-build |
||||
|
|
||||
|
VOLUME /app |
||||
|
WORKDIR /app |
||||
|
|
||||
|
RUN apt-get update \ |
||||
|
&& apt-get -y install python3-dev \ |
||||
|
&& apt-get -y install build-essential |
||||
|
|
||||
|
RUN python3 -m venv /opt/venv |
||||
|
|
||||
|
COPY . . |
||||
|
|
||||
|
RUN . /opt/venv/bin/activate \ |
||||
|
&& pip install --upgrade setuptools wheel \ |
||||
|
&& pip install -r requirements.txt \ |
||||
|
&& python setup.py sdist bdist_wheel \ |
||||
|
&& pip install monsun_backend --no-index --find-links file:///app/dist |
||||
|
|
||||
|
# stage 2 |
||||
|
FROM python:3.8-slim-buster |
||||
|
|
||||
|
RUN apt-get update \ |
||||
|
&& apt-get -y install nginx \ |
||||
|
&& apt-get -y install python3-dev \ |
||||
|
&& apt-get -y install build-essential \ |
||||
|
&& apt-get -qy install netcat |
||||
|
|
||||
|
RUN mkdir /var/config |
||||
|
VOLUME /var/config |
||||
|
|
||||
|
VOLUME /app |
||||
|
WORKDIR /app |
||||
|
|
||||
|
COPY docker-entrypoint.sh /app/docker-entrypoint.sh |
||||
|
COPY wait-for-it.sh /app/wait-for-it.sh |
||||
|
COPY wsgi.py /app/wsgi.py |
||||
|
COPY nginx.conf /etc/nginx |
||||
|
COPY uwsgi.ini /app/uwsgi.ini |
||||
|
COPY migrations /app/migrations |
||||
|
|
||||
|
COPY --from=backend-build /opt/venv /opt/venv |
||||
|
|
||||
|
CMD ["bash", "./docker-entrypoint.sh"] |
||||
@ -0,0 +1,47 @@ |
|||||
|
user www-data; |
||||
|
worker_processes auto; |
||||
|
pid /run/nginx.pid; |
||||
|
|
||||
|
events { |
||||
|
worker_connections 1024; |
||||
|
use epoll; |
||||
|
multi_accept on; |
||||
|
} |
||||
|
|
||||
|
http { |
||||
|
access_log /dev/stdout; |
||||
|
error_log /dev/stdout; |
||||
|
|
||||
|
sendfile on; |
||||
|
tcp_nopush on; |
||||
|
tcp_nodelay on; |
||||
|
keepalive_timeout 65; |
||||
|
types_hash_max_size 2048; |
||||
|
|
||||
|
client_max_body_size 20M; |
||||
|
|
||||
|
include /etc/nginx/mime.types; |
||||
|
default_type application/octet-stream; |
||||
|
|
||||
|
index index.html index.htm; |
||||
|
|
||||
|
server { |
||||
|
listen 80 default_server; |
||||
|
listen [::]:80 default_server; |
||||
|
server_name localhost; |
||||
|
root /var/www/html; |
||||
|
|
||||
|
location / { |
||||
|
include uwsgi_params; |
||||
|
uwsgi_pass unix:/tmp/uwsgi.socket; |
||||
|
uwsgi_read_timeout 1h; |
||||
|
uwsgi_send_timeout 1h; |
||||
|
proxy_send_timeout 1h; |
||||
|
proxy_read_timeout 1h; |
||||
|
|
||||
|
proxy_buffer_size 128k; |
||||
|
proxy_buffers 4 256k; |
||||
|
proxy_busy_buffers_size 256k; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,74 @@ |
|||||
|
import logging |
||||
|
import os |
||||
|
|
||||
|
import pytest |
||||
|
import requests |
||||
|
from flask_api import status |
||||
|
|
||||
|
BASE_URL = os.environ.get("TEST_BASE_URL", "http://localhost") |
||||
|
LOGIN_URI = BASE_URL + "/login" |
||||
|
LOGOUT_URI = BASE_URL + "/logout" |
||||
|
ADMIN_URI = BASE_URL + "/admin" |
||||
|
|
||||
|
PASSWORD = os.environ.get("MONSUN_PASSWORD", "password") |
||||
|
|
||||
|
|
||||
|
@pytest.fixture(autouse=True) |
||||
|
def log_variables(): |
||||
|
logger = logging.getLogger("system tests") |
||||
|
logger.info(f"BASE_URL: {BASE_URL}") |
||||
|
|
||||
|
|
||||
|
@pytest.fixture() |
||||
|
def session() -> requests.Session: |
||||
|
session = requests.Session() |
||||
|
response_login = session.post( |
||||
|
url=LOGIN_URI, |
||||
|
data={"email": "andreasberthoud@gmail.com", "password": PASSWORD}, |
||||
|
) |
||||
|
assert response_login.status_code == status.HTTP_200_OK |
||||
|
return session |
||||
|
|
||||
|
|
||||
|
def test_login_as_admin_and_accessing_admin_endpoint(): |
||||
|
session_admin_ = requests.Session() |
||||
|
response_login = session_admin_.post( |
||||
|
url=LOGIN_URI, |
||||
|
data={"email": "andreasberthoud@gmail.com", "password": PASSWORD}, |
||||
|
) |
||||
|
assert response_login.status_code == status.HTTP_200_OK |
||||
|
|
||||
|
response_admin_logged_in = session_admin_.get( |
||||
|
url=ADMIN_URI, |
||||
|
) |
||||
|
assert response_admin_logged_in.status_code == status.HTTP_200_OK |
||||
|
|
||||
|
response_logout = session_admin_.delete( |
||||
|
url=LOGOUT_URI, |
||||
|
) |
||||
|
assert response_logout.status_code == status.HTTP_200_OK |
||||
|
|
||||
|
response_admin_logged_out = session_admin_.get( |
||||
|
url=ADMIN_URI, |
||||
|
) |
||||
|
assert response_admin_logged_out.status_code == status.HTTP_403_FORBIDDEN |
||||
|
|
||||
|
|
||||
|
def test_toggle_client_led_then_status_is_ok(session): |
||||
|
response = session.post( |
||||
|
url=BASE_URL + "/client/command?cmd=led&id=red&command=toggle", |
||||
|
) |
||||
|
assert response.status_code == status.HTTP_200_OK |
||||
|
|
||||
|
|
||||
|
def test_pair_with_server_then_status_is_ok(session): |
||||
|
response = session.post(url=BASE_URL + "/client/command?cmd=gp&command_id=1") |
||||
|
assert response.status_code == status.HTTP_200_OK |
||||
|
|
||||
|
|
||||
|
def test_toggle_server_led_then_status_is_ok(session): |
||||
|
"""Requires a connected GATT server""" |
||||
|
response = session.post( |
||||
|
url=BASE_URL + "/client/command?cmd=led&id=red&command=toggle&target=server", |
||||
|
) |
||||
|
assert response.status_code == status.HTTP_200_OK |
||||
@ -0,0 +1,12 @@ |
|||||
|
version: "2" |
||||
|
|
||||
|
services: |
||||
|
tests_monsun_postgres-test: |
||||
|
image: postgres |
||||
|
environment: |
||||
|
POSTGRES_PASSWORD: pass |
||||
|
POSTGRES_USER: usr |
||||
|
POSTGRES_DB: sqlalchemy |
||||
|
POSTGRES_HOST: postgres |
||||
|
ports: |
||||
|
- 5432:5432 |
||||
@ -1 +1,3 @@ |
|||||
pytest |
pytest |
||||
|
pytest-env |
||||
|
requests |
||||
|
|||||
@ -0,0 +1,12 @@ |
|||||
|
[uwsgi] |
||||
|
wsgi-file = wsgi.py |
||||
|
uid = www-data |
||||
|
gid = www-data |
||||
|
master = true |
||||
|
processes = 5 |
||||
|
|
||||
|
socket = /tmp/uwsgi.socket |
||||
|
chmod-sock = 664 |
||||
|
vacuum = true |
||||
|
|
||||
|
die-on-term = true |
||||
@ -0,0 +1,79 @@ |
|||||
|
#!/bin/sh |
||||
|
# https://github.com/vishnubob/wait-for-it |
||||
|
TIMEOUT=15 |
||||
|
QUIET=0 |
||||
|
|
||||
|
echoerr() { |
||||
|
if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi |
||||
|
} |
||||
|
|
||||
|
usage() { |
||||
|
exitcode="$1" |
||||
|
cat << USAGE >&2 |
||||
|
Usage: |
||||
|
$cmdname host:port [-t timeout] [-- command args] |
||||
|
-q | --quiet Do not 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 "$exitcode" |
||||
|
} |
||||
|
|
||||
|
wait_for() { |
||||
|
for i in `seq $TIMEOUT` ; do |
||||
|
nc -z "$HOST" "$PORT" > /dev/null 2>&1 |
||||
|
|
||||
|
result=$? |
||||
|
if [ $result -eq 0 ] ; then |
||||
|
if [ $# -gt 0 ] ; then |
||||
|
exec "$@" |
||||
|
fi |
||||
|
exit 0 |
||||
|
fi |
||||
|
sleep 1 |
||||
|
done |
||||
|
echo "Operation timed out" >&2 |
||||
|
exit 1 |
||||
|
} |
||||
|
|
||||
|
while [ $# -gt 0 ] |
||||
|
do |
||||
|
case "$1" in |
||||
|
*:* ) |
||||
|
HOST=$(printf "%s\n" "$1"| cut -d : -f 1) |
||||
|
PORT=$(printf "%s\n" "$1"| cut -d : -f 2) |
||||
|
shift 1 |
||||
|
;; |
||||
|
-q | --quiet) |
||||
|
QUIET=1 |
||||
|
shift 1 |
||||
|
;; |
||||
|
-t) |
||||
|
TIMEOUT="$2" |
||||
|
if [ "$TIMEOUT" = "" ]; then break; fi |
||||
|
shift 2 |
||||
|
;; |
||||
|
--timeout=*) |
||||
|
TIMEOUT="${1#*=}" |
||||
|
shift 1 |
||||
|
;; |
||||
|
--) |
||||
|
shift |
||||
|
break |
||||
|
;; |
||||
|
--help) |
||||
|
usage 0 |
||||
|
;; |
||||
|
*) |
||||
|
echoerr "Unknown argument: $1" |
||||
|
usage 1 |
||||
|
;; |
||||
|
esac |
||||
|
done |
||||
|
|
||||
|
if [ "$HOST" = "" -o "$PORT" = "" ]; then |
||||
|
echoerr "Error: you need to provide a host and port to test." |
||||
|
usage 2 |
||||
|
fi |
||||
|
|
||||
|
wait_for "$@" |
||||
Loading…
Reference in new issue