diff --git a/.github/workflows/plugin-alertMessenger.yml b/.github/workflows/plugin-alertMessenger.yml new file mode 100644 index 000000000..036e7555c --- /dev/null +++ b/.github/workflows/plugin-alertMessenger.yml @@ -0,0 +1,40 @@ +name: CI - Plugin - Alert Messenger + +# Controls when the workflow will run +on: + # Triggers the workflow on push or pull request events but only for the main branch + push: + branches: [ "**" ] + paths: + - "software/plugins/alert-messenger/**" + - ".github/workflows/plugin-alertMessenger.yml" + pull_request: + branches: [ "**" ] + paths: + - "software/plugins/alert-messenger/**" + - ".github/workflows/plugin-alertMessenger.yml" + workflow_call: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: +defaults: + run: + working-directory: "software/plugins/alert-messenger/" +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + build: + uses: ./.github/workflows/wf-gradleBuild.yaml + with: + path: "software/plugins/alert-messenger/" + unitTest: + uses: ./.github/workflows/wf-gradleUnitTest.yaml + with: + path: "software/plugins/alert-messenger/" + intTest: + uses: ./.github/workflows/wf-gradleQuarkusIntTest.yaml + strategy: + matrix: + containerBased: [ false ] # TODO:: enable true + with: + path: "software/plugins/alert-messenger/" + containerBased: ${{ matrix.containerBased }} + diff --git a/deployment/Single Host/Infrastructure/jaeger/properties.json b/deployment/Single Host/Infrastructure/jaeger/properties.json index e83ba0d51..0df24eb51 100644 --- a/deployment/Single Host/Infrastructure/jaeger/properties.json +++ b/deployment/Single Host/Infrastructure/jaeger/properties.json @@ -1,6 +1,6 @@ { "packageName":"oqm-infra-jaeger", - "version":"1.2.0", + "version":"1.2.1", "description":"Jaeger instance for Open QuarterMaster.", "homepage":"https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/Infrastructure/jaeger", "configs": [], diff --git a/deployment/Single Host/Infrastructure/kafka-red-panda/properties.json b/deployment/Single Host/Infrastructure/kafka-red-panda/properties.json index 8037b92e0..aaaeddad8 100644 --- a/deployment/Single Host/Infrastructure/kafka-red-panda/properties.json +++ b/deployment/Single Host/Infrastructure/kafka-red-panda/properties.json @@ -1,6 +1,6 @@ { "packageName":"oqm-infra-kafka+red+panda", - "version":"1.0.0", + "version":"1.0.1", "description":"Kafka instance for Open QuarterMaster using Red Panda.", "homepage":"https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/Infrastructure/kafka-red-panda", "configs": [], diff --git a/deployment/Single Host/Infrastructure/keycloak/oqm-infra-keycloak.service b/deployment/Single Host/Infrastructure/keycloak/oqm-infra-keycloak.service index ef54869d8..4a2b45fb1 100644 --- a/deployment/Single Host/Infrastructure/keycloak/oqm-infra-keycloak.service +++ b/deployment/Single Host/Infrastructure/keycloak/oqm-infra-keycloak.service @@ -10,7 +10,7 @@ # [Unit] -Description=Keycloak server for Open Quartermaster. Version ${version}, using Keycloak tagged to "24.0". +Description=Keycloak server for Open Quartermaster. Version ${version}, using Keycloak tagged to "26.0". Documentation=https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/Infrastructure After=docker.service Wants=network-online.target @@ -20,11 +20,11 @@ Requires=oqm-infra-postgres.service [Service] Type=simple Restart=always -TimeoutSec=5m +TimeoutSec=10m # setup operating variables Environment="CONTAINER_NAME=oqm-infra-keycloak" Environment="IMAGE_NAME=quay.io/keycloak/keycloak" -Environment="IMAGE_VERSION=24.0" +Environment="IMAGE_VERSION=26.0" Environment="ENV_CONFIG_FILE=/tmp/oqm/serviceConfig/infra/keycloak/env.list" ExecStartPre=/bin/bash -c "/usr/bin/docker stop -t 10 $CONTAINER_NAME || echo 'Could not stop keycloak container'" @@ -38,6 +38,7 @@ ExecStartPre=/bin/bash -c "cp \"$(oqm-config -g cert.certs.privateKey)\" /etc/oq ExecStartPre=/bin/bash -c "cp \"$(oqm-config -g cert.certs.systemCert)\" /etc/oqm/serviceConfig/infra/keycloak/files/publicCert.pem" ExecStartPre=/bin/bash -c "cp \"$(oqm-config -g cert.certs.keystore)\" /etc/oqm/serviceConfig/infra/keycloak/files/keystore.p12" ExecStartPre=/bin/bash -c "mkdir -p /tmp/oqm/serviceConfig/infra/keycloak" +# TODO:: use file templating to achieve this ExecStartPre=/bin/bash -c "touch $ENV_CONFIG_FILE" ExecStartPre=/bin/bash -c "chmod 600 $ENV_CONFIG_FILE" ExecStartPre=/bin/bash -c "truncate -s 0 $ENV_CONFIG_FILE" @@ -101,7 +102,7 @@ ExecStartPost=/bin/bash -c "running=\"false\"; \ echo \"Container was stopped!\"; \ exit 1; \ fi; \ - hcGet=\"$(/usr/bin/curl -k \"https://$hostname:$servicePort/health\")\"; \ + hcGet=\"$(docker run --rm --name oqm-infra-keycloak-hc --network=oqm-internal docker.io/curlimages/curl:latest https://oqm-infra-keycloak:9000/health -k)\"; \ echo \"Health check get: $hcGet\"; \ status=\"$(jq --argjson hcGet \"$hcGet\" -nr '$hcGet.status')\"; \ echo \"Status: $status\"; \ diff --git a/deployment/Single Host/Infrastructure/keycloak/properties.json b/deployment/Single Host/Infrastructure/keycloak/properties.json index 8b5499d17..2a62ef4a1 100644 --- a/deployment/Single Host/Infrastructure/keycloak/properties.json +++ b/deployment/Single Host/Infrastructure/keycloak/properties.json @@ -1,6 +1,6 @@ { "packageName":"oqm-infra-keycloak", - "version":"1.2.0", + "version":"1.2.2", "description":"Keycloak instance for Open QuarterMaster.", "homepage":"https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/deployment/Single%20Host/Infrastructure/keycloak", "configs": [ diff --git a/deployment/Single Host/Infrastructure/makeInstallers.sh b/deployment/Single Host/Infrastructure/makeInstallers.sh index d0d38a63e..999eb2328 100755 --- a/deployment/Single Host/Infrastructure/makeInstallers.sh +++ b/deployment/Single Host/Infrastructure/makeInstallers.sh @@ -92,7 +92,7 @@ Developer: EBP Architecture: all Description: $(cat "$packageConfigFile" | jq -r '.description') Homepage: $(cat "$packageConfigFile" | jq -r '.homepage') -Depends: docker, docker.io, oqm-manager-station+captain (>= 2.2.0)$(cat "$packageConfigFile" | jq -r '.dependencies.deb') +Depends: docker.io, oqm-manager-station+captain (>= 2.2.0)$(cat "$packageConfigFile" | jq -r '.dependencies.deb') EOT # TODO:: add conflicts diff --git a/deployment/Single Host/Infrastructure/mongo/properties.json b/deployment/Single Host/Infrastructure/mongo/properties.json index 967aec4cc..e9d76ad67 100644 --- a/deployment/Single Host/Infrastructure/mongo/properties.json +++ b/deployment/Single Host/Infrastructure/mongo/properties.json @@ -1,6 +1,6 @@ { "packageName":"oqm-infra-mongodb", - "version":"1.2.0", + "version":"1.2.1", "description":"MongoDb instance for Open QuarterMaster.", "homepage":"https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/Infrastructure/mongo", "configs": [], diff --git a/deployment/Single Host/Infrastructure/postgres/properties.json b/deployment/Single Host/Infrastructure/postgres/properties.json index 4f01a32b2..100c2d277 100644 --- a/deployment/Single Host/Infrastructure/postgres/properties.json +++ b/deployment/Single Host/Infrastructure/postgres/properties.json @@ -1,6 +1,6 @@ { "packageName":"oqm-infra-postgres", - "version":"1.2.0", + "version":"1.2.1", "description":"Postgresql instance for Open QuarterMaster.", "homepage":"https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/Infrastructure/postgresql", "configs": [ diff --git a/deployment/Single Host/Station-Captain/properties.json b/deployment/Single Host/Station-Captain/properties.json index db515a825..99814b9e6 100644 --- a/deployment/Single Host/Station-Captain/properties.json +++ b/deployment/Single Host/Station-Captain/properties.json @@ -1,13 +1,13 @@ { "packageName":"oqm-manager-station+captain", - "version":"2.4.0", + "version":"2.4.2", "description":"Utility for setting up and maintaining an instance of Open QuarterMaster.", "maintainer": { "name":"EBP" }, "homepage":"https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/Station%20Captain", "dependencies": { - "deb":"bash, curl, jq, libnss-mdns, hwinfo, moreutils, dialog, docker, docker.io, unattended-upgrades, ca-certificates, python3 (>= 3.10.0), python3-dialog, python3-docker, python3-systemd, python3-argcomplete, python3-jinja2", + "deb":"bash, curl, jq, libnss-mdns, hwinfo, moreutils, dialog, docker.io, unattended-upgrades, ca-certificates, python3 (>= 3.10.0), python3-dialog, python3-docker, python3-systemd, python3-argcomplete, python3-jinja2, python3-distutils-extra", "rpm":"bash, curl, jq, hwinfo, moreutils, dialog, docker, python3" }, "copyright": { diff --git a/deployment/Single Host/Station-Captain/src/lib/LogUtils.py b/deployment/Single Host/Station-Captain/src/lib/LogUtils.py index 3c0b1ad7c..918b4fa65 100644 --- a/deployment/Single Host/Station-Captain/src/lib/LogUtils.py +++ b/deployment/Single Host/Station-Captain/src/lib/LogUtils.py @@ -16,25 +16,36 @@ class LogUtils: @staticmethod def setupLogging(logFile:str, console:bool=False): - Path(LogUtils.logDir).mkdir(parents=True, exist_ok=True) - LogUtils.logFile = logFile + filePresent:bool = False + if not os.path.exists(logFile): + try: + Path(LogUtils.logDir).mkdir(parents=True, exist_ok=True) + os.mknod(logFile) + LogUtils.logFile = logFile + filePresent = True + except Exception as e: + LogUtils.logFile = False + filePresent = False + else: + filePresent = True logging.basicConfig(level=logging.NOTSET) - if console: LogUtils.logLevel = logging.DEBUG @staticmethod def setupLogger(name: str) -> logging.Logger: - fh = logging.handlers.RotatingFileHandler(LogUtils.logDir+LogUtils.logFile, maxBytes=10*1024*1024, backupCount=5) - fh.setLevel(logging.DEBUG) - # sh = logging.StreamHandler() # sh.setLevel(LogUtils.logLevel) logOut = logging.getLogger(name) # print(LogUtils.logLevel == logging.DEBUG) logOut.setLevel(LogUtils.logLevel) - logOut.addHandler(fh) + + if not LogUtils.logFile: + fh = logging.handlers.RotatingFileHandler(LogUtils.logDir+LogUtils.logFile, maxBytes=10*1024*1024, backupCount=5) + fh.setLevel(logging.DEBUG) + logOut.addHandler(fh) + # logOut.addHandler(sh) return logOut diff --git a/deployment/Single Host/docs/System Requirements.md b/deployment/Single Host/docs/System Requirements.md index b1904d91a..291bec9eb 100644 --- a/deployment/Single Host/docs/System Requirements.md +++ b/deployment/Single Host/docs/System Requirements.md @@ -2,35 +2,36 @@ This is a set of requirements for the entire system, not necessarily just the station captain. -This system is regularly tested on Ubuntu 22.04. +This system is regularly tested on Ubuntu 24.04. ## Software Requirements - A Modern Linux OS - - At the moment we only support Debian-based systems (`apt`), we plan on eventually also supporting Fedora/RHEL (`dnf`) systems. (Tested on Ubuntu 22.04, Raspbian) + - At the moment we only support Debian-based systems (`apt`), we plan on eventually also supporting Fedora/RHEL (`dnf`) systems. - Tested and verified: - Ubuntu 22.04 - Lubuntu 22.04 + - Ubuntu 24.04 - Raspbian (current version as of Dec 2023) ## Hardware Requirements: -- 2 cores on headless server, 4 cores on a host with a desktop - 4gb of RAM, 8gb recommended for minimum - CPU Requirements + - 2 cores on headless server, 4 cores on a host with a desktop - One of the following architectures: - 64-bit `x64` ISA, intel or AMD - Must include [AVX](https://en.wikipedia.org/wiki/Advanced_Vector_Extensions). Known supported: - Any AMD - Any modern Intel i3, i5, i7, i9 - - Intel N95, N100 + - Intel N95, N100, N300 - 64-bit ARM v8 -Note:: it is possible certain plugins, or a large number of plugins, will require more resources or have different hardware requirements. +> [!NOTE] +> it is possible certain plugins, or a large number of plugins, will require more resources or have different hardware requirements. ### Proven SBC's and other 'specialty' hardware: - ARM: - - [Raspberry Pi 5B](https://www.raspberrypi.com/products/raspberry-pi-5/), 8Gb memory recommended. 4Gb would probably be fine for testing and minimal purposes only, but any less is probably not going to be enough for a good experience. - - + - [Raspberry Pi 5B](https://www.raspberrypi.com/products/raspberry-pi-5/ + - 8Gb memory recommended. 4Gb would probably be fine for testing and minimal purposes only, but any less is probably not going to be enough for a good experience. diff --git a/media/diagrams/Simple OQM Diagram.drawio b/media/diagrams/Simple OQM Diagram.drawio new file mode 100644 index 000000000..2393c7a8f --- /dev/null +++ b/media/diagrams/Simple OQM Diagram.drawio @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/media/diagrams/Simple OQM Diagram.drawio.svg b/media/diagrams/Simple OQM Diagram.drawio.svg new file mode 100644 index 000000000..04564cdf5 --- /dev/null +++ b/media/diagrams/Simple OQM Diagram.drawio.svg @@ -0,0 +1,4 @@ + + + +

