feat: added support for mongodb

This commit is contained in:
2024-11-27 10:46:41 +01:00
parent 8160d9a383
commit 4a45119549
25 changed files with 923 additions and 348 deletions

View File

@ -0,0 +1,32 @@
# set base image (host OS)
ARG PY_VERSION=3.10 CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX
FROM python:${PY_VERSION}
ARG BEC_ATLAS_BRANCH=main BEC_CORE_BRANCH=main
RUN echo "Building BEC Atlas environment for branch ${BEC_ATLAS_BRANCH} with BEC branch ${BEC_CORE_BRANCH}"
RUN apt update
RUN apt install git -y
RUN apt install netcat-openbsd -y
# set the working directory in the container
WORKDIR /code
# clone the bec repo
RUN git clone --branch ${BEC_CORE_BRANCH} https://gitlab.psi.ch/bec/bec.git
WORKDIR /code/bec/
RUN pip install -e bec_lib[dev]
WORKDIR /code
RUN git clone --branch ${BEC_ATLAS_BRANCH} https://gitlab.psi.ch/bec/bec_atlas.git
WORKDIR /code/bec_atlas
RUN pip install -e ./backend[dev]
RUN mkdir -p /code/bec_atlas/test_files
# command to run on container start
ENTRYPOINT [ "./backend/tests/coverage_run.sh" ]

View File

