mirror of
https://gitlab.com/signalytic/client-external/streamline/streamline-emr.git
synced 2026-09-11 18:51:31 +00:00
Compare commits
4
Commits
ft-3.3
..
develop-v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69c5fd8fe2 | ||
|
|
fdc5645341 | ||
|
|
f14359b3cd | ||
|
|
60021ae47a |
@@ -1,4 +1,3 @@
|
|||||||
build-packages
|
build-packages
|
||||||
.local
|
.local
|
||||||
vendor/
|
vendor/
|
||||||
.vscode/
|
|
||||||
Executable
+25
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
LOCATION="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
|
||||||
|
# build an app-only package (ie don't include images) and store the package path
|
||||||
|
echo "building app-only package"
|
||||||
|
package=$(${LOCATION}/package --app | awk -F'saved package: ' '/^saved package: / {print $2}')
|
||||||
|
echo "generated package: {package}"
|
||||||
|
|
||||||
|
# use a temp folder for unpacking and make sure to clean up when done
|
||||||
|
tmp="/tmp/build-install-local-$(date +%s)"
|
||||||
|
echo "prepping temp folder: {tmp}"
|
||||||
|
rm -rf $tmp
|
||||||
|
mkdir -p $tmp
|
||||||
|
trap 'rm -rf $tmp' EXIT
|
||||||
|
|
||||||
|
# unpack to temp folder
|
||||||
|
echo "unpacking app package: $package"
|
||||||
|
tar xf $package -C $tmp
|
||||||
|
|
||||||
|
# install package
|
||||||
|
echo "installing package"
|
||||||
|
${tmp}/*/install.sh
|
||||||
|
|
||||||
|
echo "done."
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "streamline-emr",
|
"name": "streamline-emr",
|
||||||
"org": "streamline",
|
"org": "streamline",
|
||||||
"version": "3.3",
|
"version": "2.6",
|
||||||
"platforms": [
|
"platforms": [
|
||||||
"linux/arm64"
|
"linux/arm64"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
FROM streamline:signalytic_latest
|
FROM streamlinehealth/streamline:signalytic
|
||||||
+1
-1
Submodule hosted-app-utils updated: 98c3a9ba36...6af4c4ae85
Executable
+62
@@ -0,0 +1,62 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright (C) Wendepunkt Medical Innovations, Inc - All Rights Reserved.
|
||||||
|
# Unauthorized copying of this file, via any medium is strictly prohibited.
|
||||||
|
# Proprietary and confidential
|
||||||
|
#
|
||||||
|
# For information: dev@signalytic.ca
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Install the streamline-emr application
|
||||||
|
#
|
||||||
|
# The caller of this script must check the exit value and possibly do a
|
||||||
|
# roll-back if it is non-zero. If the exit value is non-zero services have not
|
||||||
|
# been restarted.
|
||||||
|
#
|
||||||
|
# Note: This version resets data from v1 installations
|
||||||
|
|
||||||
|
LOCATION="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
|
||||||
|
if [ "$EUID" -ne 0 ]
|
||||||
|
then echo "Please run as root"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
APP_SLUG="streamline_emr"
|
||||||
|
ORG_SLUG="streamline"
|
||||||
|
INSTALL_ROOT="/var/signalytic/clientapps/${ORG_SLUG}/${APP_SLUG}"
|
||||||
|
VERSION_FILE="${INSTALL_ROOT}/version"
|
||||||
|
DATA_ROOT="${INSTALL_ROOT}/data"
|
||||||
|
|
||||||
|
# stop the application (if installed)
|
||||||
|
if [ -f ${INSTALL_ROOT}/stop ]; then
|
||||||
|
${INSTALL_ROOT}/stop
|
||||||
|
fi
|
||||||
|
|
||||||
|
# reset data for any v1 or v2.0 installations
|
||||||
|
if grep -q "^1." ${VERSION_FILE} || grep -q "^2.0" ${VERSION_FILE}; then
|
||||||
|
echo "demo installation detected (v$(cat ${VERSION_FILE})) - resetting data"
|
||||||
|
rm -rf ${DATA_ROOT}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# copy root files (if present)
|
||||||
|
if [ -d "${LOCATION}/root" ] && [ -n "$(ls -A ${LOCATION}/root)" ]; then
|
||||||
|
echo "importing root files"
|
||||||
|
cp -rfv $LOCATION/root/* /
|
||||||
|
fi
|
||||||
|
|
||||||
|
# import docker images (if present)
|
||||||
|
for f in $(find $LOCATION/images -name "*.img" 2>/dev/null);do
|
||||||
|
echo "importing docker image: $f"
|
||||||
|
docker load -i $f
|
||||||
|
done
|
||||||
|
for f in $(find $LOCATION/images -name "*.img.xz" 2>/dev/null);do
|
||||||
|
echo "importing docker image: $f"
|
||||||
|
xz -d -c $f | docker load
|
||||||
|
done
|
||||||
|
|
||||||
|
# start the application
|
||||||
|
${INSTALL_ROOT}/start
|
||||||
@@ -5,6 +5,6 @@ LOCATION="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
|||||||
CONFIG=${CONFIG:-${LOCATION}/config.json}
|
CONFIG=${CONFIG:-${LOCATION}/config.json}
|
||||||
SRC=${SRC:-${LOCATION}/src}
|
SRC=${SRC:-${LOCATION}/src}
|
||||||
BUILD_DIR=${BUILD_DIR:-${LOCATION}/build-packages}
|
BUILD_DIR=${BUILD_DIR:-${LOCATION}/build-packages}
|
||||||
#INSTALL_SCRIPT=${LOCATION}/install.sh
|
INSTALL_SCRIPT=${LOCATION}/install.sh
|
||||||
|
|
||||||
${LOCATION}/hosted-app-utils/package ${CONFIG} ${SRC} output=${BUILD_DIR} $@
|
${LOCATION}/hosted-app-utils/package ${CONFIG} ${SRC} ${INSTALL_SCRIPT} output=${BUILD_DIR} $@
|
||||||
|
|||||||
@@ -1,205 +0,0 @@
|
|||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
import sys, os, argparse, json, shutil, tempfile, subprocess, traceback
|
|
||||||
|
|
||||||
def run_script(script_path: str) -> int:
|
|
||||||
"""
|
|
||||||
Helper to handle subprocess execution
|
|
||||||
Args:
|
|
||||||
script_path (str): script path to execute
|
|
||||||
Returns:
|
|
||||||
int: 0 if both succeed, 1 if any step fails
|
|
||||||
"""
|
|
||||||
if not os.path.exists(script_path):
|
|
||||||
print(f"Error: Script not found at {script_path}", file=sys.stderr)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
try:
|
|
||||||
subprocess.run(f'{script_path}', check=True, capture_output=True, text=True)
|
|
||||||
return 0
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
print(f"Error: {os.path.basename(script_path)} failed (Exit {e.returncode})", file=sys.stderr)
|
|
||||||
print(f"Details: {e.stderr.strip() or e.stdout.strip()}", file=sys.stderr)
|
|
||||||
return 1
|
|
||||||
except PermissionError:
|
|
||||||
print(f"Error: {os.path.basename(script_path)} is not executable. Check permissions.", file=sys.stderr)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def handle_start(src_dir, install_path):
|
|
||||||
"""
|
|
||||||
Start application
|
|
||||||
|
|
||||||
Args:
|
|
||||||
src_dir (str): Path to source directory (Working directory)
|
|
||||||
install_path (str): Path to target installation directory
|
|
||||||
Returns:
|
|
||||||
int: 0 -> success
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
# disable app
|
|
||||||
if os.path.exists(os.path.join(install_path, 'disable')):
|
|
||||||
subprocess.check_output(f'{install_path}/disable')
|
|
||||||
|
|
||||||
# copy all source files to installation path
|
|
||||||
shutil.copytree(src_dir, install_path, dirs_exist_ok=True)
|
|
||||||
|
|
||||||
# start application
|
|
||||||
run_script(f'{install_path}/start')
|
|
||||||
|
|
||||||
return 0
|
|
||||||
except Exception as ex:
|
|
||||||
print(f'Error: {ex}')
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def handle_stop(install_path: str):
|
|
||||||
"""
|
|
||||||
Stop application
|
|
||||||
Args:
|
|
||||||
install_path (str): Path to installation directory
|
|
||||||
Returns:
|
|
||||||
int: 0 -> success
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not os.path.exists(os.path.join(install_path, 'stop')):
|
|
||||||
print(f"Error: stop script not found at {install_path}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
try:
|
|
||||||
# stop application
|
|
||||||
run_script(f'{install_path}/stop')
|
|
||||||
|
|
||||||
return 0
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
print(f"Error: Stop script failed with exit code {e.returncode}")
|
|
||||||
print(f"Output: {e.stderr or e.stdout}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def handle_restart(src_path: str, install_path: str):
|
|
||||||
"""
|
|
||||||
Restart application
|
|
||||||
Args:
|
|
||||||
install_path (str): Path to installation directory
|
|
||||||
Returns:
|
|
||||||
int: 0 -> success
|
|
||||||
"""
|
|
||||||
if handle_stop(install_path) != 0:
|
|
||||||
print("Restart aborted: Stop script execution failed.", file=sys.stderr)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if handle_start(src_path, install_path) != 0:
|
|
||||||
print("Restart aborted: Start script execution failed.", file=sys.stderr)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
print('Application restarted successfully.')
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def uninstall_app(args: argparse.Namespace, install_path) -> int:
|
|
||||||
"""
|
|
||||||
Uninstall application at specified installation directory.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
install_path (str): Path to target installation directory.
|
|
||||||
Returns:
|
|
||||||
Int
|
|
||||||
"""
|
|
||||||
|
|
||||||
rval = 0
|
|
||||||
try:
|
|
||||||
|
|
||||||
# disable application then uninstall
|
|
||||||
disable_path = os.path.join(install_path, 'disable')
|
|
||||||
stop_path = os.path.join(install_path, 'stop')
|
|
||||||
if os.path.exists(disable_path):
|
|
||||||
subprocess.check_output(disable_path)
|
|
||||||
|
|
||||||
if os.path.exists(stop_path):
|
|
||||||
subprocess.check_output(stop_path)
|
|
||||||
|
|
||||||
# reset vols, networks
|
|
||||||
subprocess.check_output(['docker', 'compose', f'-f {install_path}/docker-compose.yml', 'down', '-v'])
|
|
||||||
|
|
||||||
if os.path.exists(install_path):
|
|
||||||
shutil.rmtree(install_path)
|
|
||||||
except Exception as e:
|
|
||||||
print(f'Exception encountered: {e}')
|
|
||||||
traceback.print_exc()
|
|
||||||
rval = 1
|
|
||||||
return rval
|
|
||||||
|
|
||||||
# script constants
|
|
||||||
utils_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
|
|
||||||
temp_dir = tempfile.mkdtemp()
|
|
||||||
build_dir = os.path.join(temp_dir, 'build')
|
|
||||||
staging_dir = os.path.join(temp_dir, 'staging')
|
|
||||||
working_dir = working_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
src_path = os.path.join(working_dir, 'src')
|
|
||||||
CONFIG_JSON = os.path.join(working_dir, 'config.json')
|
|
||||||
|
|
||||||
templates_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'hosted-app-utils', 'templates'))
|
|
||||||
|
|
||||||
template_files = {
|
|
||||||
f'{templates_dir}/start': f'{working_dir}/src/start',
|
|
||||||
f'{templates_dir}/stop': f'{working_dir}/src/stop',
|
|
||||||
f'{templates_dir}/disable': f'{working_dir}/src/disable'
|
|
||||||
}
|
|
||||||
|
|
||||||
# command line arguments
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
prog="clientappctl",
|
|
||||||
description="Manage client application operations. [ start, stop, restart ]")
|
|
||||||
|
|
||||||
parser.add_argument("-c", "--config", default=CONFIG_JSON, help=f"Path to application configuration (default: {CONFIG_JSON})")
|
|
||||||
|
|
||||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
||||||
|
|
||||||
start_parser = subparsers.add_parser("start", help="Start the application")
|
|
||||||
stop_parser = subparsers.add_parser("stop", help="Stop the application")
|
|
||||||
restart_parser = subparsers.add_parser("restart", help="Restart the application")
|
|
||||||
|
|
||||||
def main() -> int:
|
|
||||||
# parse user args
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
# load configuration
|
|
||||||
try:
|
|
||||||
config_path = args.config
|
|
||||||
if not os.path.exists(config_path):
|
|
||||||
raise ValueError("Configuration not found.")
|
|
||||||
|
|
||||||
with open(config_path) as f:
|
|
||||||
config_data = json.load(f)
|
|
||||||
name_slug = config_data['name'].strip().replace(' ', '_').replace('-', '_').lower()
|
|
||||||
org_slug = config_data['org'].strip().replace(' ', '_').replace('-', '_').lower()
|
|
||||||
version = config_data['version']
|
|
||||||
|
|
||||||
install_path = f'/var/signalytic/clientapps/{org_slug}/{name_slug}'
|
|
||||||
|
|
||||||
# copy temp files into working dir
|
|
||||||
for src, dest in template_files.items():
|
|
||||||
if not os.path.exists(src):
|
|
||||||
continue
|
|
||||||
shutil.copy(src, dest)
|
|
||||||
|
|
||||||
if args.command == "start":
|
|
||||||
print(f"Starting app: {config_data['name']}-{version}")
|
|
||||||
|
|
||||||
if not os.path.exists(install_path):
|
|
||||||
os.makedirs(install_path)
|
|
||||||
return handle_start(src_path, install_path)
|
|
||||||
elif args.command == "stop":
|
|
||||||
print(f"Stopping app: {config_data['name']}-{version}")
|
|
||||||
return handle_stop(install_path)
|
|
||||||
elif args.command == "restart":
|
|
||||||
print(f"Restarting app: {config_data['name']}-{version}")
|
|
||||||
return handle_restart(src_path, install_path)
|
|
||||||
else:
|
|
||||||
raise ValueError('Invalid operation passed.')
|
|
||||||
|
|
||||||
except Exception as ex:
|
|
||||||
print(f'Error: {ex}')
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
||||||
Regular → Executable
+8
-17
@@ -1,12 +1,12 @@
|
|||||||
services:
|
services:
|
||||||
streamline-emr:
|
streamline-emr:
|
||||||
image: registry.gitlab.com/signalytic/client-external/streamline/streamline-emr/streamline-emr/arm64:3.3
|
image: registry.gitlab.com/signalytic/client-external/streamline/streamline-emr/streamline-emr/arm64:2.6
|
||||||
container_name: streamline-emr
|
container_name: streamline-emr
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- "${DATA_DIR:-./data}:/var/lib/mysql"
|
- ./data:/var/lib/mysql
|
||||||
ports:
|
ports:
|
||||||
- "${APP_PORT:-3000}:80"
|
- "3000:80"
|
||||||
command: |
|
command: |
|
||||||
php artisan migrate --force && exec php artisan serve --host=0.0.0.0 --port=80
|
php artisan migrate --force && exec php artisan serve --host=0.0.0.0 --port=80
|
||||||
healthcheck:
|
healthcheck:
|
||||||
@@ -18,30 +18,21 @@ services:
|
|||||||
retries: 5
|
retries: 5
|
||||||
|
|
||||||
statistics:
|
statistics:
|
||||||
image: registry.gitlab.com/signalytic/client-external/streamline/streamline-emr/statistics/arm64:3.1
|
image: registry.gitlab.com/signalytic/client-external/streamline/streamline-emr/statistics/arm64:2.6
|
||||||
container_name: streamline-emr-statistics
|
container_name: streamline-emr-statistics
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
env_file:
|
||||||
SERVER: https://impactdashboard.streamlinehealth.tech/
|
- resources/statistics/.env
|
||||||
SERVER_ENDPOINT: signalytic/receive_data
|
|
||||||
SERVER_STATUS_URL: signalytic/status
|
|
||||||
DB_HOST: streamline-emr
|
|
||||||
DB_DATABASE: streamline
|
|
||||||
DB_USERNAME: root
|
|
||||||
DB_PASSWORD: streamline
|
|
||||||
REDIS_HOST: streamline-emr-redis
|
|
||||||
REDIS_PORT: 6379
|
|
||||||
REDIS_TTL: 432000
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- streamline-emr
|
- streamline-emr
|
||||||
- redis
|
- redis
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: registry.gitlab.com/signalytic/client-external/streamline/streamline-emr/redis/arm64:v3
|
image: registry.gitlab.com/signalytic/client-external/streamline/streamline-emr/redis/arm64:2.6
|
||||||
container_name: streamline-emr-redis
|
container_name: streamline-emr-redis
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- "${REDIS_DATA_DIR:-./redis_data}:/data"
|
- ./redis_data:/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "redis-cli", "ping"]
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
SERVER=https://impactdashboard.streamlinehealth.tech/
|
||||||
|
SERVER_ENDPOINT=signalytic/receive_data
|
||||||
|
SERVER_STATUS_URL=signalytic/status
|
||||||
|
DB_HOST=streamline-emr
|
||||||
|
DB_DATABASE=streamline
|
||||||
|
DB_USERNAME=root
|
||||||
|
DB_PASSWORD=streamline
|
||||||
|
REDIS_HOST=streamline-emr-redis
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_TTL=432000
|
||||||
Reference in New Issue
Block a user