diff --git a/.dbrepo2/deploy b/.dbrepo2/deploy deleted file mode 100755 index 2cda49aec781a27fc0a36336a6e3990003bb863e..0000000000000000000000000000000000000000 --- a/.dbrepo2/deploy +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -# set version -TAG=latest - -# tear everything down -echo "Removing all data ..." -/bin/bash teardown -docker system prune -f --volumes || true - -echo "Pulling new images ..." -docker pull "dbrepo/analyse-service:${TAG}" -docker pull "dbrepo/authentication-service:${TAG}" -docker pull "dbrepo/metadata-db:${TAG}" -docker pull "dbrepo/ui:${TAG}" -docker pull "dbrepo/ui-proxy:${TAG}" -docker pull "dbrepo/identifier-service:${TAG}" -docker pull "dbrepo/container-service:${TAG}" -docker pull "dbrepo/database-service:${TAG}" -docker pull "dbrepo/discovery-service:${TAG}" -docker pull "dbrepo/gateway-service:${TAG}" -docker pull "dbrepo/query-service:${TAG}" -docker pull "dbrepo/table-service:${TAG}" -docker pull "dbrepo/units-service:${TAG}" -docker pull "dbrepo/broker-service:${TAG}" -docker pull "dbrepo/metadata-service:${TAG}" -echo "Pulled new images" - -# deploy dbrepo -echo "Deploy DBRepo ..." -docker compose -f ./docker-compose.dbrepo2.yml up -d - -# clone tuw specific deployment -git -C "/home/demo/dbrepo-tuw" pull || git clone ssh://git@gitlab.tuwien.ac.at:822/martin.weise/dbrepo-tuw.git "/home/demo/dbrepo-tuw" -cd /home/demo/dbrepo-tuw && git checkout dev - -# build tuw specific deployment -docker compose -f /home/demo/dbrepo-tuw/docker-compose.dbrepo2.yml build || exit 3 -docker compose -f /home/demo/dbrepo-tuw/docker-compose.dbrepo2.yml up -d || exit 4 -echo "Deployed TU Wien specific deployment" \ No newline at end of file diff --git a/.dbrepo2/known_hosts b/.dbrepo2/known_hosts deleted file mode 100644 index d17a72e2de908c97eb551254d51770e6725332b8..0000000000000000000000000000000000000000 --- a/.dbrepo2/known_hosts +++ /dev/null @@ -1,6 +0,0 @@ -gitlab.tuwien.ac.at ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKslN24njaMeH0xyVBO/lzeQ5/X/6UFkiz2qdcWihjT28slO/6pFBAxSzPUTBeVJWxKJgX9N+Hm65S9/Z2521E8Y9F56dcrOgeQBZ4GbLPSbEZIFN/71VL4cOh6tLahNZsAwd6y2Zi5XTAqho31VWfdCZkegZB3dNzLfOuC0t3KpxEAmWus5j8InNYDTBIy6U351/3h3oy32EdLvLpaHP+oy+QFAqXOlcXlKwHTfv9SSchQRLfWzrL4hVvohbCwMDBBvIP8J0WQ9mV95xfcwuipMWP3TksDGbst2MQ6HRXZ+yfie9Vgzg+++AjpHXQCMdalEmedNxCmxbHWYJxFHUV -gitlab.tuwien.ac.at ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBC+2QClFaM3ZNQ6nl3nHkZdFSyNP26uHPzJEUBu9J4yC1ON9GPHb2P3rC//wS819e3LWP4PXb8ug/EyEjWN30MA= -gitlab.tuwien.ac.at ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILTzOKU3zEYNo1xy8rxZsa8D0/y4EN4oB0E7wgWCkOpZ -dbrepo2.ec.tuwien.ac.at ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC5GFfX4xmYeQdQQL81heBjKb4d1M8xjOjF4lpfNmc3/wyCPtP/dt4r3nkcOW3X14yPximy8BlArsPk4ul14BWNI9yrU5VA1FLlWq9Og6SfMJ1EAUNsePDd3qCpr/ljlydS3kWCVrXD1bNO0kQ3/36e9l64BDvZXyhI3n9DvkPO93n9xJ151IC9IwjnSzJQPghboUDRiYwT2B9wt+uC+k7tTV5tQH5kJk8fEa8nMyHOc8aD2miHubrcQJrYO/fv+vVxVWJKtSdz22wuvFnj8SfGClxbT8cfMo8X+LpIQOH8VYwIZVznuSlnNYOOYO6EGYyRnqud6oz0B5RUbwyeBhtAgZW1C1OXO9DVDLnazzFxJIzwhwyZCPurpLpP7bd6P+oFWy1A7bxIhfvdduEDE80vEOPrBl44TDe6RJR6QILtdUn9rrvcV/kgfj04zkQJjqMvX2pdCpdMIU1Pm+NQ53k3oOap7j9UHnpWX7C3mk76ueQddQxWZUhGsrFUAYSJfus= -dbrepo2.ec.tuwien.ac.at ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOGTeKw2aKnykIUmvLiBNaGbq3xlSEsnD1M1HiZsPJ9ZtfSV12y9F0yutV4j68Rb+eHbyOxoyVekfl19ODDvXLM= -dbrepo2.ec.tuwien.ac.at ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPpSoshRRtQBj4ebWeaWoeGr1XFIlx3L+BXV69fafBGr \ No newline at end of file diff --git a/.fda-deployment/clean b/.fda-deployment/clean deleted file mode 100755 index 03506fc6ef3a480eea7269f90c2f8a99209a1bc0..0000000000000000000000000000000000000000 --- a/.fda-deployment/clean +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -docker container stop $(docker container ls -aq) || true -docker container rm $(docker container ls -aq) || true -docker volume rm $(docker volume ls -q) || true diff --git a/.fda-deployment/clean-tmp b/.fda-deployment/clean-tmp deleted file mode 100755 index ac34df7e9c815917e5908b129f3502c18e97e2f4..0000000000000000000000000000000000000000 --- a/.fda-deployment/clean-tmp +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -FILES=$(cd /tmp && find -exec basename '{}' ';' 2>/dev/null | egrep '^.{32}$' | egrep "^([a-z0-9]+)$") -for file in $FILES; do - rm -f /tmp/$file - echo "Removed /tmp/${file}" -done \ No newline at end of file diff --git a/.fda-deployment/crontab b/.fda-deployment/crontab deleted file mode 100644 index bbc97b1a429e174b4a42e99503e70098f1acb441..0000000000000000000000000000000000000000 --- a/.fda-deployment/crontab +++ /dev/null @@ -1,2 +0,0 @@ -0 2 * * * /usr/bin/make -C /home/rocky/fda-services teardown -1 2 * * * /usr/bin/make -C /home/rocky/fda-services run \ No newline at end of file diff --git a/.fda-deployment/fda-authentication-service/install_cert b/.fda-deployment/fda-authentication-service/install_cert deleted file mode 100755 index f52db602f44a1c08cb4cb4e8e8cc6e17e45d190b..0000000000000000000000000000000000000000 --- a/.fda-deployment/fda-authentication-service/install_cert +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash -TMP_CERT_LOCATION="/root/keys" -TMP_SAML_LOCATION="/root/keys" -KEY_STORE_LOCATION="/tmp/dbrepo.jks" -KEY_STORE_PASS="dbrepo" -CERT_LOCATION="/etc/letsencrypt/live/dbrepo.ossdip.at" -SAML_KEY="/root/keys/saml_sign.key" -SAML_PUB="/root/keys/saml_sign.cer" -TU_SAML_CERT="./fda-authentication-service/rest-service/src/main/resources/saml/tu.crt" - -# PLACE -sudo mkdir -p "${TMP_CERT_LOCATION}" -sudo mkdir -p "${TMP_SAML_LOCATION}" - -# REQUEST -sudo certbot certonly --standalone --preferred-challenges http -d dbrepo.ossdip.at \ - -m martin.weise@tuwien.ac.at --agree-tos --keep-until-expiring - -# CONVERT PKCS12 -sudo openssl pkcs12 -export -out "${TMP_SAML_LOCATION}/saml.p12" -in "${SAML_PUB}" \ - -inkey "${SAML_KEY}" -passout "pass:${KEY_STORE_PASS}" - -# CONVERT PKCS12 -sudo openssl pkcs12 -export -out "${TMP_CERT_LOCATION}/cert.p12" -in "${CERT_LOCATION}/cert.pem" \ - -inkey "${CERT_LOCATION}/privkey.pem" -passout "pass:${KEY_STORE_PASS}" - -# FIX PERMISSIONS -sudo chmod -R 644 "${TMP_CERT_LOCATION}" -sudo chmod -R 644 "${TMP_SAML_LOCATION}" - -# IMPORT SSL SIGN PRIVKEY -sudo keytool -noprompt -importkeystore -deststorepass "${KEY_STORE_PASS}" -destkeypass "${KEY_STORE_PASS}" \ - -destkeystore "${KEY_STORE_LOCATION}" -srckeystore "${TMP_CERT_LOCATION}/cert.p12" -srcstoretype PKCS12 \ - -srcstorepass "${KEY_STORE_PASS}" -alias 1 -destalias ssl - -# IMPORT SAML MESSAGE SIGN PRIVKEY -sudo keytool -noprompt -importkeystore -deststorepass "${KEY_STORE_PASS}" -destkeypass "${KEY_STORE_PASS}" \ - -destkeystore "${KEY_STORE_LOCATION}" -srckeystore "${TMP_SAML_LOCATION}" -srcstoretype PKCS12 \ - -srcstorepass "${KEY_STORE_PASS}" -alias 1 -destalias saml - -# IMPORT METADATA VERIFICATION PUBKEY -sudo keytool -noprompt -importcert -file "${TU_SAML_CERT}" -storepass "${KEY_STORE_PASS}" \ - -keystore "${KEY_STORE_LOCATION}" -alias tu - -# OWNERSHIP -sudo chown centos:docker "${TMP_CERT_LOCATION}" -sudo chown centos:docker "${TMP_SAML_LOCATION}" -sudo chown centos:docker "${KEY_STORE_LOCATION}" - -# TRUST LET'S ENCRYPT -sudo keytool -noprompt -import -alias letsencrypt -keystore "${KEY_STORE_LOCATION}" -storepass "${KEY_STORE_PASS}" \ - -file "${CERT_LOCATION}/chain.pem" diff --git a/.fda-deployment/fda-authentication-service/install_smtp b/.fda-deployment/fda-authentication-service/install_smtp deleted file mode 100755 index 22b0afaa76093e4c311b2451e365733963b15b49..0000000000000000000000000000000000000000 --- a/.fda-deployment/fda-authentication-service/install_smtp +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -sudo cat /root/smtp.secret >> ./.env diff --git a/.fda-deployment/fda-ui/install_cert b/.fda-deployment/fda-ui/install_cert deleted file mode 100755 index 92553123718052ab77978aea4d8ad3a699c0c816..0000000000000000000000000000000000000000 --- a/.fda-deployment/fda-ui/install_cert +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -CA_PATH="/etc/letsencrypt/live/dbrepo.ossdip.at" - -sudo certbot certonly --standalone --preferred-challenges http -d dbrepo.ossdip.at --agree-tos --keep-until-expiring - -KEY=$(sudo sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g' "${CA_PATH}/privkey.pem") -CERT=$(sudo sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g' "${CA_PATH}/cert.pem") - -cat << EOF -UI_KEY="${KEY}" -UI_CERT="${CERT}" -EOF \ No newline at end of file diff --git a/.fda-deployment/hosts b/.fda-deployment/hosts deleted file mode 100644 index 40da214c6af6d90f416cca86829a26ae06edec66..0000000000000000000000000000000000000000 --- a/.fda-deployment/hosts +++ /dev/null @@ -1,7 +0,0 @@ -# FDA USERDB -172.28.0.2 fda-userdb-weather-aus -172.28.0.3 fda-userdb-infection -172.28.0.4 fda-userdb-air -172.28.0.5 fda-userdb-u01 -172.28.0.6 fda-userdb-u02 -172.28.0.7 fda-userdb-u03 \ No newline at end of file diff --git a/.gitignore b/.gitignore index e372ff156bcb23dc9ed7f1706104b725510dcdcf..ae9e683f84116b3457f7a61d93748f2e47c31c2a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ target/ !.mvn/wrapper/maven-wrapper.jar !**/src/main/**/target/ !**/src/test/**/target/ - +dbrepo-* # Notebooks .jupyter/ .pytest_cache/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c18ce65e3b9ed6b126c279b57784086a06dc3f0e..1967e4afeacc6e81ad68eca7d0ccb97337f32f3d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,7 +5,6 @@ before_script: - "mvn --version" - "python3 --version" - "df / -h" - - "grep -rnw '@Test' | wc -l" variables: HOSTALIASES: ./hosts @@ -23,76 +22,77 @@ stages: - build-backend - build-frontend - test-backend + - test-frontend - build-docker - release -build-backend-metadata-db: +build-metadata-db: stage: build-backend script: - - "make build-backend-metadata-db" + - "make build-metadata-db" -build-backend-authentication: +build-authentication-service: stage: build-backend needs: - - build-backend-metadata-db + - build-metadata-db script: - - "make build-backend-authentication" + - "make build-authentication-service" -build-backend-identifier: +build-identifier-service: stage: build-backend needs: - - build-backend-metadata-db + - build-metadata-db script: - - "make build-backend-identifier" + - "make build-identifier-service" -build-backend-container: +build-container-service: stage: build-backend needs: - - build-backend-metadata-db + - build-metadata-db script: - - "make build-backend-container" + - "make build-container-service" -build-backend-database: +build-database-service: stage: build-backend needs: - - build-backend-metadata-db + - build-metadata-db script: - - "make build-backend-database" + - "make build-database-service" -build-backend-discovery: +build-discovery-service: stage: build-backend needs: - - build-backend-metadata-db + - build-metadata-db script: - - "make build-backend-discovery" + - "make build-discovery-service" -build-backend-gateway: +build-gateway-service: stage: build-backend needs: - - build-backend-metadata-db + - build-metadata-db script: - - "make build-backend-gateway" + - "make build-gateway-service" -build-backend-query: +build-query-service: stage: build-backend needs: - - build-backend-metadata-db + - build-metadata-db script: - - "make build-backend-query" + - "make build-query-service" -build-backend-table: +build-table-service: stage: build-backend needs: - - build-backend-metadata-db + - build-metadata-db script: - - "make build-backend-table" + - "make build-table-service" -build-backend-metadata: +build-metadata-service: stage: build-backend needs: - - build-backend-metadata-db + - build-metadata-db script: - - "make build-backend-metadata" + - "make build-metadata-service" build-semantics-service: stage: build-backend @@ -107,7 +107,7 @@ build-analyse-service: test-backend-authentication: stage: test-backend needs: - - build-backend-authentication + - build-authentication-service script: - "make test-authentication-service" - "cat ./fda-authentication-service/report/target/site/jacoco-aggregate/index.html | grep -o 'Total[^%]*%' | sed 's/<.*>/ /; s/Total/Jacoco Coverage Total:/'" @@ -120,10 +120,11 @@ test-backend-authentication: reports: junit: ./fda-authentication-service/rest-service/target/surefire-reports/TEST-*.xml coverage: '/Total.*?([0-9]{1,3})%/' -test-backend-identifier: + +test-identifier-service: stage: test-backend needs: - - build-backend-authentication + - build-authentication-service script: - "make test-identifier-service" - "cat ./fda-identifier-service/report/target/site/jacoco-aggregate/index.html | grep -o 'Total[^%]*%' | sed 's/<.*>/ /; s/Total/Jacoco Coverage Total:/'" @@ -137,10 +138,10 @@ test-backend-identifier: junit: ./fda-identifier-service/rest-service/target/surefire-reports/TEST-*.xml coverage: '/Total.*?([0-9]{1,3})%/' -test-backend-container: +test-container-service: stage: test-backend needs: - - build-backend-container + - build-container-service script: - "make test-container-service" - "cat ./fda-container-service/report/target/site/jacoco-aggregate/index.html | grep -o 'Total[^%]*%' | sed 's/<.*>/ /; s/Total/Jacoco Coverage Total:/'" @@ -154,10 +155,10 @@ test-backend-container: junit: ./fda-container-service/rest-service/target/surefire-reports/TEST-*.xml coverage: '/Total.*?([0-9]{1,3})%/' -test-backend-database: +test-database-service: stage: test-backend needs: - - build-backend-database + - build-database-service script: - "docker pull elasticsearch:7.13.4" - "make test-database-service" @@ -171,11 +172,12 @@ test-backend-database: reports: junit: ./fda-database-service/rest-service/target/surefire-reports/TEST-*.xml coverage: '/Total.*?([0-9]{1,3})%/' + timeout: 2 hour -test-backend-discovery: +test-discovery-service: stage: test-backend needs: - - build-backend-discovery + - build-discovery-service script: - "make test-discovery-service" - "cat ./fda-discovery-service/report/target/site/jacoco-aggregate/index.html | grep -o 'Total[^%]*%' | sed 's/<.*>/ /; s/Total/Jacoco Coverage Total:/'" @@ -189,10 +191,10 @@ test-backend-discovery: junit: ./fda-discovery-service/discovery/target/surefire-reports/TEST-*.xml coverage: '/Total.*?([0-9]{1,3})%/' -test-backend-query: +test-query-service: stage: test-backend needs: - - build-backend-query + - build-query-service script: - "make test-query-service" - "cat ./fda-query-service/report/target/site/jacoco-aggregate/index.html | grep -o 'Total[^%]*%' | sed 's/<.*>/ /; s/Total/Jacoco Coverage Total:/'" @@ -205,11 +207,12 @@ test-backend-query: reports: junit: ./fda-query-service/rest-service/target/surefire-reports/TEST-*.xml coverage: '/Total.*?([0-9]{1,3})%/' + timeout: 2 hour -test-backend-table: +test-table-service: stage: test-backend needs: - - build-backend-table + - build-table-service script: - "make test-table-service" - "cat ./fda-table-service/report/target/site/jacoco-aggregate/index.html | grep -o 'Total[^%]*%' | sed 's/<.*>/ /; s/Total/Jacoco Coverage Total:/'" @@ -223,10 +226,10 @@ test-backend-table: junit: ./fda-table-service/rest-service/target/surefire-reports/TEST-*.xml coverage: '/Total.*?([0-9]{1,3})%/' -test-backend-metadata: +test-metadata-service: stage: test-backend needs: - - build-backend-metadata + - build-metadata-service script: - "make test-metadata-service" - "cat ./fda-metadata-service/report/target/site/jacoco-aggregate/index.html | grep -o 'Total[^%]*%' | sed 's/<.*>/ /; s/Total/Jacoco Coverage Total:/'" @@ -240,10 +243,10 @@ test-backend-metadata: junit: ./fda-metadata-service/rest-service/target/surefire-reports/TEST-*.xml coverage: '/Total.*?([0-9]{1,3})%/' -test-backend-gateway: +test-gateway-service: stage: test-backend needs: - - build-backend-gateway + - build-gateway-service script: - "make test-gateway-service" - "cat ./fda-gateway-service/report/target/site/jacoco-aggregate/index.html | grep -o 'Total[^%]*%' | sed 's/<.*>/ /; s/Total/Jacoco Coverage Total:/'" @@ -289,19 +292,35 @@ test-analyse-service: junit: ./fda-analyse-service/report.xml coverage: '/TOTAL.*?([0-9]{1,3})%/' +test-frontend: + stage: test-frontend + needs: + - build-frontend + script: + - "make test-frontend" + - "cat ./fda-ui/coverage.txt | grep -o 'Lines[^%]*%'" + artifacts: + when: always + paths: + - ./fda-analyse-service/report.xml + expire_in: 1 days + reports: + junit: ./fda-analyse-service/report.xml + coverage: '/TOTAL.*?([0-9]{1,3})%/' + build-docker: stage: build-docker needs: - - build-backend-metadata-db - - build-backend-authentication - - build-backend-identifier - - build-backend-container - - build-backend-database - - build-backend-discovery - - build-backend-gateway - - build-backend-query - - build-backend-table - - build-backend-metadata + - build-metadata-db + - build-authentication-service + - build-identifier-service + - build-container-service + - build-database-service + - build-discovery-service + - build-gateway-service + - build-query-service + - build-table-service + - build-metadata-service - build-semantics-service - build-analyse-service script: diff --git a/.gitlab/jacoco2cobertura.py b/.gitlab/jacoco2cobertura.py deleted file mode 100755 index 76ad75a70583ae4689952ef037ecb241eec48897..0000000000000000000000000000000000000000 --- a/.gitlab/jacoco2cobertura.py +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/env python3 -import sys -import xml.etree.ElementTree as ET -import re -import os.path - -# branch-rate="0.0" complexity="0.0" line-rate="1.0" -# branch="true" hits="1" number="86" - -def find_lines(j_package, filename): - """Return all <line> elements for a given source file in a package.""" - lines = list() - sourcefiles = j_package.findall("sourcefile") - for sourcefile in sourcefiles: - if sourcefile.attrib.get("name") == os.path.basename(filename): - lines = lines + sourcefile.findall("line") - return lines - -def line_is_after(jm, start_line): - return int(jm.attrib.get('line', 0)) > start_line - -def method_lines(jmethod, jmethods, jlines): - """Filter the lines from the given set of jlines that apply to the given jmethod.""" - start_line = int(jmethod.attrib.get('line', 0)) - larger = list(int(jm.attrib.get('line', 0)) for jm in jmethods if line_is_after(jm, start_line)) - end_line = min(larger) if len(larger) else 99999999 - - for jline in jlines: - if start_line <= int(jline.attrib['nr']) < end_line: - yield jline - -def convert_lines(j_lines, into): - """Convert the JaCoCo <line> elements into Cobertura <line> elements, add them under the given element.""" - c_lines = ET.SubElement(into, 'lines') - for jline in j_lines: - mb = int(jline.attrib['mb']) - cb = int(jline.attrib['cb']) - ci = int(jline.attrib['ci']) - - cline = ET.SubElement(c_lines, 'line') - cline.set('number', jline.attrib['nr']) - cline.set('hits', '1' if ci > 0 else '0') # Probably not true but no way to know from JaCoCo XML file - - if mb + cb > 0: - percentage = str(int(100 * (float(cb) / (float(cb) + float(mb))))) + '%' - cline.set('branch', 'true') - cline.set('condition-coverage', percentage + ' (' + str(cb) + '/' + str(cb + mb) + ')') - - cond = ET.SubElement(ET.SubElement(cline, 'conditions'), 'condition') - cond.set('number', '0') - cond.set('type', 'jump') - cond.set('coverage', percentage) - else: - cline.set('branch', 'false') - -def guess_filename(path_to_class): - m = re.match('([^$]*)', path_to_class) - return (m.group(1) if m else path_to_class) + '.java' - -def add_counters(source, target): - target.set('line-rate', counter(source, 'LINE')) - target.set('branch-rate', counter(source, 'BRANCH')) - target.set('complexity', counter(source, 'COMPLEXITY', sum)) - -def fraction(covered, missed): - return covered / (covered + missed) - -def sum(covered, missed): - return covered + missed - -def counter(source, type, operation=fraction): - cs = source.findall('counter') - c = next((ct for ct in cs if ct.attrib.get('type') == type), None) - - if c is not None: - covered = float(c.attrib['covered']) - missed = float(c.attrib['missed']) - - return str(operation(covered, missed)) - else: - return '0.0' - -def convert_method(j_method, j_lines): - c_method = ET.Element('method') - c_method.set('name', j_method.attrib['name']) - c_method.set('signature', j_method.attrib['desc']) - - add_counters(j_method, c_method) - convert_lines(j_lines, c_method) - - return c_method - -def convert_class(j_class, j_package): - c_class = ET.Element('class') - c_class.set('name', j_class.attrib['name'].replace('/', '.')) - c_class.set('filename', guess_filename(j_class.attrib['name'])) - - all_j_lines = list(find_lines(j_package, c_class.attrib['filename'])) - - c_methods = ET.SubElement(c_class, 'methods') - all_j_methods = list(j_class.findall('method')) - for j_method in all_j_methods: - j_method_lines = method_lines(j_method, all_j_methods, all_j_lines) - c_methods.append(convert_method(j_method, j_method_lines)) - - add_counters(j_class, c_class) - convert_lines(all_j_lines, c_class) - - return c_class - -def convert_package(j_package): - c_package = ET.Element('package') - c_package.attrib['name'] = j_package.attrib['name'].replace('/', '.') - - c_classes = ET.SubElement(c_package, 'classes') - for j_class in j_package.findall('class'): - c_classes.append(convert_class(j_class, j_package)) - - add_counters(j_package, c_package) - - return c_package - -def convert_root(source, target, source_roots): - target.set('timestamp', str(int(source.find('sessioninfo').attrib['start']) / 1000)) - - sources = ET.SubElement(target, 'sources') - for s in source_roots: - ET.SubElement(sources, 'source').text = s - - packages = ET.SubElement(target, 'packages') - for package in source.findall('package'): - packages.append(convert_package(package)) - - add_counters(source, target) - -def jacoco2cobertura(filename, source_roots): - if filename == '-': - root = ET.fromstring(sys.stdin.read()) - else: - tree = ET.parse(filename) - root = tree.getroot() - - into = ET.Element('coverage') - convert_root(root, into, source_roots) - print(ET.tostring(into, encoding='utf8', method='xml').decode("utf-8")) - -if __name__ == '__main__': - if len(sys.argv) < 2: - print("Usage: cover2cover.py FILENAME [SOURCE_ROOTS]") - sys.exit(1) - - filename = sys.argv[1] - source_roots = sys.argv[2:] if 2 < len(sys.argv) else '.' - - jacoco2cobertura(filename, source_roots) \ No newline at end of file diff --git a/.gitlab/tests/test_containers.py b/.gitlab/tests/test_containers.py deleted file mode 100644 index dd4e1a97cc9cd2ea9a3ff9740b8720f600e62a35..0000000000000000000000000000000000000000 --- a/.gitlab/tests/test_containers.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/env python3 -from api_container.api.container_endpoint_api import ContainerEndpointApi -from api_database.api.database_endpoint_api import DatabaseEndpointApi -import time - -container = ContainerEndpointApi() -database = DatabaseEndpointApi() - -def create_container(): - response = container.create1({ - "name": "Pilot Factory Data", - "repository": "mariadb", - "tag": "10.5" - }) - print("created container with id %d" % response.id) - return response - - -def start_container(container_id): - response = container.modify({ - "action": "start" - }, container_id) - print("... starting") - time.sleep(5) - print("started container with id %d" % response.id) - return response - - -def create_database(container_id, is_public=True): - response = database.create({ - "name": "Pilot Factory Data", - "is_public": is_public - }, container_id) - print("created database with id %d" % response.id) - return response - -token = "" # keep - -from api_authentication.api.authentication_endpoint_api import AuthenticationEndpointApi -from api_authentication.api.user_endpoint_api import UserEndpointApi -import uuid - -authentication = AuthenticationEndpointApi() -user = UserEndpointApi() - -def create_user(username): - response = user.register({ - "username": username, - "password": username, - "email": username + "@gmail.com" - }) - print("created user with id %d" % response.id) - return response - - -def auth_user(username): - response = authentication.authenticate_user1({ - "username": username, - "password": username - }) - print("authenticated user with id %d" % response.id) - token = response.token - container.api_client.default_headers = {"Authorization": "Bearer " + token} - database.api_client.default_headers = {"Authorization": "Bearer " + token} - return response - - -def find_database(container_id, database_id): - response = database.find_by_id(container_id, database_id) - print("found database with id %d" % response.id) - return response - - -def update_database(container_id, database_id): - response = database.update({ - "description": "This dataset includes daily values from 1983 to the current day, divided into annual files. This includes the maximum hourly average and the number of times the hourly average limit value for ozone was exceeded and the daily averages for sulfur dioxide (SO2), carbon monoxide (CO), nitrogen oxide (NOx), nitrogen monoxide (NO), nitrogen dioxide (NO2), particulate matter (PM10 and PM2.5). ) and particle number (PN), provided that they are of sufficient quality. The values of the completed day for the current year are updated every 30 minutes after midnight (UTC+1).", - "publisher": "Technical University of Vienna", - "license": { - "identifier": "CC0-1.0", - "uri": "https://creativecommons.org/publicdomain/zero/1.0/legalcode" - }, - "language": "en", - "publication_year": 2022 - }, container_id, database_id) - print("updated database with id %d" % response.id) - return response - - -def test_containers(): - username = str(uuid.uuid1()).replace("-", "") - uid = create_user(username).id - auth_user(username) - # container 1 - cid = create_container().id - start_container(cid) - dbid = create_database(cid).id - update_database(cid, dbid) diff --git a/.gitlab/tests/test_query.py b/.gitlab/tests/test_query.py deleted file mode 100644 index 283f311b6554b76393568be0efaf1b44f24077a1..0000000000000000000000000000000000000000 --- a/.gitlab/tests/test_query.py +++ /dev/null @@ -1,284 +0,0 @@ -#!/bin/env python3 - -import time -import os -import shutil -import uuid - -from api_authentication.api.authentication_endpoint_api import AuthenticationEndpointApi -from api_authentication.api.user_endpoint_api import UserEndpointApi -from api_container.api.container_endpoint_api import ContainerEndpointApi -from api_database.api.database_endpoint_api import DatabaseEndpointApi -from api_table.api.table_endpoint_api import TableEndpointApi -from api_query.api.table_data_endpoint_api import TableDataEndpointApi -from api_query.api.query_endpoint_api import QueryEndpointApi -from api_query.api.table_history_endpoint_api import TableHistoryEndpointApi -from api_identifier.api.identifier_endpoint_api import IdentifierEndpointApi -from api_identifier.api.persistence_endpoint_api import PersistenceEndpointApi -from api_query.api.view_endpoint_api import ViewEndpointApi -from api_query.rest import ApiException - -authentication = AuthenticationEndpointApi() -user = UserEndpointApi() -container = ContainerEndpointApi() -database = DatabaseEndpointApi() -table = TableEndpointApi() -query = QueryEndpointApi() -history = TableHistoryEndpointApi() -data = TableDataEndpointApi() -identifier = IdentifierEndpointApi() -persistence = PersistenceEndpointApi() -view = ViewEndpointApi() - -token = "" # keep - - -def create_user(username): - response = user.register({ - "username": username, - "password": username, - "email": username + "@gmail.com" - }) - print("created user with id %d" % response.id) - return response - - -def update_password(user_id, password): - response = user.update_password({ - "password": password - }, user_id) - print("updated password for user with id %d" % user_id) - return response - - -def auth_user(username): - response = authentication.authenticate_user1({ - "username": username, - "password": username - }) - print("authenticated user with id %d" % response.id) - token = response.token - container.api_client.default_headers = {"Authorization": "Bearer " + token} - database.api_client.default_headers = {"Authorization": "Bearer " + token} - table.api_client.default_headers = {"Authorization": "Bearer " + token} - data.api_client.default_headers = {"Authorization": "Bearer " + token} - query.api_client.default_headers = {"Authorization": "Bearer " + token} - identifier.api_client.default_headers = {"Authorization": "Bearer " + token} - user.api_client.default_headers = {"Authorization": "Bearer " + token} - persistence.api_client.default_headers = {"Authorization": "Bearer " + token} - history.api_client.default_headers = {"Authorization": "Bearer " + token} - view.api_client.default_headers = {"Authorization": "Bearer " + token} - return response - - -def create_container(): - response = container.create1({ - "name": "Pilot Factory Data", - "repository": "mariadb", - "tag": "10.5" - }) - print("created container with id %d" % response.id) - return response - - -def start_container(container_id): - response = container.modify({ - "action": "start" - }, container_id) - print("... starting") - time.sleep(5) - print("started container with id %d" % response.id) - return response - - -def create_database(container_id, is_public=True): - response = database.create({ - "name": "Pilot Factory Data", - "is_public": is_public - }, container_id) - print("created database with id %d" % response.id) - return response - - -def find_database(container_id, database_id): - response = database.find_by_id(container_id, database_id) - print("found database with id %d" % response.id) - return response - - -def update_database(container_id, database_id): - response = database.update({ - "description": "This dataset includes daily values from 1983 to the current day, divided into annual files. This includes the maximum hourly average and the number of times the hourly average limit value for ozone was exceeded and the daily averages for sulfur dioxide (SO2), carbon monoxide (CO), nitrogen oxide (NOx), nitrogen monoxide (NO), nitrogen dioxide (NO2), particulate matter (PM10 and PM2.5). ) and particle number (PN), provided that they are of sufficient quality. The values of the completed day for the current year are updated every 30 minutes after midnight (UTC+1).", - "publisher": "Technical University of Vienna", - "license": { - "identifier": "CC0-1.0", - "uri": "https://creativecommons.org/publicdomain/zero/1.0/legalcode" - }, - "language": "en", - "publication_year": 2022 - }, container_id, database_id) - print("updated database with id %d" % response.id) - return response - - -def create_table(container_id, database_id, columns=None): - if columns is None: - columns = [{ - "name": "Date", - "type": "date", - "dfid": 1, - "unique": False, - "primary_key": False, - "null_allowed": True, - }, { - "name": "Location", - "type": "string", - "unique": False, - "primary_key": False, - "null_allowed": True, - }, { - "name": "Parameter", - "type": "string", - "unique": False, - "primary_key": False, - "null_allowed": True, - }, { - "name": "Interval", - "type": "string", - "unique": False, - "primary_key": False, - "null_allowed": True, - }, { - "name": "Unit", - "type": "string", - "unique": False, - "primary_key": False, - "null_allowed": True, - }, { - "name": "Value", - "type": "decimal", - "unique": False, - "primary_key": False, - "null_allowed": True, - }, { - "name": "Status", - "type": "string", - "unique": False, - "primary_key": False, - "null_allowed": True, - }] - response = table.create({ - "name": "Airquality " + str(uuid.uuid1()), - "description": "Airquality in Zürich, Switzerland", - "columns": columns - }, "Bearer " + token, container_id, database_id) - print("created table with id %d" % response.id) - return response - - -def find_table(container_id, database_id, table_id): - response = table.find_by_id(container_id, database_id, table_id) - print("found table with id %d" % response.id) - return response - - -def fill_table(container_id, database_id, table_id): - response = data.import_csv({ - "location": "/path/to/data.csv", - "quote": "\"", - "null_element": "NA" - "separator": ",", - }, container_id, database_id, table_id) - print("filled table with id %d" % table_id) - return response - - -def create_query(container_id, database_id, statement, page=0, size=3): - response = query.execute({ - "statement": statement - }, container_id, database_id, page=page, size=size) - print("executed query with id %d" % response.id) - return response - - -def delete_tuple(container_id, database_id, table_id, keys): - response = data.delete(keys, container_id, database_id, table_id) - print("deleted tuples for table with id %d" % table_id) - return response - - -def download_query_data(container_id, database_id, query_id): - response = query.export1(container_id, database_id, query_id) - print("downloaded query data for query with id %d" % query_id) - return response - - -def list_views(container_id, database_id): - response = view.find_all(container_id, database_id) - print("list views for database with id %d" % database_id) - return response - - -def create_view(container_id, database_id, table_name): - response = view.create({ - "name": "Air Quality " + str(uuid.uuid1()), - "query": "SELECT `date`, `parameter`, `value` FROM `" + table_name + "` WHERE `date` = '2021-10-02T14:00'", - "is_public": True - }, container_id, database_id) - print("created view with id %d" % response.id) - return response - - -def data_view(container_id, database_id, view_id): - response = view.data(container_id, database_id, view_id) - print("retrieved data for view with id %d" % response.id) - return response - - -def test_identifiers(): - # - # create 1 user and 2 containers (public, private) - # - username = str(uuid.uuid1()).replace("-", "") - uid = create_user(username).id - auth_user(username) - # container 1 - cid = create_container().id - start_container(cid) - dbid = create_database(cid).id - update_database(cid, dbid) - tid = create_table(cid, dbid).id - tname = find_table(cid, dbid, tid).internal_name - fill_table(cid, dbid, tid) - create_query(cid, dbid, "select `id` from `" + tname + "`") - create_query(cid, dbid, "select `date` from `" + tname + "`") - qid = create_query(cid, dbid, "select `date`, `location`, `status` from `" + tname + "`").id - create_query(cid, dbid, "select `date`, `location`, `status` from `" + tname + "` order by `date` asc") - create_query(cid, dbid, "select t.`date`, t.location, t.status from `" + tname + "` t group by t.`date` order by t.`date` asc") - create_query(cid, dbid, "select `date`, `location`, `status` from `" + tname + "` group by `date`, `location` asc") - download_query_data(cid, dbid, qid) - # container 2 (=private) - cid = create_container().id - start_container(cid) - dbid = create_database(cid, False).id - update_database(cid, dbid) - tid = create_table(cid, dbid).id - tname = find_table(cid, dbid, tid).internal_name - fill_table(cid, dbid, tid) - qid = create_query(cid, dbid, "select `id` from `" + tname + "`").id - qid = create_query(cid, dbid, "select `id` from `" + tname + "`").id - vid = create_view(cid, dbid, tname).id - data_view(cid, dbid, vid) - list_views(cid, dbid) - for i in range(5, 10): - delete_tuple(cid, dbid, tid, { - "keys": { - "id": i - } - }) - time.sleep(1) - delete_tuple(cid, dbid, tid, { - "keys": { - "location": "Schimmelstrasse" - } - }) diff --git a/.junit/hosts b/.junit/hosts new file mode 100644 index 0000000000000000000000000000000000000000..701ef56fa315ea16163432c842816c946150d97f --- /dev/null +++ b/.junit/hosts @@ -0,0 +1,10 @@ +########################################################### +# PLACE IN /etc/hosts # +########################################################### + +172.30.0.5 dbrepo-userdb-u01 +172.30.0.6 dbrepo-userdb-u02 +172.30.0.7 dbrepo-userdb-u03 +172.30.0.8 dbrepo-userdb-u04 +172.31.0.2 dbrepo-broker-service +172.31.0.3 dbrepo-search-service \ No newline at end of file diff --git a/.dbrepo2/teardown b/.junit/teardown similarity index 100% rename from .dbrepo2/teardown rename to .junit/teardown diff --git a/Makefile b/Makefile index ec1921ff29552a4a0bd432d26a0c4708a4f15c36..a5bce8de2e48b1547e456f13be75256590b415c9 100644 --- a/Makefile +++ b/Makefile @@ -4,39 +4,36 @@ TAG ?= latest all: -clean: - bash ./.dbrepo2/clean.sh - -build-backend: build-backend-metadata-db build-backend-database build-backend-query build-backend-table build-backend-identifier build-backend-authentication build-backend-container build-backend-discovery build-backend-gateway build-backend-metadata build-analyse-service +build-backend: build-metadata-db build-database-service build-query-service build-table-service build-identifier-service build-authentication-service build-container-service build-discovery-service build-gateway-service build-metadata-service build-analyse-service -build-backend-metadata-db: +build-metadata-db: mvn -f ./fda-metadata-db/pom.xml clean install -build-backend-authentication: build-backend-metadata-db +build-authentication-service: build-metadata-db mvn -f ./fda-authentication-service/pom.xml clean package -DskipTests -build-backend-identifier: build-backend-metadata-db +build-identifier-service: build-metadata-db mvn -f ./fda-identifier-service/pom.xml clean package -DskipTests -build-backend-table: build-backend-metadata-db +build-table-service: build-metadata-db mvn -f ./fda-table-service/pom.xml clean package -DskipTests -build-backend-container: build-backend-metadata-db +build-container-service: build-metadata-db mvn -f ./fda-container-service/pom.xml clean package -DskipTests -build-backend-database: build-backend-metadata-db +build-database-service: build-metadata-db mvn -f ./fda-database-service/pom.xml clean package -DskipTests -build-backend-discovery: build-backend-metadata-db +build-discovery-service: build-metadata-db mvn -f ./fda-discovery-service/pom.xml clean package -DskipTests -build-backend-gateway: build-backend-metadata-db +build-gateway-service: build-metadata-db mvn -f ./fda-gateway-service/pom.xml clean package -DskipTests -build-backend-query: build-backend-metadata-db +build-query-service: build-metadata-db mvn -f ./fda-query-service/pom.xml clean package -DskipTests -build-backend-metadata: build-backend-metadata-db +build-metadata-service: build-metadata-db mvn -f ./fda-metadata-service/pom.xml clean package -DskipTests build-semantics-service: @@ -150,93 +147,35 @@ release-search: release-metadata: docker push "dbrepo/metadata-service:${TAG}" -pull: pull-identifier pull-container pull-search pull-database pull-discovery pull-gateway pull-query pull-table pull-analyse pull-authentication pull-metadata-db pull-ui pull-units pull-broker pull-metadata - -pull-analyse: - docker pull "dbrepo/analyse-service:${TAG}" - -pull-authentication: - docker pull "dbrepo/authentication-service:${TAG}" - -pull-metadata-db: - docker pull "dbrepo/metadata-db:${TAG}" - -pull-ui: - docker pull "dbrepo/ui:${TAG}" - -pull-identifier: - docker pull "dbrepo/identifier-service:${TAG}" - -pull-container: - docker pull "dbrepo/container-service:${TAG}" - -pull-database: - docker pull "dbrepo/database-service:${TAG}" - -pull-discovery: - docker pull "dbrepo/discovery-service:${TAG}" - -pull-gateway: - docker pull "dbrepo/gateway-service:${TAG}" - -pull-query: - docker pull "dbrepo/query-service:${TAG}" - -pull-table: - docker pull "dbrepo/table-service:${TAG}" - -pull-units: - docker pull "dbrepo/semantics-service:${TAG}" - -pull-broker: - docker pull "dbrepo/broker-service:${TAG}" - -pull-metadata: - docker pull "dbrepo/metadata-service:${TAG}" - -pull-search: - docker pull "dbrepo/search-service:${TAG}" - test-backend: test-authentication-service test-container-service test-database-service test-discovery-service test-gateway-service test-query-service test-table-service test-identifier-service test-metadata-service test-semantics-service test-analyse-service -test-authentication-service: build-backend-metadata-db build-backend-authentication - docker system prune -f --volumes +test-authentication-service: clean build-metadata-db build-authentication-service docker pull rabbitmq:3-management-alpine mvn -f ./fda-authentication-service/pom.xml clean test verify -test-identifier-service: build-backend-metadata-db build-backend-identifier - docker system prune -f --volumes +test-identifier-service: clean build-metadata-db build-identifier-service mvn -f ./fda-identifier-service/pom.xml clean test verify -test-container-service: build-backend-metadata-db build-backend-container - docker system prune -f --volumes - docker pull mysql:8.0 +test-container-service: clean build-metadata-db build-container-service mvn -f ./fda-container-service/pom.xml clean test verify -test-database-service: build-backend-metadata-db build-backend-database - docker system prune -f --volumes +test-database-service: clean build-metadata-db build-database-service docker pull rabbitmq:3-management-alpine - docker pull nginx:alpine mvn -f ./fda-database-service/pom.xml clean test verify -test-discovery-service: build-backend-metadata-db build-backend-discovery - docker system prune -f --volumes +test-discovery-service: clean build-metadata-db build-discovery-service mvn -f ./fda-discovery-service/pom.xml clean test verify -test-gateway-service: build-backend-metadata-db build-backend-gateway - docker system prune -f --volumes +test-gateway-service: clean build-metadata-db build-gateway-service mvn -f ./fda-gateway-service/pom.xml clean test verify -test-query-service: build-backend-metadata-db build-backend-query - docker system prune -f --volumes +test-query-service: clean build-metadata-db build-query-service mvn -f ./fda-query-service/pom.xml clean test verify -test-table-service: build-backend-metadata-db build-backend-table - docker system prune -f --volumes +test-table-service: clean build-metadata-db build-table-service mvn -f ./fda-table-service/pom.xml clean test verify -test-metadata-service: build-backend-metadata-db build-backend-metadata - docker system prune -f --volumes +test-metadata-service: clean build-metadata-db build-metadata-service mvn -f ./fda-metadata-service/pom.xml clean test verify test-semantics-service: build-semantics-service @@ -245,13 +184,16 @@ test-semantics-service: build-semantics-service test-analyse-service: build-analyse-service bash ./fda-analyse-service/test.sh -coverage-frontend: clean build-frontend +coverage-frontend: build-frontend yarn --cwd ./fda-ui run coverage || true test-frontend: clean build-frontend yarn --cwd ./fda-ui install - docker compose up -d - yarn --cwd ./fda-ui run test + yarn --cwd ./fda-ui run test:unit || true + yarn --cwd ./fda-ui run coverage || true + +clean: + docker system prune -f --volumes test-clients: bash ./.gitlab/test.sh @@ -259,4 +201,4 @@ test-clients: test: test-backend test-frontend teardown: - ./.dbrepo2/teardown + ./.junit/teardown diff --git a/docker-compose.dbrepo1.yml b/docker-compose.dbrepo1.yml index dfd09f5097236500634958c7072211892968336c..01db36561d40b6d328fade93b271caa6666d750d 100644 --- a/docker-compose.dbrepo1.yml +++ b/docker-compose.dbrepo1.yml @@ -31,7 +31,7 @@ networks: services: - metadata-db: + dbrepo-metadata-db: restart: on-failure container_name: dbrepo-metadata-db hostname: metadata-db @@ -60,7 +60,7 @@ services: logging: driver: json-file - gateway-service: + dbrepo-gateway-service: restart: on-failure container_name: dbrepo-gateway-service hostname: gateway-service @@ -72,12 +72,12 @@ services: env_file: - .env depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy logging: driver: json-file - database-service: + dbrepo-database-service: restart: on-failure container_name: dbrepo-database-service hostname: database-service @@ -90,16 +90,16 @@ services: volumes: - /var/run/docker.sock:/var/run/docker.sock depends_on: - container-service: + dbrepo-container-service: condition: service_healthy - broker-service: + dbrepo-broker-service: condition: service_started - authentication-service: + dbrepo-authentication-service: condition: service_healthy logging: driver: json-file - container-service: + dbrepo-container-service: restart: on-failure container_name: dbrepo-container-service hostname: container-service @@ -111,12 +111,12 @@ services: volumes: - /var/run/docker.sock:/var/run/docker.sock depends_on: - authentication-service: + dbrepo-authentication-service: condition: service_healthy logging: driver: json-file - authentication-service: + dbrepo-authentication-service: restart: on-failure container_name: dbrepo-authentication-service hostname: authentication-service @@ -126,16 +126,16 @@ services: env_file: - .env depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy - broker-service: + dbrepo-broker-service: condition: service_started - metadata-db: + dbrepo-metadata-db: condition: service_healthy logging: driver: json-file - query-service: + dbrepo-query-service: restart: on-failure container_name: dbrepo-query-service hostname: query-service @@ -148,14 +148,14 @@ services: volumes: - ${SHARED_FILESYSTEM}:/tmp depends_on: - table-service: + dbrepo-table-service: condition: service_healthy - authentication-service: + dbrepo-authentication-service: condition: service_healthy logging: driver: json-file - table-service: + dbrepo-table-service: restart: on-failure container_name: dbrepo-table-service hostname: table-service @@ -169,16 +169,16 @@ services: - /var/run/docker.sock:/var/run/docker.sock - ${SHARED_FILESYSTEM}:/tmp depends_on: - authentication-service: + dbrepo-authentication-service: condition: service_healthy - search-service: + dbrepo-search-service: condition: service_started - broker-service: + dbrepo-broker-service: condition: service_started logging: driver: json-file - identifier-service: + dbrepo-identifier-service: restart: on-failure container_name: dbrepo-identifier-service hostname: identifier-service @@ -188,16 +188,16 @@ services: env_file: - .env depends_on: - query-service: + dbrepo-query-service: condition: service_healthy - authentication-service: + dbrepo-authentication-service: condition: service_healthy volumes: - ${SHARED_FILESYSTEM}:/tmp logging: driver: json-file - fda-metadata-service: + dbrepo-metadata-service: restart: on-failure container_name: dbrepo-metadata-service hostname: metadata-service @@ -207,12 +207,12 @@ services: env_file: - .env depends_on: - metadata-db: + dbrepo-metadata-db: condition: service_started logging: driver: json-file - analyse-service: + dbrepo-analyse-service: restart: on-failure container_name: dbrepo-analyse-service hostname: analyse-service @@ -226,12 +226,12 @@ services: - ${SHARED_FILESYSTEM}:/tmp - /var/run/docker.sock:/var/run/docker.sock depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy logging: driver: json-file - semantics-service: + dbrepo-semantics-service: restart: on-failure container_name: dbrepo-semantics-service hostname: semantics-service @@ -244,14 +244,14 @@ services: - ${SHARED_FILESYSTEM}:/tmp - /var/run/docker.sock:/var/run/docker.sock depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy - metadata-db: + dbrepo-metadata-db: condition: service_healthy logging: driver: json-file - broker-service: + dbrepo-broker-service: restart: on-failure container_name: dbrepo-broker-service hostname: broker-service @@ -264,14 +264,14 @@ services: env_file: - .env depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy volumes: - broker-service-data:/var/lib/rabbitmq/ logging: driver: json-file - search-service: + dbrepo-search-service: restart: always container_name: dbrepo-search-service hostname: search-service @@ -279,7 +279,7 @@ services: networks: core: depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy ports: - 9200:9200 @@ -290,7 +290,7 @@ services: logging: driver: json-file - ui: + dbrepo-ui: restart: on-failure container_name: dbrepo-ui hostname: ui @@ -303,9 +303,9 @@ services: volumes: - ${SHARED_FILESYSTEM}:/tmp depends_on: - identifier-service: + dbrepo-identifier-service: condition: service_healthy - database-service: + dbrepo-database-service: condition: service_healthy logging: driver: json-file diff --git a/docker-compose.dbrepo2.yml b/docker-compose.dbrepo2.yml index dbd34f265e1c072684a60209978b9304a1b04fd4..7c169dd1cecfd8f1c9674ea6fb5c1be5a738c07c 100644 --- a/docker-compose.dbrepo2.yml +++ b/docker-compose.dbrepo2.yml @@ -31,7 +31,7 @@ networks: services: - metadata-db: + dbrepo-metadata-db: restart: on-failure container_name: dbrepo-metadata-db hostname: metadata-db @@ -48,7 +48,7 @@ services: logging: driver: json-file - discovery-service: + dbrepo-discovery-service: restart: on-failure container_name: dbrepo-discovery-service hostname: discovery-service @@ -60,7 +60,7 @@ services: logging: driver: json-file - gateway-service: + dbrepo-gateway-service: restart: on-failure container_name: dbrepo-gateway-service hostname: gateway-service @@ -72,12 +72,12 @@ services: env_file: - .env depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy logging: driver: json-file - database-service: + dbrepo-database-service: restart: on-failure container_name: dbrepo-database-service hostname: database-service @@ -90,16 +90,16 @@ services: volumes: - /var/run/docker.sock:/var/run/docker.sock depends_on: - container-service: + dbrepo-container-service: condition: service_healthy - broker-service: + dbrepo-broker-service: condition: service_started - authentication-service: + dbrepo-authentication-service: condition: service_healthy logging: driver: json-file - container-service: + dbrepo-container-service: restart: on-failure container_name: dbrepo-container-service hostname: container-service @@ -111,12 +111,12 @@ services: volumes: - /var/run/docker.sock:/var/run/docker.sock depends_on: - authentication-service: + dbrepo-authentication-service: condition: service_healthy logging: driver: json-file - authentication-service: + dbrepo-authentication-service: restart: on-failure container_name: dbrepo-authentication-service hostname: authentication-service @@ -126,16 +126,16 @@ services: env_file: - .env depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy - broker-service: + dbrepo-broker-service: condition: service_started - metadata-db: + dbrepo-metadata-db: condition: service_healthy logging: driver: json-file - query-service: + dbrepo-query-service: restart: on-failure container_name: dbrepo-query-service hostname: query-service @@ -148,14 +148,14 @@ services: volumes: - ${SHARED_FILESYSTEM}:/tmp depends_on: - table-service: + dbrepo-table-service: condition: service_healthy - authentication-service: + dbrepo-authentication-service: condition: service_healthy logging: driver: json-file - table-service: + dbrepo-table-service: restart: on-failure container_name: dbrepo-table-service hostname: table-service @@ -169,16 +169,16 @@ services: - /var/run/docker.sock:/var/run/docker.sock - ${SHARED_FILESYSTEM}:/tmp depends_on: - authentication-service: + dbrepo-authentication-service: condition: service_healthy - search-service: + dbrepo-search-service: condition: service_started - broker-service: + dbrepo-broker-service: condition: service_started logging: driver: json-file - identifier-service: + dbrepo-identifier-service: restart: on-failure container_name: dbrepo-identifier-service hostname: identifier-service @@ -188,16 +188,16 @@ services: env_file: - .env depends_on: - query-service: + dbrepo-query-service: condition: service_healthy - authentication-service: + dbrepo-authentication-service: condition: service_healthy volumes: - ${SHARED_FILESYSTEM}:/tmp logging: driver: json-file - metadata-service: + dbrepo-metadata-service: restart: on-failure container_name: dbrepo-metadata-service hostname: metadata-service @@ -207,12 +207,12 @@ services: env_file: - .env depends_on: - metadata-db: + dbrepo-metadata-db: condition: service_started logging: driver: json-file - analyse-service: + dbrepo-analyse-service: restart: on-failure container_name: dbrepo-analyse-service hostname: analyse-service @@ -226,12 +226,12 @@ services: - ${SHARED_FILESYSTEM}:/tmp - /var/run/docker.sock:/var/run/docker.sock depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy logging: driver: json-file - semantics-service: + dbrepo-semantics-service: restart: on-failure container_name: dbrepo-semantics-service hostname: semantics-service @@ -244,14 +244,14 @@ services: - ${SHARED_FILESYSTEM}:/tmp - /var/run/docker.sock:/var/run/docker.sock depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy - metadata-db: + dbrepo-metadata-db: condition: service_healthy logging: driver: json-file - broker-service: + dbrepo-broker-service: restart: on-failure container_name: dbrepo-broker-service hostname: broker-service @@ -264,14 +264,14 @@ services: env_file: - .env depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy volumes: - broker-service-data:/var/lib/rabbitmq/ logging: driver: json-file - search-service: + dbrepo-search-service: restart: always container_name: dbrepo-search-service hostname: search-service @@ -279,7 +279,7 @@ services: networks: core: depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy env_file: - .env @@ -288,7 +288,7 @@ services: logging: driver: json-file - ui: + dbrepo-ui: restart: on-failure container_name: dbrepo-ui hostname: ui @@ -301,9 +301,9 @@ services: volumes: - ${SHARED_FILESYSTEM}:/tmp depends_on: - identifier-service: + dbrepo-identifier-service: condition: service_healthy - database-service: + dbrepo-database-service: condition: service_healthy logging: driver: json-file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 78fc30f91141e52b6d647c1e901aba2e987e7ca6..8984baecab55922994fb89672234edc276ec221e 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -31,7 +31,7 @@ networks: services: - metadata-db: + dbrepo-metadata-db: restart: on-failure container_name: dbrepo-metadata-db hostname: metadata-db @@ -48,7 +48,7 @@ services: logging: driver: json-file - discovery-service: + dbrepo-discovery-service: restart: on-failure container_name: dbrepo-discovery-service hostname: discovery-service @@ -60,7 +60,7 @@ services: logging: driver: json-file - gateway-service: + dbrepo-gateway-service: restart: on-failure container_name: dbrepo-gateway-service hostname: gateway-service @@ -72,12 +72,12 @@ services: env_file: - .env depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy logging: driver: json-file - database-service: + dbrepo-database-service: restart: on-failure container_name: dbrepo-database-service hostname: database-service @@ -90,16 +90,16 @@ services: volumes: - /var/run/docker.sock:/var/run/docker.sock depends_on: - container-service: + dbrepo-container-service: condition: service_healthy - broker-service: + dbrepo-broker-service: condition: service_started - authentication-service: + dbrepo-authentication-service: condition: service_healthy logging: driver: json-file - container-service: + dbrepo-container-service: restart: on-failure container_name: dbrepo-container-service hostname: container-service @@ -111,12 +111,12 @@ services: volumes: - /var/run/docker.sock:/var/run/docker.sock depends_on: - authentication-service: + dbrepo-authentication-service: condition: service_healthy logging: driver: json-file - authentication-service: + dbrepo-authentication-service: restart: on-failure container_name: dbrepo-authentication-service hostname: authentication-service @@ -126,16 +126,16 @@ services: env_file: - .env depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy - broker-service: + dbrepo-broker-service: condition: service_started - metadata-db: + dbrepo-metadata-db: condition: service_healthy logging: driver: json-file - query-service: + dbrepo-query-service: restart: on-failure container_name: dbrepo-query-service hostname: query-service @@ -148,14 +148,14 @@ services: volumes: - ${SHARED_FILESYSTEM}:/tmp depends_on: - table-service: + dbrepo-table-service: condition: service_healthy - authentication-service: + dbrepo-authentication-service: condition: service_healthy logging: driver: json-file - table-service: + dbrepo-table-service: restart: on-failure container_name: dbrepo-table-service hostname: table-service @@ -169,16 +169,16 @@ services: - /var/run/docker.sock:/var/run/docker.sock - ${SHARED_FILESYSTEM}:/tmp depends_on: - authentication-service: + dbrepo-authentication-service: condition: service_healthy - search-service: + dbrepo-search-service: condition: service_started - broker-service: + dbrepo-broker-service: condition: service_started logging: driver: json-file - identifier-service: + dbrepo-identifier-service: restart: on-failure container_name: dbrepo-identifier-service hostname: identifier-service @@ -188,16 +188,16 @@ services: env_file: - .env depends_on: - query-service: + dbrepo-query-service: condition: service_healthy - authentication-service: + dbrepo-authentication-service: condition: service_healthy volumes: - ${SHARED_FILESYSTEM}:/tmp logging: driver: json-file - metadata-service: + dbrepo-metadata-service: restart: on-failure container_name: dbrepo-metadata-service hostname: metadata-service @@ -207,12 +207,12 @@ services: env_file: - .env depends_on: - metadata-db: + dbrepo-metadata-db: condition: service_started logging: driver: json-file - analyse-service: + dbrepo-analyse-service: restart: on-failure container_name: dbrepo-analyse-service hostname: analyse-service @@ -226,12 +226,12 @@ services: - ${SHARED_FILESYSTEM}:/tmp - /var/run/docker.sock:/var/run/docker.sock depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy logging: driver: json-file - semantics-service: + dbrepo-semantics-service: restart: on-failure container_name: dbrepo-semantics-service hostname: semantics-service @@ -244,14 +244,14 @@ services: - ${SHARED_FILESYSTEM}:/tmp - /var/run/docker.sock:/var/run/docker.sock depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy - metadata-db: + dbrepo-metadata-db: condition: service_healthy logging: driver: json-file - broker-service: + dbrepo-broker-service: restart: on-failure container_name: dbrepo-broker-service hostname: broker-service @@ -263,14 +263,14 @@ services: env_file: - .env depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy volumes: - broker-service-data:/var/lib/rabbitmq/ logging: driver: json-file - search-service: + dbrepo-search-service: restart: always container_name: dbrepo-search-service hostname: search-service @@ -278,7 +278,7 @@ services: networks: core: depends_on: - discovery-service: + dbrepo-discovery-service: condition: service_healthy env_file: - .env @@ -287,7 +287,7 @@ services: logging: driver: json-file - ui: + dbrepo-ui: restart: on-failure container_name: dbrepo-ui hostname: ui @@ -302,9 +302,9 @@ services: volumes: - ${SHARED_FILESYSTEM}:/tmp depends_on: - identifier-service: + dbrepo-identifier-service: condition: service_healthy - database-service: + dbrepo-database-service: condition: service_healthy logging: driver: json-file diff --git a/docker-compose.yml b/docker-compose.yml index fd864bd166bfed2443e866de714ba9c4ce269c49..955a59d41ca1896c6915aaf8aa4cf3916567f141 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,27 +10,26 @@ volumes: broker-service-data: networks: - public: - name: public + userdb: + name: userdb driver: bridge ipam: config: - - subnet: 172.29.0.0/16 - userdb: - name: userdb + - subnet: 172.30.0.0/16 + public: + name: public driver: bridge ipam: config: - - subnet: 172.28.0.0/16 + - subnet: 172.31.0.0/16 core: name: core driver: bridge ipam: config: - - subnet: 172.27.0.0/16 + - subnet: 172.32.0.0/16 services: - fda-metadata-db: restart: on-failure container_name: dbrepo-metadata-db diff --git a/fda-authentication-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java b/fda-authentication-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java index be355787b98d46890355f5ddabf7fe1e5c38a86e..c6c927f9b93472b3f544dfae2544ce024375bfb7 100644 --- a/fda-authentication-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java +++ b/fda-authentication-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java @@ -294,7 +294,7 @@ public abstract class BaseUnitTest { public final static Long CONTAINER_BROKER_ID = 1L; public final static String CONTAINER_BROKER_NAME = "broker-service"; public final static String CONTAINER_BROKER_INTERNAL_NAME = "broker-service"; - public final static String CONTAINER_BROKER_IP = "172.29.0.2"; + public final static String CONTAINER_BROKER_IP = "172.31.0.2"; public final static Container CONTAINER_BROKER = Container.builder() .id(CONTAINER_BROKER_ID) diff --git a/fda-authentication-service/rest-service/src/test/java/at/tuwien/config/DockerConfig.java b/fda-authentication-service/rest-service/src/test/java/at/tuwien/config/DockerConfig.java index fc15443f9e2a8843a187ccebba2e57a75be38546..37b2ca7d1b18fb9dacc025176e9967fc3c990021 100644 --- a/fda-authentication-service/rest-service/src/test/java/at/tuwien/config/DockerConfig.java +++ b/fda-authentication-service/rest-service/src/test/java/at/tuwien/config/DockerConfig.java @@ -4,7 +4,9 @@ import at.tuwien.entities.container.Container; import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.exception.NotModifiedException; import com.github.dockerjava.api.model.HostConfig; +import com.github.dockerjava.api.model.Network; import com.github.dockerjava.api.model.RestartPolicy; import com.github.dockerjava.core.DefaultDockerClientConfig; import com.github.dockerjava.core.DockerClientBuilder; @@ -13,6 +15,7 @@ import com.github.dockerjava.httpclient5.ApacheDockerHttpClient; import com.github.dockerjava.transport.DockerHttpClient; import lombok.extern.log4j.Log4j2; +import java.util.Arrays; import java.util.Objects; @Log4j2 @@ -56,7 +59,7 @@ public class DockerConfig { final CreateContainerResponse response = dockerClient.createContainerCmd(container.getImage().getRepository() + ":" + container.getImage().getTag()) .withHostConfig(hostConfig.withNetworkMode("fda-userdb")) .withName(container.getInternalName()) - .withIpv4Address("172.28.0.5") + .withIpv4Address("172.30.0.5") .withHostName(container.getInternalName()) .withEnv("MARIADB_USER=mariadb", "MARIADB_PASSWORD=mariadb", "MARIADB_ROOT_PASSWORD=mariadb", "MARIADB_DATABASE=weather") .exec(); @@ -86,4 +89,59 @@ public class DockerConfig { log.debug("container {} was removed", container.getHash()); } + public static void removeAllContainers() { + dockerClient.listContainersCmd() + .withShowAll(true) + .exec() + .forEach(container -> { + log.info("Delete container {}", Arrays.asList(container.getNames())); + try { + dockerClient.stopContainerCmd(container.getId()).exec(); + } catch (NotModifiedException e) { + // ignore + } + dockerClient.removeContainerCmd(container.getId()).exec(); + }); + dockerClient.listVolumesCmd() + .withDanglingFilter(true) + .exec() + .getVolumes() + .forEach(volume -> { + log.info("Delete volume {}", volume.getName()); + try { + dockerClient.removeVolumeCmd(volume.getName()).exec(); + } catch (NotModifiedException e) { + // ignore + } + }); + } + + public static void removeAllNetworks() { + dockerClient.listNetworksCmd() + .exec() + .stream() + .filter(n -> n.getName().startsWith("fda")) + .forEach(network -> { + log.info("Delete network {}", network.getName()); + dockerClient.removeNetworkCmd(network.getId()).exec(); + }); + } + + public static void createAllNetworks() { + dockerClient.createNetworkCmd() + .withName("fda-userdb") + .withIpam(new Network.Ipam() + .withConfig(new Network.Ipam.Config() + .withSubnet("172.30.0.0/16"))) + .withEnableIpv6(false) + .exec(); + dockerClient.createNetworkCmd() + .withName("fda-public") + .withIpam(new Network.Ipam() + .withConfig(new Network.Ipam.Config() + .withSubnet("172.31.0.0/16"))) + .withEnableIpv6(false) + .exec(); + } + } diff --git a/fda-authentication-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java b/fda-authentication-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java index f887b5a86cc45732941fdfa2491c734eb6d8e55c..ba84081446b1d902dad583a0b2c0602a55684ceb 100644 --- a/fda-authentication-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java +++ b/fda-authentication-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java @@ -2,6 +2,7 @@ package at.tuwien.service; import at.tuwien.BaseUnitTest; import at.tuwien.api.amqp.CreateUserDto; +import at.tuwien.config.DockerConfig; import at.tuwien.config.RabbitMqConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.dto.AmqpUserBriefDto; @@ -13,9 +14,7 @@ import com.github.dockerjava.api.exception.NotModifiedException; import com.github.dockerjava.api.model.Network; import com.github.dockerjava.api.model.PortBinding; import lombok.extern.log4j.Log4j2; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -56,24 +55,16 @@ public class QueueServiceIntegrationTest extends BaseUnitTest { @Autowired private RabbitMqConfig amqpConfig; + @BeforeAll + public static void beforeAll() { + afterAll(); + DockerConfig.createAllNetworks(); + } + @BeforeEach public void beforeEach() throws InterruptedException { afterEach(); - /* create networks */ - dockerClient.createNetworkCmd() - .withName("fda-userdb") - .withIpam(new Network.Ipam() - .withConfig(new Network.Ipam.Config() - .withSubnet("172.28.0.0/16"))) - .withEnableIpv6(false) - .exec(); - dockerClient.createNetworkCmd() - .withName("fda-public") - .withIpam(new Network.Ipam() - .withConfig(new Network.Ipam.Config() - .withSubnet("172.29.0.0/16"))) - .withEnableIpv6(false) - .exec(); + DockerConfig.createAllNetworks(); /* create container */ final PortBinding binding = PortBinding.parse("15672:15672"); final CreateContainerResponse response1 = dockerClient.createContainerCmd(IMAGE_BROKER_IMAGE + ":" + IMAGE_BROKER_TAG) @@ -92,28 +83,14 @@ public class QueueServiceIntegrationTest extends BaseUnitTest { @AfterEach public void afterEach() { - /* stop containers and remove them */ - dockerClient.listContainersCmd() - .withShowAll(true) - .exec() - .forEach(container -> { - log.info("Delete container {}", Arrays.asList(container.getNames())); - try { - dockerClient.stopContainerCmd(container.getId()).exec(); - } catch (NotModifiedException e) { - // ignore - } - dockerClient.removeContainerCmd(container.getId()).exec(); - }); - /* remove networks */ - dockerClient.listNetworksCmd() - .exec() - .stream() - .filter(n -> n.getName().startsWith("fda")) - .forEach(network -> { - log.info("Delete network {}", network.getName()); - dockerClient.removeNetworkCmd(network.getId()).exec(); - }); + DockerConfig.removeAllContainers(); + DockerConfig.removeAllNetworks(); + } + + @AfterAll + public static void afterAll() { + DockerConfig.removeAllContainers(); + DockerConfig.removeAllNetworks(); } @Test diff --git a/fda-authentication-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java b/fda-authentication-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java index 371ed3450a01c2f2c1803e69797e88e56f87dbc1..c72d988189d61e44b59a33015effb1a69789c94a 100644 --- a/fda-authentication-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java +++ b/fda-authentication-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java @@ -6,6 +6,7 @@ import at.tuwien.api.user.RoleTypeDto; import at.tuwien.api.user.UserPasswordDto; import at.tuwien.api.user.UserRolesDto; import at.tuwien.config.AuthenticationConfig; +import at.tuwien.config.DockerConfig; import at.tuwien.config.RabbitMqConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.entities.user.RoleType; @@ -14,8 +15,6 @@ import at.tuwien.exception.*; import at.tuwien.repositories.ImageRepository; import at.tuwien.repositories.UserRepository; import com.github.dockerjava.api.command.CreateContainerResponse; -import com.github.dockerjava.api.exception.NotModifiedException; -import com.github.dockerjava.api.model.Network; import com.github.dockerjava.api.model.PortBinding; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.*; @@ -25,13 +24,10 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.dao.DuplicateKeyException; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.web.client.RestTemplate; -import javax.validation.ConstraintViolationException; -import java.util.Arrays; import java.util.List; import static at.tuwien.config.DockerConfig.*; @@ -71,57 +67,28 @@ public class UserServiceIntegrationTest extends BaseUnitTest { @BeforeAll public static void beforeAll() { afterAll(); - /* create networks */ - dockerClient.createNetworkCmd() - .withName("fda-userdb") - .withIpam(new Network.Ipam() - .withConfig(new Network.Ipam.Config() - .withSubnet("172.28.0.0/16"))) - .withEnableIpv6(false) - .exec(); - dockerClient.createNetworkCmd() - .withName("fda-public") - .withIpam(new Network.Ipam() - .withConfig(new Network.Ipam.Config() - .withSubnet("172.29.0.0/16"))) - .withEnableIpv6(false) - .exec(); - } - - @AfterAll - public static void afterAll() { - /* remove networks */ - dockerClient.listNetworksCmd() - .exec() - .stream() - .filter(n -> n.getName().startsWith("fda")) - .forEach(network -> { - log.info("Delete network {}", network.getName()); - dockerClient.removeNetworkCmd(network.getId()).exec(); - }); + DockerConfig.createAllNetworks(); } @BeforeEach public void beforeEach() { + afterEach(); + DockerConfig.createAllNetworks(); + /* metadata database */ imageRepository.save(IMAGE_1); userRepository.save(USER_1); } @AfterEach public void afterEach() { - /* stop containers and remove them */ - dockerClient.listContainersCmd() - .withShowAll(true) - .exec() - .forEach(container -> { - log.info("Delete container {}", Arrays.asList(container.getNames())); - try { - dockerClient.stopContainerCmd(container.getId()).exec(); - } catch (NotModifiedException e) { - // ignore - } - dockerClient.removeContainerCmd(container.getId()).exec(); - }); + DockerConfig.removeAllContainers(); + DockerConfig.removeAllNetworks(); + } + + @AfterAll + public static void afterAll() { + DockerConfig.removeAllContainers(); + DockerConfig.removeAllNetworks(); } @Test diff --git a/fda-authentication-service/rest-service/src/test/resources/application.properties b/fda-authentication-service/rest-service/src/test/resources/application.properties index b0ccd00eda3328d89ea1cea158719ad810e6712b..d57104b1eaa5bb5e645f82671879ae16d2e2b015 100644 --- a/fda-authentication-service/rest-service/src/test/resources/application.properties +++ b/fda-authentication-service/rest-service/src/test/resources/application.properties @@ -25,6 +25,6 @@ spring.rabbitmq.username=guest spring.rabbitmq.password=guest # user -fda.gateway.endpoint=http://172.29.0.2:15672/api/ +fda.gateway.endpoint=http://172.31.0.2:15672/api/ fda.mail.verify=true fda.token.max=1 \ No newline at end of file diff --git a/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java b/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java index 9dfe9e4b53e3072a2aa40bb88b4820473fb649f4..5c3d11e564d31020f65612052bbe570c212f887d 100644 --- a/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java +++ b/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java @@ -5,6 +5,7 @@ import at.tuwien.entities.container.Container; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.mapper.ContainerMapper; +import at.tuwien.service.ContainerService; import at.tuwien.service.UserService; import at.tuwien.service.impl.ContainerServiceImpl; import io.micrometer.core.annotation.Timed; @@ -34,7 +35,7 @@ public class ContainerEndpoint { private final UserService userService; private final ContainerMapper containerMapper; - private final ContainerServiceImpl containerService; + private final ContainerService containerService; @Autowired public ContainerEndpoint(UserService userService, ContainerServiceImpl containerService, @@ -47,9 +48,10 @@ public class ContainerEndpoint { @GetMapping @Transactional(readOnly = true) @Operation(summary = "Find all containers") - public ResponseEntity<List<ContainerBriefDto>> findAll(Principal principal) { - log.debug("endpoint find all containers, principal={}", principal); - final List<Container> containers = containerService.getAll(); + public ResponseEntity<List<ContainerBriefDto>> findAll(Principal principal, + @RequestParam(required = false) Integer limit) { + log.debug("endpoint find all containers, principal={}, limit={}", principal, limit); + final List<Container> containers = containerService.getAll(limit); return ResponseEntity.ok() .body(containers.stream() .map(containerMapper::containerToDatabaseContainerBriefDto) @@ -95,7 +97,7 @@ public class ContainerEndpoint { @Valid @RequestBody ContainerChangeDto changeDto, @NotNull Principal principal) throws ContainerNotFoundException, ContainerAlreadyRunningException, ContainerAlreadyStoppedException, - UserNotFoundException, NotAllowedException { + UserNotFoundException, NotAllowedException, DockerClientException { log.debug("endpoint modify container, containerId={}, changeDto={}, principal={}", containerId, changeDto, principal); final User user = userService.findByUsername(principal.getName()); final Container container = containerService.find(containerId); @@ -124,7 +126,7 @@ public class ContainerEndpoint { @Operation(summary = "Delete some container", security = @SecurityRequirement(name = "bearerAuth")) public ResponseEntity<?> delete(@NotNull @PathVariable("id") Long containerId, @NotNull Principal principal) throws ContainerNotFoundException, - ContainerStillRunningException, ContainerAlreadyRemovedException { + ContainerStillRunningException, ContainerAlreadyRemovedException, DockerClientException { log.debug("endpoint delete container, containerId={}, principal={}", containerId, principal); containerService.remove(containerId); return ResponseEntity.status(HttpStatus.ACCEPTED) diff --git a/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java b/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java index 7f02363385b4618a4d5430694de644ac54e54284..bbb5d2ecba97a1acd2314ce9a9cbb9b16de68e82 100644 --- a/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java +++ b/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java @@ -10,10 +10,6 @@ import at.tuwien.mapper.ImageMapper; import at.tuwien.service.impl.ImageServiceImpl; import io.micrometer.core.annotation.Timed; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; @@ -46,9 +42,6 @@ public class ImageEndpoint { } @GetMapping - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Found images") - }) @Transactional(readOnly = true) @Timed(value = "image.list", description = "Time needed to list the container images") @Operation(summary = "Find all images") @@ -62,10 +55,6 @@ public class ImageEndpoint { } @PostMapping - @ApiResponses(value = { - @ApiResponse(responseCode = "201", description = "Created image"), - @ApiResponse(responseCode = "404", description = "Image not found"), - }) @Transactional @Timed(value = "image.create", description = "Time needed to create a container image") @PreAuthorize("hasRole('ROLE_DEVELOPER')") @@ -86,10 +75,6 @@ public class ImageEndpoint { } @GetMapping("/{id}") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Found some image"), - @ApiResponse(responseCode = "404", description = "Image not found"), - }) @Transactional(readOnly = true) @Timed(value = "image.find", description = "Time needed to find a container image") @Operation(summary = "Find some image") @@ -104,10 +89,6 @@ public class ImageEndpoint { } @PutMapping("/{id}") - @ApiResponses(value = { - @ApiResponse(responseCode = "202", description = "Updated image"), - @ApiResponse(responseCode = "404", description = "Image not found"), - }) @Transactional @Timed(value = "image.update", description = "Time needed to update a container image") @PreAuthorize("hasRole('DEVELOPER')") @@ -125,11 +106,6 @@ public class ImageEndpoint { } @DeleteMapping("/{id}") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Deleted image"), - @ApiResponse(responseCode = "403", description = "Unable to delete image"), - @ApiResponse(responseCode = "404", description = "Image not found"), - }) @Transactional @Timed(value = "image.delete", description = "Time needed to delete a container image") @PreAuthorize("hasRole('DEVELOPER')") diff --git a/fda-container-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java b/fda-container-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java index c22a810fea54b58c45b71cf70b23efcde52ae031..0a59ea1f4519a9212ddabb9f05ed96276fc07441 100644 --- a/fda-container-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java +++ b/fda-container-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java @@ -12,6 +12,7 @@ import at.tuwien.entities.container.image.ContainerImageEnvironmentItemType; import at.tuwien.entities.user.RoleType; import at.tuwien.entities.user.User; import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.model.HealthCheck; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; @@ -284,30 +285,36 @@ public abstract class BaseUnitTest { public final static Long CONTAINER_1_ID = 1L; public final static String CONTAINER_1_HASH = "deadbeef"; - public final static String CONTAINER_1_NAME = "fda-userdb-u01"; - public final static String CONTAINER_1_INTERNALNAME = "dbrepo-userdb-fda-userdb-u01"; - public final static String CONTAINER_1_DATABASE = "univie"; - public final static String CONTAINER_1_IP = "172.28.0.5"; - public final static Instant CONTAINER_1_CREATED = Instant.now().minus(1, HOURS); + public final static String CONTAINER_1_IP = "172.30.0.5"; + public final static String CONTAINER_1_NAME = "u01"; + public final static String CONTAINER_1_INTERNALNAME = "dbrepo-userdb-u01"; + public final static Instant CONTAINER_1_CREATED = Instant.now().minus(2, HOURS); + public final static Instant CONTAINER_1_UPDATED = Instant.now(); + public final static HealthCheck CONTAINER_1_HEALTHCHECK = new HealthCheck() + .withTest(List.of("CMD", "mysqladmin", "ping", "--host=127.0.0.1", "--password=mariadb")); + + public final static String[] CONTAINER_1_ENV = new String[]{"MARIADB_ROOT_PASSWORD=mariadb", "MARIADB_USER=mariadb", + "MARIADB_PASSWORD=mariadb", "MARIADB_DATABASE=weather"}; public final static Container CONTAINER_1 = Container.builder() .id(CONTAINER_1_ID) .name(CONTAINER_1_NAME) + .hash(CONTAINER_1_HASH) .internalName(CONTAINER_1_INTERNALNAME) + .created(CONTAINER_1_CREATED) + .lastModified(CONTAINER_1_UPDATED) + .ipAddress(CONTAINER_1_IP) .imageId(IMAGE_1_ID) .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) .creator(USER_1) + .owner(USER_1) .build(); public final static Long CONTAINER_2_ID = 2L; public final static String CONTAINER_2_HASH = "deadbeef"; - public final static String CONTAINER_2_NAME = "fda-userdb-u02"; - public final static String CONTAINER_2_INTERNALNAME = "dbrepo-userdb-fda-userdb-u02"; - public final static String CONTAINER_2_DATABASE = "univie"; - public final static String CONTAINER_2_IP = "172.28.0.6"; + public final static String CONTAINER_2_NAME = "u02"; + public final static String CONTAINER_2_INTERNALNAME = "dbrepo-userdb-u02"; + public final static String CONTAINER_2_IP = "172.30.0.6"; public final static Instant CONTAINER_2_CREATED = Instant.now().minus(2, HOURS); public final static Container CONTAINER_2 = Container.builder() @@ -324,8 +331,8 @@ public abstract class BaseUnitTest { public final static Long CONTAINER_3_ID = 3L; public final static String CONTAINER_3_HASH = "deadbeef"; - public final static String CONTAINER_3_NAME = "fda-userdb-u03"; - public final static String CONTAINER_3_INTERNALNAME = "dbrepo-userdb-fda-userdb-u03"; + public final static String CONTAINER_3_NAME = "u03"; + public final static String CONTAINER_3_INTERNALNAME = "dbrepo-userdb-u03"; public final static String CONTAINER_3_DATABASE = "u03"; public final static String CONTAINER_3_IP = "173.38.0.7"; public final static Instant CONTAINER_3_CREATED = Instant.now().minus(2, HOURS); diff --git a/fda-container-service/rest-service/src/test/java/at/tuwien/endpoint/ContainerEndpointUnitTest.java b/fda-container-service/rest-service/src/test/java/at/tuwien/endpoint/ContainerEndpointUnitTest.java index 7407254558e316d28a8fbccc878d9b789712cd81..cd82d0b81d9e7befddfea0c1018863fcf7c8670d 100644 --- a/fda-container-service/rest-service/src/test/java/at/tuwien/endpoint/ContainerEndpointUnitTest.java +++ b/fda-container-service/rest-service/src/test/java/at/tuwien/endpoint/ContainerEndpointUnitTest.java @@ -2,7 +2,7 @@ package at.tuwien.endpoint; import at.tuwien.BaseUnitTest; import at.tuwien.api.container.*; -import at.tuwien.config.DockerUtil; +import at.tuwien.config.DockerConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.endpoints.ContainerEndpoint; import at.tuwien.entities.container.Container; @@ -48,7 +48,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { private ContainerEndpoint containerEndpoint; @Autowired - private DockerUtil dockerUtil; + private DockerConfig dockerUtil; @Test public void findById_anonymous_succeeds() throws DockerClientException, ContainerNotFoundException, @@ -142,7 +142,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, roles = {"DEVELOPER"}) public void delete_developer_succeeds() throws ContainerStillRunningException, ContainerAlreadyRemovedException, - ContainerNotFoundException { + ContainerNotFoundException, DockerClientException { /* mock */ when(userRepository.findByUsername(USER_2_USERNAME)) @@ -170,7 +170,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { public void findAll_anonymous_succeeds() { /* test */ - findAll_generic(null); + findAll_generic(null, null); } @Test @@ -178,7 +178,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { public void findAll_anonymous2_succeeds() { /* test */ - findAll_generic(null); + findAll_generic(null, null); } @Test @@ -190,7 +190,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { .thenReturn(Optional.of(USER_1)); /* test */ - findAll_generic(USER_1_PRINCIPAL); + findAll_generic(USER_1_PRINCIPAL, null); } @Test @@ -202,7 +202,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { .thenReturn(Optional.of(USER_2)); /* test */ - findAll_generic(USER_2_PRINCIPAL); + findAll_generic(USER_2_PRINCIPAL, null); } @Test @@ -214,7 +214,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { .thenReturn(Optional.of(USER_3)); /* test */ - findAll_generic(USER_3_PRINCIPAL); + findAll_generic(USER_3_PRINCIPAL, null); } @Test @@ -337,7 +337,8 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, roles = {"RESEARCHER"}) public void modify_researcherStart_succeeds() throws ContainerAlreadyRunningException, - ContainerAlreadyStoppedException, ContainerNotFoundException, UserNotFoundException, NotAllowedException { + ContainerAlreadyStoppedException, ContainerNotFoundException, UserNotFoundException, NotAllowedException, + DockerClientException { /* mock */ when(userRepository.findByUsername(USER_1_USERNAME)) @@ -367,7 +368,8 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, roles = {"RESEARCHER"}) public void modify_researcherStop_succeeds() throws ContainerAlreadyRunningException, - ContainerAlreadyStoppedException, ContainerNotFoundException, UserNotFoundException, NotAllowedException { + ContainerAlreadyStoppedException, ContainerNotFoundException, UserNotFoundException, NotAllowedException, + DockerClientException { /* mock */ when(userRepository.findByUsername(USER_1_USERNAME)) @@ -398,7 +400,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, roles = {"DEVELOPER"}) public void modify_developerForeignStart_succeeds() throws UserNotFoundException, ContainerAlreadyRunningException, - NotAllowedException, ContainerAlreadyStoppedException, ContainerNotFoundException { + NotAllowedException, ContainerAlreadyStoppedException, ContainerNotFoundException, DockerClientException { /* mock */ when(userRepository.findByUsername(USER_2_USERNAME)) @@ -411,7 +413,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, roles = {"DEVELOPER"}) public void modify_developerForeignStop_succeeds() throws UserNotFoundException, ContainerAlreadyRunningException, - NotAllowedException, ContainerAlreadyStoppedException, ContainerNotFoundException { + NotAllowedException, ContainerAlreadyStoppedException, ContainerNotFoundException, DockerClientException { /* mock */ when(userRepository.findByUsername(USER_2_USERNAME)) @@ -471,7 +473,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { } public void delete_generic(Long containerId, Container container, Principal principal) throws ContainerNotFoundException, - ContainerStillRunningException, ContainerAlreadyRemovedException { + ContainerStillRunningException, ContainerAlreadyRemovedException, DockerClientException { /* mock */ when(containerService.find(containerId)) @@ -486,14 +488,14 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { assertNull(response.getBody()); } - public void findAll_generic(Principal principal) { + public void findAll_generic(Principal principal, Integer limit) { /* mock */ - when(containerService.getAll()) + when(containerService.getAll(limit)) .thenReturn(List.of(CONTAINER_1, CONTAINER_2)); /* test */ - final ResponseEntity<List<ContainerBriefDto>> response = containerEndpoint.findAll(principal); + final ResponseEntity<List<ContainerBriefDto>> response = containerEndpoint.findAll(principal, limit); assertEquals(HttpStatus.OK, response.getStatusCode()); assertNotNull(response.getBody()); final List<ContainerBriefDto> body = response.getBody(); @@ -522,7 +524,8 @@ public class ContainerEndpointUnitTest extends BaseUnitTest { } public void modify_generic(ContainerActionTypeDto data, Long containerId, Container container, Principal principal) - throws ContainerAlreadyRunningException, ContainerNotFoundException, ContainerAlreadyStoppedException, UserNotFoundException, NotAllowedException { + throws ContainerAlreadyRunningException, ContainerNotFoundException, ContainerAlreadyStoppedException, + UserNotFoundException, NotAllowedException, DockerClientException { final ContainerChangeDto request = ContainerChangeDto.builder() .action(data) .build(); diff --git a/fda-container-service/rest-service/src/test/java/at/tuwien/endpoint/ImageEndpointUnitTest.java b/fda-container-service/rest-service/src/test/java/at/tuwien/endpoint/ImageEndpointUnitTest.java index f84ae04db59091c81e86ff91854ff0106cb6bd5e..9ef775d53dde5ee5f99ede094d4a1944dbd7a879 100644 --- a/fda-container-service/rest-service/src/test/java/at/tuwien/endpoint/ImageEndpointUnitTest.java +++ b/fda-container-service/rest-service/src/test/java/at/tuwien/endpoint/ImageEndpointUnitTest.java @@ -1,21 +1,17 @@ package at.tuwien.endpoint; import at.tuwien.BaseUnitTest; -import at.tuwien.api.container.*; import at.tuwien.api.container.image.ImageBriefDto; import at.tuwien.api.container.image.ImageChangeDto; import at.tuwien.api.container.image.ImageCreateDto; import at.tuwien.api.container.image.ImageDto; -import at.tuwien.config.DockerUtil; +import at.tuwien.config.DockerConfig; import at.tuwien.config.ReadyConfig; -import at.tuwien.endpoints.ContainerEndpoint; import at.tuwien.endpoints.ImageEndpoint; -import at.tuwien.entities.container.Container; import at.tuwien.entities.container.image.ContainerImage; import at.tuwien.exception.*; import at.tuwien.repository.jpa.ImageRepository; import at.tuwien.repository.jpa.UserRepository; -import at.tuwien.service.impl.ContainerServiceImpl; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -31,7 +27,6 @@ import org.springframework.security.test.context.support.WithAnonymousUser; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; -import javax.ws.rs.NotAllowedException; import java.security.Principal; import java.util.List; import java.util.Optional; @@ -57,7 +52,7 @@ public class ImageEndpointUnitTest extends BaseUnitTest { private ImageEndpoint imageEndpoint; @Autowired - private DockerUtil dockerUtil; + private DockerConfig dockerUtil; @Test public void findAll_anonymous_succeeds() { diff --git a/fda-container-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java b/fda-container-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java index 8aef59c9fcc56627c6a651a6fe457875abc91932..fd1c316006658919c030f290a359b3a3bdb115fe 100644 --- a/fda-container-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java +++ b/fda-container-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java @@ -5,7 +5,6 @@ import at.tuwien.api.container.ContainerCreateRequestDto; import at.tuwien.config.DockerUtil; import at.tuwien.config.ReadyConfig; import at.tuwien.entities.container.Container; -import at.tuwien.entities.container.image.ContainerImage; import at.tuwien.exception.*; import at.tuwien.repository.jpa.ContainerRepository; import at.tuwien.repository.jpa.ImageRepository; @@ -66,32 +65,19 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { .withName("fda-userdb") .withIpam(new Network.Ipam() .withConfig(new Network.Ipam.Config() - .withSubnet("172.28.0.0/16"))) + .withSubnet("172.30.0.0/16"))) .withEnableIpv6(false) .exec(); dockerClient.createNetworkCmd() .withName("fda-public") .withIpam(new Network.Ipam() .withConfig(new Network.Ipam.Config() - .withSubnet("172.29.0.0/16"))) + .withSubnet("172.31.0.0/16"))) .withEnableIpv6(false) .exec(); /* mock data */ userRepository.save(USER_1); - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); imageRepository.save(IMAGE_1); } @@ -151,30 +137,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { final Principal principal = new BasicUserPrincipal(USER_1_USERNAME); /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); containerRepository.save(CONTAINER_1); /* test */ @@ -221,30 +183,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { ContainerAlreadyRunningException { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); dockerUtil.createContainer(CONTAINER_1); containerRepository.save(CONTAINER_1); @@ -257,30 +195,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { ContainerAlreadyStoppedException { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); dockerUtil.createContainer(CONTAINER_1); dockerUtil.startContainer(CONTAINER_1); containerRepository.save(CONTAINER_1); @@ -293,30 +207,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { public void change_startSavedButNotFound_fails() { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); containerRepository.save(CONTAINER_1); /* test */ @@ -329,30 +219,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { public void change_removeSavedButNotFound_fails() { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); containerRepository.save(CONTAINER_1); /* test */ @@ -365,77 +231,31 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { public void getAll_succeeds() { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - final Container CONTAINER_2 = Container.builder() - .id(CONTAINER_2_ID) - .name(CONTAINER_2_NAME) - .internalName(CONTAINER_2_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_2_HASH) - .ipAddress(CONTAINER_2_IP) - .created(CONTAINER_2_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); containerRepository.save(CONTAINER_1); containerRepository.save(CONTAINER_2); /* test */ - final List<Container> response = containerService.getAll(); + final List<Container> response = containerService.getAll(null); assertEquals(2, response.size()); } + @Test + public void getAll_limit_succeeds() { + + /* mock */ + containerRepository.save(CONTAINER_1); + containerRepository.save(CONTAINER_2); + + /* test */ + final List<Container> response = containerService.getAll(1); + assertEquals(1, response.size()); + } + @Test public void remove_succeeds() throws DockerClientException, ContainerStillRunningException, ContainerNotFoundException, ContainerAlreadyRemovedException { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); dockerUtil.createContainer(CONTAINER_1); dockerUtil.stopContainer(CONTAINER_1); containerRepository.save(CONTAINER_1); @@ -457,30 +277,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { public void remove_stillRunning_fails() throws InterruptedException { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); dockerUtil.createContainer(CONTAINER_1); dockerUtil.startContainer(CONTAINER_1); containerRepository.save(CONTAINER_1); @@ -495,30 +291,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { public void change_alreadyRunning_fails() throws InterruptedException { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); dockerUtil.createContainer(CONTAINER_1); dockerUtil.startContainer(CONTAINER_1); containerRepository.save(CONTAINER_1); @@ -533,30 +305,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { public void change_startNotFound_fails() { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); dockerUtil.createContainer(CONTAINER_1); /* test */ @@ -569,30 +317,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { public void change_alreadyStopped_fails() throws InterruptedException { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); dockerUtil.createContainer(CONTAINER_1); dockerUtil.startContainer(CONTAINER_1); dockerUtil.stopContainer(CONTAINER_1); @@ -608,30 +332,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { public void change_stopNeverStarted_fails() { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); dockerUtil.createContainer(CONTAINER_1); containerRepository.save(CONTAINER_1); @@ -645,30 +345,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { public void change_stopSavedButNotFound_fails() { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); containerRepository.save(CONTAINER_1); /* test */ @@ -682,30 +358,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { ContainerNotRunningException { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); dockerUtil.createContainer(CONTAINER_1); dockerUtil.startContainer(CONTAINER_1); containerRepository.save(CONTAINER_1); @@ -731,30 +383,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { public void inspect_notRunning_fails() { /* mock */ - final ContainerImage IMAGE_1 = ContainerImage.builder() - .id(IMAGE_1_ID) - .repository(IMAGE_1_REPOSITORY) - .tag(IMAGE_1_TAG) - .hash(IMAGE_1_HASH) - .jdbcMethod(IMAGE_1_JDBC) - .dialect(IMAGE_1_DIALECT) - .driverClass(IMAGE_1_DRIVER) - .compiled(IMAGE_1_BUILT) - .size(IMAGE_1_SIZE) - .environment(IMAGE_1_ENV) - .defaultPort(IMAGE_1_PORT) - .build(); - final Container CONTAINER_1 = Container.builder() - .id(CONTAINER_1_ID) - .name(CONTAINER_1_NAME) - .internalName(CONTAINER_1_INTERNALNAME) - .imageId(IMAGE_1_ID) - .image(IMAGE_1) - .hash(CONTAINER_1_HASH) - .ipAddress(CONTAINER_1_IP) - .created(CONTAINER_1_CREATED) - .build(); - log.info("Container id {}", CONTAINER_1.getId()); dockerUtil.createContainer(CONTAINER_1); containerRepository.save(CONTAINER_1); diff --git a/fda-container-service/services/src/main/java/at/tuwien/mapper/DatabaseMapper.java b/fda-container-service/services/src/main/java/at/tuwien/mapper/DatabaseMapper.java index 6a7b557780c2eae87d2f4e741358c9cd11272973..1879065a2df2056603679e9d8a505633a702178a 100644 --- a/fda-container-service/services/src/main/java/at/tuwien/mapper/DatabaseMapper.java +++ b/fda-container-service/services/src/main/java/at/tuwien/mapper/DatabaseMapper.java @@ -1,5 +1,6 @@ package at.tuwien.mapper; +import at.tuwien.api.database.DatabaseBriefDto; import at.tuwien.api.database.DatabaseDto; import at.tuwien.entities.database.Database; import org.mapstruct.Mapper; @@ -14,4 +15,10 @@ public interface DatabaseMapper { }) DatabaseDto databaseToDatabaseDto(Database data); + /* keep */ + @Mappings({ + @Mapping(target = "container", ignore = true) + }) + DatabaseBriefDto databaseToDatabaseBriefDto(Database data); + } diff --git a/fda-container-service/services/src/main/java/at/tuwien/repository/jpa/ContainerRepository.java b/fda-container-service/services/src/main/java/at/tuwien/repository/jpa/ContainerRepository.java index 37b8abb7735952160ae69ddb85c748441050a575..df2a6eba16e4bdbefa3a5de7eaff1dea507ed8ad 100644 --- a/fda-container-service/services/src/main/java/at/tuwien/repository/jpa/ContainerRepository.java +++ b/fda-container-service/services/src/main/java/at/tuwien/repository/jpa/ContainerRepository.java @@ -9,8 +9,6 @@ import java.util.Optional; @Repository public interface ContainerRepository extends JpaRepository<Container, Long> { - Optional<Container> findByHash(String hash); - Optional<Container> findByInternalName(String internalName); } diff --git a/fda-container-service/services/src/main/java/at/tuwien/repository/jpa/DatabaseRepository.java b/fda-container-service/services/src/main/java/at/tuwien/repository/jpa/DatabaseRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..688993ab3ca2e32edeb59b6c66dc838f58333b02 --- /dev/null +++ b/fda-container-service/services/src/main/java/at/tuwien/repository/jpa/DatabaseRepository.java @@ -0,0 +1,10 @@ +package at.tuwien.repository.jpa; + +import at.tuwien.entities.database.Database; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface DatabaseRepository extends JpaRepository<Database, Long> { + +} diff --git a/fda-container-service/services/src/main/java/at/tuwien/repository/jpa/IdentifierRepository.java b/fda-container-service/services/src/main/java/at/tuwien/repository/jpa/IdentifierRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..f76f9976d6de9884579ac242ce616d6c0caf099e --- /dev/null +++ b/fda-container-service/services/src/main/java/at/tuwien/repository/jpa/IdentifierRepository.java @@ -0,0 +1,10 @@ +package at.tuwien.repository.jpa; + +import at.tuwien.entities.identifier.Identifier; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface IdentifierRepository extends JpaRepository<Identifier, Long> { + +} diff --git a/fda-container-service/services/src/main/java/at/tuwien/service/ContainerService.java b/fda-container-service/services/src/main/java/at/tuwien/service/ContainerService.java index 2528621ed475406bb055f32457420bc116d158e2..26654fc34f51bb974b91036fadeb26eca12a1f55 100644 --- a/fda-container-service/services/src/main/java/at/tuwien/service/ContainerService.java +++ b/fda-container-service/services/src/main/java/at/tuwien/service/ContainerService.java @@ -56,9 +56,12 @@ public interface ContainerService { Container inspect(Long id) throws ContainerNotFoundException, DockerClientException, ContainerNotRunningException; /** - * @return + * Retrieve a list of all containers from the metadata database + * + * @param limit Return at most this amount of results, optional. + * @return The list of containers. */ - List<Container> getAll(); + List<Container> getAll(Integer limit); /** * @param containerId diff --git a/fda-container-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java b/fda-container-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java index 4dc699622912b6ac69c2ab2d2a71246be2ee4c62..9753d9687e7ec0113b00bde7cede4a4d3e41b1e6 100644 --- a/fda-container-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java +++ b/fda-container-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java @@ -22,6 +22,7 @@ import com.github.dockerjava.api.exception.NotModifiedException; import com.github.dockerjava.api.model.*; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.util.SocketUtils; @@ -31,6 +32,7 @@ import org.springframework.transaction.annotation.Transactional; import java.security.Principal; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @Log4j2 @Service @@ -79,7 +81,7 @@ public class ContainerServiceImpl implements ContainerService { /* check duplicate */ final Optional<Container> optional = containerRepository.findByInternalName(container.getInternalName()); if (optional.isPresent()) { - log.error("Failed to create container with internal name {}", container.getInternalName()); + log.error("Failed to create container with internal name {}, it already exists", container.getInternalName()); throw new ContainerAlreadyExistsException("Container name already exists"); } /* create the volume */ @@ -212,9 +214,15 @@ public class ContainerServiceImpl implements ContainerService { } @Override - @Transactional - public List<Container> getAll() { - final List<Container> containers = containerRepository.findAll(Sort.by(Sort.Direction.DESC, "created")); + @Transactional(readOnly = true) + public List<Container> getAll(Integer limit) { + final List<Container> containers; + if (limit == null) { + containers = containerRepository.findAll(Sort.by(Sort.Direction.DESC, "created")); + } else { + containers = containerRepository.findAll(PageRequest.of(0, limit, Sort.by(Sort.Direction.DESC, "created"))) + .toList(); + } log.info("Found {} containers", containers.size()); return containers; } diff --git a/fda-database-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java b/fda-database-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java index 57820c3a21bde65e110d829e6b7413ba4678768d..bfeb98549b44ad1c38c2dbc84c399aa99f475cf6 100644 --- a/fda-database-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java +++ b/fda-database-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java @@ -3,12 +3,9 @@ package at.tuwien.endpoints; import at.tuwien.api.database.*; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.identifier.Identifier; -import at.tuwien.entities.identifier.IdentifierType; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.mapper.DatabaseMapper; -import at.tuwien.mapper.IdentifierMapper; import at.tuwien.repository.jpa.DatabaseAccessRepository; import at.tuwien.service.*; import at.tuwien.service.impl.MariaDbServiceImpl; @@ -27,7 +24,6 @@ import javax.validation.Valid; import javax.validation.constraints.NotNull; import java.security.Principal; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; @Log4j2 @@ -39,27 +35,22 @@ public class DatabaseEndpoint extends AbstractEndpoint { private final UserService userService; private final AccessService accessService; private final DatabaseMapper databaseMapper; - private final IdentifierMapper identifierMapper; private final MariaDbServiceImpl databaseService; private final QueryStoreService queryStoreService; - private final IdentifierService identifierService; private final MessageQueueService messageQueueService; private final DatabaseAccessRepository databaseAccessRepository; @Autowired public DatabaseEndpoint(DatabaseMapper databaseMapper, ContainerService containerService, UserService userService, MariaDbServiceImpl databaseService, QueryStoreService queryStoreService, - IdentifierService identifierService, IdentifierMapper identifierMapper, MessageQueueService messageQueueService, AccessService accessService, DatabaseAccessRepository databaseAccessRepository) { super(databaseService, containerService, databaseAccessRepository); this.userService = userService; this.accessService = accessService; this.databaseMapper = databaseMapper; - this.identifierMapper = identifierMapper; this.databaseService = databaseService; this.queryStoreService = queryStoreService; - this.identifierService = identifierService; this.messageQueueService = messageQueueService; this.databaseAccessRepository = databaseAccessRepository; } @@ -71,18 +62,10 @@ public class DatabaseEndpoint extends AbstractEndpoint { public ResponseEntity<List<DatabaseBriefDto>> list(@NotNull @PathVariable("id") Long containerId, @NotNull Principal principal) { log.debug("endpoint list databases, containerId={}, principal={}", containerId, principal); - final List<Identifier> identifiers = identifierService.findAll(containerId); final List<DatabaseBriefDto> databases = databaseService.findAll(containerId) .stream() .map(databaseMapper::databaseToDatabaseBriefDto) .collect(Collectors.toList()); - databases.forEach(db -> { - final Optional<Identifier> id = identifiers.stream() - .filter(i -> i.getContainerId().equals(containerId) && i.getDatabaseId().equals(containerId) && - i.getType().equals(IdentifierType.DATABASE)) - .findFirst(); - id.ifPresent(identifier -> db.setIdentifier(identifierMapper.identifierToIdentifierDto(identifier))); - }); log.trace("list databases resulted in databases {}", databases); return ResponseEntity.ok(databases); } @@ -175,12 +158,6 @@ public class DatabaseEndpoint extends AbstractEndpoint { log.debug("endpoint find database, containerId={}, databaseId={}", containerId, databaseId); final Database database = databaseService.findById(containerId, databaseId); final DatabaseDto dto = databaseMapper.databaseToDatabaseDto(database); - try { - final Identifier identifier = identifierService.find(containerId, databaseId, IdentifierType.DATABASE); - dto.setIdentifier(identifierMapper.identifierToIdentifierDto(identifier)); - } catch (IdentifierNotFoundException e) { - // ignore - } if (principal != null && database.getOwner().getUsername().equals(principal.getName())) { /* only owner sees the access rights */ final List<DatabaseAccess> accesses = accessService.list(databaseId); diff --git a/fda-database-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java b/fda-database-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java index 7a1890e25df228c438451cca2ce8efee0a589d53..e32140f007c003e33e6a48b9224080ea216d3d58 100644 --- a/fda-database-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java +++ b/fda-database-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java @@ -50,7 +50,7 @@ public abstract class BaseUnitTest { .build(); public final static String GATEWAY_NAME = "fda-gateway-service"; - public final static String GATEWAY_IP = "172.29.0.3"; + public final static String GATEWAY_IP = "172.31.0.3"; public final static String GATEWAY_HOSTNAME = "gateway-service"; public final static Integer GATEWAY_PORT = 9095; public final static String GATEWAY_IMAGE = "nginx"; @@ -58,7 +58,7 @@ public abstract class BaseUnitTest { public final static String CONTAINER_SEARCH_NAME = "search-mock-service"; public final static String CONTAINER_SEARCH_INTERNAL_NAME = "search-mock-service"; - public final static String CONTAINER_SEARCH_IP = "172.29.0.3"; + public final static String CONTAINER_SEARCH_IP = "172.31.0.3"; public final static String CONTAINER_SEARCH_REPOSITORY = "elasticsearch"; public final static String CONTAINER_SEARCH_TAG = "7.13.4"; @@ -330,9 +330,9 @@ public abstract class BaseUnitTest { .build(); public final static Long CONTAINER_BROKER_ID = 5L; - public final static String CONTAINER_BROKER_NAME = "broker-service"; - public final static String CONTAINER_BROKER_INTERNAL_NAME = "broker-service"; - public final static String CONTAINER_BROKER_IP = "172.29.0.2"; + public final static String CONTAINER_BROKER_NAME = "dbrepo-broker-service"; + public final static String CONTAINER_BROKER_INTERNAL_NAME = "dbrepo-broker-service"; + public final static String CONTAINER_BROKER_IP = "172.31.0.2"; public final static String CONTAINER_BROKER_HASH = "deadbeef"; public final static Instant CONTAINER_BROKER_CREATED = Instant.now().minus(1, HOURS); public final static HealthCheck CONTAINER_BROKER_HEALTHCHECK = new HealthCheck() @@ -366,9 +366,9 @@ public abstract class BaseUnitTest { public final static Long CONTAINER_1_ID = 1L; public final static String CONTAINER_1_HASH = "deadbeef"; - public final static String CONTAINER_1_IP = "172.28.0.5"; - public final static String CONTAINER_1_NAME = "fda-userdb-u01"; - public final static String CONTAINER_1_INTERNALNAME = "fda-userdb-u01"; + public final static String CONTAINER_1_IP = "172.30.0.5"; + public final static String CONTAINER_1_NAME = "u01"; + public final static String CONTAINER_1_INTERNALNAME = "dbrepo-userdb-u01"; public final static Instant CONTAINER_1_CREATED = Instant.now().minus(2, HOURS); public final static Instant CONTAINER_1_UPDATED = Instant.now(); public final static HealthCheck CONTAINER_1_HEALTHCHECK = new HealthCheck() @@ -393,9 +393,9 @@ public abstract class BaseUnitTest { public final static Long CONTAINER_2_ID = 2L; public final static String CONTAINER_2_HASH = "deadbeef"; - public final static String CONTAINER_2_IP = "172.28.0.6"; - public final static String CONTAINER_2_NAME = "fda-userdb-u02"; - public final static String CONTAINER_2_INTERNALNAME = "fda-userdb-u02"; + public final static String CONTAINER_2_IP = "172.30.0.6"; + public final static String CONTAINER_2_NAME = "u02"; + public final static String CONTAINER_2_INTERNALNAME = "dbrepo-userdb-u02"; public final static Instant CONTAINER_2_CREATED = Instant.now().minus(2, HOURS); public final static Instant CONTAINER_2_UPDATED = Instant.now(); public final static HealthCheck CONTAINER_2_HEALTHCHECK = new HealthCheck() @@ -420,9 +420,9 @@ public abstract class BaseUnitTest { public final static Long CONTAINER_3_ID = 3L; public final static String CONTAINER_3_HASH = "deadbeef"; - public final static String CONTAINER_3_IP = "172.28.0.7"; - public final static String CONTAINER_3_NAME = "fda-userdb-u03"; - public final static String CONTAINER_3_INTERNALNAME = "fda-userdb-u03"; + public final static String CONTAINER_3_IP = "172.30.0.7"; + public final static String CONTAINER_3_NAME = "u03"; + public final static String CONTAINER_3_INTERNALNAME = "dbrepo-userdb-u03"; public final static Instant CONTAINER_3_CREATED = Instant.now().minus(2, HOURS); public final static Instant CONTAINER_3_UPDATED = Instant.now(); public final static HealthCheck CONTAINER_3_HEALTHCHECK = new HealthCheck() @@ -447,9 +447,9 @@ public abstract class BaseUnitTest { public final static Long CONTAINER_4_ID = 4L; public final static String CONTAINER_4_HASH = "deadbeef"; - public final static String CONTAINER_4_IP = "172.28.0.8"; - public final static String CONTAINER_4_NAME = "fda-userdb-u04"; - public final static String CONTAINER_4_INTERNALNAME = "fda-userdb-u04"; + public final static String CONTAINER_4_IP = "172.30.0.8"; + public final static String CONTAINER_4_NAME = "u04"; + public final static String CONTAINER_4_INTERNALNAME = "dbrepo-userdb-u04"; public final static Instant CONTAINER_4_CREATED = Instant.now().minus(2, HOURS); public final static Instant CONTAINER_4_UPDATED = Instant.now(); public final static HealthCheck CONTAINER_4_HEALTHCHECK = new HealthCheck() @@ -473,7 +473,7 @@ public abstract class BaseUnitTest { public final static Long CONTAINER_ELASTIC_ID = 5L; public final static String CONTAINER_ELASTIC_NAME = "fda-elastic-service"; public final static String CONTAINER_ELASTIC_INTERNAL_NAME = "search-mock-service"; - public final static String CONTAINER_ELASTIC_IP = "172.29.0.3"; + public final static String CONTAINER_ELASTIC_IP = "172.31.0.3"; public final static String CONTAINER_ELASTIC_HASH = "deadbeef"; public final static Instant CONTAINER_ELASTIC_CREATED = Instant.now().minus(1, HOURS); diff --git a/fda-database-service/rest-service/src/test/java/at/tuwien/config/DockerConfig.java b/fda-database-service/rest-service/src/test/java/at/tuwien/config/DockerConfig.java index 5340810c86ad9dd7b7cd93a7e7d874cdb31d2c2e..7c55429c92d2f748d706cc990843b0f86883929e 100644 --- a/fda-database-service/rest-service/src/test/java/at/tuwien/config/DockerConfig.java +++ b/fda-database-service/rest-service/src/test/java/at/tuwien/config/DockerConfig.java @@ -157,14 +157,14 @@ public class DockerConfig extends BaseUnitTest { .withName("fda-userdb") .withIpam(new Network.Ipam() .withConfig(new Network.Ipam.Config() - .withSubnet("172.28.0.0/16"))) + .withSubnet("172.30.0.0/16"))) .withEnableIpv6(false) .exec(); dockerClient.createNetworkCmd() .withName("fda-public") .withIpam(new Network.Ipam() .withConfig(new Network.Ipam.Config() - .withSubnet("172.29.0.0/16"))) + .withSubnet("172.31.0.0/16"))) .withEnableIpv6(false) .exec(); } diff --git a/fda-database-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java b/fda-database-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java index 4808082aff0dbaadbd9cf296306c3be6a3b62759..61cbf30d0255572bc1ca4d62ec5df76672aa478c 100644 --- a/fda-database-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java +++ b/fda-database-service/rest-service/src/test/java/at/tuwien/endpoint/DatabaseEndpointUnitTest.java @@ -143,49 +143,67 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { @Test public void list_anonymousPublic_succeeds() { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* test */ - list_generic(CONTAINER_1_ID, CONTAINER_1, List.of(DATABASE_1), null); + list_generic(CONTAINER_3_ID, CONTAINER_3, List.of(DATABASE_3), null); } @Test @WithAnonymousUser public void list_anonymous2Public_succeeds() { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* test */ - list_generic(CONTAINER_1_ID, CONTAINER_1, List.of(DATABASE_1), null); + list_generic(CONTAINER_3_ID, CONTAINER_3, List.of(DATABASE_3), null); } @Test public void list_anonymousPrivate_succeeds() { + /* pre-condition */ + assertFalse(DATABASE_1_PUBLIC); + /* test */ - list_generic(CONTAINER_1_ID, CONTAINER_1, List.of(DATABASE_2), null); + list_generic(CONTAINER_1_ID, CONTAINER_1, List.of(DATABASE_1), null); } @Test @WithAnonymousUser public void list_anonymous2Private_succeeds() { + /* pre-condition */ + assertFalse(DATABASE_1_PUBLIC); + /* test */ - list_generic(CONTAINER_1_ID, CONTAINER_1, List.of(DATABASE_2), null); + list_generic(CONTAINER_1_ID, CONTAINER_1, List.of(DATABASE_1), null); } @Test @WithMockUser(username = USER_1_USERNAME, roles = {"RESEARCHER"}) public void list_researcherPublic_succeeds() { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_1_USERNAME)) .thenReturn(Optional.of(USER_1)); /* test */ - list_generic(CONTAINER_1_ID, CONTAINER_1, List.of(DATABASE_1), USER_1_PRINCIPAL); + list_generic(CONTAINER_3_ID, CONTAINER_3, List.of(DATABASE_3), USER_1_PRINCIPAL); } @Test @WithMockUser(username = USER_1_USERNAME, roles = {"RESEARCHER"}) public void list_researcherPublicWithIdentifiers_succeeds() { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_1_USERNAME)) .thenReturn(Optional.of(USER_1)); @@ -193,13 +211,16 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { .thenReturn(List.of(IDENTIFIER_1)); /* test */ - list_generic(CONTAINER_1_ID, CONTAINER_1, List.of(DATABASE_1), USER_1_PRINCIPAL); + list_generic(CONTAINER_3_ID, CONTAINER_3, List.of(DATABASE_3), USER_1_PRINCIPAL); } @Test @WithMockUser(username = USER_1_USERNAME, roles = {"RESEARCHER"}) public void list_researcherPrivate_succeeds() { + /* pre-condition */ + assertFalse(DATABASE_2_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_1_USERNAME)) .thenReturn(Optional.of(USER_1)); @@ -212,18 +233,24 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { @WithMockUser(username = USER_1_USERNAME, roles = {"RESEARCHER"}) public void list_researcherPublicForeignContainer_succeeds() { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_1_USERNAME)) .thenReturn(Optional.of(USER_1)); /* test */ - list_generic(CONTAINER_2_ID, CONTAINER_2, List.of(DATABASE_1), USER_1_PRINCIPAL); + list_generic(CONTAINER_3_ID, CONTAINER_3, List.of(DATABASE_3), USER_1_PRINCIPAL); } @Test @WithMockUser(username = USER_1_USERNAME, roles = {"RESEARCHER"}) public void list_researcherPrivateForeignContainer_succeeds() { + /* pre-condition */ + assertFalse(DATABASE_2_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_1_USERNAME)) .thenReturn(Optional.of(USER_1)); @@ -236,18 +263,24 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { @WithMockUser(username = USER_2_USERNAME, roles = {"DEVELOPER"}) public void list_developerPublic_succeeds() { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_2_USERNAME)) .thenReturn(Optional.of(USER_2)); /* test */ - list_generic(CONTAINER_2_ID, CONTAINER_2, List.of(DATABASE_1), USER_2_PRINCIPAL); + list_generic(CONTAINER_3_ID, CONTAINER_3, List.of(DATABASE_3), USER_2_PRINCIPAL); } @Test @WithMockUser(username = USER_2_USERNAME, roles = {"DEVELOPER"}) public void list_developerPrivate_succeeds() { + /* pre-condition */ + assertFalse(DATABASE_2_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_2_USERNAME)) .thenReturn(Optional.of(USER_2)); @@ -260,66 +293,84 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { @WithMockUser(username = USER_2_USERNAME, roles = {"DEVELOPER"}) public void list_developerPublicForeignContainer_succeeds() { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_2_USERNAME)) .thenReturn(Optional.of(USER_2)); /* test */ - list_generic(CONTAINER_1_ID, CONTAINER_1, List.of(DATABASE_1), USER_2_PRINCIPAL); + list_generic(CONTAINER_3_ID, CONTAINER_3, List.of(DATABASE_3), USER_2_PRINCIPAL); } @Test @WithMockUser(username = USER_2_USERNAME, roles = {"DEVELOPER"}) public void list_developerPrivateForeignContainer_succeeds() { + /* pre-condition */ + assertFalse(DATABASE_1_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_2_USERNAME)) .thenReturn(Optional.of(USER_2)); /* test */ - list_generic(CONTAINER_1_ID, CONTAINER_1, List.of(DATABASE_2), USER_2_PRINCIPAL); + list_generic(CONTAINER_1_ID, CONTAINER_1, List.of(DATABASE_1), USER_2_PRINCIPAL); } @Test @WithMockUser(username = USER_3_USERNAME, roles = {"DATA_STEWARD"}) public void list_dataStewardPublic_succeeds() { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_3_USERNAME)) .thenReturn(Optional.of(USER_3)); /* test */ - list_generic(CONTAINER_3_ID, CONTAINER_3, List.of(DATABASE_1), USER_3_PRINCIPAL); + list_generic(CONTAINER_3_ID, CONTAINER_3, List.of(DATABASE_3), USER_3_PRINCIPAL); } @Test @WithMockUser(username = USER_3_USERNAME, roles = {"DATA_STEWARD"}) public void list_dataStewardPrivate_succeeds() { + /* pre-condition */ + assertFalse(DATABASE_1_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_3_USERNAME)) .thenReturn(Optional.of(USER_3)); /* test */ - list_generic(CONTAINER_3_ID, CONTAINER_3, List.of(DATABASE_2), USER_3_PRINCIPAL); + list_generic(CONTAINER_1_ID, CONTAINER_1, List.of(DATABASE_1), USER_3_PRINCIPAL); } @Test @WithMockUser(username = USER_3_USERNAME, roles = {"DATA_STEWARD"}) public void list_dataStewardPublicForeignContainer_succeeds() { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_3_USERNAME)) .thenReturn(Optional.of(USER_3)); /* test */ - list_generic(CONTAINER_2_ID, CONTAINER_2, List.of(DATABASE_1), USER_3_PRINCIPAL); + list_generic(CONTAINER_3_ID, CONTAINER_3, List.of(DATABASE_3), USER_3_PRINCIPAL); } @Test @WithMockUser(username = USER_3_USERNAME, roles = {"DATA_STEWARD"}) public void list_dataStewardPrivateForeignContainer_succeeds() { + /* pre-condition */ + assertFalse(DATABASE_2_PUBLIC); + /* mock */ when(userRepository.findByUsername(USER_3_USERNAME)) .thenReturn(Optional.of(USER_3)); @@ -497,8 +548,11 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { @WithMockUser(username = USER_1_USERNAME, roles = {"RESEARCHER"}) public void findById_researcherPublic_succeeds() throws AccessDeniedException, DatabaseNotFoundException { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* test */ - findById_generic(CONTAINER_1_ID, CONTAINER_1, DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL); + findById_generic(CONTAINER_3_ID, CONTAINER_3, DATABASE_3_ID, DATABASE_3, USER_1_PRINCIPAL); } @Test @@ -506,6 +560,9 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { public void findById_researcherPublicForeignDatabase_succeeds() throws AccessDeniedException, DatabaseNotFoundException { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* test */ findById_generic(CONTAINER_3_ID, CONTAINER_3, DATABASE_3_ID, DATABASE_3, USER_1_PRINCIPAL); } @@ -514,6 +571,9 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { @WithMockUser(username = USER_1_USERNAME, roles = {"RESEARCHER"}) public void findById_researcherPrivate_succeeds() throws AccessDeniedException, DatabaseNotFoundException { + /* pre-condition */ + assertFalse(DATABASE_2_PUBLIC); + /* test */ findById_generic(CONTAINER_2_ID, CONTAINER_2, DATABASE_2_ID, DATABASE_2, USER_1_PRINCIPAL); } @@ -523,6 +583,9 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { public void findById_researcherPrivateForeignDatabase_succeeds() throws AccessDeniedException, DatabaseNotFoundException { + /* pre-condition */ + assertFalse(DATABASE_2_PUBLIC); + /* test */ findById_generic(CONTAINER_2_ID, CONTAINER_2, DATABASE_2_ID, DATABASE_2, USER_1_PRINCIPAL); } @@ -532,6 +595,9 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { public void findById_developerPublicForeignDatabase_succeeds() throws AccessDeniedException, DatabaseNotFoundException { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* test */ findById_generic(CONTAINER_3_ID, CONTAINER_3, DATABASE_3_ID, DATABASE_3, USER_2_PRINCIPAL); } @@ -540,6 +606,9 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { @WithMockUser(username = USER_2_USERNAME, roles = {"DEVELOPER"}) public void findById_developerPrivate_succeeds() throws AccessDeniedException, DatabaseNotFoundException { + /* pre-condition */ + assertFalse(DATABASE_2_PUBLIC); + /* test */ findById_generic(CONTAINER_2_ID, CONTAINER_2, DATABASE_2_ID, DATABASE_2, USER_2_PRINCIPAL); } @@ -548,6 +617,9 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { @WithMockUser(username = USER_3_USERNAME, roles = {"DATA_STEWARD"}) public void findById_dataStewardPublic_succeeds() throws AccessDeniedException, DatabaseNotFoundException { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* test */ findById_generic(CONTAINER_3_ID, CONTAINER_3, DATABASE_3_ID, DATABASE_3, USER_3_PRINCIPAL); } @@ -557,8 +629,11 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { public void findById_dataStewardPublicForeignDatabase_succeeds() throws AccessDeniedException, DatabaseNotFoundException { + /* pre-condition */ + assertTrue(DATABASE_3_PUBLIC); + /* test */ - findById_generic(CONTAINER_1_ID, CONTAINER_1, DATABASE_1_ID, DATABASE_1, USER_3_PRINCIPAL); + findById_generic(CONTAINER_3_ID, CONTAINER_3, DATABASE_3_ID, DATABASE_3, USER_3_PRINCIPAL); } @Test @@ -566,6 +641,9 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest { public void findById_dataStewardPrivateForeignDatabase_succeeds() throws AccessDeniedException, DatabaseNotFoundException { + /* pre-condition */ + assertFalse(DATABASE_2_PUBLIC); + /* test */ findById_generic(CONTAINER_2_ID, CONTAINER_2, DATABASE_2_ID, DATABASE_2, USER_3_PRINCIPAL); } diff --git a/fda-database-service/rest-service/src/test/resources/application.properties b/fda-database-service/rest-service/src/test/resources/application.properties index 33b8c25e25a0fe7db1a47bc8349d3d31e834e179..ddfddd8b33f6b4807c1047703d873571b4f89c24 100644 --- a/fda-database-service/rest-service/src/test/resources/application.properties +++ b/fda-database-service/rest-service/src/test/resources/application.properties @@ -22,8 +22,8 @@ logging.level.root=error logging.level.at.tuwien.=info # rabbitmq -fda.gateway.endpoint=http://broker-service:15672 -spring.rabbitmq.host=broker-service +fda.gateway.endpoint=http://dbrepo-broker-service:15672 +spring.rabbitmq.host=dbrepo-broker-service # elastic fda.elastic.endpoint=search-mock-service:9200 \ No newline at end of file diff --git a/fda-database-service/rest-service/src/test/resources/nginx/nginx.conf b/fda-database-service/rest-service/src/test/resources/nginx/nginx.conf index f4ada65dc83ba0cb149a1136ef36bbaf87fff513..6604865024d8e32d66f23a8f49fd0bca5e2c3e70 100644 --- a/fda-database-service/rest-service/src/test/resources/nginx/nginx.conf +++ b/fda-database-service/rest-service/src/test/resources/nginx/nginx.conf @@ -39,7 +39,7 @@ http { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://broker-service:15672; + proxy_pass http://dbrepo-broker-service:15672; proxy_read_timeout 90; } } diff --git a/fda-database-service/services/src/main/java/at/tuwien/mapper/DatabaseMapper.java b/fda-database-service/services/src/main/java/at/tuwien/mapper/DatabaseMapper.java index 26aca837e2aa6721fbf29c42bd0cdb6336bd11db..f986f7577245bb0161e9d5d046da92fd22e40012 100644 --- a/fda-database-service/services/src/main/java/at/tuwien/mapper/DatabaseMapper.java +++ b/fda-database-service/services/src/main/java/at/tuwien/mapper/DatabaseMapper.java @@ -85,6 +85,7 @@ public interface DatabaseMapper { @Mapping(target = "id", source = "id"), @Mapping(target = "engine", source = "container.image", qualifiedByName = "engineMapping"), @Mapping(target = "created", source = "created", dateFormat = "dd-MM-yyyy HH:mm"), + @Mapping(target = "container", ignore = true), }) DatabaseBriefDto databaseToDatabaseBriefDto(Database data); diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java index c8a6ff55aa0d1bd132e4980faf983eed383fa230..e48292d75310ad48545ef11501778970e166fe6e 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java @@ -1,5 +1,6 @@ package at.tuwien.api.container; +import at.tuwien.api.database.DatabaseBriefDto; import at.tuwien.api.user.UserBriefDto; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; @@ -36,6 +37,9 @@ public class ContainerBriefDto { @Schema(example = "air-quality") private String internalName; + @org.springframework.data.annotation.Transient + private DatabaseBriefDto database; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC") private Instant created; } diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java index 699889b1c14ae5b0dea7b269859a75f7d5ec0b41..d91f7ce74dfda4a4ef483c774ab25f3b8f7e763e 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java @@ -1,6 +1,7 @@ package at.tuwien.api.database; import at.tuwien.api.container.ContainerBriefDto; +import at.tuwien.api.identifier.IdentifierBriefDto; import at.tuwien.api.identifier.IdentifierDto; import at.tuwien.api.user.UserBriefDto; import com.fasterxml.jackson.annotation.JsonFormat; @@ -30,7 +31,7 @@ public class DatabaseBriefDto { @Schema(example = "Air Quality in Austria") private String description; - private IdentifierDto identifier; + private IdentifierBriefDto identifier; @JsonProperty("is_public") @Schema(example = "true") @@ -39,11 +40,10 @@ public class DatabaseBriefDto { @Schema(example = "mariadb:10.5") private String engine; + @ToString.Exclude @org.springframework.data.annotation.Transient private ContainerBriefDto container; - private UserBriefDto creator; - @Schema(example = "2020-08-04 11:12:00") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC") private Instant created; diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/CreatorBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/CreatorBriefDto.java new file mode 100644 index 0000000000000000000000000000000000000000..ad0910407b22e7c89f9e9f10a18e622a475e6cf7 --- /dev/null +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/CreatorBriefDto.java @@ -0,0 +1,28 @@ + +package at.tuwien.api.identifier; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotBlank; +@Data +@Getter +@Setter +@Builder +public class CreatorBriefDto { + + @NotBlank + @Schema(example = "Josiah") + private String firstname; + + @NotBlank + @Schema(example = "Carberry") + private String lastname; + + @Schema(example = "Wesleyan University") + private String affiliation; + +} diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierBriefDto.java index a3e816be75a185466c64e6c91b86a5318e072771..c17feec05c19de48c19767e6cf083a8a7a8d01d8 100644 --- a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierBriefDto.java +++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierBriefDto.java @@ -12,6 +12,7 @@ import lombok.Setter; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.time.Instant; +import java.util.List; @Data @Getter @@ -43,6 +44,24 @@ public class IdentifierBriefDto { @NotNull private IdentifierTypeDto type; + @NotNull + @Schema(example = "everyone") + private VisibilityTypeDto visibility; + + @Schema(example = "10.1038/nphys1170") + private String doi; + + @Schema(example = "TU Wien") + private String publisher; + + @NotNull + @JsonProperty("publication_year") + @Schema(example = "2022") + private Integer publicationYear; + + @NotNull + private List<CreatorBriefDto> creators; + @JsonIgnore @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC") private Instant created; diff --git a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/database/Database.java b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/database/Database.java index 90a49b81b8ff9b4d7606ccab40af547aa8850e55..a3233d71357167b90055506402e4d873f59a3c5c 100644 --- a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/database/Database.java +++ b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/database/Database.java @@ -5,16 +5,15 @@ import at.tuwien.entities.database.table.Table; import at.tuwien.entities.identifier.Identifier; import at.tuwien.entities.user.User; import lombok.*; -import net.sf.jsqlparser.statement.select.FromItem; -import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.SQLDelete; -import org.hibernate.annotations.Where; +import org.hibernate.annotations.*; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; -import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import java.io.Serializable; import java.time.Instant; import java.util.List; @@ -28,7 +27,7 @@ import java.util.List; @javax.persistence.Table(name = "mdb_databases", uniqueConstraints = { @UniqueConstraint(columnNames = {"id", "internalName"}) }) -public class Database { +public class Database implements Serializable { @Id @EqualsAndHashCode.Include @@ -73,6 +72,13 @@ public class Database { }) private User contact; + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumnsOrFormulas({ + @JoinColumnOrFormula(formula = @JoinFormula(value = "'DATABASE'", referencedColumnName = "identifier_type")), + @JoinColumnOrFormula(column = @JoinColumn(name = "id", referencedColumnName = "dbid", insertable = false, updatable = false)), + }) + private Identifier identifier; + @ToString.Exclude @org.springframework.data.annotation.Transient @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) diff --git a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java index a6385bb9088b4e703a479f229213141401839b76..95ffd29e5907c9585f1f64402e396dc5d24065d1 100644 --- a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java +++ b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java @@ -3,19 +3,16 @@ package at.tuwien.entities.identifier; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.LanguageType; import at.tuwien.entities.database.License; -import at.tuwien.entities.user.Token; import at.tuwien.entities.user.User; import lombok.*; import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.SQLDelete; -import org.hibernate.annotations.Where; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; -import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; import javax.validation.constraints.NotBlank; +import java.io.Serializable; import java.time.Instant; import java.util.List; @@ -29,7 +26,7 @@ import java.util.List; @javax.persistence.Table(name = "mdb_identifiers", uniqueConstraints = { @UniqueConstraint(columnNames = {"qid", "cid", "dbid"}) }) -public class Identifier { +public class Identifier implements Serializable { @Id @EqualsAndHashCode.Include diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableDataEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableDataEndpoint.java index 117a60a338a2fca66f2bd6ae3a412a969585c634..277e622b6273f66827b116972b8498e30b20dc43 100644 --- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableDataEndpoint.java +++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/TableDataEndpoint.java @@ -147,7 +147,7 @@ public class TableDataEndpoint extends AbstractEndpoint { @RequestParam(required = false) String sortColumn) throws TableNotFoundException, DatabaseNotFoundException, DatabaseConnectionException, ImageNotSupportedException, TableMalformedException, PaginationException, ContainerNotFoundException, - QueryStoreException, NotAllowedException, QueryMalformedException, SortException, UserNotFoundException { + NotAllowedException, QueryMalformedException, SortException, UserNotFoundException { log.debug("endpoint find table data, containerId={}, databaseId={}, tableId={}, principal={}, timestamp={}, page={}, size={}, sortDirection={}, sortColumn={}", containerId, databaseId, tableId, principal, timestamp, page, size, sortDirection, sortColumn); /* check */ @@ -156,16 +156,9 @@ public class TableDataEndpoint extends AbstractEndpoint { throw new NotAllowedException("Missing data view permission"); } validateDataParams(page, size, sortDirection, sortColumn); - /* find */ - // TODO: Remove these comments - //final Long count = queryService.count(containerId, databaseId, tableId, timestamp, principal); - //log.debug("find table data has produced {} tuples", count); - //final HttpHeaders headers = new HttpHeaders(); - //headers.set("FDA-COUNT", count.toString()); final QueryResultDto response = queryService.tableFindAll(containerId, databaseId, tableId, timestamp, page, size, principal); log.trace("find table data resulted in result {}", response); return ResponseEntity.ok() - // .headers(headers) .body(response); } diff --git a/fda-query-service/rest-service/src/main/resources/application-local.yml b/fda-query-service/rest-service/src/main/resources/application-local.yml index 8e36da9b7be6e9aa2e1ba5aee7d69ab244f1cd24..9451262fbd588419c058cfa6f760a81500a7b1e6 100644 --- a/fda-query-service/rest-service/src/main/resources/application-local.yml +++ b/fda-query-service/rest-service/src/main/resources/application-local.yml @@ -32,7 +32,7 @@ logging: pattern.console: "%d %highlight(%-5level) %msg%n" level: root: warn - at.tuwien.: info + at.tuwien.: trace org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug eureka: instance.hostname: query-service diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java index dd59dcd081f4fabaf29f7bd24bcba943190eb90a..556aa3937d3830d8f2c40b6c679ceb874843190b 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java @@ -300,12 +300,22 @@ public abstract class BaseUnitTest { .tag(IMAGE_ELASTIC_TAG) .build(); + public final static Long IMAGE_PROXY_ID = 4L; + public final static String IMAGE_PROXY_REPOSITORY = "nginx"; + public final static String IMAGE_PROXY_TAG = "latest"; + + public final static ContainerImage IMAGE_PROXY = ContainerImage.builder() + .id(IMAGE_PROXY_ID) + .repository(IMAGE_PROXY_REPOSITORY) + .tag(IMAGE_PROXY_TAG) + .build(); + public final static Long CONTAINER_1_ID = 1L; public final static String CONTAINER_1_HASH = "deadbeef"; public final static ContainerImage CONTAINER_1_IMAGE = IMAGE_1; public final static String CONTAINER_1_NAME = "u01"; - public final static String CONTAINER_1_INTERNALNAME = "fda-userdb-u01"; - public final static String CONTAINER_1_IP = "172.28.0.5"; + public final static String CONTAINER_1_INTERNALNAME = "dbrepo-userdb-u01"; + public final static String CONTAINER_1_IP = "172.30.0.5"; public final static Instant CONTAINER_1_CREATED = Instant.now().minus(1, HOURS); public final static String[] CONTAINER_1_ENV = new String[]{"MARIADB_USER=mariadb", "MARIADB_PASSWORD=mariadb", "MARIADB_ROOT_PASSWORD=mariadb", "MARIADB_DATABASE=weather"}; @@ -328,8 +338,8 @@ public abstract class BaseUnitTest { public final static String CONTAINER_2_HASH = "deadbeef"; public final static ContainerImage CONTAINER_2_IMAGE = IMAGE_1; public final static String CONTAINER_2_NAME = "u02"; - public final static String CONTAINER_2_INTERNALNAME = "fda-userdb-u02"; - public final static String CONTAINER_2_IP = "172.28.0.6"; + public final static String CONTAINER_2_INTERNALNAME = "dbrepo-userdb-u02"; + public final static String CONTAINER_2_IP = "172.30.0.6"; public final static Instant CONTAINER_2_CREATED = Instant.now().minus(1, HOURS); public final static String[] CONTAINER_2_ENV = new String[]{"MARIADB_USER=mariadb", "MARIADB_PASSWORD=mariadb", "MARIADB_ROOT_PASSWORD=mariadb", "MARIADB_DATABASE=zoo"}; @@ -352,8 +362,8 @@ public abstract class BaseUnitTest { public final static String CONTAINER_3_HASH = "deadbeef"; public final static ContainerImage CONTAINER_3_IMAGE = IMAGE_1; public final static String CONTAINER_3_NAME = "u03"; - public final static String CONTAINER_3_INTERNALNAME = "fda-userdb-u03"; - public final static String CONTAINER_3_IP = "172.28.0.7"; + public final static String CONTAINER_3_INTERNALNAME = "dbrepo-userdb-u03"; + public final static String CONTAINER_3_IP = "172.30.0.7"; public final static Instant CONTAINER_3_CREATED = Instant.now().minus(1, HOURS); public final static HealthCheck CONTAINER_3_HEALTHCHECK = new HealthCheck() .withTest(List.of("CMD", "mysqladmin", "ping", "--host=127.0.0.1", "--password=mariadb")); @@ -373,8 +383,8 @@ public abstract class BaseUnitTest { public final static String CONTAINER_4_HASH = "deadbeef"; public final static ContainerImage CONTAINER_4_IMAGE = IMAGE_1; public final static String CONTAINER_4_NAME = "u04"; - public final static String CONTAINER_4_INTERNALNAME = "fda-userdb-u04"; - public final static String CONTAINER_4_IP = "172.28.0.8"; + public final static String CONTAINER_4_INTERNALNAME = "dbrepo-userdb-u04"; + public final static String CONTAINER_4_IP = "172.30.0.8"; public final static Instant CONTAINER_4_CREATED = Instant.now().minus(1, HOURS); public final static HealthCheck CONTAINER_4_HEALTHCHECK = new HealthCheck() .withTest(List.of("CMD", "mysqladmin", "ping", "--host=127.0.0.1", "--password=mariadb")); @@ -394,9 +404,9 @@ public abstract class BaseUnitTest { .build(); public final static Long CONTAINER_BROKER_ID = 5L; - public final static String CONTAINER_BROKER_NAME = "broker-service"; - public final static String CONTAINER_BROKER_INTERNAL_NAME = "broker-service"; - public final static String CONTAINER_BROKER_IP = "172.29.0.2"; + public final static String CONTAINER_BROKER_NAME = "dbrepo-broker-service"; + public final static String CONTAINER_BROKER_INTERNAL_NAME = "dbrepo-broker-service"; + public final static String CONTAINER_BROKER_IP = "172.31.0.2"; public final static String CONTAINER_BROKER_HASH = "deadbeef"; public final static Instant CONTAINER_BROKER_CREATED = Instant.now().minus(1, HOURS); public final static HealthCheck CONTAINER_BROKER_HEALTHCHECK = new HealthCheck() @@ -418,7 +428,7 @@ public abstract class BaseUnitTest { public final static Long CONTAINER_ELASTIC_ID = 6L; public final static String CONTAINER_ELASTIC_NAME = "fda-elastic-service"; public final static String CONTAINER_ELASTIC_INTERNAL_NAME = "search-mock-service"; - public final static String CONTAINER_ELASTIC_IP = "172.29.0.3"; + public final static String CONTAINER_ELASTIC_IP = "172.31.0.3"; public final static String CONTAINER_ELASTIC_HASH = "deadbeef"; public final static Instant CONTAINER_ELASTIC_CREATED = Instant.now().minus(1, HOURS); @@ -434,6 +444,28 @@ public abstract class BaseUnitTest { .creator(USER_1) .build(); + public final static Long CONTAINER_PROXY_ID = 7L; + public final static String CONTAINER_PROXY_NAME = "dbrepo-proxy"; + public final static String CONTAINER_PROXY_INTERNAL_NAME = "dbrepo-proxy"; + public final static String CONTAINER_PROXY_IP = "172.31.0.4"; + public final static String CONTAINER_PROXY_HASH = "deadbeef"; + public final static Instant CONTAINER_PROXY_CREATED = Instant.now().minus(1, HOURS); + public final static String[] CONTAINER_PROXY_ENV = new String[]{}; + public final static HealthCheck CONTAINER_PROXY_HEALTHCHECK = new HealthCheck() + .withTest(List.of("CMD", "service", "nginx", "status")); + + public final static Container CONTAINER_PROXY = Container.builder() + .id(CONTAINER_PROXY_ID) + .name(CONTAINER_PROXY_NAME) + .internalName(CONTAINER_PROXY_INTERNAL_NAME) + .imageId(IMAGE_PROXY_ID) + .image(IMAGE_PROXY) + .hash(CONTAINER_PROXY_HASH) + .ipAddress(CONTAINER_PROXY_IP) + .created(CONTAINER_PROXY_CREATED) + .creator(USER_1) + .build(); + public final static Long DATABASE_1_ID = 1L; public final static String DATABASE_1_NAME = "Weather"; public final static String DATABASE_1_INTERNALNAME = "weather"; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/auth/AuthTokenFilterTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/auth/AuthTokenFilterTest.java index eac19243984f0eb4936c6121ade14f9b9ece160f..bf3df721bafd91903a06bc74726a6347a1a293e5 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/auth/AuthTokenFilterTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/auth/AuthTokenFilterTest.java @@ -5,7 +5,6 @@ import at.tuwien.config.H2Utils; import at.tuwien.config.IndexConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.gateway.AuthenticationServiceGateway; -import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.repository.jpa.UserRepository; import com.rabbitmq.client.Channel; import lombok.extern.log4j.Log4j2; @@ -46,9 +45,6 @@ public class AuthTokenFilterTest extends BaseUnitTest { @MockBean private UserRepository userRepository; - @MockBean - private RabbitMqListenerImpl rabbitMqListener; - @MockBean private AuthenticationServiceGateway authenticationServiceGateway; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/config/DockerConfig.java b/fda-query-service/rest-service/src/test/java/at/tuwien/config/DockerConfig.java index 2f03e666f19c250ae0afe19f3bdc548586e2acc3..f91219b29e5831a008e39cc3656d47d9bbdcf6e0 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/config/DockerConfig.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/config/DockerConfig.java @@ -90,12 +90,16 @@ public class DockerConfig extends BaseUnitTest { final HostConfig hostConfig1; final String network = (container.getInternalName().contains("userdb") ? "fda-userdb" : "fda-public"); if (bind == null) { + log.trace("map standard binding /tmp:/tmp"); hostConfig1 = hostConfig.withNetworkMode(network) .withBinds(Bind.parse("/tmp:/tmp")); } else { - hostConfig1 = hostConfig.withNetworkMode(network).withBinds(Bind.parse(bind), Bind.parse("/tmp:/tmp")); + log.trace("map non-standard binding {}, /tmp:/tmp", bind); + hostConfig1 = hostConfig.withNetworkMode(network) + .withBinds(Bind.parse(bind), Bind.parse("/tmp:/tmp")); } if (port != null) { + log.trace("map port binding {}:{}", port, port); hostConfig1.withPortBindings(PortBinding.parse(port + ":" + port)); } final CreateContainerCmd cmd = dockerClient.createContainerCmd(container.getImage().getRepository() + ":" + container.getImage().getTag()) @@ -158,14 +162,14 @@ public class DockerConfig extends BaseUnitTest { .withName("fda-userdb") .withIpam(new Network.Ipam() .withConfig(new Network.Ipam.Config() - .withSubnet("172.28.0.0/16"))) + .withSubnet("172.30.0.0/16"))) .withEnableIpv6(false) .exec(); dockerClient.createNetworkCmd() .withName("fda-public") .withIpam(new Network.Ipam() .withConfig(new Network.Ipam.Config() - .withSubnet("172.29.0.0/16"))) + .withSubnet("172.31.0.0/16"))) .withEnableIpv6(false) .exec(); } @@ -191,6 +195,9 @@ public class DockerConfig extends BaseUnitTest { case 5: log.debug("container with id {} has a health check config", containerId); return CONTAINER_BROKER_HEALTHCHECK; + case 7: + log.debug("container with id {} has a health check config", containerId); + return CONTAINER_PROXY_HEALTHCHECK; } log.trace("container with id {} does not have a healthcheck config", containerId); return null; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/config/RabbitMqConfig.java b/fda-query-service/rest-service/src/test/java/at/tuwien/config/RabbitMqConfig.java index 0ee03e69ad4e85d2f54c09488fb5bf94265946d6..72ef54c966d37a7f92566228f9e00cbf6f8643a1 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/config/RabbitMqConfig.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/config/RabbitMqConfig.java @@ -33,7 +33,7 @@ public class RabbitMqConfig { public List<ConsumerDto> findAllConsumers() throws IOException { log.trace("gateway broker find all consumers"); - final URI findUri = URI.create("http://broker-service:15672/api/consumers/%2F"); + final URI findUri = URI.create("http://dbrepo-broker-service:15672/api/consumers/%2F"); final ResponseEntity<List<ConsumerDto>> response = restTemplate.exchange(findUri, HttpMethod.GET, new HttpEntity<>(null, getHeaders()), new ParameterizedTypeReference<>() { }); @@ -52,7 +52,7 @@ public class RabbitMqConfig { } } for (Map.Entry<String, Integer> consumer : consumers.entrySet()) { - log.debug("queue {} has {} consumers", consumer.getKey(), consumer.getValue()); + log.trace("queue {} has {} consumers", consumer.getKey(), consumer.getValue()); } return response.getBody(); } diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/ExportEndpointUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/ExportEndpointUnitTest.java index 4b3898d83a64f5dfc8c5cfc5973dcbf5b1e56847..f5126e08b48fb31b936fd2e56d4ab8ff7bd3f685 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/ExportEndpointUnitTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/ExportEndpointUnitTest.java @@ -7,6 +7,8 @@ import at.tuwien.config.ReadyConfig; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.exception.*; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.repository.jpa.DatabaseAccessRepository; import at.tuwien.repository.jpa.TableRepository; @@ -49,9 +51,14 @@ public class ExportEndpointUnitTest extends BaseUnitTest { @MockBean private IndexConfig indexInitializer; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @MockBean private QueryService queryService; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointUnitTest.java index 7b1e9ade2c5e6b276207d2ebcc714da4b95cd464..8f315d2b404e95c7e0675ef36e13f6d9a88b0485 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointUnitTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointUnitTest.java @@ -10,6 +10,8 @@ import at.tuwien.config.ReadyConfig; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.exception.*; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.repository.jpa.ContainerRepository; import at.tuwien.repository.jpa.DatabaseAccessRepository; @@ -52,9 +54,14 @@ public class QueryEndpointUnitTest extends BaseUnitTest { @MockBean private IndexConfig indexInitializer; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @MockBean private DatabaseAccessRepository databaseAccessRepository; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/StoreEndpointUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/StoreEndpointUnitTest.java index f323836cf21f413ec01d6ae0374c52915e966e64..42782640bde805393dcf28bc3e735c5e9ecd1461 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/StoreEndpointUnitTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/StoreEndpointUnitTest.java @@ -9,6 +9,8 @@ import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.entities.user.User; import at.tuwien.exception.*; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.querystore.Query; import at.tuwien.repository.jpa.IdentifierRepository; @@ -51,9 +53,14 @@ public class StoreEndpointUnitTest extends BaseUnitTest { @MockBean private IndexConfig indexInitializer; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @Autowired private StoreEndpoint storeEndpoint; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/TableDataEndpointUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/TableDataEndpointUnitTest.java index 38de6122bf4c2ed9ef83dcbe79f41c2bc86204b5..4cf2392ed0a94319043e7738151d0c86123b7cf7 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/TableDataEndpointUnitTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/TableDataEndpointUnitTest.java @@ -11,6 +11,8 @@ import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.entities.database.table.Table; import at.tuwien.exception.*; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.service.AccessService; import at.tuwien.service.DatabaseService; @@ -47,9 +49,14 @@ public class TableDataEndpointUnitTest extends BaseUnitTest { @MockBean private Channel channel; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @MockBean private QueryServiceImpl queryService; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/TableHistoryEndpointUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/TableHistoryEndpointUnitTest.java index a06089955e982a0ae2862c283330e95b001e07d1..9a649b2e39f4a8978ebdf5b490f8aa70eab8c11d 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/TableHistoryEndpointUnitTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/TableHistoryEndpointUnitTest.java @@ -9,6 +9,8 @@ import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.entities.database.table.Table; import at.tuwien.exception.*; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.repository.jpa.DatabaseAccessRepository; import at.tuwien.service.DatabaseService; @@ -48,9 +50,14 @@ public class TableHistoryEndpointUnitTest extends BaseUnitTest { @MockBean private Channel channel; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @MockBean private QueryService queryService; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java index 36430b419c6528093e95776f6373d462bc8ad5bf..5cf4aadd98085ace3f9bfe569c5d9e0a063c9103 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/ViewEndpointUnitTest.java @@ -11,6 +11,8 @@ import at.tuwien.config.ReadyConfig; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.exception.*; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.service.AccessService; import at.tuwien.service.DatabaseService; @@ -50,9 +52,14 @@ public class ViewEndpointUnitTest extends BaseUnitTest { @MockBean private IndexConfig indexInitializer; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @MockBean private QueryService queryService; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/listener/RabbitMqListenerIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/listener/RabbitMqListenerIntegrationTest.java index 1ddaac142af69e4b7dfab255160e6cd6a1f87618..79b0f37ba1eba66423510c703ec9992249b3098e 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/listener/RabbitMqListenerIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/listener/RabbitMqListenerIntegrationTest.java @@ -3,9 +3,6 @@ package at.tuwien.listener; import at.tuwien.BaseUnitTest; import at.tuwien.api.amqp.ConsumerDto; import at.tuwien.config.*; -import at.tuwien.exception.*; -import at.tuwien.gateway.BrokerServiceGateway; -import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.repository.jpa.*; import com.rabbitmq.client.BuiltinExchangeType; import com.rabbitmq.client.Channel; @@ -18,16 +15,18 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.io.IOException; import java.util.*; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.when; @Log4j2 +@ActiveProfiles(profiles = "junit") @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @SpringBootTest @ExtendWith(SpringExtension.class) @@ -39,9 +38,6 @@ public class RabbitMqListenerIntegrationTest extends BaseUnitTest { @MockBean private IndexConfig indexConfig; - @MockBean - private BrokerServiceGateway brokerServiceGateway; - @Autowired private Channel channel; @@ -57,12 +53,6 @@ public class RabbitMqListenerIntegrationTest extends BaseUnitTest { @Autowired private TableRepository tableRepository; - @Autowired - private RabbitMqListenerImpl rabbitMqListener; - - @Autowired - private TableColumnRepository tableColumnRepository; - @Autowired private H2Utils h2Utils; @@ -73,12 +63,14 @@ public class RabbitMqListenerIntegrationTest extends BaseUnitTest { private AmqpConfig amqpConfig; @Rule - public Timeout globalTimeout = Timeout.seconds(60); + public Timeout globalTimeout = Timeout.seconds(300); @BeforeAll public static void beforeAll() throws InterruptedException { afterAll(); + /* create networks */ DockerConfig.createAllNetworks(); + /* create containers */ DockerConfig.createContainer(null, CONTAINER_BROKER, 15672, CONTAINER_BROKER_ENV); DockerConfig.startContainer(CONTAINER_BROKER); } @@ -104,7 +96,11 @@ public class RabbitMqListenerIntegrationTest extends BaseUnitTest { } @Test - public void updateConsumers_succeeds() throws AmqpException, IOException, InterruptedException { + public void updateConsumers_succeeds() throws IOException, InterruptedException { + + /* pre-condition */ + assertEquals(0, getConsumers().size()); + assertEquals(2, amqpConfig.getAmqpConsumers()); /* mock */ channel.exchangeDeclare(DATABASE_1_EXCHANGE, BuiltinExchangeType.FANOUT); @@ -114,21 +110,23 @@ public class RabbitMqListenerIntegrationTest extends BaseUnitTest { channel.queueBind(TABLE_2_QUEUE_NAME, DATABASE_1_EXCHANGE, TABLE_2_ROUTING_KEY); channel.queueDeclare(TABLE_3_QUEUE_NAME, true, false, false, null); channel.queueBind(TABLE_3_QUEUE_NAME, DATABASE_1_EXCHANGE, TABLE_3_ROUTING_KEY); - when(brokerServiceGateway.findAllConsumers()) - .thenReturn(List.of()); - - /* pre-condition */ - assertEquals(0, rabbitMqConfig.findAllConsumers().size()); - assertEquals(2, amqpConfig.getAmqpConsumers()); /* test */ - rabbitMqListener.updateConsumers(); - Thread.sleep(10 * 1000); - final List<ConsumerDto> response = rabbitMqConfig.findAllConsumers(); - assertEquals(6, response.size()); - assertEquals(2, (int) response.stream().filter(c -> c.getQueue().getName().equals(TABLE_1_QUEUE_NAME)).count()); - assertEquals(2, (int) response.stream().filter(c -> c.getQueue().getName().equals(TABLE_2_QUEUE_NAME)).count()); - assertEquals(2, (int) response.stream().filter(c -> c.getQueue().getName().equals(TABLE_3_QUEUE_NAME)).count()); + Thread.sleep(30 * 1000) /* wait for scheduled insert */; + final List<ConsumerDto> response = getConsumers(); + final List<ConsumerDto> consumers1 = response.stream().filter(c -> c.getQueue().getName().equals(TABLE_1_QUEUE_NAME)).collect(Collectors.toList()); + assertEquals(2, consumers1.size()); + final List<ConsumerDto> consumers2 = response.stream().filter(c -> c.getQueue().getName().equals(TABLE_2_QUEUE_NAME)).collect(Collectors.toList()); + assertEquals(2, consumers2.size()); + final List<ConsumerDto> consumers3 = response.stream().filter(c -> c.getQueue().getName().equals(TABLE_3_QUEUE_NAME)).collect(Collectors.toList()); + assertEquals(2, consumers3.size()); + } + + private List<ConsumerDto> getConsumers() throws IOException { + return rabbitMqConfig.findAllConsumers() + .stream() + .filter(c -> List.of(TABLE_1_QUEUE_NAME, TABLE_2_QUEUE_NAME, TABLE_3_QUEUE_NAME).contains(c.getQueue().getName())) + .collect(Collectors.toList()); } } diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/repository/ViewIdxRepositoryIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/repository/ViewIdxRepositoryIntegrationTest.java index d8d59487f6392de975b5fc300306202c604da683..834eb218364aa250de500e3c96f84c9f9bea064e 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/repository/ViewIdxRepositoryIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/repository/ViewIdxRepositoryIntegrationTest.java @@ -7,6 +7,8 @@ import at.tuwien.config.DockerConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.entities.database.View; import at.tuwien.exception.*; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.repository.elastic.ViewIdxRepository; import at.tuwien.repository.jpa.*; @@ -45,9 +47,14 @@ public class ViewIdxRepositoryIntegrationTest extends BaseUnitTest { @MockBean private Channel channel; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @MockBean private UserRepository userRepository; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/repository/ViewRepositoryIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/repository/ViewRepositoryIntegrationTest.java index 4000a1559936d4cdfc754f3707f21cc9f439c85e..eddcffdc8e9e12dc638394e60ef7849286f684c0 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/repository/ViewRepositoryIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/repository/ViewRepositoryIntegrationTest.java @@ -5,6 +5,8 @@ import at.tuwien.config.H2Utils; import at.tuwien.config.IndexConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.entities.database.View; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.repository.jpa.*; import com.rabbitmq.client.Channel; @@ -36,9 +38,14 @@ public class ViewRepositoryIntegrationTest extends BaseUnitTest { @MockBean private Channel channel; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @MockBean private IndexConfig indexConfig; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java index 29d3e0f2d8ebf9c89d4c6ff2c234f7a0048dd473..ba53952bab69043e081cd65e2cd7c7d8d1a9c62f 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java @@ -5,6 +5,8 @@ import at.tuwien.config.IndexConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.entities.container.Container; import at.tuwien.exception.*; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.repository.jpa.*; import com.rabbitmq.client.Channel; @@ -35,9 +37,14 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest { @MockBean private Channel channel; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @Autowired private ImageRepository imageRepository; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java index ba2db43d65cc1c7fa79e8529571bf3ce89475697..421304d117fab2be463d6fd752a080d52a7171cb 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java @@ -10,6 +10,8 @@ import at.tuwien.config.IndexConfig; import at.tuwien.config.MariaDbConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.exception.*; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.querystore.Query; import at.tuwien.repository.jpa.*; @@ -56,9 +58,14 @@ public class QueryServiceIntegrationTest extends BaseUnitTest { @MockBean private IndexConfig indexInitializer; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @MockBean private DatabaseRepository databaseRepository; @@ -79,12 +86,10 @@ public class QueryServiceIntegrationTest extends BaseUnitTest { private final static String BIND_ZOO = new File("./src/test/resources/zoo").toPath().toAbsolutePath() + ":/docker-entrypoint-initdb.d"; @BeforeAll - public static void beforeAll() throws InterruptedException { + public static void beforeAll() { afterAll(); /* create network */ DockerConfig.createAllNetworks(); - DockerConfig.createContainer(null, CONTAINER_BROKER, 15672, CONTAINER_BROKER_ENV); - DockerConfig.startContainer(CONTAINER_BROKER); } @AfterAll diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java index 0fe3b659ef0ec5d9e7ceee04e6e7344a021f5f64..49a47646b20d3fe4dc98c7dcf95df339c3beaafb 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueueServiceIntegrationTest.java @@ -8,6 +8,8 @@ import at.tuwien.config.DockerConfig; import at.tuwien.config.IndexConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.exception.AmqpException; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.repository.jpa.DatabaseRepository; import at.tuwien.repository.jpa.TableRepository; @@ -53,11 +55,16 @@ public class QueueServiceIntegrationTest extends BaseUnitTest { @MockBean private IndexConfig indexInitializer; + @MockBean + private RabbitMqConsumer rabbitMqConsumer; + + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ @MockBean - private RabbitMqConsumer rabbitMqConsumer; + private BrokerServiceGateway brokerServiceGateway; @Autowired private AmqpConfig amqpConfig; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/StoreServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/StoreServiceIntegrationTest.java index 17e9cb979bc2eaecb2480ba558bbafb540b219ef..3307d1bf8187628cf95afa287bf2fc231ad27cf7 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/StoreServiceIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/StoreServiceIntegrationTest.java @@ -9,6 +9,8 @@ import at.tuwien.config.MariaDbConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.exception.*; import at.tuwien.entities.database.Database; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.querystore.Query; import at.tuwien.repository.jpa.*; @@ -51,9 +53,14 @@ public class StoreServiceIntegrationTest extends BaseUnitTest { @MockBean private Channel channel; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @MockBean private TableRepository tableRepository; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java index 14b294520f0cf4d6ba88f1d45f87b36eb47744d4..87c8fa13f7008a0f129a1f04d3acf718826a27d2 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java @@ -8,6 +8,8 @@ import at.tuwien.config.IndexConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.entities.database.table.columns.TableColumn; import at.tuwien.exception.*; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.repository.jpa.ContainerRepository; import at.tuwien.repository.jpa.DatabaseRepository; @@ -50,9 +52,14 @@ public class TableServiceIntegrationTest extends BaseUnitTest { @MockBean private Channel channel; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @MockBean private TableRepository tableRepository; @@ -94,6 +101,7 @@ public class TableServiceIntegrationTest extends BaseUnitTest { /* metadata db */ imageRepository.save(IMAGE_1); containerRepository.save(CONTAINER_1); + DATABASE_1.setTables(List.of()); databaseRepository.save(DATABASE_1); } diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java index 69ce154d9fa9b65765110ba1a27d9468903f3df7..4a523c0a2325d56636b7519368b06a0027e39f25 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java @@ -5,6 +5,8 @@ import at.tuwien.config.IndexConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.entities.database.table.columns.TableColumn; import at.tuwien.exception.*; +import at.tuwien.gateway.BrokerServiceGateway; +import at.tuwien.listener.MessageQueueListener; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.repository.jpa.*; import com.rabbitmq.client.Channel; @@ -39,9 +41,14 @@ public class TableServiceUnitTest extends BaseUnitTest { @MockBean private IndexConfig indexInitializer; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @Autowired private TableService tableService; diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java index d827ec5bfa4e153f6c22f27e0bb77ee7702ab329..c2cf5c3008a214fa63ec571c527e9248ec7c256a 100644 --- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java +++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/ViewServiceIntegrationTest.java @@ -9,13 +9,10 @@ import at.tuwien.config.MariaDbConfig; import at.tuwien.config.ReadyConfig; import at.tuwien.entities.database.View; import at.tuwien.exception.*; +import at.tuwien.gateway.BrokerServiceGateway; import at.tuwien.listener.impl.RabbitMqListenerImpl; import at.tuwien.repository.elastic.ViewIdxRepository; import at.tuwien.repository.jpa.*; -import com.github.dockerjava.api.command.CreateContainerResponse; -import com.github.dockerjava.api.exception.NotModifiedException; -import com.github.dockerjava.api.model.Bind; -import com.github.dockerjava.api.model.Network; import com.rabbitmq.client.Channel; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.AfterAll; @@ -30,12 +27,10 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import java.io.File; import java.sql.SQLException; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Optional; -import static at.tuwien.config.DockerConfig.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.ArgumentMatchers.any; @@ -60,9 +55,14 @@ public class ViewServiceIntegrationTest extends BaseUnitTest { @MockBean private ViewIdxRepository viewIdxRepository; + /* keep */ @MockBean private RabbitMqListenerImpl rabbitMqListener; + /* keep */ + @MockBean + private BrokerServiceGateway brokerServiceGateway; + @MockBean private DatabaseRepository databaseRepository; diff --git a/fda-query-service/rest-service/src/test/resources/application.properties b/fda-query-service/rest-service/src/test/resources/application.properties index aac636db158551adcc6c17b6dc229f68a96bdd69..4eea490a9199d7e0155b1f33cf3500a5e1f2863f 100644 --- a/fda-query-service/rest-service/src/test/resources/application.properties +++ b/fda-query-service/rest-service/src/test/resources/application.properties @@ -19,12 +19,14 @@ spring.jpa.show-sql=false # additional logging logging.level.root=error -logging.level.at.tuwien.=info +logging.level.at.tuwien.=trace # broker service -spring.rabbitmq.host=broker-service +spring.rabbitmq.host=dbrepo-broker-service spring.rabbitmq.username=guest spring.rabbitmq.password=guest # search service -fda.elastic.endpoint=search-mock-service:9200 \ No newline at end of file +fda.consumers=2 +fda.gateway.endpoint: http://localhost:15672 +fda.elastic.endpoint=dbrepo-search-service:9200 \ No newline at end of file diff --git a/fda-query-service/rest-service/src/test/resources/webserver/weather_aus.csv b/fda-query-service/rest-service/src/test/resources/webserver/weather_aus.csv deleted file mode 100644 index 9bfb33891d9c10db7cd04ba1cf8d32ddc1dcde96..0000000000000000000000000000000000000000 --- a/fda-query-service/rest-service/src/test/resources/webserver/weather_aus.csv +++ /dev/null @@ -1,3 +0,0 @@ -1,2008-12-01,Albury,13.4,0.6 -2,2008-12-02,Albury,7.4,0 -3,2008-12-03,Albury,12.9,0 \ No newline at end of file diff --git a/fda-query-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java b/fda-query-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java index 8a5bc1c3f10f354b0cf1bd850ed208419bb147e3..e8f0b9c364dd7c2166cc605c71572c8efc305e6f 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java +++ b/fda-query-service/services/src/main/java/at/tuwien/gateway/BrokerServiceGateway.java @@ -5,5 +5,6 @@ import at.tuwien.api.amqp.ConsumerDto; import java.util.List; public interface BrokerServiceGateway { + List<ConsumerDto> findAllConsumers(); } diff --git a/fda-query-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java b/fda-query-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java index 16afe426ad48f3bc7733fd86f1140e886319261f..4629fbe4ccb3c567001e215a25d0c1182d78c472 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java +++ b/fda-query-service/services/src/main/java/at/tuwien/gateway/impl/BrokerServiceGatewayImpl.java @@ -7,7 +7,9 @@ import at.tuwien.gateway.BrokerServiceGateway; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.env.Environment; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -17,6 +19,7 @@ import org.springframework.web.client.RestTemplate; import java.net.URI; import java.nio.charset.Charset; +import java.util.Arrays; import java.util.List; @Slf4j @@ -26,20 +29,30 @@ public class BrokerServiceGatewayImpl implements BrokerServiceGateway { private final AmqpConfig amqpConfig; private final RestTemplate restTemplate; private final GatewayConfig gatewayConfig; + private final Environment environment; private final static String VIRTUAL_SERVER = "%2F"; @Autowired - public BrokerServiceGatewayImpl(AmqpConfig amqpConfig, RestTemplate restTemplate, GatewayConfig gatewayConfig) { + public BrokerServiceGatewayImpl(AmqpConfig amqpConfig, RestTemplate restTemplate, GatewayConfig gatewayConfig, + Environment environment) { this.amqpConfig = amqpConfig; this.restTemplate = restTemplate; this.gatewayConfig = gatewayConfig; + this.environment = environment; } @Override public List<ConsumerDto> findAllConsumers() { + final StringBuilder urlBuilder = new StringBuilder(gatewayConfig.getGatewayEndpoint()) + .append("/api"); + if (Arrays.stream(environment.getActiveProfiles()).noneMatch(p -> p.equals("junit"))) { + urlBuilder.append("/broker"); + } + urlBuilder.append("/consumers/") + .append(VIRTUAL_SERVER); log.trace("gateway broker find all consumers, virtual server={}", VIRTUAL_SERVER); - final URI findUri = URI.create(gatewayConfig.getGatewayEndpoint() + "/api/broker/consumers/" + VIRTUAL_SERVER); + final URI findUri = URI.create(urlBuilder.toString()); final ResponseEntity<List<ConsumerDto>> response = restTemplate.exchange(findUri, HttpMethod.GET, new HttpEntity<>(null, getHeaders()), new ParameterizedTypeReference<>() { }); diff --git a/fda-query-service/services/src/main/java/at/tuwien/listener/MessageQueueListener.java b/fda-query-service/services/src/main/java/at/tuwien/listener/MessageQueueListener.java index ebdc5a473931d742f7199067a78468947ee4c597..afac64a7a0b323bb9745a47365e1a8fd8e20f4ae 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/listener/MessageQueueListener.java +++ b/fda-query-service/services/src/main/java/at/tuwien/listener/MessageQueueListener.java @@ -1,4 +1,10 @@ package at.tuwien.listener; +import at.tuwien.exception.AmqpException; +import org.springframework.scheduling.annotation.Scheduled; + public interface MessageQueueListener { + + @Scheduled(fixedDelay = 5000) + void updateConsumers() throws AmqpException; } diff --git a/fda-query-service/services/src/main/java/at/tuwien/listener/impl/RabbitMqListenerImpl.java b/fda-query-service/services/src/main/java/at/tuwien/listener/impl/RabbitMqListenerImpl.java index 1423461dd1d7d5a13a0b031e4ca49039283155a8..bc45a7888800822c806a6ded90cb043670e14fc8 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/listener/impl/RabbitMqListenerImpl.java +++ b/fda-query-service/services/src/main/java/at/tuwien/listener/impl/RabbitMqListenerImpl.java @@ -14,7 +14,6 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.io.IOException; import java.util.List; @Log4j2 @@ -35,6 +34,7 @@ public class RabbitMqListenerImpl implements MessageQueueListener { this.brokerServiceGateway = brokerServiceGateway; } + @Override @Scheduled(fixedDelay = 5000) @Transactional(readOnly = true) public void updateConsumers() throws AmqpException { diff --git a/fda-query-service/services/src/main/java/at/tuwien/mapper/ContainerMapper.java b/fda-query-service/services/src/main/java/at/tuwien/mapper/ContainerMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..7c49211efb805355ea851c87dcbf340474f2d64f --- /dev/null +++ b/fda-query-service/services/src/main/java/at/tuwien/mapper/ContainerMapper.java @@ -0,0 +1,15 @@ +package at.tuwien.mapper; + +import at.tuwien.api.container.ContainerDto; +import at.tuwien.entities.container.Container; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface ContainerMapper { + + org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ContainerMapper.class); + + /* keep */ + ContainerDto containerToContainerDto(Container data); + +} diff --git a/fda-query-service/services/src/main/java/at/tuwien/mapper/ViewMapper.java b/fda-query-service/services/src/main/java/at/tuwien/mapper/ViewMapper.java index 35bcfffb455bb099e0fc067b5801dbc8eb5d1d48..04234f583fe89abaa5556f60495fadf3287f60f9 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/mapper/ViewMapper.java +++ b/fda-query-service/services/src/main/java/at/tuwien/mapper/ViewMapper.java @@ -26,7 +26,7 @@ import java.util.List; import java.util.Locale; import java.util.regex.Pattern; -@Mapper(componentModel = "spring") +@Mapper(componentModel = "spring", uses = {ContainerMapper.class}) public interface ViewMapper { org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ViewMapper.class); diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java b/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java index 686e0c78ec4c3dcf947d03ad6276cd33b76c39c7..01924d9fb29b8729987e5621bd6d4a4006cfa04d 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java @@ -165,7 +165,7 @@ public interface QueryService { QueryResultDto viewFindAll(Long containerId, Long databaseId, View view, Long page, Long size, Principal principal) throws ViewNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, DatabaseConnectionException, ViewMalformedException, PaginationException, - ContainerNotFoundException, QueryMalformedException, UserNotFoundException; + ContainerNotFoundException, QueryMalformedException, UserNotFoundException, TableMalformedException; /** * Finds one query by container-database-query triple. diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java index 0bd5f0c99281ba322971094ec7299ebbb6853972..0c84ec5bb7fc3cefee07784ba145ff748baafa36 100644 --- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java +++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java @@ -101,7 +101,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService columns = parseColumns(query.getQuery(), database); } catch (JSQLParserException e) { log.error("Failed to map/parse columns: {}", e.getMessage()); - throw new ColumnParseException(e.getMessage(), e); + throw new ColumnParseException("Failed to map/parse columns: " + e.getMessage(), e); } final String statement = queryMapper.queryToRawTimestampedQuery(query.getQuery(), database, query.getCreated(), true, page, size); final QueryResultDto dto = executeNonPersistent(containerId, databaseId, statement, columns); @@ -143,7 +143,8 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService } } - private QueryResultDto executeNonPersistent(Long containerId, Long databaseId, String statement, List<TableColumn> columns) throws QueryMalformedException, DatabaseNotFoundException { + private QueryResultDto executeNonPersistent(Long containerId, Long databaseId, String statement, List<TableColumn> columns) + throws QueryMalformedException, DatabaseNotFoundException, TableMalformedException { /* find */ final Database database = databaseService.find(containerId, databaseId); final User root = databaseMapper.containerToPrivilegedUser(database.getContainer()); @@ -156,14 +157,15 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService final ResultSet resultSet = preparedStatement.executeQuery(); return queryMapper.resultListToQueryResultDto(columns, resultSet); } catch (SQLException e) { - log.error("Failed to map object: {}", e.getMessage()); - throw new QueryMalformedException("Failed to map object", e); + log.error("Failed to execute and map time-versioned query: {}", e.getMessage()); + throw new TableMalformedException("Failed to execute and map time-versioned query: " + e.getMessage(), e); } finally { dataSource.close(); } } - private Long executeCountNonPersistent(Long containerId, Long databaseId, String statement) throws QueryMalformedException, TableMalformedException, DatabaseNotFoundException, QueryStoreException { + private Long executeCountNonPersistent(Long containerId, Long databaseId, String statement) + throws QueryMalformedException, TableMalformedException, DatabaseNotFoundException, QueryStoreException { /* find */ final Database database = databaseService.find(containerId, databaseId); final User root = databaseMapper.containerToPrivilegedUser(database.getContainer()); @@ -177,7 +179,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService return queryMapper.resultSetToNumber(resultSet); } catch (SQLException e) { log.error("Failed to map object: {}", e.getMessage()); - throw new TableMalformedException("Failed to map object", e); + throw new TableMalformedException("Failed to map object: " + e.getMessage(), e); } finally { dataSource.close(); } @@ -187,8 +189,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService @Transactional(readOnly = true) public QueryResultDto tableFindAll(Long containerId, Long databaseId, Long tableId, Instant timestamp, Long page, Long size, Principal principal) throws TableNotFoundException, DatabaseNotFoundException, - ImageNotSupportedException, DatabaseConnectionException, TableMalformedException, PaginationException, - ContainerNotFoundException, QueryMalformedException, UserNotFoundException { + ImageNotSupportedException, TableMalformedException, QueryMalformedException { /* find */ final Table table = tableService.find(containerId, databaseId, tableId); /* run query */ @@ -199,9 +200,8 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService @Override @Transactional(readOnly = true) public QueryResultDto viewFindAll(Long containerId, Long databaseId, View view, - Long page, Long size, Principal principal) throws ViewNotFoundException, DatabaseNotFoundException, - ImageNotSupportedException, DatabaseConnectionException, ViewMalformedException, PaginationException, - ContainerNotFoundException, QueryMalformedException, UserNotFoundException { + Long page, Long size, Principal principal) throws DatabaseNotFoundException, + ImageNotSupportedException, QueryMalformedException, TableMalformedException { /* find */ /* run query */ String statement = queryMapper.viewToRawFindAllQuery(view, size, page); @@ -231,9 +231,8 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService @Transactional(readOnly = true) public QueryResultDto findAllView(Long containerId, Long databaseId, Long viewId, Instant timestamp, Long page, - Long size, Principal principal) throws TableNotFoundException, DatabaseNotFoundException, - ImageNotSupportedException, DatabaseConnectionException, TableMalformedException, PaginationException, - ContainerNotFoundException, QueryMalformedException, UserNotFoundException { + Long size, Principal principal) throws TableNotFoundException, DatabaseNotFoundException, + ImageNotSupportedException, TableMalformedException, QueryMalformedException { /* find */ final Table table = tableService.find(containerId, databaseId, viewId); /* run query */ @@ -244,9 +243,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService @Override @Transactional(readOnly = true) public ExportResource tableFindAll(Long containerId, Long databaseId, Long tableId, Instant timestamp, Principal principal) - throws TableNotFoundException, DatabaseNotFoundException, ImageNotSupportedException, - DatabaseConnectionException, TableMalformedException, PaginationException, ContainerNotFoundException, - FileStorageException, QueryMalformedException, UserNotFoundException { + throws TableNotFoundException, DatabaseNotFoundException, FileStorageException, QueryMalformedException { final String filename = RandomStringUtils.randomAlphabetic(40) + ".csv"; /* find */ final Database database = databaseService.find(containerId, databaseId); @@ -266,7 +263,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService FileUtils.forceDelete(file); } catch (IOException | SQLException e) { log.error("Failed to execute query and/or export file: {}", e.getMessage()); - throw new FileStorageException("Failed to execute query and/or export file", e); + throw new FileStorageException("Failed to execute query and/or export file: " + e.getMessage(), e); } finally { dataSource.close(); } @@ -319,7 +316,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService @Transactional public void update(Long containerId, Long databaseId, Long tableId, TableCsvUpdateDto data, Principal principal) throws ImageNotSupportedException, TableMalformedException, DatabaseNotFoundException, - TableNotFoundException, QueryMalformedException, UserNotFoundException { + TableNotFoundException, QueryMalformedException { /* find */ final Database database = databaseService.find(containerId, databaseId); final Table table = tableService.find(containerId, databaseId, tableId); @@ -334,7 +331,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService preparedStatement.executeUpdate(); } catch (SQLException e) { log.error("Failed to update tuples: {}", e.getMessage()); - throw new TableMalformedException("Failed to update tuples", e); + throw new TableMalformedException("Failed to update tuples: " + e.getMessage(), e); } finally { dataSource.close(); } @@ -351,10 +348,6 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService final User root = databaseMapper.containerToPrivilegedUser(database.getContainer()); log.trace("parsed insert data {}", data); /* run query */ - if (data.getData().size() == 0) { - log.error("Failed to parse data, the provided map {} is empty", data.getData()); - throw new TableMalformedException("Failed to parse data"); - } final ComboPooledDataSource dataSource = getDataSource(database.getContainer().getImage(), database.getContainer(), database, root); /* prepare the statement */ @@ -364,14 +357,14 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService preparedStatement.executeUpdate(); } catch (DateTimeParseException e) { log.error("Failed to parse date: {}", e.getMessage()); - throw new TableMalformedException("Failed to parse date", e); + throw new TableMalformedException("Failed to parse date: " + e.getMessage(), e); } catch (NumberFormatException e) { log.error("Failed to parse number: {}", e.getMessage()); - throw new TableMalformedException("Failed to parse number", e); + throw new TableMalformedException("Failed to parse number: " + e.getMessage(), e); } catch (Exception e) { log.error("Database failed to accept tuple: {}", e.getMessage()); log.throwing(e); - throw new TableMalformedException("Database failed to accept tuple " + e.getMessage(), e); + throw new TableMalformedException("Database failed to accept tuple: " + e.getMessage(), e); } finally { dataSource.close(); } @@ -397,7 +390,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService preparedStatement.executeUpdate(); } catch (SQLException e) { log.error("Failed to delete tuples: {}", e.getMessage()); - throw new TableMalformedException("Failed to delete tuples", e); + throw new TableMalformedException("Failed to delete tuples: " + e.getMessage(), e); } finally { dataSource.close(); } diff --git a/fda-table-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java b/fda-table-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java index ff9d2c1e77d97ce40c7192c37caed20457eab013..d971603dd8dd5f1e3c387b75759ca34359923590 100644 --- a/fda-table-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java +++ b/fda-table-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java @@ -83,9 +83,9 @@ public abstract class BaseUnitTest { public final static String DATABASE_NET = "fda-userdb"; - public final static String BROKER_NAME = "fda-broker-service"; - public final static String BROKER_IP = "172.29.0.2"; - public final static String BROKER_HOSTNAME = "broker-service"; + public final static String BROKER_NAME = "dbrepo-broker-service"; + public final static String BROKER_IP = "172.31.0.2"; + public final static String BROKER_HOSTNAME = "dbrepo-broker-service"; public final static Integer BROKER_MANAGEMENT_PORT = 15672; public final static String BROKER_IMAGE = "rabbitmq"; public final static String BROKER_TAG = "3-management-alpine"; @@ -146,24 +146,24 @@ public abstract class BaseUnitTest { public final static String CONTAINER_1_HASH = "deadbeef"; public final static ContainerImage CONTAINER_1_IMAGE = IMAGE_1; public final static String CONTAINER_1_NAME = "u01"; - public final static String CONTAINER_1_INTERNALNAME = "fda-userdb-u01"; - public final static String CONTAINER_1_IP = "172.28.0.5"; + public final static String CONTAINER_1_INTERNALNAME = "dbrepo-userdb-u01"; + public final static String CONTAINER_1_IP = "172.30.0.5"; public final static Instant CONTAINER_1_CREATED = Instant.now().minus(1, HOURS); public final static Long CONTAINER_2_ID = 2L; public final static String CONTAINER_2_HASH = "deadbeef"; public final static ContainerImage CONTAINER_2_IMAGE = IMAGE_1; public final static String CONTAINER_2_NAME = "u02"; - public final static String CONTAINER_2_INTERNALNAME = "fda-userdb-u02"; - public final static String CONTAINER_2_IP = "172.28.0.6"; + public final static String CONTAINER_2_INTERNALNAME = "dbrepo-userdb-u02"; + public final static String CONTAINER_2_IP = "172.30.0.6"; public final static Instant CONTAINER_2_CREATED = Instant.now().minus(1, HOURS); public final static Long CONTAINER_3_ID = 3L; public final static String CONTAINER_3_HASH = "deadbeef"; public final static ContainerImage CONTAINER_3_IMAGE = IMAGE_1; public final static String CONTAINER_3_NAME = "u03"; - public final static String CONTAINER_3_INTERNALNAME = "fda-userdb-u03"; - public final static String CONTAINER_3_IP = "172.28.0.7"; + public final static String CONTAINER_3_INTERNALNAME = "dbrepo-userdb-u03"; + public final static String CONTAINER_3_IP = "172.30.0.7"; public final static Instant CONTAINER_3_CREATED = Instant.now().minus(1, HOURS); public final static Long DATABASE_1_ID = 1L; @@ -739,7 +739,7 @@ public abstract class BaseUnitTest { public final static String CONTAINER_NGINX_NET = "fda-public"; public final static String CONTAINER_NGINX_NAME = "file-service"; public final static String CONTAINER_NGINX_INTERNALNAME = "fda-test-file-service"; - public final static String CONTAINER_NGINX_IP = "172.29.0.3"; + public final static String CONTAINER_NGINX_IP = "172.31.0.3"; public final static Instant CONTAINER_NGINX_CREATED = Instant.now().minus(3, HOURS); public final static Long CONCEPT_1_ID = 1L; diff --git a/fda-table-service/rest-service/src/test/java/at/tuwien/config/GatewayConfig.java b/fda-table-service/rest-service/src/test/java/at/tuwien/config/GatewayConfig.java index 6cf55041bae2691730fb6c5131673c568471cc03..26d1b50051997b362f19029252437e06aea44e63 100644 --- a/fda-table-service/rest-service/src/test/java/at/tuwien/config/GatewayConfig.java +++ b/fda-table-service/rest-service/src/test/java/at/tuwien/config/GatewayConfig.java @@ -21,7 +21,7 @@ public class GatewayConfig { @Bean("brokerRestTemplate") public RestTemplate brokerRestTemplate() { final RestTemplate restTemplate = new RestTemplate(); - restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory("http://broker-service:15672")); + restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory("http://dbrepo-broker-service:15672")); restTemplate.getInterceptors() .add(new BasicAuthenticationInterceptor(brokerUsername, brokerPassword)); return restTemplate; diff --git a/fda-table-service/rest-service/src/test/java/at/tuwien/service/MessageQueueServiceIntegrationTest.java b/fda-table-service/rest-service/src/test/java/at/tuwien/service/MessageQueueServiceIntegrationTest.java index 300e882c68bf1fd1dcbee8ab12312598030b83ba..1b5a0ecb183d79aa34a3aa66aafcd24aed43a49f 100644 --- a/fda-table-service/rest-service/src/test/java/at/tuwien/service/MessageQueueServiceIntegrationTest.java +++ b/fda-table-service/rest-service/src/test/java/at/tuwien/service/MessageQueueServiceIntegrationTest.java @@ -67,14 +67,14 @@ public class MessageQueueServiceIntegrationTest extends BaseUnitTest { .withName("fda-userdb") .withIpam(new Network.Ipam() .withConfig(new Network.Ipam.Config() - .withSubnet("172.28.0.0/16"))) + .withSubnet("172.30.0.0/16"))) .withEnableIpv6(false) .exec(); dockerClient.createNetworkCmd() .withName("fda-public") .withIpam(new Network.Ipam() .withConfig(new Network.Ipam.Config() - .withSubnet("172.29.0.0/16"))) + .withSubnet("172.31.0.0/16"))) .withEnableIpv6(false) .exec(); /* create amqp */ diff --git a/fda-table-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java b/fda-table-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java index 059284210924f98846d57f109e174a55aad2f745..49fc8fef9ea21eedeb34c2cdf011f96f340a05be 100644 --- a/fda-table-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java +++ b/fda-table-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationTest.java @@ -98,14 +98,14 @@ public class TableServiceIntegrationTest extends BaseUnitTest { .withName("fda-userdb") .withIpam(new Network.Ipam() .withConfig(new Network.Ipam.Config() - .withSubnet("172.28.0.0/16"))) + .withSubnet("172.30.0.0/16"))) .withEnableIpv6(false) .exec(); dockerClient.createNetworkCmd() .withName("fda-public") .withIpam(new Network.Ipam() .withConfig(new Network.Ipam.Config() - .withSubnet("172.29.0.0/16"))) + .withSubnet("172.31.0.0/16"))) .withEnableIpv6(false) .exec(); /* create container */ diff --git a/fda-table-service/rest-service/src/test/java/at/tuwien/utils/AmqpUtils.java b/fda-table-service/rest-service/src/test/java/at/tuwien/utils/AmqpUtils.java index 6caf0d930eb80c443a319292d5f749981002668d..dfc90d2ea25ae4920fd2edd74a26660209190554 100644 --- a/fda-table-service/rest-service/src/test/java/at/tuwien/utils/AmqpUtils.java +++ b/fda-table-service/rest-service/src/test/java/at/tuwien/utils/AmqpUtils.java @@ -34,7 +34,7 @@ public class AmqpUtils { public void createExchange(String exchange) { exchange = exchange.replace("/", "%2F"); - final URI uri = URI.create("http://broker-service:15672/api/exchanges/%2F/" + exchange); + final URI uri = URI.create("http://dbrepo-broker-service:15672/api/exchanges/%2F/" + exchange); final CreateExchangeDto payload = CreateExchangeDto.builder() .type("fanout") .autoDelete(false) @@ -67,7 +67,7 @@ public class AmqpUtils { } public boolean queueExists(String queue) { - final URI uri = URI.create("http://broker-service:15672/api/queues/%2F/"); + final URI uri = URI.create("http://dbrepo-broker-service:15672/api/queues/%2F/"); final ResponseEntity<QueueDto[]> response = restTemplate.exchange(uri, HttpMethod.GET, new HttpEntity<>(null), QueueDto[].class); if (!response.getStatusCode().equals(HttpStatus.OK)) { log.error("Failed to find queue, code is {}", response.getStatusCode()); diff --git a/fda-ui/.gitignore b/fda-ui/.gitignore index 0c83f47701873d10665a28e24aad623e89467776..a6a8dd571f3fc30997a2b59aab90d21abc4aff7c 100644 --- a/fda-ui/.gitignore +++ b/fda-ui/.gitignore @@ -21,6 +21,7 @@ lib-cov # Coverage directory used by tools like istanbul coverage/ +coverage.txt # nyc test coverage .nyc_output @@ -93,4 +94,5 @@ sw.* *.swp # CI records some videos for the e2e tests -videos +videos/ +screenshots/ diff --git a/fda-ui/.nycrc b/fda-ui/.nycrc index ccda5111b9ac9d41694692f5c4e0a12dadc6fbbb..a4841b7947c1e8e06b5ca816319f1eb0f20b952e 100644 --- a/fda-ui/.nycrc +++ b/fda-ui/.nycrc @@ -6,7 +6,7 @@ "branches": 35, "check-coverage": true, "include": [ "components/**/*.vue", "layouts/**/*.vue", "pages/**/*.vue", "server-middleware/**/*.js", "store/**/*.js"], - "exclude": ["node_modules"], + "exclude": ["node_modules", "server-middleware", "store"], "extension": [".js", ".vue"], "reporter": [ "lcov", diff --git a/fda-ui/.prod/default.conf b/fda-ui/.prod/default.conf deleted file mode 100644 index 43a88f37d85a14ad680cfe0e2c2d483b8ba3bafc..0000000000000000000000000000000000000000 --- a/fda-ui/.prod/default.conf +++ /dev/null @@ -1,30 +0,0 @@ -server { - listen 3000 default_server; - server_name dbrepo.local; - proxy_set_header Host dbrepo.local; - - root /usr/share/nginx/html; - index index.html index.htm; - - location /api { - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://fda-gateway-service:9095; - } - - location / { - root /usr/share/nginx/html; - try_files $uri $uri/ /index.html; - index index.html index.htm; - } - - # allow post on static pages - error_page 405 =200 $uri; - - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; - } - -} diff --git a/fda-ui/.prod/secure.conf b/fda-ui/.prod/secure.conf deleted file mode 100644 index 402ce356e6f69ac6a322b36c7f3fe78672d6264f..0000000000000000000000000000000000000000 --- a/fda-ui/.prod/secure.conf +++ /dev/null @@ -1,38 +0,0 @@ -server { - listen 443 default_server; - server_name dbrepo.ossdip.at; - proxy_set_header Host dbrepo.ossdip.at; - - root /usr/share/nginx/html; - - index index.html; - location / { - root /usr/share/nginx/html; - try_files $uri $uri/ /index.html; - index index.html index.htm; - } - - location /api { - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://fda-gateway-service:9095; - } - - location /server-middleware { - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass https://fda-ui:443; - } - - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; - } - - ssl on; - ssl_certificate /etc/nginx/conf.d/cert.pem; - ssl_certificate_key /etc/nginx/conf.d/privkey.pem; - -} diff --git a/fda-ui/Dockerfile b/fda-ui/Dockerfile index b7d21fc55b84240c6a1fdd86f44cf6425c487e98..0df37b3162497a09a783844a2b2eef4f264f9a14 100644 --- a/fda-ui/Dockerfile +++ b/fda-ui/Dockerfile @@ -1,4 +1,3 @@ -# FROM node:lts as build FROM node:14-alpine as build MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> @@ -35,6 +34,9 @@ COPY ./utils ./utils RUN yarn build > /dev/null +FROM node:14-alpine as runtime +MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> + EXPOSE 3000 EXPOSE 9100 @@ -51,6 +53,13 @@ ENV VERSION="${TAG}" ENV TITLE="Database Repository" ENV ICON="/favicon.ico" +WORKDIR /app + +COPY --from=build /usr/local/bin/node_exporter/ /usr/local/bin/node_exporter/ +COPY --from=build /app /app + +RUN ls -la + COPY ./docker-entrypoint.sh /app/docker-entrypoint.sh RUN chmod +x /app/docker-entrypoint.sh diff --git a/fda-ui/components/DatabaseList.vue b/fda-ui/components/DatabaseList.vue new file mode 100644 index 0000000000000000000000000000000000000000..ab94f978c1a2eb4b67a09951eb095e6831dcc11a --- /dev/null +++ b/fda-ui/components/DatabaseList.vue @@ -0,0 +1,192 @@ +<template> + <div> + <v-progress-linear v-if="loadingContainers || loadingDatabases" :color="loadingColor" :indeterminate="!error" /> + <v-card + v-for="(container, idx) in containers" + :key="idx" + :to="link(container)" + :disabled="!container.database" + flat + tile> + <v-divider class="mx-4" /> + <v-card-title v-if="!hasDatabase(container)" v-text="container.name" /> + <v-card-title v-if="hasDatabase(container)"> + <a :href="`/container/${container.id}/database/${container.database.id}`">{{ container.name }}</a> + </v-card-title> + <v-card-subtitle v-if="!hasIdentifier(container)" class="db-subtitle" v-text="formatCreator(container.creator)" /> + <v-card-subtitle v-if="hasIdentifier(container)" class="db-subtitle" v-text="formatCreatorz(container)" /> + <v-card-text class="db-description"> + <div class="db-tags"> + <v-chip v-if="hasDatabase(container) && container.database.is_public" small color="green" outlined>Public</v-chip> + <v-chip v-if="hasDatabase(container) && !container.database.is_public" small color="red" outlined>Private</v-chip> + <v-chip v-if="hasIdentifier(container)" small outlined>PID</v-chip> + <v-chip + v-if="identifierCreated(container)" + small + outlined + v-text="container.database.identifier.publisher" /> + </div> + <div v-text="identifierDescription(container)" /> + </v-card-text> + <v-card-text v-if="canInit(container)" class="db-buttons"> + <v-btn + small + secondary + :loading="container.database.loading" + @click.stop="initDatabase(container)"> + Start + </v-btn> + </v-card-text> + <v-divider v-if="idx - 1 === databases.length" class="mx-4" /> + </v-card> + <v-toolbar flat> + <v-toolbar-title> + <v-btn + small + color="secondary"> + More + </v-btn> + </v-toolbar-title> + </v-toolbar> + </div> +</template> + +<script> +import { formatCreators, formatUser, formatYearUTC, isResearcher } from '@/utils' + +export default { + data () { + return { + loadingContainers: false, + loadingCreate: false, + createDbDialog: false, + databases: [], + containers: [], + searchQuery: null, + createDatabaseDto: { + name: null, + is_public: true + }, + items: [ + { text: 'Databases', to: '/container', activeClass: '' } + ], + loadingDatabases: false, + error: false + } + }, + computed: { + loadingColor () { + return this.error ? 'red lighten-2' : 'primary' + }, + token () { + return this.$store.state.token + }, + user () { + return this.$store.state.user + }, + isResearcher () { + return isResearcher(this.user) + }, + config () { + if (this.token === null) { + return {} + } + return { + headers: { Authorization: `Bearer ${this.token}` } + } + } + }, + mounted () { + this.loadContainers() + }, + methods: { + formatCreator (creator) { + return formatUser(creator) + }, + formatCreatorz (container) { + const creators = formatCreators(container) + return creators || this.formatCreator(container.creator) + }, + canInit (container) { + if (!this.token) { + return false + } + if (container.creator.username !== this.user.username) { + return false + } + return !container.database.id && !this.loadingDatabases + }, + hasDatabase (container) { + return container.database + }, + hasIdentifier (container) { + return container.database && container.database.identifier + }, + async initDatabase (container) { + await this.startContainer(container) + .then(() => this.createDatabase(container)) + }, + identifierCreated (container) { + if (!container.database.identifier) { + return null + } + return formatYearUTC(container.database.identifier.created) + }, + identifierDescription (container) { + if (!container.database.identifier) { + return null + } + return container.database.identifier.description + }, + async loadContainers () { + this.createDbDialog = false + try { + this.loadingContainers = true + const res = await this.$axios.get('/api/container?limit=100') + this.containers = res.data + console.debug('containers', this.containers) + this.error = false + } catch (error) { + this.error = true + console.error('Failed to retrieve containers', error) + const { message } = error.response.data + this.$toast.error(`Failed to retrieve containers: ${message}`) + } + this.loadingContainers = false + }, + async startContainer (container) { + try { + container.database.loading = true + const res = await this.$axios.put(`/api/container/${container.id}`, { action: 'start' }, this.config) + console.debug('started container', res.data) + this.error = false + } catch (error) { + const { status } = error.response + if (status !== 409) { + this.error = true + this.$toast.error('Failed to start container') + } + } + container.database.loading = false + }, + link (container) { + if (!container.database || !container.database.id) { + return null + } + return `/container/${container.id}/database/${container.database.id}` + } + } +} +</script> + +<style> +.v-chip:not(:first-child) { + margin-left: 8px; +} +.db-subtitle { + padding-bottom: 8px; +} +.db-tags { + margin-bottom: 8px; +} +</style> diff --git a/fda-ui/components/QueryList.vue b/fda-ui/components/QueryList.vue index 96227d2816243e881c2a21d01b2a5702e5474041..5e5f6772b115f0755ff1c138b05a823ba1eed2ce 100644 --- a/fda-ui/components/QueryList.vue +++ b/fda-ui/components/QueryList.vue @@ -2,9 +2,6 @@ <div> <v-progress-linear v-if="loadingIdentifiers || loadingQueries || error" :color="loadingColor" :value="loadProgress" /> <v-tabs-items> - <v-card v-if="!loadingQueries && queries.length === 0 && !error" flat> - <v-card-text v-text="emptyMessage" /> - </v-card> <div v-if="!loadingQueries && !error"> <div v-for="(item,i) in queries" :key="i"> <v-divider v-if="i !== 0" class="mx-4" /> @@ -16,12 +13,15 @@ <pre>{{ item.query }}</pre> </v-list-item-subtitle> </v-list-item-content> + <v-list-item-action v-if="item.identifier"> + <v-icon color="primary">mdi-identifier</v-icon> + </v-list-item-action> </v-list-item> </v-list-item-group> </div> </div> <div v-if="!loadingIdentifiers && loadingQueries"> - <!-- show identifiers when error --> + <!-- show identifiers when loading subsets --> <div v-for="(item,i) in identifiers" :key="i"> <v-divider v-if="i !== 0" class="mx-4" /> <v-list-item-group> @@ -32,6 +32,28 @@ <pre>{{ item.query }}</pre> </v-list-item-subtitle> </v-list-item-content> + <v-list-item-action> + <v-icon color="primary">mdi-identifier</v-icon> + </v-list-item-action> + </v-list-item> + </v-list-item-group> + </div> + </div> + <div v-if="!loadingIdentifiers && !isPublicOrOwner"> + <!-- show identifiers when private --> + <div v-for="(item,i) in identifiers" :key="i"> + <v-divider v-if="i !== 0" class="mx-4" /> + <v-list-item-group> + <v-list-item two-line :class="clazz(item)" :to="link(item)" :href="navigate(item)"> + <v-list-item-content> + <v-list-item-title v-text="item.title" /> + <v-list-item-subtitle class="mt-2"> + <pre>{{ item.query }}</pre> + </v-list-item-subtitle> + </v-list-item-content> + <v-list-item-action> + <v-icon color="primary">mdi-identifier</v-icon> + </v-list-item-action> </v-list-item> </v-list-item-group> </div> @@ -81,11 +103,20 @@ export default { creator () { return this.queryDetails.creator }, - emptyMessage () { - if (this.isPublicOrOwner()) { - return '(no subsets)' + isPublicOrOwner () { + if (!this.database) { + return false + } + if (this.database.is_public) { + return true + } + if (this.token === null) { + return false } - return '(private database)' + if (!this.user) { + return false + } + return this.database.creator.username === this.user.username } }, mounted () { @@ -117,10 +148,14 @@ export default { const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/query?persisted=true`, this.config) this.queries = res.data console.debug('queries', this.queries) - } catch (err) { - this.error = true - console.error('Connection to query store failed', err.response.index) - this.$toast.error(err.response.index.message) + } catch (error) { + const { status, data } = error.response + const { message } = data + if (status !== 405) { + this.error = true + console.error('Connection to query store failed', error) + this.$toast.error(`Failed to connect to query store: ${message}`) + } } this.loadingQueries = false }, @@ -149,29 +184,11 @@ export default { return `/pid/${queryOrIdentifier.identifier.id}` }, clazz (queryOrIdentifier) { - if (!('identifier' in queryOrIdentifier) || queryOrIdentifier.identifier === null) { - return null - } if ('query_id' in queryOrIdentifier || queryOrIdentifier.identifier) { return 'primary--text' } return null }, - isPublicOrOwner () { - if (!this.database) { - return false - } - if (this.database.is_public) { - return true - } - if (this.token === null) { - return false - } - if (!this.user) { - return false - } - return this.database.creator.username === this.user.username - }, simulateProgress () { if (this.loadProgress !== 0) { return diff --git a/fda-ui/components/TableList.vue b/fda-ui/components/TableList.vue index c326f81505cee79b2c62bec9635bd4514f916a4b..456a8f6b087409e8a728ac0acc20830706db27a0 100644 --- a/fda-ui/components/TableList.vue +++ b/fda-ui/components/TableList.vue @@ -9,7 +9,9 @@ <div v-for="(item,i) in tables" :key="i"> <v-divider v-if="i !== 0" class="mx-4" /> <v-list-item-group> - <v-list-item two-line :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${item.id}`"> + <v-list-item + two-line + :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${item.id}`"> <v-list-item-content> <v-list-item-title v-text="item.name" /> <v-list-item-subtitle class="mt-2" v-text="item.description" /> @@ -113,29 +115,11 @@ export default { } return formatTimestampUTCLabel(this.tableDetails.created) }, - hasReadAccess () { - if (!this.database) { - return false - } - if (this.database.is_public) { - /* database is public */ - return true - } - if (!this.user) { + canRead () { + if (!this.user || !this.access) { return false } - if (this.database.creator.username === this.user.username) { - /* user is creator of database */ - return true - } - if (!this.access) { - return false - } - if (this.access.type === 'read' || this.access.type === 'write_own' || this.access.type === 'write_all') { - /* user has some level of access */ - return true - } - return false + return this.access.type === 'read' || this.access.type === 'write_own' || this.access.type === 'write_all' }, canModify () { if (!this.token || !this.user.username) { @@ -171,7 +155,7 @@ export default { /* use cache */ this.tableDetails = table /* load remaining info */ - if (this.hasReadAccess) { + if (this.canRead) { try { this.loadingDetails = true const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/table/${table.id}`, this.config) diff --git a/fda-ui/components/TableToolbar.vue b/fda-ui/components/TableToolbar.vue index 350f5a1e50327094dbe0ac3865882cb8972d58e8..c138b2e7dcb4337733f04beb6ae07d9719edcdb3 100644 --- a/fda-ui/components/TableToolbar.vue +++ b/fda-ui/components/TableToolbar.vue @@ -35,7 +35,7 @@ <v-tab :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${$route.params.table_id}/info`"> Info </v-tab> - <v-tab :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${$route.params.table_id}/data`"> + <v-tab v-if="canRead" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${$route.params.table_id}/data`"> Data </v-tab> <v-tab :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${$route.params.table_id}/schema`"> diff --git a/fda-ui/components/ViewList.vue b/fda-ui/components/ViewList.vue index ef511dbd6e10ca85f502d5adb00c45c1c71b0219..b2aff93d4e03c52af606c7792d50141af0dff87a 100644 --- a/fda-ui/components/ViewList.vue +++ b/fda-ui/components/ViewList.vue @@ -9,7 +9,7 @@ <div v-for="(item,i) in views" :key="i"> <v-divider v-if="i !== 0" class="mx-4" /> <v-list-item-group> - <v-list-item two-line :class="clazz(item)" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/view/${item.id}`"> + <v-list-item two-line :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/view/${item.id}`"> <v-list-item-content> <v-list-item-title v-text="item.name" /> <v-list-item-subtitle class="mt-2"> @@ -127,12 +127,6 @@ export default { this.$toast.error('Failed to delete view') console.error('Failed to delete view') } - }, - clazz (view) { - if (view.is_public === false) { - return null - } - return 'primary--text' } } } diff --git a/fda-ui/components/dialogs/Persist.vue b/fda-ui/components/dialogs/Persist.vue index f57c31ec2234cc99d62751787255285a492b1a16..a8595e18fd1151270c670c256f2509997c799b63 100644 --- a/fda-ui/components/dialogs/Persist.vue +++ b/fda-ui/components/dialogs/Persist.vue @@ -64,6 +64,19 @@ required /> </v-col> </v-row> + <v-row dense> + <v-col> + <v-select + id="visibility" + v-model="visibility" + name="visibility" + label="Visibility *" + :items="['Public']" + disabled + :rules="[v => !!v || $t('Required')]" + required /> + </v-col> + </v-row> <v-row v-for="(creator,i) in identifier.creators" :key="`c-${i}`" dense> <v-col cols="3"> <v-text-field @@ -200,6 +213,7 @@ export default { loading: false, error: false, // XXX: `error` is never changed licenses: [], + visibility: 'Public', identifier: { cid: parseInt(this.$route.params.container_id), dbid: parseInt(this.$route.params.database_id), diff --git a/fda-ui/components/query/Builder.vue b/fda-ui/components/query/Builder.vue index 218ec97969ea05f4abc5efd2abfd85bea688562f..311aac14f2dce772d544e29c11b558dab57e9e9e 100644 --- a/fda-ui/components/query/Builder.vue +++ b/fda-ui/components/query/Builder.vue @@ -209,10 +209,6 @@ export default { } }, computed: { - selectItems () { - const columns = this.tableDetails && this.tableDetails.columns - return columns || [] - }, columnNames () { return this.columns && this.columns.map(s => s.internal_name) }, diff --git a/fda-ui/layouts/default.vue b/fda-ui/layouts/default.vue index 03887d4bed746416a37d0271c9f32ded815e797b..c49740af9ebf5baa051f3481010b89197a74363c 100644 --- a/fda-ui/layouts/default.vue +++ b/fda-ui/layouts/default.vue @@ -50,7 +50,7 @@ single-line hide-details placeholder="Search ..." /> - <v-btn icon class="ml-2" type="submit" @click="retrieve"> + <v-btn icon class="ml-2" type="submit" name="search-submit" @click="retrieve"> <v-icon>mdi-magnify</v-icon> </v-btn> <v-spacer /> @@ -227,8 +227,10 @@ export default { this.loadUser() this.setTheme() this.loadDatabase() - .then(() => this.loadIdentifier()) - this.loadTable() + .then(() => { + this.loadIdentifier() + this.loadTable() + }) this.loadAccess() if (this.$route.query && this.$route.query.q) { this.search = this.$route.query.q @@ -298,9 +300,17 @@ export default { const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/table/${this.$route.params.table_id}`, this.config) this.$store.commit('SET_TABLE', res.data) console.debug('table', this.table) - } catch (err) { - console.error('Could not load table', err) - this.$toast.error('Could not load table') + } catch (error) { + const { status, data } = error.response + if (status === 405) { + const table = this.database.tables.filter(t => t.id === Number(this.$route.params.table_id))[0] + console.debug('====>', table, this.$route.params.table_id) + this.$store.commit('SET_TABLE', table) + } else { + const { message } = data + console.error('Failed to load table', error) + this.$toast.error(`Failed to load table: ${message}`) + } } this.loading = false }, diff --git a/fda-ui/package.json b/fda-ui/package.json index de4d543b8929a002388db5d4e3a55e9cc2e96bfa..1649177b07b97389c2827d1c565f2db4f7e77ca9 100644 --- a/fda-ui/package.json +++ b/fda-ui/package.json @@ -8,15 +8,16 @@ "build": "nuxt build", "start": "nuxt start", "generate": "nuxt generate", + "clean": "rm -f ./videos/*", "ver": "nuxt --version", "lint:js": "eslint --ext .js,.vue --ignore-path .gitignore .", "lint": "yarn lint:js", - "coverage": "nyc ava test/unit/**/* test/specs/**/*", + "coverage": "nyc ava test/unit/**/* test/specs/**/* > ./coverage.txt", "test:unit": "ava test/unit/**/* test/specs/**/*", "test:watch": "ava --watch test/unit/**/* test/specs/**/*", - "test:e2e": "cross-env PORT=3001 ava --timeout=2h --fail-fast test/e2e/**", + "test:e2e": "yarn clean && cross-env PORT=3001 ava --timeout=2h --fail-fast test/e2e/**", "test:e2e:docker": "cross-env PORT=3000 SLOWMO=500 ava --timeout=2h --fail-fast test/e2e/**", - "test": "yarn test:unit && yarn test:e2e:docker" + "test": "yarn clean && yarn test:unit && yarn test:e2e:docker && yarn coverage" }, "dependencies": { "@babel/plugin-transform-runtime": "^7.13.9", @@ -25,6 +26,7 @@ "@nuxtjs/eslint-module": "^2.0.0", "@nuxtjs/proxy": "^2.1.0", "@nuxtjs/vuetify": "^1.11.2", + "axios": "^1.3.0", "chart.js": "^3.8.0", "core-js": "^3.6.5", "date-fns": "^2.16.1", diff --git a/fda-ui/pages/container/_container_id/database/_database_id/info.vue b/fda-ui/pages/container/_container_id/database/_database_id/info.vue index 6b4849304911ec51016292a87a7034d335a04d43..b9224362e62047fb60aa8b81f72f49b67b949b53 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/info.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/info.vue @@ -114,33 +114,7 @@ </v-card-actions> </v-card-text> </v-card> - <v-divider v-if="hasIdentifier || (isCreator && isResearcher) || isDataSteward" /> - <v-card flat tile> - <v-card-title>Container</v-card-title> - <v-card-text> - <v-list dense> - <v-list-item> - <v-list-item-content> - <v-list-item-title class="mt-2"> - Container Name - </v-list-item-title> - <v-list-item-content> - <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" /> - <span v-if="!loading" v-text="container_name" /> - </v-list-item-content> - <v-list-item-title class="mt-2"> - Container Internal Name - </v-list-item-title> - <v-list-item-content> - <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" /> - <span v-if="!loading" v-text="container_internal_name" /> - </v-list-item-content> - </v-list-item-content> - </v-list-item> - </v-list> - </v-card-text> - </v-card> - <v-divider /> + <v-divider v-if="isDataSteward || hasIdentifier || (!hasIdentifier && isCreator && isResearcher)" /> <v-card flat tile> <v-card-title>Database</v-card-title> <v-card-text> @@ -205,6 +179,32 @@ </v-list> </v-card-text> </v-card> + <v-divider /> + <v-card flat tile> + <v-card-title>Container</v-card-title> + <v-card-text> + <v-list dense> + <v-list-item> + <v-list-item-content> + <v-list-item-title class="mt-2"> + Container Name + </v-list-item-title> + <v-list-item-content> + <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" /> + <span v-if="!loading" v-text="container_name" /> + </v-list-item-content> + <v-list-item-title class="mt-2"> + Container Internal Name + </v-list-item-title> + <v-list-item-content> + <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" /> + <span v-if="!loading" v-text="container_internal_name" /> + </v-list-item-content> + </v-list-item-content> + </v-list-item> + </v-list> + </v-card-text> + </v-card> </v-tab-item> </v-tabs-items> <v-dialog diff --git a/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue b/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue index 47c5a02fe7dd866f45855bb8c0e0d1e9979efac6..4ca589d1527db7c2bd3eea1a845348c3f3d2d9c9 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue @@ -336,6 +336,9 @@ export default { if (this.query.creator.username === this.username) { return true } + if (!this.query.identifier) { + return false + } return this.query.identifier.visibility === 'everyone' }, canWrite () { diff --git a/fda-ui/pages/container/_container_id/database/_database_id/settings.vue b/fda-ui/pages/container/_container_id/database/_database_id/settings.vue index 63f3d69a7d1a6a5b5c72c760e6cbd7c2add615f6..a22d9092ede9f2dca88c0e21c619011358dc403e 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/settings.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/settings.vue @@ -174,7 +174,7 @@ export default { async updateDatabaseVisibility () { try { this.loading = true - await this.$axios.put(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/transfer`, this.modifyVisibility, this.config) + await this.$axios.put(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/visibility`, this.modifyVisibility, this.config) this.$toast.success('Successfully updated the database') location.reload() } catch (err) { diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/data.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/data.vue index c532c2814e8dd4ff7242318c7eb05ac671829426..b401b043bfae20a4f4621ea5fc29621726330998 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/data.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/data.vue @@ -1,5 +1,5 @@ <template> - <div> + <div v-if="canRead"> <TableToolbar :selection="selection" @modified="modified" /> <v-toolbar :color="versionColor" flat> <v-toolbar-title> diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/info.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/info.vue index 50e51aaafa3be94accfb3769bc8b58875acd0186..9a27f6db5cac79fa2ea91b15ffd0c1f441aa98d0 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/info.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/info.vue @@ -31,16 +31,18 @@ <span v-if="table && table.creator">{{ formatCreator(table.creator) }} <span v-if="is_owner(table)" style="flex:none;"> (you)</span></span> <v-skeleton-loader v-if="!table" type="text" class="skeleton-medium" /> </v-list-item-content> - <v-list-item-title class="mt-2"> + <v-list-item-title v-if="table && table.created" class="mt-2"> Table Creation </v-list-item-title> - <v-list-item-content> - <span v-if="table && table.created">{{ createdUTC }}</span> - <v-skeleton-loader v-if="!table" type="text" class="skeleton-small" /> + <v-list-item-content v-if="table && table.created"> + <span>{{ createdUTC }}</span> + </v-list-item-content> + <v-list-item-content v-if="!table"> + <v-skeleton-loader type="text" class="skeleton-medium" /> </v-list-item-content> </v-list-item-content> </v-list-item> - <v-list-item> + <v-list-item v-if="canModify"> <v-list-item-icon> <v-icon>mdi-rabbit</v-icon> </v-list-item-icon> @@ -58,29 +60,35 @@ <pre v-if="database && database.exchange_name">{{ database.exchange_name }}</pre> <v-skeleton-loader v-if="!table" type="text" class="skeleton-medium" /> </v-list-item-content> - <v-list-item-title class="mt-2"> + <v-list-item-title v-if="table && table.queue_name" class="mt-2"> Queue Name </v-list-item-title> - <v-list-item-content> - <pre v-if="table && table.queue_name">{{ table.queue_name }}</pre> - <v-skeleton-loader v-if="!table" type="text" class="skeleton-medium" /> + <v-list-item-content v-if="table && table.queue_name"> + <pre>{{ table.queue_name }}</pre> </v-list-item-content> - <v-list-item-title class="mt-2"> + <v-list-item-content v-if="!table"> + <v-skeleton-loader type="text" class="skeleton-medium" /> + </v-list-item-content> + <v-list-item-title v-if="table && table.routing_key" class="mt-2"> Routing Key </v-list-item-title> - <v-list-item-content> - <pre v-if="table && table.routing_key">{{ table.routing_key }}</pre> - <v-skeleton-loader v-if="!table" type="text" class="skeleton-medium" /> + <v-list-item-content v-if="table && table.routing_key"> + <pre>{{ table.routing_key }}</pre> </v-list-item-content> - <v-list-item-title v-if="hasReadAccess" class="mt-2"> + <v-list-item-content v-if="!table"> + <v-skeleton-loader type="text" class="skeleton-medium" /> + </v-list-item-content> + <v-list-item-title v-if="canRead" class="mt-2"> Consumer Count </v-list-item-title> - <v-list-item-content v-if="hasReadAccess" class="amqp-consumer"> - <span v-text="`${consumersUp}/${consumersTotal}`" /> + <v-list-item-content v-if="canRead" class="amqp-consumer"> + <span v-if="attemptedLoadingConsumers" v-text="`${consumersUp}/${consumersTotal}`" /> <v-badge + v-if="attemptedLoadingConsumers" class="ml-1" :color="consumersState.color" :content="consumersState.text" /> + <v-skeleton-loader v-else type="text" class="skeleton-xsmall" /> </v-list-item-content> </v-list-item-content> </v-list-item> @@ -101,6 +109,7 @@ export default { data () { return { loadingConsumers: false, + attemptedLoadingConsumers: false, selection: [], consumers: [], items: [ @@ -137,29 +146,11 @@ export default { table () { return this.$store.state.table }, - hasReadAccess () { - if (!this.database) { - return false - } - if (this.database.is_public) { - /* database is public */ - return true - } - if (!this.user) { + canRead () { + if (!this.user || !this.access) { return false } - if (this.database.creator.username === this.user.username) { - /* user is creator of database */ - return true - } - if (!this.access) { - return false - } - if (this.access.type === 'read' || this.access.type === 'write_own' || this.access.type === 'write_all') { - /* user has some level of access */ - return true - } - return false + return this.access.type === 'read' || this.access.type === 'write_own' || this.access.type === 'write_all' }, createdUTC () { if (this.table.created === undefined || this.table.created === null) { @@ -192,7 +183,7 @@ export default { return this.consumers.filter(c => c.active).length }, canModify () { - if (!this.token || !this.user.username) { + if (!this.token || !this.user.username || !this.table || !('creator' in this.table) || !this.table.creator || !('username' in this.table.creator) || !this.table.creator.username) { /* not yet loaded */ return false } @@ -223,9 +214,11 @@ export default { } } }, - mounted () { - this.pollConsumerStatus(true) - setInterval(() => this.pollConsumerStatus(false), 5 * 1000) + watch: { + table (val) { + this.pollConsumerStatus(true) + setInterval(() => this.pollConsumerStatus(false), 5 * 1000) + } }, methods: { formatCreator (creator) { @@ -247,10 +240,13 @@ export default { const consumers = res.data.filter(c => c.queue.name === this.table.queue_name) console.debug('filtered', consumers) this.consumers = consumers - } catch (err) { - console.error('Could not find consumers', err) + } catch (error) { + const { message } = error + console.error('Failed to find consumers', error) + this.$toast.error(`Failed to find consumers: ${message}`) } this.loadingConsumers = false + this.attemptedLoadingConsumers = true } } } diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/schema.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/schema.vue index 712dafbd367544bcb34a374d75527b8173dd3e26..72022b57c94af3625d59739cbba55c117b764262 100644 --- a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/schema.vue +++ b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/schema.vue @@ -183,10 +183,10 @@ export default { return null }, hasUnit (item) { - return item.unit !== null + return item.unit && 'uri' in item.unit }, hasConcept (item) { - return item.concept !== null + return item.concept && 'uri' in item.concept }, pick (item) { this.column = item diff --git a/fda-ui/pages/container/index.vue b/fda-ui/pages/container/index.vue index f2036ed2d7a95b6aa88f5c01e3189d6696130986..b442a2e51a1d7bd799f2406e1432896608ff3f35 100644 --- a/fda-ui/pages/container/index.vue +++ b/fda-ui/pages/container/index.vue @@ -2,67 +2,16 @@ <div> <v-toolbar flat> <v-toolbar-title> - <span>Databases</span> + Recent Databases </v-toolbar-title> <v-spacer /> <v-toolbar-title> - <v-btn v-if="isResearcher" color="primary" @click.stop="createDbDialog = true"> + <v-btn v-if="isResearcher" color="primary" name="create-database" @click.stop="createDbDialog = true"> <v-icon left>mdi-plus</v-icon> Database </v-btn> </v-toolbar-title> </v-toolbar> - <v-toolbar dense flat> - <v-toolbar-items> - <span class="mr-4">Filter:</span> - <v-checkbox - v-model="filterPrivate" - label="Private" /> - <v-checkbox - v-if="user" - v-model="filterMine" - class="ml-2" - label="Mine" /> - </v-toolbar-items> - </v-toolbar> - <v-progress-linear v-if="loadingContainers || loadingDatabases" :color="loadingColor" :indeterminate="!error" /> - <v-card - v-for="(container, idx) in filter(containers)" - :key="idx" - :to="link(container)" - :disabled="!container.database" - flat - tile> - <v-divider class="mx-4" /> - <v-card-title v-if="notInit(container)" v-text="container.name" /> - <v-card-title v-if="!notInit(container)"> - <a :href="`/container/${container.id}/database/${container.database.id}`">{{ container.name }}</a> - </v-card-title> - <v-card-subtitle v-if="!container.database.identifier" class="db-subtitle" v-text="formatCreator(container.creator)" /> - <v-card-subtitle v-if="container.database.identifier" class="db-subtitle" v-text="formatCreatorz(container)" /> - <v-card-text class="db-description"> - <div class="db-tags"> - <v-chip v-if="!notInit(container) && container.database.is_public" small color="green" outlined>Public</v-chip> - <v-chip v-if="!notInit(container) && !container.database.is_public" small color="red" outlined>Private</v-chip> - <v-chip v-if="identifierCreated(container)" small outlined>Database</v-chip> - <v-chip - v-if="identifierCreated(container)" - small - outlined - v-text="container.database.identifier.publisher" /> - <v-chip v-if="identifierCreated(container)" small outlined v-text="identifierCreated(container)" /> - </div> - <div v-text="identifierDescription(container)" /> - </v-card-text> - <v-card-text v-if="canInit(container)" class="db-buttons"> - <v-btn - small - secondary - :loading="container.database.loading" - @click.stop="initDatabase(container)"> - Start - </v-btn> - </v-card-text> - </v-card> + <DatabaseList /> <v-dialog v-model="createDbDialog" persistent @@ -75,22 +24,19 @@ <script> import { mdiDatabaseArrowRightOutline } from '@mdi/js' import CreateDB from '@/components/dialogs/CreateDB' -import { formatTimestampUTCLabel, formatCreators, formatYearUTC, formatUser, isResearcher } from '@/utils' +import DatabaseList from '@/components/DatabaseList' +import { isResearcher } from '@/utils' export default { components: { - CreateDB + CreateDB, + DatabaseList }, data () { return { loadingContainers: false, loadingCreate: false, createDbDialog: false, - databases: [], - containers: [], - filterPrivate: false, - filterMine: false, - searchQuery: null, createDatabaseDto: { name: null, is_public: true @@ -104,18 +50,12 @@ export default { } }, computed: { - loadingColor () { - return this.error ? 'red lighten-2' : 'primary' - }, token () { return this.$store.state.token }, user () { return this.$store.state.user }, - isResearcher () { - return isResearcher(this.user) - }, config () { if (this.token === null) { return {} @@ -123,119 +63,12 @@ export default { return { headers: { Authorization: `Bearer ${this.token}` } } + }, + isResearcher () { + return isResearcher(this.user) } }, - mounted () { - this.loadContainers() - .then(() => this.loadDatabases()) - }, methods: { - formatCreator (creator) { - return formatUser(creator) - }, - formatCreatorz (container) { - return formatCreators(container) - }, - canInit (container) { - if (!this.token) { - return false - } - if (container.creator.username !== this.user.username) { - return false - } - return !container.database.id && !this.loadingDatabases - }, - notInit (container) { - return !container.database.id - }, - async initDatabase (container) { - await this.startContainer(container) - .then(() => this.createDatabase(container)) - }, - filter (containers) { - if (this.loadingDatabases) { - return [] - } - let filtered = containers - if (this.filterPrivate) { - filtered = filtered.filter(c => !c.database.is_public) - } - if (this.user && this.filterMine) { - filtered = filtered.filter(c => c.creator.username === this.user.username) - } - return filtered - }, - identifierCreated (container) { - if (!container.database.identifier) { - return null - } - return formatYearUTC(container.database.identifier.created) - }, - identifierDescription (container) { - if (!container.database.identifier) { - return null - } - return container.database.identifier.description - }, - async loadContainers () { - this.createDbDialog = false - try { - this.loadingContainers = true - const res = await this.$axios.get('/api/container/') - this.containers = res.data.map((container) => { - container.database = { - id: null, - loading: false - } - return container - }) - console.debug('containers', this.containers) - this.error = false - } catch (err) { - console.error('containers', err) - this.error = true - } - this.loadingContainers = false - }, - async loadDatabases () { - if (this.containers.length === 0) { - return - } - this.loadingDatabases = true - for (const container of this.containers) { - try { - const res = await this.$axios.get(`/api/container/${container.id}/database`, this.config) - for (const info of res.data) { - info.container_id = container.id - info.visibility = info.is_public - info.created = formatTimestampUTCLabel(info.created) - const filtered = this.containers.filter(c => c.id === container.id)[0] - filtered.database = info - } - } catch (err) { - if (err.response === undefined || err.response.status === undefined || err.response.status !== 401) { - console.error('Failed to load databases for container', err) - } - } - } - this.loadingDatabases = false - console.debug('containers with databases', this.containers) - }, - async startContainer (container) { - try { - container.database.loading = true - const res = await this.$axios.put(`/api/container/${container.id}`, { action: 'start' }, this.config) - console.debug('started container', res.data) - this.error = false - } catch (error) { - const { status } = error.response - if (status !== 409) { - this.error = true - this.$toast.error('Failed to start container') - } - } - container.database.loading = false - }, async createDatabase (container) { try { container.database.loading = true @@ -256,29 +89,8 @@ export default { this.createDbDialog = false if (event.success) { this.loadContainers() - .then(() => this.loadDatabases()) } - }, - link (container) { - if (!container.database || !container.database.id) { - return null - } - return `/container/${container.id}/database/${container.database.id}` } } } </script> -<style scoped> - tbody tr { - cursor: pointer; - } - .v-chip:not(:first-child) { - margin-left: 8px; - } - .db-subtitle { - padding-bottom: 8px; - } - .db-tags { - margin-bottom: 8px; - } -</style> diff --git a/fda-ui/pages/forgot.vue b/fda-ui/pages/forgot.vue index af20390b04503bc6484650995cb66b270b6b2f47..809139658b9b5bb04f1bb430a62b69ef4a03de14 100644 --- a/fda-ui/pages/forgot.vue +++ b/fda-ui/pages/forgot.vue @@ -18,6 +18,7 @@ v-model="data.username" autocomplete="off" autofocus + name="username" label="Username" /> </v-col> </v-row> @@ -27,6 +28,7 @@ v-model="data.email" autocomplete="off" type="email" + name="email" label="E-Mail Address" /> </v-col> </v-row> @@ -38,6 +40,7 @@ :disabled="!valid || !formValid" color="primary" type="submit" + name="submit" @click="forgot"> Reset password </v-btn> diff --git a/fda-ui/pages/login.vue b/fda-ui/pages/login.vue index c063503b9032528cfab050acd94800e930ed1a75..44ee3235cf09fd0e02f0e3e4eb09bd1f2a6a94fa 100644 --- a/fda-ui/pages/login.vue +++ b/fda-ui/pages/login.vue @@ -18,6 +18,7 @@ autocomplete="off" autofocus required + name="username" :rules="[v => !!v || $t('Required')]" label="Username *" /> </v-col> @@ -29,6 +30,7 @@ autocomplete="off" type="password" required + name="password" :rules="[v => !!v || $t('Required')]" label="Password *" /> </v-col> @@ -41,6 +43,7 @@ :disabled="!valid" color="primary" type="submit" + name="submit" :loading="loading" @click="login"> Login diff --git a/fda-ui/pages/search/index.vue b/fda-ui/pages/search/index.vue index a6d5489897dd90fa00ffa80b667cf9e2454b3dd5..a466a0f9229d395bfd03be5e671e250eec482079 100644 --- a/fda-ui/pages/search/index.vue +++ b/fda-ui/pages/search/index.vue @@ -46,6 +46,12 @@ export default { } return this.$route.query.q }, + type () { + if (!this.$route.query || !this.$route.query.t) { + return null + } + return this.$route.query.t + }, header () { if (this.results.length !== 1) { return `${this.results.length} results` @@ -64,7 +70,14 @@ export default { watch: { '$route.query.q': { handler (query) { - this.retrieve(query) + this.retrieve() + }, + deep: true, + immediate: true + }, + '$route.query.t': { + handler (type) { + this.retrieve() }, deep: true, immediate: true @@ -76,13 +89,13 @@ export default { } }, methods: { - async retrieve (v) { + async retrieve () { if (this.loading) { return } this.loading = true try { - const res = await this.$axios.get(`/retrieve/databaseindex,tableindex,columnindex,identifierindex,viewindex/_search?q=${v}*&terminate_after=50`, this.elasticConfig) + const res = await this.$axios.get(`/retrieve/_all/_search?q=${this.query}*&terminate_after=50`, this.elasticConfig) console.info('search results', res.data.hits.total.value) console.debug('search results for', this.$route.query.q, 'are', res.data.hits.hits) this.results = res.data.hits.hits.map(h => h._source) diff --git a/fda-ui/pages/signup.vue b/fda-ui/pages/signup.vue index d777c2b568f46725f0527491e390bc94ce65713e..2b88602a4e7b006558a5f5759771a9c2dcbde622 100644 --- a/fda-ui/pages/signup.vue +++ b/fda-ui/pages/signup.vue @@ -20,6 +20,7 @@ autocomplete="off" autofocus required + name="email" :rules="[v => !!v || $t('Required')]" hint="e.g. max.mustermann@work.com" label="Work E-Mail Address *" /> @@ -31,6 +32,7 @@ v-model="createAccount.username" autocomplete="off" required + name="username" :rules="[v => !!v || $t('Required'), v => /^[a-z0-9]{3,}$/.test(v) || $t('Only lowercase letters, min. 3 length')]" hint="e.g. mmustermann" @@ -43,6 +45,7 @@ v-model="createAccount.password" autocomplete="off" required + name="password" :rules="[v => !!v || $t('Required')]" type="password" label="Password *" /> @@ -54,6 +57,7 @@ v-model="password2" autocomplete="off" required + name="password-confirm" :rules="[v => !!v || $t('Required'), v => (!!v && v) === createAccount.password || $t('Not matching!')]" type="password" label="Repeat Password *" /> @@ -64,6 +68,7 @@ <v-checkbox v-model="consent" required + name="consent" :rules="[v => !!v || $t('Required')]" label="I understand the warning and do not use production data" /> </v-col> @@ -73,6 +78,7 @@ <v-checkbox v-model="privacy" required + name="privacy" :rules="[v => !!v || $t('Required')]" label="I have read and accept the privacy statement" /> </v-col> @@ -84,6 +90,7 @@ :disabled="!valid" color="primary" type="submit" + name="submit" :loading="loading" @click="register"> Submit diff --git a/fda-ui/test/e2e/database.js b/fda-ui/test/e2e/database.js index 1820f89fbf91fa90839baa5c082e46e1b2b41798..15a86e980b777905aa866d6162fd4976371905a2 100644 --- a/fda-ui/test/e2e/database.js +++ b/fda-ui/test/e2e/database.js @@ -1,63 +1,24 @@ const test = require('ava') -const axios = require('axios') +const { mutations } = require('store') const { pageMacro, before, after } = require('./_utils') test.before(before) test.after(after) -test('create database and see the tabs', pageMacro, async (t, page) => { - const database = 'Test Database ' + Math.random().toString(36).substring(7) - const description = 'Test Description' - - await page.go('/databases') - - // Click create new button - await page.click('button:has-text("Database")') - - // Fill database name - await page.fill('input[name="database"]', database) - - // Fill database description - await page.fill('textarea[name="description"]', description) - - // Press Tab - await page.press('textarea[name="description"]', 'Tab') - - // Select mariadb:10.5 - await page.press('#engine', 'ArrowDown') - - // Click submit button - await page.click('button:has-text("Create")') - - // See page load - let success = await page.waitForSelector('text=' + database) - t.true(!!success, `Database ${database} seems not to be created, notification not found`) - - const id = await axios.get('http://localhost:9092/api/database/').then(function (response) { - return response.filter(function (item) { - return item.name === database - }).id - }) - - // ------------------------------------------------------------------------------------------------------------------- - - await page.go('/databases/' + id + '/info') - - // find 'mariadb' anywhere on the page: - success = await page.waitForSelector('text=mariadb:10.5') - t.true(!!success, 'Could not find the mariadb image on the site') - - await page.go('/databases/' + id + '/tables') - - // find 'mariadb' anywhere on the page: - success = await page.waitForSelector('text=(no tables)') - t.true(!!success, 'Could not find the tables on the site') - - // ------------------------------------------------------------------------------------------------------------------- +test('databases_seeDatabases_succeeds', pageMacro, async (t, page) => { + await page.go('/container') + /* test */ + const success = await page.waitForSelector('main >> header >> text=Databases') + t.true(!!success, 'Failed to find \'Databases\' in page') +}) - await page.go('/databases/' + id + '/queries') +test('databases_createDatabase_succeeds', pageMacro, async (t, page) => { + const state = { token: null, user: null, database: null, table: null, access: null } - // find 'mariadb' anywhere on the page: - success = await page.waitForSelector('text=(no queries)') - t.true(!!success, 'Could not find the queries on the site') + await page.go('/container') + mutations.SET_TOKEN(state, 'ABC') + mutations.SET_USER(state, { username: 'ava' }) + await page.screenshot({ path: './screenshots/databases_createDatabase_succeeds.png' }) + /* test */ + t.true(true) }) diff --git a/fda-ui/test/e2e/forgot.js b/fda-ui/test/e2e/forgot.js new file mode 100644 index 0000000000000000000000000000000000000000..03c3415564e006031ec606d4be3c2b0948737b01 --- /dev/null +++ b/fda-ui/test/e2e/forgot.js @@ -0,0 +1,18 @@ +const test = require('ava') +const { pageMacro, before, after } = require('./_utils') + +test.before(before) +test.after(after) + +test('login_succeeds', pageMacro, async (t, page) => { + const email = 'ava@example.com' + const username = 'ava' + + await page.go('/forgot') + await page.fill('input[name="username"]', username) + await page.fill('input[name="email"]', email) + + /* test */ + const success = await page.waitForSelector('button[name="submit"]:not([disabled])') + t.true(!!success, 'Failed to reset user information') +}) diff --git a/fda-ui/test/e2e/index.js b/fda-ui/test/e2e/index.js index ee391d1d6d52aa4d5a364a6da3c4ac4675dbb2c4..399bd9485ec9a043ac1638517c48e133ba936aff 100644 --- a/fda-ui/test/e2e/index.js +++ b/fda-ui/test/e2e/index.js @@ -4,7 +4,50 @@ const { pageMacro, before, after } = require('./_utils') test.before(before) test.after(after) -test('visit homepage', pageMacro, async (t, page) => { +test('home_seeDatabaseRepository_succeeds', pageMacro, async (t, page) => { await page.go('/') - t.is(await page.title(), 'FAIR Data Austria - Database Repository (Sandbox)') + + // find 'Database Repository' anywhere on the page: + const success = await page.waitForSelector('text=Database Repository') + t.true(!!success, 'Failed to find \'Database Repository\' in page') +}) + +test('home_seeInformation_succeeds', pageMacro, async (t, page) => { + await page.go('/') + + // find 'Information' anywhere on the page: + const success = await page.waitForSelector('text=Information') + t.true(!!success, 'Failed to find \'Information\' in page') +}) + +test('home_seeDatabases_succeeds', pageMacro, async (t, page) => { + await page.go('/') + + // find 'Databases' anywhere on the page: + const success = await page.waitForSelector('text=Databases') + t.true(!!success, 'Failed to find \'Databases\' in page') +}) + +test('home_seeLogin_succeeds', pageMacro, async (t, page) => { + await page.go('/') + + // find 'Login' anywhere on the page: + const success = await page.waitForSelector('text=Login') + t.true(!!success, 'Failed to find \'Login\' in page') +}) + +test('home_seeSignup_succeeds', pageMacro, async (t, page) => { + await page.go('/') + + // find 'Signup' anywhere on the page: + const success = await page.waitForSelector('text=Signup') + t.true(!!success, 'Failed to find \'Signup\' in page') +}) + +test('home_seeSearch_succeeds', pageMacro, async (t, page) => { + await page.go('/') + + // find 'Search' anywhere on the page: + const success = await page.waitForSelector('[placeholder="Search ..."]') + t.true(!!success, 'Failed to find \'Search\' in page') }) diff --git a/fda-ui/test/e2e/login.js b/fda-ui/test/e2e/login.js new file mode 100644 index 0000000000000000000000000000000000000000..1ddae6a394c3d1bccc933b8e8a6e7d1fa0e50552 --- /dev/null +++ b/fda-ui/test/e2e/login.js @@ -0,0 +1,18 @@ +const test = require('ava') +const { pageMacro, before, after } = require('./_utils') + +test.before(before) +test.after(after) + +test('login_succeeds', pageMacro, async (t, page) => { + const username = 'ava' + const password = Math.random().toString(36).substring(7) + + await page.go('/login') + await page.fill('input[name="username"]', username) + await page.fill('input[name="password"]', password) + + /* test */ + const success = await page.waitForSelector('button[name="submit"]:not([disabled])') + t.true(!!success, 'Failed to login') +}) diff --git a/fda-ui/test/e2e/search.js b/fda-ui/test/e2e/search.js new file mode 100644 index 0000000000000000000000000000000000000000..b2fbc9868e30f8ec0caa4a6d0103c0ca271c3d05 --- /dev/null +++ b/fda-ui/test/e2e/search.js @@ -0,0 +1,28 @@ +const test = require('ava') +const { pageMacro, before, after } = require('./_utils') + +test.before(before) +test.after(after) + +test('search_succeeds', pageMacro, async (t, page) => { + const query = 'dummy' + + await page.go('/') + await page.fill('input[placeholder="Search ..."]', query) + + /* test */ + const success = await page.waitForSelector('button[name="search-submit"]') + t.true(!!success, 'Failed to search') +}) + +test('search_execute_succeeds', pageMacro, async (t, page) => { + const query = 'dummy' + + await page.go('/') + await page.fill('input[placeholder="Search ..."]', query) + await page.click('button[name="search-submit"]') + + /* test */ + const success = await page.waitForSelector('button[name="search-submit"]') + t.true(!!success, 'Failed to search') +}) diff --git a/fda-ui/test/e2e/signup.js b/fda-ui/test/e2e/signup.js new file mode 100644 index 0000000000000000000000000000000000000000..d25e27a274b212fc671dba8be5bd3f3990922ec4 --- /dev/null +++ b/fda-ui/test/e2e/signup.js @@ -0,0 +1,21 @@ +const test = require('ava') +const { pageMacro, before, after } = require('./_utils') + +test.before(before) +test.after(after) + +test('signup_succeeds', pageMacro, async (t, page) => { + const email = 'ava@example.com' + const username = 'ava' + const password = Math.random().toString(36).substring(7) + + await page.go('/signup') + await page.fill('input[name="email"]', email) + await page.fill('input[name="username"]', username) + await page.fill('input[name="password"]', password) + await page.fill('input[name="password-confirm"]', password) + + /* test */ + const success = await page.waitForSelector('button[name="submit"]:not([disabled])') + t.true(!!success, 'Failed to sign-up') +}) diff --git a/fda-ui/test/e2e/tables.js b/fda-ui/test/e2e/tables.js deleted file mode 100644 index 208280da7730b141049532b2e1dc73c8866ea02d..0000000000000000000000000000000000000000 --- a/fda-ui/test/e2e/tables.js +++ /dev/null @@ -1,62 +0,0 @@ -const test = require('ava') -const axios = require('axios') -const { pageMacro, before, after } = require('./_utils') - -test.before(before) -test.after(after) - -test('create table using form', pageMacro, async (t, page) => { - const database = 'Test Database ' + Math.random().toString(36).substring(7) - const table = 'Test Table ' + Math.random().toString(36).substring(7) - const description = 'Test Description' - - await page.go('/databases') - - // Click create new button - await page.click('button:has-text("Database")') - - // Fill database name - await page.fill('input[name="database"]', database) - - // Fill database description - await page.fill('textarea[name="description"]', description) - - // Press Tab - await page.press('textarea[name="description"]', 'Tab') - - // Select mariadb:10.5 - await page.press('#engine', 'ArrowDown') - - // Click submit button - await page.click('button:has-text("Create")') - - // See page load - let success = await page.waitForSelector('text=' + database) - t.true(!!success, `Database ${database} seems not to be created, notification not found`) - - const id = await axios.get('http://localhost:9092/api/database/').then(function (response) { - return response.filter(function (item) { - return item.name === database - }).id - }) - - // ------------------------------------------------------------------------------------------------------------------- - - await page.go('/databases/' + id + '/tables') - - // Click create new button - await page.click('button:has-text("Create Table")') - - // Fill table name - await page.fill('input[name="name"]', table) - - // Fill table description - await page.fill('input[name="description"]', description) - - // Click submit button - await page.click('button:has-text("Create Table")') - - // See page load - success = await page.waitForSelector('text=aaaaaaaa') - t.true(!!success, `Table ${database} seems not to be created, notification not found`) -}) diff --git a/fda-ui/test/unit/query.js b/fda-ui/test/unit/query.js index af97f551459143ea52318666258bae5387e0a0a0..1721491863978b8b2ee50141700991768a852504 100644 --- a/fda-ui/test/unit/query.js +++ b/fda-ui/test/unit/query.js @@ -1,14 +1,14 @@ const test = require('ava') const { buildQuery, castNum } = require('@/server-middleware/query') -test('simple select', (t) => { +test('buildQuery_succeeds', (t) => { const r = buildQuery({ table: 'Table' }) t.is(r.sql, 'select * from `Table`') }) -test('select some columns', (t) => { +test('buildQuery_columns_succeeds', (t) => { const r = buildQuery({ table: 'Table', select: ['database', 'bbb'] @@ -16,7 +16,7 @@ test('select some columns', (t) => { t.is(r.sql, 'select `database`, `bbb` from `Table`') }) -test('simple where clause', (t) => { +test('buildQuery_where_succeeds', (t) => { const r = buildQuery({ table: 'Table', clauses: [ @@ -26,7 +26,7 @@ test('simple where clause', (t) => { t.is(r.sql, 'select * from `Table` where `foo` = 42') }) -test('simple where clause with numeric string', (t) => { +test('buildQuery_whereNumeric_succeeds', (t) => { const r = buildQuery({ table: 'Table', clauses: [ @@ -36,7 +36,7 @@ test('simple where clause with numeric string', (t) => { t.is(r.sql, 'select * from `Table` where `foo` = 42') }) -test('simple where clause with non-numeric string', (t) => { +test('buildQuery_whereString_succeeds', (t) => { const r = buildQuery({ table: 'Table', clauses: [ @@ -46,7 +46,7 @@ test('simple where clause with non-numeric string', (t) => { t.is(r.sql, 'select * from `Table` where `foo` = \'bla\'') }) -test('using unallowed operator', (t) => { +test('buildQuery_illegalOperator_fails', (t) => { const r = buildQuery({ table: 'Table', clauses: [ @@ -57,7 +57,7 @@ test('using unallowed operator', (t) => { t.is(r.error, 'The operator "UNKNOWN" is not permitted') }) -test('where clause with explicit `and`', (t) => { +test('buildQuery_whereAndExplicit_succeeds', (t) => { const r = buildQuery({ table: 'Table', clauses: [ @@ -69,7 +69,7 @@ test('where clause with explicit `and`', (t) => { t.is(r.sql, 'select * from `Table` where `foo` = 42 and `bar` = 42') }) -test('where clause with implicit `and`', (t) => { +test('buildQuery_whereAndImplicit_succeeds', (t) => { const r = buildQuery({ table: 'Table', clauses: [ @@ -81,7 +81,7 @@ test('where clause with implicit `and`', (t) => { t.is(r.sql, 'select * from `Table` where `foo` = 42 and `bar` = 42') }) -test('where clause with `or`', (t) => { +test('buildQuery_whereOr', (t) => { const r = buildQuery({ table: 'Table', clauses: [ @@ -93,7 +93,7 @@ test('where clause with `or`', (t) => { t.is(r.sql, 'select * from `Table` where `foo` = 42 or `bar` = 42') }) -test('cast numeric strings to numbers', (t) => { +test('castNum_succeeds', (t) => { t.is(castNum(''), '') t.is(castNum(' '), ' ') t.is(castNum('0'), 0) diff --git a/fda-ui/test/unit/utils.js b/fda-ui/test/unit/utils.js new file mode 100644 index 0000000000000000000000000000000000000000..4b6a0f0be00d091b169c13c70a1b5daf55d708be --- /dev/null +++ b/fda-ui/test/unit/utils.js @@ -0,0 +1,279 @@ +const test = require('ava') +const { + isNonNegativeInteger, + isDeveloper, + isResearcher, + isDataSteward, + formatUser, + formatDateUTC, + formatYearUTC, + formatMonthUTC, + formatDayUTC, + formatTimestamp, + formatCreators, + formatTimestampUTCLabel, + formatTimestampUTC +} = require('@/utils') + +test('isNonNegativeInteger_succeeds', (t) => { + /* test */ + const response = isNonNegativeInteger('1') + t.is(response, true) +}) + +test('isNonNegativeInteger_zero_succeeds', (t) => { + /* test */ + const response = isNonNegativeInteger('0') + t.is(response, true) +}) + +test('isNonNegativeInteger_fails', (t) => { + /* test */ + const response = isNonNegativeInteger('-1') + t.is(response, false) +}) + +test('isDeveloper_succeeds', (t) => { + const user = { roles: ['ROLE_DEVELOPER'] } + /* test */ + const response = isDeveloper(user) + t.is(response, true) +}) + +test('isDeveloper_fails', (t) => { + const user = { roles: [] } + /* test */ + const response = isDeveloper(user) + t.is(response, false) +}) + +test('isDeveloper_otherRole_fails', (t) => { + const user = { roles: ['ROLE_RESEARCHER'] } + /* test */ + const response = isDeveloper(user) + t.is(response, false) +}) + +test('isResearcher_succeeds', (t) => { + const user = { roles: ['ROLE_RESEARCHER'] } + /* test */ + const response = isResearcher(user) + t.is(response, true) +}) + +test('isResearcher_fails', (t) => { + const user = { roles: [] } + /* test */ + const response = isResearcher(user) + t.is(response, false) +}) + +test('isResearcher_otherRole_fails', (t) => { + const user = { roles: ['ROLE_DEVELOPER'] } + /* test */ + const response = isResearcher(user) + t.is(response, false) +}) + +test('isDataSteward_succeeds', (t) => { + const user = { roles: ['ROLE_DATA_STEWARD'] } + /* test */ + const response = isDataSteward(user) + t.is(response, true) +}) + +test('isDataSteward_fails', (t) => { + const user = { roles: [] } + /* test */ + const response = isDataSteward(user) + t.is(response, false) +}) + +test('isDataSteward_otherRole_fails', (t) => { + const user = { roles: ['ROLE_DEVELOPER'] } + /* test */ + const response = isDataSteward(user) + t.is(response, false) +}) + +test('formatUser_fails', (t) => { + const user = null + /* test */ + const response = formatUser(user) + t.is(response, null) +}) + +test('formatUser_usernameMissing_fails', (t) => { + const user = { lastname: null, firstname: null } + /* test */ + const response = formatUser(user) + t.is(response, null) +}) + +test('formatUser_succeeds', (t) => { + const user = { lastname: null, firstname: null, username: 'mweise' } + /* test */ + const response = formatUser(user) + t.is(response, 'mweise') +}) + +test('formatUser_firstnameLastname_succeeds', (t) => { + const user = { lastname: 'Martin', firstname: 'Weise', username: 'mweise' } + /* test */ + const response = formatUser(user) + t.is(response, 'Weise Martin') +}) + +test('formatUser_titles_succeeds', (t) => { + const user = { lastname: 'Martin', firstname: 'Weise', username: 'mweise', titles_before: 'Dipl.-Ing.', titles_after: 'BSc' } + /* test */ + const response = formatUser(user) + t.is(response, 'Dipl.-Ing. Weise Martin BSc') +}) + +test('formatDateUTC_succeeds', (t) => { + /* test */ + const response = formatDateUTC('2023-02-15 10:32:21') + t.is(response, '2023-02-15') +}) + +test('formatDateUTC_fails', (t) => { + /* test */ + const response = formatDateUTC(null) + t.is(response, null) +}) + +test('formatYearUTC_fails', (t) => { + /* test */ + const response = formatYearUTC(null) + t.is(response, null) +}) + +test('formatYearUTC_succeeds', (t) => { + /* test */ + const response = formatYearUTC('2023-02-15 10:32:21') + t.is(response, '2023') +}) + +test('formatMonthUTC_fails', (t) => { + /* test */ + const response = formatMonthUTC(null) + t.is(response, null) +}) + +test('formatMonthUTC_succeeds', (t) => { + /* test */ + const response = formatMonthUTC('2023-02-15 10:32:21') + t.is(response, '02') +}) + +test('formatDayUTC_fails', (t) => { + /* test */ + const response = formatDayUTC(null) + t.is(response, null) +}) + +test('formatDayUTC_succeeds', (t) => { + /* test */ + const response = formatDayUTC('2023-02-15 10:32:21') + t.is(response, '15') +}) + +test('formatTimestamp_fails', (t) => { + /* test */ + const response = formatTimestamp(null) + t.is(response, null) +}) + +test('formatTimestamp_succeeds', (t) => { + /* test */ + const response = formatTimestamp('2023-02-15 10:32:21') + t.is(response, '2023-02-15 10:32:21') +}) + +test('formatCreators_containerMissing_fails', (t) => { + const container = null + /* test */ + const response = formatCreators(container) + t.is(response, null) +}) + +test('formatCreators_databaseMissing_fails', (t) => { + const container = { } + /* test */ + const response = formatCreators(container) + t.is(response, null) +}) + +test('formatCreators_identifierMissing_fails', (t) => { + const container = { database: { } } + /* test */ + const response = formatCreators(container) + t.is(response, null) +}) + +test('formatCreators_creatorsMissing_fails', (t) => { + const container = { database: { identifier: { } } } + /* test */ + const response = formatCreators(container) + t.is(response, null) +}) + +test('formatCreators_identifierNull_fails', (t) => { + const container = { database: { identifier: null } } + /* test */ + const response = formatCreators(container) + t.is(response, null) +}) + +test('formatCreators_creatorsEmpty_fails', (t) => { + const container = { database: { identifier: { creators: [] } } } + /* test */ + const response = formatCreators(container) + t.is(response, null) +}) + +test('formatCreators_single_succeeds', (t) => { + const container = { database: { identifier: { creators: [{ firstname: 'Martin', lastname: 'Weise' }] } } } + /* test */ + const response = formatCreators(container) + t.is(response, 'M., Weise') +}) + +test('formatCreators_double_succeeds', (t) => { + const container = { database: { identifier: { creators: [{ firstname: 'Martin', lastname: 'Weise' }, { firstname: 'Tobias', lastname: 'Grantner' }] } } } + /* test */ + const response = formatCreators(container) + t.is(response, 'M., Weise, & T., Grantner') +}) + +test('formatCreators_multiple_succeeds', (t) => { + const container = { database: { identifier: { creators: [{ firstname: 'Martin', lastname: 'Weise' }, { firstname: 'Tobias', lastname: 'Grantner' }, { firstname: 'Josef', lastname: 'Taha' }] } } } + /* test */ + const response = formatCreators(container) + t.is(response, 'M., Weise, T., Grantner, & J., Taha') +}) + +test('formatTimestampUTCLabel_succeeds', (t) => { + /* test */ + const response = formatTimestampUTCLabel('2023-02-15 10:32:21') + t.is(response, '2023-02-15 09:32:21 (UTC)') +}) + +test('formatTimestampUTCLabel_fails', (t) => { + /* test */ + const response = formatTimestampUTCLabel(null) + t.is(response, null) +}) + +test('formatTimestampUTC_fails', (t) => { + /* test */ + const response = formatTimestampUTC(null) + t.is(response, null) +}) + +test('formatTimestampUTC_succeeds', (t) => { + /* test */ + const response = formatTimestampUTC('2023-02-15 10:32:21') + t.is(response, '2023-02-15 09:32:21') +}) diff --git a/fda-ui/utils/index.js b/fda-ui/utils/index.js index 5e8dde78716edfb27d7341feb5ec45592a921bc9..2cb3310639179d677ae038562ba7be92a03504c8 100644 --- a/fda-ui/utils/index.js +++ b/fda-ui/utils/index.js @@ -53,10 +53,10 @@ function formatUser (user) { if (!user) { return null } - if (!('firstname' in user) || !('lastname' in user)) { - return user.username - } - if (user.firstname === null || user.lastname === null) { + if (!('firstname' in user) || !('lastname' in user) || user.firstname === null || user.lastname === null) { + if (!('username' in user)) { + return null + } return user.username } let name = '' @@ -70,13 +70,6 @@ function formatUser (user) { return name } -function padLeft (str, padString, length) { - while (str.length < length) { - str = padString + str - } - return str -} - function formatDateUTC (str) { if (str === null) { return null @@ -117,8 +110,8 @@ function formatTimestamp (str) { } function formatCreators (container) { - if (!container.database.identifier || !container.database.identifier.creators) { - return '' + if (!container || !('database' in container) || !('identifier' in container.database) || !container.database.identifier || !('creators' in container.database.identifier) || !container.database.identifier.creators) { + return null } const creators = container.database.identifier.creators if (creators.length === 0) { @@ -127,8 +120,8 @@ function formatCreators (container) { let str = '' for (let i = 0; i < creators.length; i++) { /* separator */ - if (i > 0 && creators.length === 2) { - str += ' & ' + if (creators.length > 1 && i === creators.length - 1) { + str += ', & ' } else if (i > 0 && creators.length !== 2) { str += ', ' } @@ -170,7 +163,6 @@ module.exports = { formatYearUTC, formatMonthUTC, formatDayUTC, - padLeft, formatCreators, isDeveloper, isResearcher, diff --git a/fda-ui/yarn.lock b/fda-ui/yarn.lock index e302f9ae08538f8432dbf7fe79485fca4dc56503..421217b621020514a9f20925a4ba668b5d2735c6 100644 --- a/fda-ui/yarn.lock +++ b/fda-ui/yarn.lock @@ -2767,6 +2767,15 @@ axios@^0.21.1: dependencies: follow-redirects "^1.14.0" +axios@^1.3.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.3.tgz#e7011384ba839b885007c9c9fae1ff23dceb295b" + integrity sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + babel-eslint@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" @@ -5639,6 +5648,11 @@ follow-redirects@^1.0.0, follow-redirects@^1.14.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== +follow-redirects@^1.15.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -5661,6 +5675,15 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -10091,6 +10114,11 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"