@ -3,11 +3,11 @@ import os
from typing import Iterator
import pytest
from bec_atlas.main import AtlasApp
from bec_atlas.utils.setup_database import setup_database
from fastapi.testclient import TestClient
from pytest_docker.plugin import DockerComposeExecutor, Services
from bec_atlas.main import AtlasApp
def pytest_addoption(parser):
parser.addoption(
@ -101,42 +101,39 @@ def docker_services(
yield docker_service
@pytest.fixture(scope="session")
def scylla_container(docker_ip, docker_services):
host = docker_ip
if os.path.exists("/.dockerenv"):
# if we are running in the CI, scylla was started as 'scylla' service
host = "scylla"
if docker_services is None:
port = 9042
else:
port = docker_services.port_for("scylla", 9042)
setup_database(host=host, port=port)
return host, port
@pytest.fixture(scope="session")
def redis_container(docker_ip, docker_services):
host = docker_ip
if os.path.exists("/.dockerenv"):
# if we are running in the CI, scylla was started as 'scylla' service
host = "redis"
if docker_services is None:
port = 6380
else:
port = docker_services.port_for("redis", 6379)
return host, port
return "localhost", port
@pytest.fixture(scope="session")
def backend(scylla_container, redis_container):
scylla_host, scylla_port = scylla_container
def mongo_container(docker_ip, docker_services):
host = docker_ip
if os.path.exists("/.dockerenv"):
host = "mongo"
if docker_services is None:
port = 27017
else:
port = docker_services.port_for("mongodb", 27017)
return "localhost", port
@pytest.fixture(scope="session")
def backend(redis_container, mongo_container):
redis_host, redis_port = redis_container
mongo_host, mongo_port = mongo_container
config = {
"scylla": {"hosts": [(scylla_host, scylla_port)]},
"redis": {"host": redis_host, "port": redis_port},
"mongodb": {"host": mongo_host, "port": mongo_port},
}
app = AtlasApp(config)

23
backend/tests/coverage_run.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash
# check if redis is running on port 6380 and mongodb on port 27017 and scylladb on port 9070
if [ "$(nc -z localhost 6380; echo $?)" -ne 0 ]; then
echo "Redis is not running on port 6380"
exit 1
fi
if [ "$(nc -z localhost 27017; echo $?)" -ne 0 ]; then
echo "MongoDB is not running on port 27017"
exit 1
fi
coverage run --concurrency=thread --source=./backend --omit=*/backend/tests/* -m pytest -v --junitxml=./test_files/report.xml --skip-docker --random-order --full-trace ./backend/tests
EXIT_STATUS=$?
if [ $EXIT_STATUS -ne 0 ]; then
exit $EXIT_STATUS
fi
coverage report
coverage xml -o ./test_files/coverage.xml

View File

@ -1,10 +1,10 @@
version: '2'
services:
scylla:
image: scylladb/scylla:latest
ports:
- "9070:9042"
redis:
image: redis:latest
ports:
- "6380:6379"
- "6380:6379"
mongodb:
image: mongo:latest
ports:
- "27017:27017"

View File

@ -72,7 +72,7 @@ async def test_redis_websocket_multiple_disconnect_same_sid(backend_client):
async def test_redis_websocket_register_wrong_endpoint_raises(backend_client):
client, app = backend_client
with mock.patch.object(app.redis_websocket.socket, "emit") as emit:
app.redis_websocket.socket.handlers["/"]["connect"]("sid")
await app.redis_websocket.socket.handlers["/"]["connect"]("sid")
await app.redis_websocket.socket.handlers["/"]["register"](
"sid", json.dumps({"endpoint": "wrong_endpoint"})
)

View File

@ -0,0 +1,107 @@
import pytest
from bec_lib import messages
from bec_atlas.ingestor.data_ingestor import DataIngestor
@pytest.fixture
def scan_ingestor(backend):
client, app = backend
app.redis_websocket.users = {}
ingestor = DataIngestor(config=app.config)
yield ingestor
ingestor.shutdown()
@pytest.mark.timeout(60)
def test_scan_ingestor_create_scan(scan_ingestor, backend):
"""
Test that the login endpoint returns a token.
"""
client, app = backend
msg = messages.ScanStatusMessage(
metadata={},
scan_id="92429a81-4bd4-41c2-82df-eccfaddf3d96",
status="open",
# session_id="5cc67967-744d-4115-a46b-13246580cb3f",
info={
"readout_priority": {
"monitored": ["bpm3i", "diode", "ftp", "bpm5c", "bpm3x", "bpm3z", "bpm4x"],
"baseline": ["ddg1a", "bs1y", "mobdco"],
"async": ["eiger", "monitor_async", "waveform"],
"continuous": [],
"on_request": ["flyer_sim"],
},
"file_suffix": None,
"file_directory": None,
"user_metadata": {"sample_name": "testA"},
"RID": "5cc67967-744d-4115-a46b-13246580cb3f",
"scan_id": "92429a81-4bd4-41c2-82df-eccfaddf3d96",
"queue_id": "7d77d976-bee0-4bb8-aabb-2b862b4506ec",
"session_id": "5cc67967-744d-4115-a46b-13246580cb3f",
"scan_motors": ["samx"],
"num_points": 10,
"positions": [
[-5.0024118137239455],
[-3.8913007026128343],
[-2.780189591501723],
[-1.6690784803906122],
[-0.557967369279501],
[0.5531437418316097],
[1.6642548529427212],
[2.775365964053833],
[3.886477075164944],
[4.9975881862760545],
],
"scan_name": "line_scan",
"scan_type": "step",
"scan_number": 2,
"dataset_number": 2,
"exp_time": 0,
"frames_per_trigger": 1,
"settling_time": 0,
"readout_time": 0,
"acquisition_config": {"default": {"exp_time": 0, "readout_time": 0}},
"scan_report_devices": ["samx"],
"monitor_sync": "bec",
"scan_msgs": [
"metadata={'file_suffix': None, 'file_directory': None, 'user_metadata': {'sample_name': 'testA'}, 'RID': '5cc67967-744d-4115-a46b-13246580cb3f'} scan_type='line_scan' parameter={'args': {'samx': [-5, 5]}, 'kwargs': {'steps': 10, 'exp_time': 0, 'relative': True, 'system_config': {'file_suffix': None, 'file_directory': None}}} queue='primary'"
],
"args": {"samx": [-5, 5]},
"kwargs": {
"steps": 10,
"exp_time": 0,
"relative": True,
"system_config": {"file_suffix": None, "file_directory": None},
},
},
timestamp=1732610545.15924,
)
scan_ingestor.update_scan_status(msg)
response = client.post(
"/api/v1/user/login", json={"username": "admin@bec_atlas.ch", "password": "admin"}
)
client.headers.update({"Authorization": f"Bearer {response.json()}"})
session_id = msg.info.get("session_id")
scan_id = msg.scan_id
response = client.get(f"/api/v1/scans/session/{session_id}")
assert response.status_code == 200
out = response.json()[0]
# assert out["session_id"] == session_id
assert out["scan_id"] == scan_id
assert out["status"] == "open"
msg.status = "closed"
scan_ingestor.update_scan_status(msg)
response = client.get(f"/api/v1/scans/id/{scan_id}")
assert response.status_code == 200
out = response.json()
assert out["status"] == "closed"
assert out["scan_id"] == scan_id
response = client.get(f"/api/v1/scans/session/{session_id}")
assert response.status_code == 200
out = response.json()
assert len(out) == 1