Core Services

Actor
Core API
Depot
(Landing page)
Base Station
(Main UI)

Databases

& Infra

MongoDB
PostgreSQL
Keycloak
(User Auth)

Plugins

External Item Search
Kafka
(Messaging)
Alert Messenger

...

\ No newline at end of file diff --git a/pagesSource/repos/main/deb/InRelease b/pagesSource/repos/main/deb/InRelease index c256b32f3..d2909fe90 100644 --- a/pagesSource/repos/main/deb/InRelease +++ b/pagesSource/repos/main/deb/InRelease @@ -1,37 +1,37 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 -Date: Sat, 03 Aug 2024 18:25:06 +0000 +Date: Wed, 16 Oct 2024 02:13:30 +0000 MD5Sum: - 49fd3a3d837a207aede87e484cfb8906 29998 Packages - 016870bd83db4989f936d3e5d374f920 5481 Packages.gz - f0a62f2d1e0c142e9450fc6ee6194212 38 Release + 0337451d1241e2ce3d3dea579ff07bbb 41030 Packages + 8cf98b2f940c2deb47514f41b9cc320f 7225 Packages.gz + 6be1c711a1f342ffe1683577ea64c8a3 38 Release SHA1: - 1d09ab5e95ebc08eeecc59430f4be1f5adf380dc 29998 Packages - 844eda917dc73398c19857fd36c2a60d043bb3d7 5481 Packages.gz - 58e2def98b5fe812de296b5cb6bbd8325d0ce9ef 38 Release + 86fd856b155df1a08c09df9a99328e82ff7c348a 41030 Packages + 1ecb50fc731d1e5ee38c882e1215d2c014d1acf5 7225 Packages.gz + 580591d21e50d03423a566e73c08ee3459a1f452 38 Release SHA256: - d7482645c5e9271aa04418ccfc385d61ce9ace4282e11118d97e4ddf6de632f3 29998 Packages - 24023ceadcf10ca73bf4260236eea2dd4623f212f14320bc1bfa402cd622c4d0 5481 Packages.gz - c38bb26594bb260791766dc19f2834278e971c9ab684f693c4d293187fd88f66 38 Release + b5492936a3460714716b7c6b3f2578295ce031a5c9f4990dfdf5838b5903ebc7 41030 Packages + 5723bd5ac16a99c7e3089fd95a98c1956c516a42eb44588eee6643506c7423d1 7225 Packages.gz + 65cec2ed13a69bccea65c21ce19cf3949ca9f0528b40a09c3ff21ac8a4389e2b 38 Release SHA512: - 372c0ccef345d7655ac81c310c51433081fc23031f4d5641324564867c531fb86110c5ce0615b89f24065eb03978b8f3660f0781c98922eb159b486c052fc266 29998 Packages - cbc196f64c9f8545566b1ef14be995c448c87f5d94088b4f975b35f48363b76e0bf0d81fcfa42a61bc4a286ab1fb3d3cc95f2e87236197d0e0960af8fcfa8bcf 5481 Packages.gz - 0427c5cf6de27e038fe855d54b4dc7e2df7d79befa9d844d76a816f1023bc7f1298b70358229b91ae2ce1b530608008d814bc12c77c086b00bc4b14f613e1c4c 38 Release + 56c56468090f56f72c937dbd576581d5b54583910ab5517d7003df011ff494db7a3778ee6becfe5f58201500bd490a4ec7cc0b4cd272510bb9068f0264c01f37 41030 Packages + 069d44e4f4a7ffc69a6791fa81852f30c0010168df81cc0c81742215a6ca8b2175c1f93b0c45002c03f79185a13ca63f1dca3a2994df8dcc1601414c02c93cfd 7225 Packages.gz + 2bbf4ed4879dd0c07b4a310b54372f6498e8974ce442a4e1cc9814106da204038df0721f6ca65334a759e253679629e03cd1d46fce2e9484f3cbffe4c777ae30 38 Release -----BEGIN PGP SIGNATURE----- -iQJZBAEBCgBDFiEET4mMzDxL82g2xa7Aa9cIQRtcMhYFAmaudiUlHGdyZWdAZXBp -Yy1icmVha2Zhc3QtcHJvZHVjdGlvbnMudGVjaAAKCRBr1whBG1wyFp6tD/sGAxRO -aSJg3zvUoAuj4K7i/TLbLNZG5Ll+9AiMyL/FxE8Dccs5M7hnRcUj5tMH0mJnLkze -8NVmaUEGt/AFODvaSJTjtEhfHqH5A51VGwLmp+isX3PDwKOrEBQdLi69w5M4Kg3t -Ycwk6ckJd83ZApjvYxlDGWvJdsZN/gpTpuRfaduEkXTzf9o3rgS3HJ7DPZReghbD -NyI4VmSKBnowE1U4nXPkYk8ALb9MZoj3apP9MudCQ9T0JikxyCAjGHCz7YKDaGNv -ycO4gjtyYRN8ZzH+A1IOETHGTtRsRiINrATi2GJgTWHc2p/ALqqL2dt+Pb5HSLnu -W1EQP0piERwKLoVWAoQmv0FWr5no/PlY/OHB44qjCfyKl6xpIez9ziviK276196X -cusxjrBsjexFv7rnFaFdQ/W4lPCrlFo24XW6sT9czHXDSNCwVH2Dg2wAu6bx4svE -Q4xmXLT570Xlwpct4AS/H1m0bGyjNOxP/naG9S6gpPc0i2yhE95OBsi9LRgmX/Mp -S0jqUBmiNuWWWUyLyMhxCKwB8BYuOI7fQaHm/VguxCcf6lxSbRLEUN0SRpQgY++0 -LB2ua8LhSmuahw/DUeuXg92apQtsHbErtWcaEIRfl8GyaXud13ICKOr7RXIu9TtN -yySqNPJIPSaLsTWr9LsxKZVaf4LTWZpZDcOKZQ== -=ok/j +iQJZBAEBCgBDFiEET4mMzDxL82g2xa7Aa9cIQRtcMhYFAmcPIWElHGdyZWdAZXBp +Yy1icmVha2Zhc3QtcHJvZHVjdGlvbnMudGVjaAAKCRBr1whBG1wyFsFED/sFzB4H +eyH5/IJgWmNTPe7h/nEoSZI0JOH+DP4Qy3455KSlbApo6tvRybNFFmid4ClRewxv +vhfUiVzCQ71HMPskRtmKpQHWSPWVO5kaO8SQD7PZph3Rrt8/gmPWlh8ixDfmmCIY +atcFX3MsLqn9qbnICyeZ08XHSdkZdbkgH5F5K5Iv2Oc9u4AJA5Yh8N4bltQcTT2O +laaREpKXeSYMxQQH3IWmPiGC2yPFrYzF0RYV6uVihEKQDNNwwBrgeTN5dFW7diUn +5K8T3P7NksKuVx+kNTrIhtYvTZRuJCm/ZFzG2wJYIX/f2Xt3WMArgnVHBcA/QxXN +IYbiLfJA8QEkFMKZSmzDmW83lzLzMhL9e5qTYJ1FoKrAHtTuAlougRcZv/Wgb5vk +EWsVm9+kKSbLsgtAZpsz7IHiM/4IyrenUxIhCV9gkaV/zl7Xp4KCXMhswMS+q9bm +3vSYFOYit5iqTAb7uDnXXAy0AQilpy0HPX3wSn08u5OF1dYUZb7lcJ8zbyFDSPCe +55lgtil9/XJu12f9p0Xbm7o5F46KRDhBSJTkrIBToEUjhG0uGgQk/1XW/qC2PVZ0 +59IQoTMyRMlLXXiqSM6XZukNXZAYDab7iCylX5ntMJX12Y7X5Ml6AQu5/Vigytha +9FeHnOIRBD73E8D2cdQxZ0vdmYwKNXOHxL8PRA== +=4Gt+ -----END PGP SIGNATURE----- diff --git a/pagesSource/repos/main/deb/Packages b/pagesSource/repos/main/deb/Packages index cf8fbc76a..626fef823 100644 --- a/pagesSource/repos/main/deb/Packages +++ b/pagesSource/repos/main/deb/Packages @@ -118,6 +118,51 @@ Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/m Description: Core API instance for Open QuarterMaster. Licence: GPL-3+ +Package: oqm-core-api +Version: 2.1.3 +Architecture: all +Maintainer: EBP +Depends: curl, jq, docker.io, docker, oqm-manager-station+captain (>= 2.1.0), oqm-infra-jaeger (>= 1.1.0), oqm-infra-mongodb (>= 1.1.0), oqm-core-depot (>= 1.0.0) +Filename: ./oqm-core-api_2.1.3_all.deb +Size: 4070 +MD5sum: c52f7409ae54cc25d926660c8272a727 +SHA1: 6d954e893fb76be98853462262d97581a3670998 +SHA256: 494fc748352eca3aa2fe0bd1e498943743baf84fb01b46c3cf621cbc9240e4e3 +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/oqm-core-api +Description: Core API instance for Open QuarterMaster. +Licence: GPL-3+ + +Package: oqm-core-api +Version: 2.1.4 +Architecture: all +Maintainer: EBP +Depends: curl, jq, docker.io, docker, oqm-manager-station+captain (>= 2.1.0), oqm-infra-jaeger (>= 1.1.0), oqm-infra-mongodb (>= 1.1.0), oqm-core-depot (>= 1.0.0) +Filename: ./oqm-core-api_2.1.4_all.deb +Size: 4070 +MD5sum: ce245f9b00ce5efe77864b529c5e69af +SHA1: 087114c2c217bfe9a58180e2b3d8a460837f97d1 +SHA256: 99e58da431757d8c2f069d38cc6277f62279dd5d6fcd82c7a4240d6ee187025b +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/oqm-core-api +Description: Core API instance for Open QuarterMaster. +Licence: GPL-3+ + +Package: oqm-core-api +Version: 2.1.5 +Architecture: all +Maintainer: EBP +Depends: curl, jq, docker.io, oqm-manager-station+captain (>= 2.1.0), oqm-infra-jaeger (>= 1.1.0), oqm-infra-mongodb (>= 1.1.0), oqm-core-depot (>= 1.0.0) +Filename: ./oqm-core-api_2.1.5_all.deb +Size: 4066 +MD5sum: e88b7133d02cdc25a61b4cfa6473af2e +SHA1: 90225b52d3198d8a9661c84af096ff6d15bda0b9 +SHA256: cbb9bcf2b00225b8bdde6bcad0d9da1a89bdffc61745ed556ac4ec9e3a9dbb68 +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/oqm-core-api +Description: Core API instance for Open QuarterMaster. +Licence: GPL-3+ + Package: oqm-core-base+station Version: 1.0.40 Architecture: all @@ -273,6 +318,54 @@ Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/m Description: Base Station instance for Open QuarterMaster. Licence: GPL-3+ +Package: oqm-core-base+station +Version: 1.4.3 +Architecture: all +Maintainer: EBP +Depends: curl, jq, docker.io, docker, oqm-manager-station+captain (>= 2.0.0), oqm-infra-jaeger (>= 1.1.0), oqm-infra-keycloak (>= 1.1.0), oqm-core-depot, oqm-core-api (>= 2.1.0) +Recommends: oqm-plugin-ext_item_search +Filename: ./oqm-core-base+station_1.4.3_all.deb +Size: 4128 +MD5sum: e89311abd7543a6daab006a65c59ded1 +SHA1: 77ebda26a6eb65da3a773ef5646ba460c38fafaf +SHA256: 772f58d4a2c94e1fad611c043564edef21307a9b8c0fbc3785c4e871b80747b2 +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/open-qm-base-station +Description: Base Station instance for Open QuarterMaster. +Licence: GPL-3+ + +Package: oqm-core-base+station +Version: 1.4.4 +Architecture: all +Maintainer: EBP +Depends: curl, jq, docker.io, docker, oqm-manager-station+captain (>= 2.0.0), oqm-infra-jaeger (>= 1.1.0), oqm-infra-keycloak (>= 1.1.0), oqm-core-depot, oqm-core-api (>= 2.1.0) +Recommends: oqm-plugin-ext_item_search +Filename: ./oqm-core-base+station_1.4.4_all.deb +Size: 4130 +MD5sum: 7a1447e1fbd893f09f39dd655b54cc58 +SHA1: 80636e0b402a423d548bd5e450e02e6c51111383 +SHA256: ce3a35425a5e4a7d44931a473d6bd0896bcb4eb10679b33a604a1bb6f8e56d48 +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/open-qm-base-station +Description: Base Station instance for Open QuarterMaster. +Licence: GPL-3+ + +Package: oqm-core-base+station +Version: 1.4.5 +Architecture: all +Maintainer: EBP +Depends: curl, jq, docker.io, oqm-manager-station+captain (>= 2.0.0), oqm-infra-jaeger (>= 1.1.0), oqm-infra-keycloak (>= 1.1.0), oqm-core-depot, oqm-core-api (>= 2.1.0) +Recommends: oqm-plugin-ext_item_search +Filename: ./oqm-core-base+station_1.4.5_all.deb +Size: 4134 +MD5sum: 6203ec5f3a95143fcee8409960d6e00d +SHA1: daacfd3f14ba33f22f854b1d59444a09fd2e3266 +SHA256: e516cc129f1a61a300c34669282b7e4301bb97a0e76bd464c93912c288270b80 +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/open-qm-base-station +Description: Base Station instance for Open QuarterMaster. +Licence: GPL-3+ + Package: oqm-core-depot Version: 1.0.0 Architecture: all @@ -303,6 +396,36 @@ Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/m Description: Depot instance for Open QuarterMaster. Licence: GPL-3+ +Package: oqm-core-depot +Version: 1.1.2 +Architecture: all +Maintainer: EBP +Depends: docker.io, docker, oqm-manager-station+captain (>= 2.1.0) +Filename: ./oqm-core-depot_1.1.2_all.deb +Size: 2542 +MD5sum: 496f388b836379422bdb3839ceffa854 +SHA1: c697058dcda13c47a611987f9826e72c9ff59211 +SHA256: 7689380fb8e884ebccc6b38daf92035f5458feac989aa2fcd5781248e730e8f3 +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/oqm-depot +Description: Depot instance for Open QuarterMaster. +Licence: GPL-3+ + +Package: oqm-core-depot +Version: 1.1.3 +Architecture: all +Maintainer: EBP +Depends: docker.io, oqm-manager-station+captain (>= 2.1.0) +Filename: ./oqm-core-depot_1.1.3_all.deb +Size: 2534 +MD5sum: 37afba0714d4ee87d7a8ab83a8d8b100 +SHA1: f5aafd77e74bff31bc70cf8a2fbf73e09f095592 +SHA256: cc95f0d0d7873f6e0356d97fb31f48b3592ba79d9cab0bc5a09559933335cfb8 +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/oqm-depot +Description: Depot instance for Open QuarterMaster. +Licence: GPL-3+ + Package: oqm-infra-jaeger Version: 1.1.1 Architecture: all @@ -348,6 +471,21 @@ Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/m Description: Jaeger instance for Open QuarterMaster. Developer: EBP +Package: oqm-infra-jaeger +Version: 1.2.1 +Architecture: all +Maintainer: EBP +Depends: docker.io, oqm-manager-station+captain (>= 2.2.0) +Filename: ./oqm-infra-jaeger_1.2.1_all.deb +Size: 10468 +MD5sum: 0c9271bfb1bba3298980fb4e480edeff +SHA1: 0848409042de1a3b44c3e4b32639f8ed31e6eb09 +SHA256: c9bfa3af6a31b498a3294127350bd447dd7b94b84a1f04fbb82f2ffda892dab4 +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/Infrastructure/jaeger +Description: Jaeger instance for Open QuarterMaster. +Developer: EBP + Package: oqm-infra-kafka+red+panda Version: 1.0.0 Architecture: all @@ -363,6 +501,21 @@ Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/m Description: Kafka instance for Open QuarterMaster using Red Panda. Developer: EBP +Package: oqm-infra-kafka+red+panda +Version: 1.0.1 +Architecture: all +Maintainer: EBP +Depends: docker.io, oqm-manager-station+captain (>= 2.2.0) +Filename: ./oqm-infra-kafka+red+panda_1.0.1_all.deb +Size: 2286 +MD5sum: 31cbdd418c2c71f5b658d6a8e687f085 +SHA1: f8cee686707918bcdb1606354dc64707d66677f7 +SHA256: 8828c0ee1b4e565712e1640eff08810659a8faba6d4153607ebb460ca7e5ce2d +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/Infrastructure/kafka-red-panda +Description: Kafka instance for Open QuarterMaster using Red Panda. +Developer: EBP + Package: oqm-infra-keycloak Version: 1.1.4 Architecture: all @@ -393,6 +546,36 @@ Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/m Description: Keycloak instance for Open QuarterMaster. Developer: EBP +Package: oqm-infra-keycloak +Version: 1.2.1 +Architecture: all +Maintainer: EBP +Depends: docker, docker.io, oqm-manager-station+captain (>= 2.2.0), oqm-infra-postgres (>= 1.1.0), python3 (>= 3.10.0), python3-docker, python3-watchdog +Filename: ./oqm-infra-keycloak_1.2.1_all.deb +Size: 15160 +MD5sum: e69f6be51326599991d55d4e44d3fc61 +SHA1: ea36da1ebf760937a6454001ba396db159465a8d +SHA256: 447aa5e88e66d4afa39560add717861b0d4d0425f2e52ea2a3a6022ebfb2c60d +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/deployment/Single%20Host/Infrastructure/keycloak +Description: Keycloak instance for Open QuarterMaster. +Developer: EBP + +Package: oqm-infra-keycloak +Version: 1.2.2 +Architecture: all +Maintainer: EBP +Depends: docker.io, oqm-manager-station+captain (>= 2.2.0), oqm-infra-postgres (>= 1.1.0), python3 (>= 3.10.0), python3-docker, python3-watchdog +Filename: ./oqm-infra-keycloak_1.2.2_all.deb +Size: 15168 +MD5sum: eee659c6efefc80c2df30ae5ede0d248 +SHA1: 53a73c48a8d6a0c830f57549a43e6ae3b7bf353e +SHA256: 4fb86e3e00f59fe40de1cd81cc088d600013b2bc24ae745f4312c01110de3f67 +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/deployment/Single%20Host/Infrastructure/keycloak +Description: Keycloak instance for Open QuarterMaster. +Developer: EBP + Package: oqm-infra-mongodb Version: 1.1.3 Architecture: all @@ -423,6 +606,21 @@ Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/m Description: MongoDb instance for Open QuarterMaster. Developer: EBP +Package: oqm-infra-mongodb +Version: 1.2.1 +Architecture: all +Maintainer: EBP +Depends: docker.io, oqm-manager-station+captain (>= 2.2.0) +Filename: ./oqm-infra-mongodb_1.2.1_all.deb +Size: 3582 +MD5sum: 5a4f94016087e978c6d75e0b7d19b240 +SHA1: c33b7bea1de9cd3cf28a14e706a1de5fc7d97980 +SHA256: ab1755e7f1d9f5793b5e5038db36abbfd156db890dce06fe168dc8fbe2f1e998 +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/Infrastructure/mongo +Description: MongoDb instance for Open QuarterMaster. +Developer: EBP + Package: oqm-infra-postgres Version: 1.1.3 Architecture: all @@ -453,6 +651,21 @@ Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/m Description: Postgresql instance for Open QuarterMaster. Developer: EBP +Package: oqm-infra-postgres +Version: 1.2.1 +Architecture: all +Maintainer: EBP +Depends: docker.io, oqm-manager-station+captain (>= 2.2.0) +Filename: ./oqm-infra-postgres_1.2.1_all.deb +Size: 3270 +MD5sum: 8d7a622bb04265b988f8c48a0d72e2f2 +SHA1: a21e719d5e778cb2d764bb15fd9e9289878339d3 +SHA256: 92018b5de5b7cf6b32ade458a6ec08394e36cc187d3ff60ba83df267af29e2a9 +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/Infrastructure/postgresql +Description: Postgresql instance for Open QuarterMaster. +Developer: EBP + Package: oqm-manager-station+captain Version: 2.0.10 Architecture: all @@ -618,6 +831,36 @@ Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/m Description: Utility for setting up and maintaining an instance of Open QuarterMaster. Licence: GPL-3+ +Package: oqm-manager-station+captain +Version: 2.4.1 +Architecture: all +Maintainer: EBP +Pre-Depends: bash, curl, jq, libnss-mdns, hwinfo, moreutils, dialog, docker, docker.io, unattended-upgrades, ca-certificates, python3 (>= 3.10.0), python3-dialog, python3-docker, python3-systemd, python3-argcomplete, python3-jinja2 +Filename: ./oqm-manager-station+captain_2.4.1_all.deb +Size: 41744 +MD5sum: 8c8e014e59465df88140428a70f1fdeb +SHA1: 8b54062ba73e44f0bdc2e9b10170746cb85deecc +SHA256: 43380bb45df0d4a85c118e2fc290b7dc8c416327155e8cd6445cff7bfb17627d +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/Station%20Captain +Description: Utility for setting up and maintaining an instance of Open QuarterMaster. +Licence: GPL-3+ + +Package: oqm-manager-station+captain +Version: 2.4.2 +Architecture: all +Maintainer: EBP +Pre-Depends: bash, curl, jq, libnss-mdns, hwinfo, moreutils, dialog, docker.io, unattended-upgrades, ca-certificates, python3 (>= 3.10.0), python3-dialog, python3-docker, python3-systemd, python3-argcomplete, python3-jinja2, python3-distutils-extra +Filename: ./oqm-manager-station+captain_2.4.2_all.deb +Size: 41760 +MD5sum: d2b2f04f6e83377f8658a82fd49f8c56 +SHA1: adc48f96a11dc1589ac80427729ceb2d676105cc +SHA256: 1b857d95d6540e5e803c779b18972053f8e2c5cd1ac81f483eb026eeeb1dbe13 +Section: Open QuarterMaster +Homepage: https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/Station%20Captain +Description: Utility for setting up and maintaining an instance of Open QuarterMaster. +Licence: GPL-3+ + Package: oqm-plugin-ext+item+search Version: 1.0.0 Architecture: all diff --git a/pagesSource/repos/main/deb/Packages.gz b/pagesSource/repos/main/deb/Packages.gz index f4e0e0374..cc4382af6 100644 Binary files a/pagesSource/repos/main/deb/Packages.gz and b/pagesSource/repos/main/deb/Packages.gz differ diff --git a/pagesSource/repos/main/deb/Release b/pagesSource/repos/main/deb/Release index 8b1820606..3c181eaf8 100644 --- a/pagesSource/repos/main/deb/Release +++ b/pagesSource/repos/main/deb/Release @@ -1,17 +1,17 @@ -Date: Sat, 03 Aug 2024 18:25:06 +0000 +Date: Wed, 16 Oct 2024 02:13:30 +0000 MD5Sum: - 49fd3a3d837a207aede87e484cfb8906 29998 Packages - 016870bd83db4989f936d3e5d374f920 5481 Packages.gz - f0a62f2d1e0c142e9450fc6ee6194212 38 Release + 0337451d1241e2ce3d3dea579ff07bbb 41030 Packages + 8cf98b2f940c2deb47514f41b9cc320f 7225 Packages.gz + 6be1c711a1f342ffe1683577ea64c8a3 38 Release SHA1: - 1d09ab5e95ebc08eeecc59430f4be1f5adf380dc 29998 Packages - 844eda917dc73398c19857fd36c2a60d043bb3d7 5481 Packages.gz - 58e2def98b5fe812de296b5cb6bbd8325d0ce9ef 38 Release + 86fd856b155df1a08c09df9a99328e82ff7c348a 41030 Packages + 1ecb50fc731d1e5ee38c882e1215d2c014d1acf5 7225 Packages.gz + 580591d21e50d03423a566e73c08ee3459a1f452 38 Release SHA256: - d7482645c5e9271aa04418ccfc385d61ce9ace4282e11118d97e4ddf6de632f3 29998 Packages - 24023ceadcf10ca73bf4260236eea2dd4623f212f14320bc1bfa402cd622c4d0 5481 Packages.gz - c38bb26594bb260791766dc19f2834278e971c9ab684f693c4d293187fd88f66 38 Release + b5492936a3460714716b7c6b3f2578295ce031a5c9f4990dfdf5838b5903ebc7 41030 Packages + 5723bd5ac16a99c7e3089fd95a98c1956c516a42eb44588eee6643506c7423d1 7225 Packages.gz + 65cec2ed13a69bccea65c21ce19cf3949ca9f0528b40a09c3ff21ac8a4389e2b 38 Release SHA512: - 372c0ccef345d7655ac81c310c51433081fc23031f4d5641324564867c531fb86110c5ce0615b89f24065eb03978b8f3660f0781c98922eb159b486c052fc266 29998 Packages - cbc196f64c9f8545566b1ef14be995c448c87f5d94088b4f975b35f48363b76e0bf0d81fcfa42a61bc4a286ab1fb3d3cc95f2e87236197d0e0960af8fcfa8bcf 5481 Packages.gz - 0427c5cf6de27e038fe855d54b4dc7e2df7d79befa9d844d76a816f1023bc7f1298b70358229b91ae2ce1b530608008d814bc12c77c086b00bc4b14f613e1c4c 38 Release + 56c56468090f56f72c937dbd576581d5b54583910ab5517d7003df011ff494db7a3778ee6becfe5f58201500bd490a4ec7cc0b4cd272510bb9068f0264c01f37 41030 Packages + 069d44e4f4a7ffc69a6791fa81852f30c0010168df81cc0c81742215a6ca8b2175c1f93b0c45002c03f79185a13ca63f1dca3a2994df8dcc1601414c02c93cfd 7225 Packages.gz + 2bbf4ed4879dd0c07b4a310b54372f6498e8974ce442a4e1cc9814106da204038df0721f6ca65334a759e253679629e03cd1d46fce2e9484f3cbffe4c777ae30 38 Release diff --git a/pagesSource/repos/main/deb/Release.gpg b/pagesSource/repos/main/deb/Release.gpg index faa13f541..48564857e 100644 --- a/pagesSource/repos/main/deb/Release.gpg +++ b/pagesSource/repos/main/deb/Release.gpg @@ -1,17 +1,17 @@ -----BEGIN PGP SIGNATURE----- -iQJZBAABCgBDFiEET4mMzDxL82g2xa7Aa9cIQRtcMhYFAmaudgIlHGdyZWdAZXBp -Yy1icmVha2Zhc3QtcHJvZHVjdGlvbnMudGVjaAAKCRBr1whBG1wyFspAEAC/T4Bh -EpZwBTA1KLeV7UzA+fsKJPXOiYaNV9REfvzRwHDHftoLJy0JEivu89BKfYFXz7QX -ArV2qzEV+FmXBoP4IwztJURf7sY8eUq3SCdFru89fmFj/tkAQho7YAIC9HlltFk4 -xy0Bo8rmLjGlxFTFZ5pT531so1CD4BanCVWsacFZYsSlK60ISp1QudAfrhN2c7k1 -7md1cYlE3T2j3RgBMAgaT6pIwvBQrcW4TMGrFsJ8qMxiNxmH2xdU8o1k/JiFC2Ix -D3HCvDavXt8REh7EaeEsN+Bv80cR+3UfJP6HfLLzvEZpdyEhblIxRw+XHAz/eURR -BvCAXcjx6zEXe0tsRs4jjaQJ0mIGW2BYZP3NQEbcfeg/XQTxkbx2vsFXjXmnXmfF -PZprUOGDV6xhdmJRM6V+xalVpZly3KLG9eXIvFUCns1MpGrD8r0iaHZ/ouG0hfZt -DsWNkUiJ5FlpRqWOUz5SXFzA9jbQMytumMrOlBhJcp90cG0GfY/iktAAsi7MBCk1 -Ykske0+6dUD0JDnYpqyB20o0WyCyRMQTbdIYqdKZqpRTEIlc9BtCBWNmCiTGq7lF -B6Wd60m+ZMvHJIFr40xNU1CvpjTk2u7x0delXUFcSnHRVB4w0Y82VwKQ9/CQyCV5 -ZOcTfp3vBRsODw2XARHs0yWJY9otg7pkmYlHkw== -=bfBf +iQJZBAABCgBDFiEET4mMzDxL82g2xa7Aa9cIQRtcMhYFAmcPIUolHGdyZWdAZXBp +Yy1icmVha2Zhc3QtcHJvZHVjdGlvbnMudGVjaAAKCRBr1whBG1wyFio/EAC/cSa7 +bdd2YhugklEIL3+LB7tBRNJP1eFVbKhEV/QygSxGnZtEuQjZyrg4LyDkvsvHQ99v +DAx7EmQX8JU1NXrQ4W/JFF1xsCBAmeQX/dgz69IEeBb3v4NSi2sgCc+dSyGb7SCC +oPGTnfDEUxB+pOgHX/mEemB4PCKn7vKez3N7/IVuCaSBoXQ21O/A+ImPVBxy+Ix3 +PWTHjs/QPfPYdJZ3XRfMSyZTHw988eNuT75AzMZwhHkUJpPXLqHlYtmQ/YiHkbwi +ZM7rou2dgKQ0xCHgWGddLa1QUVOr2KFBXCKR8YHk6ujnW2edd3n08e6Dv6/GElEJ +xuXVdqIEk7nMO40Sfgtl+SeTycg/bI+xIRgm81mRfp0VnV8Tqx84GFP0UrAf++at +fTfS/OTYySgHplJiDgyvLRCRV8JP1VsDbCqd6ebOkDT6JHrqGViLIhV3KOyrP3Dq +z3qYuilLVQjyS2oW9hXwjFwR0m+y3QGi/YT6BkFQTxjBj9prD5K6sXxwajE0IxNf +I/X6+Kr63ahcQAl4uWDW/tEYVl/x4V1xuXFSJt1rHDw7oIjOPPsHFb3cUHO36qi2 +eX8OPcQeojHuR9DpA4pjM9TvokiVeT3USt/73r4OAZOmsqHu7kF3lUDvlevb15Ys +HTyzLrlvnGw7lfx0iL1aS5JoNKg3cEPjH0BwTg== +=Vl2c -----END PGP SIGNATURE----- diff --git a/pagesSource/repos/main/deb/oqm-core-api_2.1.3_all.deb b/pagesSource/repos/main/deb/oqm-core-api_2.1.3_all.deb new file mode 100644 index 000000000..49ff760a7 Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-core-api_2.1.3_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-core-api_2.1.4_all.deb b/pagesSource/repos/main/deb/oqm-core-api_2.1.4_all.deb new file mode 100644 index 000000000..69fdcb207 Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-core-api_2.1.4_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-core-api_2.1.5_all.deb b/pagesSource/repos/main/deb/oqm-core-api_2.1.5_all.deb new file mode 100644 index 000000000..897009e02 Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-core-api_2.1.5_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-core-base+station_1.4.3_all.deb b/pagesSource/repos/main/deb/oqm-core-base+station_1.4.3_all.deb new file mode 100644 index 000000000..bcf80a4e3 Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-core-base+station_1.4.3_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-core-base+station_1.4.4_all.deb b/pagesSource/repos/main/deb/oqm-core-base+station_1.4.4_all.deb new file mode 100644 index 000000000..69df8c851 Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-core-base+station_1.4.4_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-core-base+station_1.4.5_all.deb b/pagesSource/repos/main/deb/oqm-core-base+station_1.4.5_all.deb new file mode 100644 index 000000000..f418e3c00 Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-core-base+station_1.4.5_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-core-depot_1.1.2_all.deb b/pagesSource/repos/main/deb/oqm-core-depot_1.1.2_all.deb new file mode 100644 index 000000000..1bdcb9521 Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-core-depot_1.1.2_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-core-depot_1.1.3_all.deb b/pagesSource/repos/main/deb/oqm-core-depot_1.1.3_all.deb new file mode 100644 index 000000000..109c69df1 Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-core-depot_1.1.3_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-infra-jaeger_1.2.1_all.deb b/pagesSource/repos/main/deb/oqm-infra-jaeger_1.2.1_all.deb new file mode 100644 index 000000000..f6bbbfb2e Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-infra-jaeger_1.2.1_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-infra-kafka+red+panda_1.0.1_all.deb b/pagesSource/repos/main/deb/oqm-infra-kafka+red+panda_1.0.1_all.deb new file mode 100644 index 000000000..0b9e8ea56 Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-infra-kafka+red+panda_1.0.1_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-infra-keycloak_1.2.1_all.deb b/pagesSource/repos/main/deb/oqm-infra-keycloak_1.2.1_all.deb new file mode 100644 index 000000000..9c91d495b Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-infra-keycloak_1.2.1_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-infra-keycloak_1.2.2_all.deb b/pagesSource/repos/main/deb/oqm-infra-keycloak_1.2.2_all.deb new file mode 100644 index 000000000..377e1086f Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-infra-keycloak_1.2.2_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-infra-mongodb_1.2.1_all.deb b/pagesSource/repos/main/deb/oqm-infra-mongodb_1.2.1_all.deb new file mode 100644 index 000000000..db69e8b80 Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-infra-mongodb_1.2.1_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-infra-postgres_1.2.1_all.deb b/pagesSource/repos/main/deb/oqm-infra-postgres_1.2.1_all.deb new file mode 100644 index 000000000..761c50d35 Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-infra-postgres_1.2.1_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-manager-station+captain_2.4.1_all.deb b/pagesSource/repos/main/deb/oqm-manager-station+captain_2.4.1_all.deb new file mode 100644 index 000000000..a01a2276d Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-manager-station+captain_2.4.1_all.deb differ diff --git a/pagesSource/repos/main/deb/oqm-manager-station+captain_2.4.2_all.deb b/pagesSource/repos/main/deb/oqm-manager-station+captain_2.4.2_all.deb new file mode 100644 index 000000000..41b3f1f35 Binary files /dev/null and b/pagesSource/repos/main/deb/oqm-manager-station+captain_2.4.2_all.deb differ diff --git a/software/libs/core-api-lib-quarkus/deployment/pom.xml b/software/libs/core-api-lib-quarkus/deployment/pom.xml index 7c0526de9..b4dc932a4 100644 --- a/software/libs/core-api-lib-quarkus/deployment/pom.xml +++ b/software/libs/core-api-lib-quarkus/deployment/pom.xml @@ -5,7 +5,7 @@ tech.ebp.oqm.lib core-api-lib-quarkus-parent - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT core-api-lib-quarkus-deployment Core Api Lib Quarkus - Deployment @@ -74,6 +74,18 @@ + + org.testcontainers + kafka + 1.20.1 + + + + org.testcontainers + redpanda + 1.20.1 + + diff --git a/software/libs/core-api-lib-quarkus/deployment/src/main/java/tech/ebp/oqm/lib/core/api/quarkus/deployment/CoreApiLibDevserviceConfig.java b/software/libs/core-api-lib-quarkus/deployment/src/main/java/tech/ebp/oqm/lib/core/api/quarkus/deployment/CoreApiLibDevserviceConfig.java index f6f158a55..a443642ba 100644 --- a/software/libs/core-api-lib-quarkus/deployment/src/main/java/tech/ebp/oqm/lib/core/api/quarkus/deployment/CoreApiLibDevserviceConfig.java +++ b/software/libs/core-api-lib-quarkus/deployment/src/main/java/tech/ebp/oqm/lib/core/api/quarkus/deployment/CoreApiLibDevserviceConfig.java @@ -17,6 +17,13 @@ public class CoreApiLibDevserviceConfig { */ @WithDefault("true") public boolean enable; + + /** + * Enables kafka. + */ + @ConfigItem(name="enableKafka") + @WithDefault("false") + public boolean enableKafka; /** * The path of the public key file @@ -33,6 +40,6 @@ public class CoreApiLibDevserviceConfig { /** * The version/ tag of the core api container image */ - @ConfigItem(name="coreApiVersion", defaultValue = "2.1.2") + @ConfigItem(name="coreApiVersion", defaultValue = "2.1.3") public String coreApiVersion; } diff --git a/software/libs/core-api-lib-quarkus/deployment/src/main/java/tech/ebp/oqm/lib/core/api/quarkus/deployment/CoreApiLibQuarkusProcessor.java b/software/libs/core-api-lib-quarkus/deployment/src/main/java/tech/ebp/oqm/lib/core/api/quarkus/deployment/CoreApiLibQuarkusProcessor.java index 297b274f1..338401577 100644 --- a/software/libs/core-api-lib-quarkus/deployment/src/main/java/tech/ebp/oqm/lib/core/api/quarkus/deployment/CoreApiLibQuarkusProcessor.java +++ b/software/libs/core-api-lib-quarkus/deployment/src/main/java/tech/ebp/oqm/lib/core/api/quarkus/deployment/CoreApiLibQuarkusProcessor.java @@ -10,6 +10,7 @@ import io.quarkus.smallrye.health.deployment.spi.HealthBuildItem; import org.testcontainers.containers.MongoDBContainer; import org.testcontainers.containers.Network; +import org.testcontainers.redpanda.RedpandaContainer; import org.testcontainers.utility.DockerImageName; import org.testcontainers.utility.MountableFile; import tech.ebp.oqm.lib.core.api.quarkus.runtime.Constants; @@ -21,23 +22,24 @@ import java.util.Map; class CoreApiLibQuarkusProcessor { - + private static final String FEATURE = "core-api-lib-quarkus"; - private static final String MONGODB_DEVSERVICE_HOSTNAME = "mongodbserver"; - + private static final String MONGODB_DEVSERVICE_HOSTNAME = "oqm-dev-mongodb-server"; + private static final String KAFKA_DEVSERVICE_HOSTNAME = "oqm-dev-kafka-server"; + @BuildStep FeatureBuildItem feature() { return new FeatureBuildItem(FEATURE); } - + @BuildStep List addRestConfiguration() { return List.of( - new RunTimeConfigurationDefaultBuildItem("quarkus.rest-client."+Constants.CORE_API_CLIENT_NAME+".url", "${quarkus." + Constants.CONFIG_ROOT_NAME + ".coreApiBaseUri}"), - new RunTimeConfigurationDefaultBuildItem("quarkus.rest-client."+Constants.CORE_API_CLIENT_OIDC_NAME+".url", "${quarkus.oidc.auth-server-url:}") + new RunTimeConfigurationDefaultBuildItem("quarkus.rest-client." + Constants.CORE_API_CLIENT_NAME + ".url", "${quarkus." + Constants.CONFIG_ROOT_NAME + ".coreApiBaseUri}"), + new RunTimeConfigurationDefaultBuildItem("quarkus.rest-client." + Constants.CORE_API_CLIENT_OIDC_NAME + ".url", "${quarkus.oidc.auth-server-url:}") ); } - + @BuildStep HealthBuildItem addHealthCheck(CoreApiLibBuildTimeConfig buildTimeConfig) { return new HealthBuildItem( @@ -45,7 +47,7 @@ HealthBuildItem addHealthCheck(CoreApiLibBuildTimeConfig buildTimeConfig) { buildTimeConfig.healthEnabled ); } - + @BuildStep(onlyIfNot = IsNormal.class, onlyIf = GlobalDevServicesConfig.Enabled.class) public List createContainer( LaunchModeBuildItem launchMode, @@ -53,41 +55,69 @@ public List createContainer( ) { List output = new ArrayList<>(); Map mongoConnectionInfo = new HashMap<>(); + Map kafkaConnectionInfo = new HashMap<>(); {//mongodb DockerImageName mongoImageName = DockerImageName.parse("mongo:7"); - + MongoDBContainer mongoDBContainer = new MongoDBContainer(mongoImageName); mongoDBContainer.addExposedPorts(); mongoDBContainer.withNetwork(Network.SHARED); mongoDBContainer.withNetworkAliases(MONGODB_DEVSERVICE_HOSTNAME); mongoDBContainer.start(); - + mongoConnectionInfo.put("quarkus.mongodb.connection-string", "mongodb://" + MONGODB_DEVSERVICE_HOSTNAME + ":27017"); - + output.add(new DevServicesResultBuildItem.RunningDevService( FEATURE, mongoDBContainer.getContainerId(), mongoDBContainer::close, Map.of() ) - .toBuildItem() + .toBuildItem() + ); + } + if (config.devservice.enableKafka) { + RedpandaContainer kafka = new RedpandaContainer(DockerImageName.parse("docker.redpanda.com/redpandadata/redpanda:v23.1.2")) + .withNetwork(Network.SHARED) + .withAccessToHost(true) + .withNetworkAliases(KAFKA_DEVSERVICE_HOSTNAME) + .withListener(() -> KAFKA_DEVSERVICE_HOSTNAME + ":19092"); + kafka.start(); + + kafkaConnectionInfo.putAll(Map.of( + "quarkus.reactive-messaging.health.enabled", "true", + "mp.messaging.outgoing.events-outgoing.bootstrap.servers", String.format("PLAINTEXT://%s:%d", KAFKA_DEVSERVICE_HOSTNAME, 19092), + "devservice.kafka.bootstrapServers", kafka.getBootstrapServers(), + "mp.messaging.outgoing.events-outgoing.connector", "smallrye-kafka", + "mp.messaging.outgoing.events-outgoing.broadcast", "true", + "mp.messaging.outgoing.events-outgoing.value.serializer", "io.quarkus.kafka.client.serialization.ObjectMapperSerializer" + )); + + output.add( + new DevServicesResultBuildItem.RunningDevService( + FEATURE, + kafka.getContainerId(), + kafka::close, + Map.of() + ).toBuildItem() ); } {//Base Station DockerImageName dockerImageName = DockerImageName.parse("ebprod/oqm-core-api:" + config.devservice.coreApiVersion); // You might want to use Quarkus config here to customise the container OqmCoreApiWebServiceContainer container = new OqmCoreApiWebServiceContainer(dockerImageName) - .withAccessToHost(true) - .withEnv(mongoConnectionInfo) - .withNetwork(Network.SHARED); + .withAccessToHost(true) + .withEnv(mongoConnectionInfo) + .withEnv(kafkaConnectionInfo) + .withNetwork(Network.SHARED); ; - + if ( config.devservice.certKeyPath.isPresent() || - config.devservice.certPath.isPresent() + config.devservice.certPath.isPresent() ) { - if(!(config.devservice.certKeyPath.isPresent() && - config.devservice.certPath.isPresent())){ + if (!(config.devservice.certKeyPath.isPresent() && + config.devservice.certPath.isPresent())) { throw new RuntimeException("Must specify both cert and key for core api devservice."); } @@ -105,23 +135,27 @@ public List createContainer( container.withEnv("mp.jwt.verify.publickey.location", "/tmp/systemCert.pem"); } - + container.start(); - + Map props = new HashMap<>(); props.put("quarkus." + Constants.CONFIG_ROOT_NAME + ".coreApiBaseUri", "http://" + container.getHost() + ":" + container.getPort()); props.put("quarkus.rest-client.oqmCoreApi.url", "${quarkus." + Constants.CONFIG_ROOT_NAME + ".coreApiBaseUri}"); - + + if (!kafkaConnectionInfo.isEmpty()) { + props.put("devservice.kafka.bootstrapServers", kafkaConnectionInfo.get("devservice.kafka.bootstrapServers")); + } + output.add(new DevServicesResultBuildItem.RunningDevService( FEATURE, container.getContainerId(), container::close, props ) - .toBuildItem() + .toBuildItem() ); } - + return output; } } diff --git a/software/libs/core-api-lib-quarkus/pom.xml b/software/libs/core-api-lib-quarkus/pom.xml index f12f81291..b30207894 100644 --- a/software/libs/core-api-lib-quarkus/pom.xml +++ b/software/libs/core-api-lib-quarkus/pom.xml @@ -5,7 +5,7 @@ tech.ebp.oqm.lib core-api-lib-quarkus-parent - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT pom Core Api Lib Quarkus - Parent diff --git a/software/libs/core-api-lib-quarkus/runtime/pom.xml b/software/libs/core-api-lib-quarkus/runtime/pom.xml index 4201fa12e..13a644670 100644 --- a/software/libs/core-api-lib-quarkus/runtime/pom.xml +++ b/software/libs/core-api-lib-quarkus/runtime/pom.xml @@ -5,7 +5,7 @@ tech.ebp.oqm.lib core-api-lib-quarkus-parent - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT core-api-lib-quarkus Core Api Lib Quarkus - Runtime diff --git a/software/libs/open-qm-moduleDriver/.idea/.gitignore b/software/libs/open-qm-moduleDriver/.idea/.gitignore new file mode 100644 index 000000000..13566b81b --- /dev/null +++ b/software/libs/open-qm-moduleDriver/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/software/libs/open-qm-moduleDriver/.idea/.name b/software/libs/open-qm-moduleDriver/.idea/.name new file mode 100644 index 000000000..e9e687cb6 --- /dev/null +++ b/software/libs/open-qm-moduleDriver/.idea/.name @@ -0,0 +1 @@ +open-qm-lib-moduleDriver \ No newline at end of file diff --git a/software/libs/open-qm-moduleDriver/.idea/compiler.xml b/software/libs/open-qm-moduleDriver/.idea/compiler.xml new file mode 100644 index 000000000..e107ed761 --- /dev/null +++ b/software/libs/open-qm-moduleDriver/.idea/compiler.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/software/libs/open-qm-moduleDriver/.idea/gradle.xml b/software/libs/open-qm-moduleDriver/.idea/gradle.xml new file mode 100644 index 000000000..ce1c62c7c --- /dev/null +++ b/software/libs/open-qm-moduleDriver/.idea/gradle.xml @@ -0,0 +1,16 @@ + + + + + + + \ No newline at end of file diff --git a/software/libs/open-qm-moduleDriver/.idea/jarRepositories.xml b/software/libs/open-qm-moduleDriver/.idea/jarRepositories.xml new file mode 100644 index 000000000..d20b5975a --- /dev/null +++ b/software/libs/open-qm-moduleDriver/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/software/libs/open-qm-moduleDriver/.idea/misc.xml b/software/libs/open-qm-moduleDriver/.idea/misc.xml new file mode 100644 index 000000000..9676474e1 --- /dev/null +++ b/software/libs/open-qm-moduleDriver/.idea/misc.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/software/libs/open-qm-moduleDriver/.idea/vcs.xml b/software/libs/open-qm-moduleDriver/.idea/vcs.xml new file mode 100644 index 000000000..c2365ab11 --- /dev/null +++ b/software/libs/open-qm-moduleDriver/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/software/oqm-core-api/build.gradle b/software/oqm-core-api/build.gradle index 640b72820..5f4a58705 100644 --- a/software/oqm-core-api/build.gradle +++ b/software/oqm-core-api/build.gradle @@ -1,11 +1,11 @@ plugins { id 'java' id 'io.quarkus' - id "io.freefair.lombok" version "8.6" + id "io.freefair.lombok" version "8.10.2" } group 'com.ebp.openQuarterMaster' -version '2.1.3-DEV' +version '2.1.5' repositories { mavenCentral() @@ -50,12 +50,12 @@ dependencies { // https://mvnrepository.com/artifact/tech.uom.lib/uom-lib-jackson implementation 'tech.uom.lib:uom-lib-jackson:2.1' - implementation 'org.apache.commons:commons-lang3:3.15.0' - implementation 'org.apache.commons:commons-compress:1.26.2' - implementation 'org.apache.commons:commons-csv:1.11.0' + implementation 'org.apache.commons:commons-lang3:3.17.0' + implementation 'org.apache.commons:commons-compress:1.27.1' + implementation 'org.apache.commons:commons-csv:1.12.0' implementation 'org.apache.commons:commons-io:1.3.2' implementation 'commons-codec:commons-codec:1.17.1' - implementation 'org.apache.tika:tika-core:2.9.2' + implementation 'org.apache.tika:tika-core:3.0.0' /* Test Dependencies @@ -65,7 +65,7 @@ dependencies { testImplementation group: 'io.rest-assured', name: 'rest-assured' testImplementation 'io.quarkus:quarkus-smallrye-jwt-build' testImplementation 'io.quarkus:quarkus-test-kafka-companion' - testImplementation 'net.datafaker:datafaker:2.3.1' + testImplementation 'net.datafaker:datafaker:2.4.1' testImplementation 'org.assertj:assertj-core:3.26.3' testImplementation 'io.jaegertracing:jaeger-testcontainers:0.7.0' } diff --git a/software/oqm-core-api/docs/development/Releasing.md b/software/oqm-core-api/docs/development/Releasing.md index ad98e0ac3..2ecf1d770 100644 --- a/software/oqm-core-api/docs/development/Releasing.md +++ b/software/oqm-core-api/docs/development/Releasing.md @@ -31,7 +31,7 @@ These are the steps to take to perform a release of the software: 4. Ensure everything committed and pushed to github. Check workflows. 5. Be logged into docker hub with ebprod user `docker login` 6. Deploy jvm version - 1. Clean/build/push project `./gradlew clean build -Pquarkus.container-image.build=true -Pquarkus.jib.platforms=linux/arm64,linux/amd64 -Pquarkus.container-image.group=ebprod -Pquarkus.container-image.name=oqm-core-api -Pquarkus.container-image.push=true -Pquarkus.jib.base-jvm-image=registry.access.redhat.com/ubi9/openjdk-21-runtime:1.20` + 1. Clean/build/push project `./gradlew clean build -Pquarkus.container-image.build=true -Pquarkus.jib.platforms=linux/arm64,linux/amd64 -Pquarkus.container-image.push=true -Pquarkus.jib.base-jvm-image=registry.access.redhat.com/ubi9/openjdk-21-runtime:1.20` 2. Ensure was deployed successfully: https://hub.docker.com/repository/registry-1.docker.io/ebprod/open-qm-base-station/tags?page=1&ordering=last_updated 7. Make installers: `./makeInstallers.sh` 8. Make release for version on Github, attach all installers to it (`build/installers`) \ No newline at end of file diff --git a/software/oqm-core-api/installerSrc/installerProperties.json b/software/oqm-core-api/installerSrc/installerProperties.json index ffe27c032..103eabf8a 100644 --- a/software/oqm-core-api/installerSrc/installerProperties.json +++ b/software/oqm-core-api/installerSrc/installerProperties.json @@ -6,7 +6,7 @@ "description": "Core API instance for Open QuarterMaster.", "homepage": "https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/oqm-core-api", "dependencies": { - "deb": "curl, jq, docker.io, docker, oqm-manager-station+captain (>= 2.1.0), oqm-infra-jaeger (>= 1.1.0), oqm-infra-mongodb (>= 1.1.0), oqm-core-depot (>= 1.0.0)" + "deb": "curl, jq, docker.io, oqm-manager-station+captain (>= 2.1.0), oqm-infra-jaeger (>= 1.1.0), oqm-infra-mongodb (>= 1.1.0), oqm-core-depot (>= 1.0.0)" }, "copyright": { "contact":"Greg Stewart ", diff --git a/software/oqm-core-api/installerSrc/oqm-core-api.service b/software/oqm-core-api/installerSrc/oqm-core-api.service index 3d9a500d3..3bd264929 100644 --- a/software/oqm-core-api/installerSrc/oqm-core-api.service +++ b/software/oqm-core-api/installerSrc/oqm-core-api.service @@ -19,7 +19,7 @@ Requires=oqm-infra-keycloak.service [Service] Type=simple Restart=always -TimeoutSec=5m +TimeoutSec=10m # Setup operating variables Environment="CONTAINER_NAME=oqm-core-api" Environment="IMAGE_NAME=ebprod/oqm-core-api" diff --git a/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/health/SchemaUpgradeHealthCheck.java b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/health/SchemaUpgradeHealthCheck.java index d3c3ffd07..c83545a74 100644 --- a/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/health/SchemaUpgradeHealthCheck.java +++ b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/health/SchemaUpgradeHealthCheck.java @@ -2,13 +2,10 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.eclipse.microprofile.health.HealthCheck; -import org.eclipse.microprofile.health.HealthCheckResponse; -import org.eclipse.microprofile.health.HealthCheckResponseBuilder; -import org.eclipse.microprofile.health.Readiness; +import org.eclipse.microprofile.health.*; import tech.ebp.oqm.core.api.service.schemaVersioning.ObjectSchemaUpgradeService; -@Readiness +@Startup @ApplicationScoped public class SchemaUpgradeHealthCheck implements HealthCheck { diff --git a/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/model/InstanceMutex.java b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/model/InstanceMutex.java new file mode 100644 index 000000000..de7d4f2e3 --- /dev/null +++ b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/model/InstanceMutex.java @@ -0,0 +1,30 @@ +package tech.ebp.oqm.core.api.model; + +import lombok.*; +import tech.ebp.oqm.core.api.model.object.MainObject; + +import java.time.ZonedDateTime; + +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Data +@NoArgsConstructor +@AllArgsConstructor +public class InstanceMutex extends MainObject { + @Override + public int getSchemaVersion() { + return 0; + } + + public InstanceMutex(String mutexId){ + this.mutexId = mutexId; + } + + private String mutexId; + + private boolean taken = false; + + private ZonedDateTime takenAt = null; + + protected String takenBy = null; +} diff --git a/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/model/rest/search/InstanceMutexSearch.java b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/model/rest/search/InstanceMutexSearch.java new file mode 100644 index 000000000..8d72955e1 --- /dev/null +++ b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/model/rest/search/InstanceMutexSearch.java @@ -0,0 +1,26 @@ +package tech.ebp.oqm.core.api.model.rest.search; + +import com.mongodb.client.model.Filters; +import jakarta.ws.rs.QueryParam; +import lombok.Getter; +import lombok.ToString; +import org.bson.conversions.Bson; +import org.bson.types.ObjectId; +import tech.ebp.oqm.core.api.model.InstanceMutex; +import tech.ebp.oqm.core.api.model.object.storage.storageBlock.StorageBlock; +import tech.ebp.oqm.core.api.service.mongo.search.SearchUtils; + +import javax.measure.Quantity; +import java.util.ArrayList; +import java.util.List; + +import static com.mongodb.client.model.Filters.*; + +@ToString(callSuper = true) +@Getter +public class InstanceMutexSearch extends SearchObject { + public static InstanceMutexSearch newInstance(){ + return new InstanceMutexSearch(); + } + +} diff --git a/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/importExport/importing/csv/InvItemCsvConverter.java b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/importExport/importing/csv/InvItemCsvConverter.java index eb05ed1d6..bdec3f982 100644 --- a/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/importExport/importing/csv/InvItemCsvConverter.java +++ b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/importExport/importing/csv/InvItemCsvConverter.java @@ -27,68 +27,70 @@ public class InvItemCsvConverter { public static final Character COMMENT_CHAR = '#'; public List> csvIsToItems(InputStream is) throws IOException { - List> output = new ArrayList<>(); - Reader in = new InputStreamReader(is); - - Iterable records = CSVFormat.Builder - .create(CSVFormat.EXCEL) - .setCommentMarker(COMMENT_CHAR) - .setHeader(CSV_HEADERS) - .setSkipHeaderRecord(true) - .setTrim(true) - .build().parse(in); - - for (CSVRecord record : records) { - StorageType storageType = StorageType.valueOf(record.get("storageType")); - InventoryItem item = switch (storageType) { - case AMOUNT_SIMPLE -> new SimpleAmountItem(); - case AMOUNT_LIST -> new ListAmountItem(); - case TRACKED -> new TrackedItem(); - default -> throw new IllegalArgumentException("Invalid Storage Type Given: " + record.get("storageType")); - }; - - item.setName(record.get("name")); - item.setDescription(record.get("description")); - - if (!record.get("barcode").isBlank()) { - item.setBarcode(record.get("barcode")); - } - if (!record.get("storageBlock").isBlank()) { - item.getStoredWrapperForStorage(new ObjectId(record.get("storageBlock")), true); - } - - String unitVal = record.get("storageBlock"); - switch (storageType) { - case AMOUNT_SIMPLE: - SimpleAmountItem sai = (SimpleAmountItem) item; - if (!unitVal.isBlank()) { - sai.setUnit(UnitUtils.unitFromString(unitVal)); - } - if (!record.get("valuePerUnit").isBlank()) { - sai.setValuePerUnit(new BigDecimal(record.get("valuePerUnit"))); - } - break; - case AMOUNT_LIST: - ListAmountItem lai = ((ListAmountItem) item); - if (!unitVal.isBlank()) { - lai.setUnit(UnitUtils.unitFromString(unitVal)); - } - if (!record.get("valuePerUnit").isBlank()) { - lai.setValuePerUnit(new BigDecimal(record.get("valuePerUnit"))); - } - break; - case TRACKED: - TrackedItem tri = ((TrackedItem) item); - - tri.setTrackedItemIdentifierName(record.get("trackedItemId")); - - if (!record.get("valuePerUnit").isBlank()) { - tri.setDefaultValue(new BigDecimal(record.get("valuePerUnit"))); - } - break; - } - output.add(item); - } - return output; + throw new IllegalStateException("Not implemented yet"); + //TODO:: 708 move to plugin +// List> output = new ArrayList<>(); +// Reader in = new InputStreamReader(is); +// +// Iterable records = CSVFormat.Builder +// .create(CSVFormat.EXCEL) +// .setCommentMarker(COMMENT_CHAR) +// .setHeader(CSV_HEADERS) +// .setSkipHeaderRecord(true) +// .setTrim(true) +// .build().parse(in); +// +// for (CSVRecord record : records) { +// StorageType storageType = StorageType.valueOf(record.get("storageType")); +// InventoryItem item = switch (storageType) { +// case AMOUNT_SIMPLE -> new SimpleAmountItem(); +// case AMOUNT_LIST -> new ListAmountItem(); +// case TRACKED -> new TrackedItem(); +// default -> throw new IllegalArgumentException("Invalid Storage Type Given: " + record.get("storageType")); +// }; +// +// item.setName(record.get("name")); +// item.setDescription(record.get("description")); +// +// if (!record.get("barcode").isBlank()) { +// item.setBarcode(record.get("barcode")); +// } +// if (!record.get("storageBlock").isBlank()) { +// item.getStoredWrapperForStorage(new ObjectId(record.get("storageBlock")), true); +// } +// +// String unitVal = record.get("storageBlock"); +// switch (storageType) { +// case AMOUNT_SIMPLE: +// SimpleAmountItem sai = (SimpleAmountItem) item; +// if (!unitVal.isBlank()) { +// sai.setUnit(UnitUtils.unitFromString(unitVal)); +// } +// if (!record.get("valuePerUnit").isBlank()) { +// sai.setValuePerUnit(new BigDecimal(record.get("valuePerUnit"))); +// } +// break; +// case AMOUNT_LIST: +// ListAmountItem lai = ((ListAmountItem) item); +// if (!unitVal.isBlank()) { +// lai.setUnit(UnitUtils.unitFromString(unitVal)); +// } +// if (!record.get("valuePerUnit").isBlank()) { +// lai.setValuePerUnit(new BigDecimal(record.get("valuePerUnit"))); +// } +// break; +// case TRACKED: +// TrackedItem tri = ((TrackedItem) item); +// +// tri.setTrackedItemIdentifierName(record.get("trackedItemId")); +// +// if (!record.get("valuePerUnit").isBlank()) { +// tri.setDefaultValue(new BigDecimal(record.get("valuePerUnit"))); +// } +// break; +// } +// output.add(item); +// } +// return output; } } diff --git a/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/mongo/InstanceMutexService.java b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/mongo/InstanceMutexService.java new file mode 100644 index 000000000..79b1a20d7 --- /dev/null +++ b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/mongo/InstanceMutexService.java @@ -0,0 +1,188 @@ +package tech.ebp.oqm.core.api.service.mongo; + +import com.mongodb.client.model.*; +import com.mongodb.client.result.UpdateResult; +import jakarta.enterprise.context.ApplicationScoped; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import org.bson.BsonDocument; +import org.bson.Document; +import org.bson.conversions.Bson; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import tech.ebp.oqm.core.api.model.InstanceMutex; +import tech.ebp.oqm.core.api.model.collectionStats.CollectionStats; +import tech.ebp.oqm.core.api.model.rest.search.InstanceMutexSearch; + +import java.time.Duration; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; +import java.time.temporal.TemporalAmount; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static com.mongodb.client.model.Filters.*; + +/** + * Original inspiration: https://www.disk91.com/2018/technology/programming/springboot-mongo-create-a-mutex-to-synchronize-multiple-frontends/ + */ +@ApplicationScoped +@Slf4j +public class InstanceMutexService extends TopLevelMongoService { + + private TemporalAmount lockExpire = Duration.of(10, ChronoUnit.MINUTES); + + @ConfigProperty(name = "quarkus.uuid") + protected String instanceUuid; + + protected InstanceMutexService() { + super(InstanceMutex.class); + } + + protected String getIdentity(Optional additionalIdentity) { + return this.instanceUuid + additionalIdentity.map(s -> "-" + s).orElse(""); + } + + private void clearDuplicateMutexes(String mutexId) { + List mutexes = this.getCollection().find(eq("mutexId", mutexId)).into(new ArrayList<>()); + if (mutexes.size() > 1) { + log.info("Multiple mutex objects for {} detected ({} total mutexes). Deleting extra.", mutexId, mutexes.size()); + mutexes.removeFirst(); + + for (InstanceMutex mutex : mutexes) { + this.getCollection().deleteOne(eq("_id", mutex.getId())); + } + } + } + + /** + * Registers the mutex with the given id. Always call this before starting to use the mutex. + * + * @param mutexId The id of the mutex to register. + */ + public void register(String mutexId) { + // Verify if exists + List existingMutexes = this.getCollection().find(eq("mutexId", mutexId)).into(new ArrayList<>()); + + log.info("Existent mutexes: {}", existingMutexes); + + if (existingMutexes.isEmpty()) { + // create it assuming no collision at this point + InstanceMutex newMutex = new InstanceMutex(mutexId); + log.info("Creating new mutex {}", newMutex); + + UpdateResult result = this.getCollection().updateOne( + eq("mutexId", mutexId), + Updates.set("mutexId", mutexId), + new UpdateOptions().upsert(true) + ); + + if (result.getUpsertedId() != null) { + log.info("Mutex {} created.", mutexId); + } else { + log.info("Mutex {} was added in another thread before we could get to it.", mutexId); + } + } else if (existingMutexes.size() > 1) { + // problem + log.error("multiple mutex for id {}", mutexId); + this.clearDuplicateMutexes(mutexId); + } + } + + /** + * Locks the mutex with the given id. + *

+ * Non blocking. + *

+ * Call {@link #register(String)} before using this method. + * + * @param mutexId The is of the mutex to get the lock for + * @param additionalIdentity If an additional identity is required. Only use if need the mutex to offer concurrency within the same instance of the app. + * @return true when reserved, false when not. + */ + public boolean lock(@NonNull String mutexId, Optional additionalIdentity) { + String identity = this.getIdentity(additionalIdentity); + Bson mutexIdEquals = eq("mutexId", mutexId); + + //ensure only one mutex object + this.clearDuplicateMutexes(mutexId); + + // try an update + InstanceMutex old = this.getCollection().findOneAndUpdate( + and( + mutexIdEquals, + or( + not(exists("taken")), + eq("taken", false) + ) + + ), + Updates.combine( + Updates.set("taken", true), + Updates.set("takenAt", ZonedDateTime.now()), + Updates.set("takenBy", identity) + ) + ); + + if (old != null) { + // success ... + // Update the information + log.debug("Got lock for {} on mutex (showing old data) {}", identity, old); + log.info("Acquired lock for {} on mutex {}", identity, mutexId); + return true; + } else { + log.info("Failed to reserve Mutex {} for {}", mutexId, identity); + + InstanceMutex lockedMutex = this.getCollection().find(mutexIdEquals).first(); + log.debug("Locked mutex: {}", lockedMutex); + + if (lockedMutex == null) { + log.warn("No mutex found. It needs to be registered first."); + } else if (lockedMutex.getTakenAt() != null && ZonedDateTime.now().isAfter(lockedMutex.getTakenAt().plus(this.lockExpire))) { + this.getCollection().findOneAndUpdate(mutexIdEquals, Updates.set("taken", false)); + log.warn("Unlocked mutex that appeared deadlocked: {}", mutexId); + } else { + log.debug("Was locked. returning."); + } + + return false; + } + } + + public boolean lock(@NonNull String mutexId) { + return this.lock(mutexId, Optional.empty()); + } + + /** + * Free a mutex previously reserved. + * + * @param mutexId The id of the mutex to free + */ + public void free(@NonNull String mutexId, Optional additionalIdentity) { + String identity = this.getIdentity(additionalIdentity); + + InstanceMutex mutex = this.getCollection().findOneAndUpdate( + and( + eq("mutexId", mutexId), + eq("taken", true), + eq("takenBy", identity) + ), + Updates.combine( + Updates.set("taken", false), + Updates.set("takenAt", null), + Updates.set("takenBy", null) + ) + ); + + if (mutex == null) { + log.info("Mutex NOT freed. Either not taken or not taken by this identity. Mutex: {}", mutex); + } else { + log.info("Mutex FREED: {}", mutexId); + } + } + + public void free(@NonNull String mutexId) { + this.free(mutexId, Optional.empty()); + } +} diff --git a/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/notification/EventNotificationWrapper.java b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/notification/EventNotificationWrapper.java index 55b22231e..4f3249942 100644 --- a/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/notification/EventNotificationWrapper.java +++ b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/notification/EventNotificationWrapper.java @@ -1,14 +1,12 @@ package tech.ebp.oqm.core.api.service.notification; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.Setter; +import lombok.*; import org.bson.types.ObjectId; import tech.ebp.oqm.core.api.model.object.history.ObjectHistoryEvent; @Data @AllArgsConstructor +@NoArgsConstructor @Setter(AccessLevel.PRIVATE) public class EventNotificationWrapper { private ObjectId database; diff --git a/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/notification/HistoryEventNotificationService.java b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/notification/HistoryEventNotificationService.java index 7f392e74f..cf40dbdaf 100644 --- a/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/notification/HistoryEventNotificationService.java +++ b/software/oqm-core-api/src/main/java/tech/ebp/oqm/core/api/service/notification/HistoryEventNotificationService.java @@ -6,6 +6,8 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import lombok.extern.slf4j.Slf4j; +import org.apache.kafka.common.header.Headers; +import org.apache.kafka.common.header.internals.RecordHeaders; import org.bson.types.ObjectId; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.reactive.messaging.Channel; @@ -22,78 +24,98 @@ @Slf4j @ApplicationScoped public class HistoryEventNotificationService { - + public static final String INTERNAL_EVENT_CHANNEL = "events-internal"; public static final String OUTGOING_EVENT_CHANNEL = "events-outgoing"; - public static final String ALL_EVENT_TOPIC = "all-events"; - + public static final String TOPIC_PREPEND = "oqm-core-"; + public static final String ALL_EVENT_TOPIC_LABEL = "all-events"; + public static final String ALL_EVENT_TOPIC = TOPIC_PREPEND + ALL_EVENT_TOPIC_LABEL; + @ConfigProperty(name = "mp.messaging.outgoing.events-outgoing.bootstrap.servers") Optional outgoingServers; @ConfigProperty(name = "kafka.bootstrap.servers") Optional kafkaServers; - + @Inject @Broadcast @Channel(INTERNAL_EVENT_CHANNEL) - @OnOverflow(value = OnOverflow.Strategy.DROP)//TODO:: this better https://quarkus.io/version/3.2/guides/kafka#sending-messages-with-emitter + @OnOverflow(value = OnOverflow.Strategy.DROP) Emitter internalEventEmitter; - + + @Inject @Broadcast @Channel(OUTGOING_EVENT_CHANNEL) @OnOverflow(value = OnOverflow.Strategy.DROP) - Emitter outgoingEventEmitter; - - private boolean haveOutgoingServers(){ + Emitter outgoingEventEmitter; + + private boolean haveOutgoingServers() { return outgoingServers.isPresent() || kafkaServers.isPresent(); } - + /** * Don't call this directly, use the other one */ @WithSpan @Incoming(INTERNAL_EVENT_CHANNEL) void sendEventOutgoing(EventNotificationWrapper notificationWrapper) { - if(!this.haveOutgoingServers()){ + if (!this.haveOutgoingServers()) { log.info("NOT Sending event to external channels (no outgoing servers configured): {}/{}", notificationWrapper.getClass().getSimpleName(), notificationWrapper.getEvent().getId()); return; } log.info("Sending event to external channels: {}/{}", notificationWrapper.getClass().getSimpleName(), notificationWrapper.getEvent().getId()); try { + Headers headers = new RecordHeaders() + .add("database", notificationWrapper.getDatabase().toHexString().getBytes()) + .add("object", notificationWrapper.getObjectName().getBytes()); this.outgoingEventEmitter.send( - Message.of( - notificationWrapper.getEvent() - ).addMetadata( - OutgoingKafkaRecordMetadata.builder() - .withTopic( - (notificationWrapper.getDatabase() == null? "" : notificationWrapper.getDatabase().toHexString() + "-") + notificationWrapper.getObjectName() + "-" + notificationWrapper.getEvent().getType() - ) - .build() - )); - this.outgoingEventEmitter.send( - Message.of( - notificationWrapper.getEvent() - ).addMetadata( - OutgoingKafkaRecordMetadata.builder() - .withTopic((notificationWrapper.getDatabase() == null? "" : notificationWrapper.getDatabase().toHexString() + "-") + ALL_EVENT_TOPIC) - .build() - )); + Message.of(notificationWrapper) + .addMetadata( + OutgoingKafkaRecordMetadata.builder() + .withTopic(ALL_EVENT_TOPIC) + .withHeaders(headers) + .build() + )); + //TODO:: maybe support in future +// this.outgoingEventEmitter.send( +// Message.of( +// notificationWrapper +// ).addMetadata( +// OutgoingKafkaRecordMetadata.builder() +// .withTopic( +// TOPIC_PREPEND + (notificationWrapper.getDatabase() == null ? "" : notificationWrapper.getDatabase().toHexString() + "-") + ALL_EVENT_TOPIC_LABEL +// ) +// .withHeaders(headers) +// .build() +// )); + + + //TODO:: maybe support this in future +// this.outgoingEventEmitter.send( +// Message.of(notificationWrapper.getEvent()).addMetadata( +// OutgoingKafkaRecordMetadata.builder() +// .withTopic( +// TOPIC_PREPEND + (notificationWrapper.getDatabase() == null ? "" : notificationWrapper.getDatabase().toHexString() + "-") + notificationWrapper.getObjectName() + "-" + notificationWrapper.getEvent().getType() +// ) +// .withHeaders(headers) +// .build() +// )); log.debug("Sent event to external channels: {}/{}", notificationWrapper.getClass().getSimpleName(), notificationWrapper.getEvent().getId()); - } catch(Throwable e) { + } catch (Throwable e) { log.error("FAILED to send event to external channels: {}/{}:", notificationWrapper.getClass().getSimpleName(), notificationWrapper.getEvent().getId(), e); throw e; } } - + public void sendEvent(ObjectId oqmDatabase, Class objectClass, ObjectHistoryEvent event) { this.sendEvents(oqmDatabase, objectClass, event); } - + public void sendEvents(ObjectId oqmDatabase, Class objectClass, ObjectHistoryEvent... events) { this.sendEvents(oqmDatabase, objectClass, Arrays.asList(events)); } - + public void sendEvents(ObjectId oqmDatabase, Class objectClass, Collection events) { for (ObjectHistoryEvent event : events) { log.info("Sending event to internal channel: {}/{}", objectClass.getSimpleName(), event.getId()); @@ -103,5 +125,5 @@ public void sendEvents(ObjectId oqmDatabase, Class objectClass, Collection getParams() { + return Stream.of( + Arguments.of(2, 10, Duration.of(250, ChronoUnit.MILLIS)), + Arguments.of(3, 10, Duration.of(250, ChronoUnit.MILLIS)), + Arguments.of(5, 10, Duration.of(250, ChronoUnit.MILLIS)), + Arguments.of(10, 10, Duration.of(250, ChronoUnit.MILLIS)), + Arguments.of(20, 20, Duration.of(150, ChronoUnit.MILLIS)) + ); + } + + @Inject + InstanceMutexService instanceMutexService; + + @Test + public void basicTest() { + String mutexId = "testMutex"; + this.instanceMutexService.register(mutexId); + + assertTrue(this.instanceMutexService.lock(mutexId)); + + assertFalse(this.instanceMutexService.lock(mutexId)); + + this.instanceMutexService.free(mutexId); + + assertTrue(this.instanceMutexService.lock(mutexId)); + this.instanceMutexService.free(mutexId); + } + + + @ParameterizedTest + @MethodSource("getParams") + public void threadTest(int numThreads, int numIterations, Duration workDuration) throws InterruptedException, ExecutionException { + String mutexId = "testMutex2"; + List>> futures = new ArrayList<>(numThreads); + SortedSet results = new TreeSet<>(); + ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(); + + TestThread.Builder threadBuilder = TestThread.builder() + .mutexId(mutexId) + .numIterations(numIterations) + .durationOfWork(workDuration) + .instanceMutexService(instanceMutexService); + + for (int i = 1; i <= numThreads; i++) { + threadBuilder.threadId("testThread-" + i); + + futures.add(executor.submit(threadBuilder.build())); + } + executor.shutdown(); + while (!executor.awaitTermination(1, TimeUnit.MINUTES)) { + log.info("Still waiting on threads..."); + } + + for (Future> future : futures) { + results.addAll(future.get()); + } + + assertEquals(numIterations * numThreads, results.size()); + + //TODO:: check results + log.info("Results: {}", results); + + Iterator iterator = results.iterator(); + ThreadResult cur = iterator.next(); + while (iterator.hasNext()) { + ThreadResult next = iterator.next(); + + assertTrue( + next.getStart().isAfter(cur.getStart()), + "result " + cur + " start overlaps with the next result " + next + " (next start is before cur start)" + ); + assertTrue( + (next.getStart().isAfter(cur.getEnd()) || next.getStart().equals(cur.getEnd())), + "result " + cur + " overlaps with the next result " + next + " (next start is before cur end)" + ); + + cur = next; + } + + } + + @Builder + @Data + @AllArgsConstructor + static + class ThreadResult implements Comparable { + private String threadId; + private LocalDateTime start; + private LocalDateTime end; + + @Override + public int compareTo(@NonNull InstanceMutexServiceTest.ThreadResult threadResult) { + return this.getStart().compareTo(threadResult.getStart()); + } + } + + @Builder + @Slf4j + @AllArgsConstructor + static class TestThread implements Callable> { + + private String mutexId; + private String threadId; + private InstanceMutexService instanceMutexService; + private int numIterations; + private Duration durationOfWork; + + @SneakyThrows + @Override + public List call() { + log.info("Running test thread {}", this.threadId); + + this.instanceMutexService.register(this.mutexId); + +// Thread.sleep(500); + + List results = new ArrayList<>(this.numIterations); + for (int i = 1; i <= this.numIterations; i++) { + log.info("Thread {} waiting for lock on iteration {}", this.threadId, i); + while (!instanceMutexService.lock(this.mutexId, Optional.of(this.threadId))) { + Thread.sleep(50); + } + log.info("Thread {} got lock on iteration {}/{}", this.threadId, i, this.numIterations); + ThreadResult.Builder resultBuilder = ThreadResult.builder() + .threadId(this.threadId) + .start(LocalDateTime.now()); + + Thread.sleep(this.durationOfWork); + + resultBuilder.end(LocalDateTime.now()); + + this.instanceMutexService.free(this.mutexId, Optional.of(this.threadId)); + log.info("Thread {} done doing work & released lock on iteration {}", this.threadId, i); + results.add(resultBuilder.build()); + } + log.info("DONE running test thread {}", this.threadId); + return results; + } + } + +} diff --git a/software/oqm-core-api/src/test/java/tech/ebp/oqm/core/api/service/mongo/MongoHistoriedObjectServiceTest.java b/software/oqm-core-api/src/test/java/tech/ebp/oqm/core/api/service/mongo/MongoHistoriedObjectServiceTest.java index 3d6c83d69..60f4ce8d3 100644 --- a/software/oqm-core-api/src/test/java/tech/ebp/oqm/core/api/service/mongo/MongoHistoriedObjectServiceTest.java +++ b/software/oqm-core-api/src/test/java/tech/ebp/oqm/core/api/service/mongo/MongoHistoriedObjectServiceTest.java @@ -11,12 +11,11 @@ import org.bson.types.ObjectId; import org.junit.jupiter.api.Test; import tech.ebp.oqm.core.api.model.object.ObjectUtils; -import tech.ebp.oqm.core.api.service.mongo.InteractingEntityService; +import tech.ebp.oqm.core.api.service.notification.EventNotificationWrapper; import tech.ebp.oqm.core.api.service.notification.HistoryEventNotificationService; import tech.ebp.oqm.core.api.service.serviceState.db.OqmDatabaseService; import tech.ebp.oqm.core.api.testResources.data.TestMainObject; import tech.ebp.oqm.core.api.testResources.data.TestMongoHistoriedService; -import tech.ebp.oqm.core.api.testResources.data.TestUserService; import tech.ebp.oqm.core.api.testResources.lifecycleManagers.TestResourceLifecycleManager; import tech.ebp.oqm.core.api.testResources.testClasses.RunningServerTest; import tech.ebp.oqm.core.api.model.object.history.ObjectHistoryEvent; @@ -73,24 +72,28 @@ public void testAdd() throws JsonProcessingException { assertEquals(objectId, createEvent.getObjectId()); assertNotNull(createEvent.getEntity()); assertEquals(testUser.getId(), createEvent.getEntity()); - + + ConsumerTask createFromAll = this.kafkaCompanion.consumeStrings().fromTopics( - this.oqmDatabaseService.getDatabaseCache().getFromName(DEFAULT_TEST_DB_NAME).get().getDbId().toHexString() + "-" + HistoryEventNotificationService.ALL_EVENT_TOPIC, + HistoryEventNotificationService.ALL_EVENT_TOPIC, 1 ); createFromAll.awaitCompletion(); assertEquals(1, createFromAll.count()); - CreateEvent createEventFromMessage = ObjectUtils.OBJECT_MAPPER.readValue(createFromAll.getFirstRecord().value(), CreateEvent.class); - assertEquals(createEvent, createEventFromMessage); - - ConsumerTask createFromCreate = this.kafkaCompanion.consumeStrings().fromTopics( - this.oqmDatabaseService.getDatabaseCache().getFromName(DEFAULT_TEST_DB_NAME).get().getDbId().toHexString() + "-" + HistoryEventNotificationService.ALL_EVENT_TOPIC, - 1 - ); - createFromCreate.awaitCompletion(); - assertEquals(1, createFromCreate.count()); - createEventFromMessage = ObjectUtils.OBJECT_MAPPER.readValue(createFromCreate.getFirstRecord().value(), CreateEvent.class); - assertEquals(createEvent, createEventFromMessage); + EventNotificationWrapper createEventFromMessage = ObjectUtils.OBJECT_MAPPER.readValue(createFromAll.getFirstRecord().value(), EventNotificationWrapper.class); + assertEquals(createEvent, createEventFromMessage.getEvent()); + + // TODO: more when we want to +// ConsumerTask createFromAllInDb = this.kafkaCompanion.consumeStrings().fromTopics( +// HistoryEventNotificationService.TOPIC_PREPEND + this.oqmDatabaseService.getDatabaseCache().getFromName(DEFAULT_TEST_DB_NAME).get().getDbId().toHexString() + "-" + HistoryEventNotificationService.ALL_EVENT_TOPIC_LABEL, +// 1 +// ); +// createFromAllInDb.awaitCompletion(); +// assertEquals(1, createFromAllInDb.count()); +// createEventFromMessage = ObjectUtils.OBJECT_MAPPER.readValue(createFromAllInDb.getFirstRecord().value(), EventNotificationWrapper.class); +// assertEquals(createEvent, createEventFromMessage.getEvent()); + + //TODO:: cover last type? } //TODO:: test rest } \ No newline at end of file diff --git a/software/oqm-core-base-station/build.gradle b/software/oqm-core-base-station/build.gradle index fe7b7505e..57c139439 100644 --- a/software/oqm-core-base-station/build.gradle +++ b/software/oqm-core-base-station/build.gradle @@ -1,11 +1,11 @@ plugins { id 'java' id 'io.quarkus' - id "io.freefair.lombok" version "8.6" + id "io.freefair.lombok" version "8.10.2" } group 'com.ebp.openQuarterMaster' -version '1.4.2' +version '1.4.5' repositories { mavenCentral() @@ -28,13 +28,13 @@ dependencies { implementation 'io.quarkus:quarkus-opentelemetry' implementation 'io.quarkus:quarkus-scheduler' - implementation 'tech.ebp.oqm.lib:core-api-lib-quarkus:2.1.0-SNAPSHOT' + implementation 'tech.ebp.oqm.lib:core-api-lib-quarkus:2.2.0-SNAPSHOT' implementation 'org.apache.commons:commons-io:1.3.2' implementation 'org.apache.commons:commons-text:1.12.0' implementation group: 'org.jsoup', name: 'jsoup', version: '1.18.1' - implementation 'uk.org.okapibarcode:okapibarcode:0.4.6' + implementation 'uk.org.okapibarcode:okapibarcode:0.4.8' implementation 'com.itextpdf:html2pdf:5.0.5' //webjars @@ -42,12 +42,12 @@ dependencies { implementation 'org.webjars:bootstrap:5.3.3' testImplementation 'io.quarkus:quarkus-junit5' - testImplementation "org.junit.jupiter:junit-jupiter-params:5.10.3" + testImplementation "org.junit.jupiter:junit-jupiter-params:5.11.3" testImplementation 'io.rest-assured:rest-assured' - testImplementation 'net.datafaker:datafaker:2.3.1' + testImplementation 'net.datafaker:datafaker:2.4.1' - testImplementation 'com.microsoft.playwright:playwright:1.45.1' - testImplementation 'com.deque.html.axe-core:playwright:4.9.1' + testImplementation 'com.microsoft.playwright:playwright:1.48.0' + testImplementation 'com.deque.html.axe-core:playwright:4.10.0' } java { diff --git a/software/oqm-core-base-station/docs/Releasing.md b/software/oqm-core-base-station/docs/Releasing.md index 4596702c3..1a881fe3f 100644 --- a/software/oqm-core-base-station/docs/Releasing.md +++ b/software/oqm-core-base-station/docs/Releasing.md @@ -31,7 +31,7 @@ These are the steps to take to perform a release of the software: 4. Ensure everything committed and pushed to github. Check workflows. 5. Be logged into docker hub with ebprod user `docker login` 6. Deploy jvm version - 1. Clean/build/push project `./gradlew clean build -Pquarkus.container-image.build=true -Pquarkus.jib.platforms=linux/arm64,linux/amd64 -Pquarkus.container-image.group=ebprod -Pquarkus.container-image.name=oqm-core-base_station -Pquarkus.container-image.push=true` + 1. Clean/build/push project `./gradlew clean build -Pquarkus.container-image.build=true -Pquarkus.jib.platforms=linux/arm64,linux/amd64 -Pquarkus.container-image.push=true` 2. Ensure was deployed successfully: https://hub.docker.com/repository/registry-1.docker.io/ebprod/open-qm-base-station/tags?page=1&ordering=last_updated 7. Make installers: `./makeInstallers.sh` 8. Make release for version on Github, attach all installers to it (`build/installers`) \ No newline at end of file diff --git a/software/oqm-core-base-station/installerSrc/installerProperties.json b/software/oqm-core-base-station/installerSrc/installerProperties.json index e72df4206..14e88f75a 100644 --- a/software/oqm-core-base-station/installerSrc/installerProperties.json +++ b/software/oqm-core-base-station/installerSrc/installerProperties.json @@ -6,7 +6,7 @@ "description": "Base Station instance for Open QuarterMaster.", "homepage": "https://github.com/Epic-Breakfast-Productions/OpenQuarterMaster/tree/main/software/open-qm-base-station", "dependencies": { - "deb": "curl, jq, docker.io, docker, oqm-manager-station+captain (>= 2.0.0), oqm-infra-jaeger (>= 1.1.0), oqm-infra-keycloak (>= 1.1.0), oqm-core-depot, oqm-core-api (>= 2.1.0)", + "deb": "curl, jq, docker.io, oqm-manager-station+captain (>= 2.0.0), oqm-infra-jaeger (>= 1.1.0), oqm-infra-keycloak (>= 1.1.0), oqm-core-depot, oqm-core-api (>= 2.1.0)", "debRec": "oqm-plugin-ext_item_search" }, "copyright": { diff --git a/software/oqm-core-base-station/installerSrc/oqm-core-base_station.service b/software/oqm-core-base-station/installerSrc/oqm-core-base_station.service index dd6f8953e..b72e51fec 100644 --- a/software/oqm-core-base-station/installerSrc/oqm-core-base_station.service +++ b/software/oqm-core-base-station/installerSrc/oqm-core-base_station.service @@ -17,7 +17,7 @@ Requires=oqm-infra-keycloak.service [Service] Type=simple Restart=always -TimeoutSec=5m +TimeoutSec=10m # Setup operating variables Environment="CONTAINER_NAME=oqm-core-base_station" Environment="IMAGE_NAME=ebprod/oqm-core-base_station" diff --git a/software/oqm-core-base-station/src/main/resources/META-INF/resources/res/js/main.js b/software/oqm-core-base-station/src/main/resources/META-INF/resources/res/js/main.js index 7eff615ef..fd2f731dd 100644 --- a/software/oqm-core-base-station/src/main/resources/META-INF/resources/res/js/main.js +++ b/software/oqm-core-base-station/src/main/resources/META-INF/resources/res/js/main.js @@ -2,14 +2,10 @@ const navSearchInput = $('#navSearchInput'); const navSearchForm = $('#navSearchForm'); const navSearchTypeSelect = $('#navSearchTypeSelect'); -navSearchTypeSelect.on("change", function(event){ - console.log( - "Changing nav form to " + - "action: " + navSearchTypeSelect[0].options[event.target.selectedIndex].dataset.action + - " with fieldName: " + navSearchTypeSelect[0].options[event.target.selectedIndex].dataset.field - ); - navSearchForm.attr("action", navSearchTypeSelect[0].options[event.target.selectedIndex].dataset.action); - navSearchInput.attr("name", navSearchTypeSelect[0].options[event.target.selectedIndex].dataset.field); -}); +function updateNavSearchDestination(action, icon, fieldName){ + navSearchForm.attr("action", action); + navSearchTypeSelect.html(icon); + navSearchInput.attr("name", fieldName); +} TimeHelpers.setupDateTimeInputs(); \ No newline at end of file diff --git a/software/oqm-core-base-station/src/main/resources/application.yml b/software/oqm-core-base-station/src/main/resources/application.yml index 25f426803..c4dd9f43f 100644 --- a/software/oqm-core-base-station/src/main/resources/application.yml +++ b/software/oqm-core-base-station/src/main/resources/application.yml @@ -68,6 +68,9 @@ ui: quarkus: application: name: ${service.nameShort} - V${service.apiVersion} + container-image: + name: oqm-core-base_station + group: ebprod rest-client: logging: scope: all @@ -123,7 +126,6 @@ quarkus: post-logout-path: /?message=You%20have%20successfully%20logged%20out&messageType=success&messageHeading=Logged%20Out oqmCoreApi: devservice: - coreApiVersion: 2.1.0-DEV certPath: ../../../../dev/devTest-cert-cert.pem certKeyPath: ../../../../dev/devTest-cert-key.pem diff --git a/software/oqm-core-base-station/src/main/resources/templates/tags/links/itemCategory.html b/software/oqm-core-base-station/src/main/resources/templates/tags/links/itemCategory.html index 6a77ada5c..9769923c9 100644 --- a/software/oqm-core-base-station/src/main/resources/templates/tags/links/itemCategory.html +++ b/software/oqm-core-base-station/src/main/resources/templates/tags/links/itemCategory.html @@ -1 +1 @@ -{#icons/categories}{/icons/categories} Categories \ No newline at end of file +{#icons/categories}{/icons/categories} Categories \ No newline at end of file diff --git a/software/oqm-core-base-station/src/main/resources/templates/webui/mainWebPageTemplate.html b/software/oqm-core-base-station/src/main/resources/templates/webui/mainWebPageTemplate.html index 56c0500b9..b80b30657 100644 --- a/software/oqm-core-base-station/src/main/resources/templates/webui/mainWebPageTemplate.html +++ b/software/oqm-core-base-station/src/main/resources/templates/webui/mainWebPageTemplate.html @@ -58,7 +58,7 @@