113 lines
4.2 KiB
Bash
Executable File
113 lines
4.2 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
DATA_ROOT="${ASSETMANAGER_DATA_ROOT:-/assetmanager-data}"
|
|
CONFIG_PATH="${APP_CONFIG:-$DATA_ROOT/config/config.json}"
|
|
APPINFO_PATH="${APPINFO_PATH:-$DATA_ROOT/config/APPINFO.json}"
|
|
DEFAULT_APPINFO="${DEFAULT_APPINFO:-/app/default-config/APPINFO.json}"
|
|
UPLOAD_DIR="${UPLOAD_DIR:-$DATA_ROOT/uploads}"
|
|
STANDARD_IMAGE_DIR="${STANDARD_IMAGE_DIR:-$UPLOAD_DIR/library}"
|
|
APP_LOG_DIR="${APP_LOG_DIR:-$DATA_ROOT/logs}"
|
|
SYNC_LOG_DIR="${SYNC_LOG_DIR:-$APP_LOG_DIR/sync}"
|
|
DIAGNOSTIC_DIR="${DIAGNOSTIC_DIR:-$APP_LOG_DIR/diagnostics}"
|
|
BACKUP_DIR="${BACKUP_DIR:-$DATA_ROOT/backups}"
|
|
SCRIPT_DIR="${SCRIPT_DIR:-$DATA_ROOT/scripts}"
|
|
SOFTWARE_PACKAGE_DIR="${SOFTWARE_PACKAGE_DIR:-$DATA_ROOT/software-packages}"
|
|
ANALYZER_PROFILE_DIR="${ANALYZER_PROFILE_DIR:-$DATA_ROOT/analyzer-profiles}"
|
|
|
|
# Export normalized paths so every application module uses the same runtime root,
|
|
# even when the container is started without the bundled Compose file.
|
|
export ASSETMANAGER_DATA_ROOT="$DATA_ROOT"
|
|
export APP_CONFIG="$CONFIG_PATH" APPINFO_PATH="$APPINFO_PATH"
|
|
export UPLOAD_DIR="$UPLOAD_DIR" STANDARD_IMAGE_DIR="$STANDARD_IMAGE_DIR"
|
|
export APP_LOG_DIR="$APP_LOG_DIR" SYNC_LOG_DIR="$SYNC_LOG_DIR" DIAGNOSTIC_DIR="$DIAGNOSTIC_DIR"
|
|
export BACKUP_DIR="$BACKUP_DIR" SCRIPT_DIR="$SCRIPT_DIR"
|
|
export SOFTWARE_PACKAGE_DIR="$SOFTWARE_PACKAGE_DIR" ANALYZER_PROFILE_DIR="$ANALYZER_PROFILE_DIR"
|
|
|
|
ensure_dir() {
|
|
path="$1"
|
|
label="$2"
|
|
if ! mkdir -p "$path"; then
|
|
echo "ERROR: Cannot create $label directory: $path" >&2
|
|
exit 1
|
|
fi
|
|
if [ ! -d "$path" ]; then
|
|
echo "ERROR: $label path is not a directory: $path" >&2
|
|
exit 1
|
|
fi
|
|
probe="$path/.assetmanager-write-test-${HOSTNAME:-container}-$$"
|
|
if ! (umask 077; : > "$probe") 2>/dev/null; then
|
|
echo "ERROR: $label directory is not writable: $path" >&2
|
|
exit 1
|
|
fi
|
|
rm -f "$probe"
|
|
}
|
|
|
|
# Keep all persistent runtime data below the single Compose bind mount.
|
|
# This avoids requiring administrators to create new feature directories by hand.
|
|
ensure_dir "$DATA_ROOT" "data root"
|
|
ensure_dir "$(dirname "$CONFIG_PATH")" "configuration"
|
|
ensure_dir "$(dirname "$APPINFO_PATH")" "application information"
|
|
ensure_dir "$UPLOAD_DIR" "uploads"
|
|
ensure_dir "$STANDARD_IMAGE_DIR" "standard image library"
|
|
ensure_dir "$APP_LOG_DIR" "logs"
|
|
ensure_dir "$SYNC_LOG_DIR" "sync logs"
|
|
ensure_dir "$DIAGNOSTIC_DIR" "diagnostics"
|
|
ensure_dir "$BACKUP_DIR" "backups"
|
|
ensure_dir "$SCRIPT_DIR" "scripts"
|
|
ensure_dir "$SOFTWARE_PACKAGE_DIR" "software packages"
|
|
ensure_dir "$ANALYZER_PROFILE_DIR" "analyzer profiles"
|
|
ensure_dir "$ANALYZER_PROFILE_DIR/community" "community analyzer profiles"
|
|
ensure_dir "$ANALYZER_PROFILE_DIR/local" "local analyzer profiles"
|
|
|
|
# Preserve the established /scripts path used by existing job definitions while
|
|
# storing the files inside the common persistent data root.
|
|
if [ "$SCRIPT_DIR" != "/scripts" ]; then
|
|
if [ -L /scripts ]; then
|
|
rm -f /scripts
|
|
elif [ -e /scripts ]; then
|
|
if [ -d /scripts ] && [ -z "$(ls -A /scripts 2>/dev/null)" ]; then
|
|
rmdir /scripts
|
|
else
|
|
echo "ERROR: /scripts exists and cannot safely be linked to $SCRIPT_DIR" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
ln -s "$SCRIPT_DIR" /scripts
|
|
fi
|
|
|
|
echo "AssetManager data root: $DATA_ROOT"
|
|
echo "Standard image library: $STANDARD_IMAGE_DIR"
|
|
|
|
if [ ! -f "$CONFIG_PATH" ]; then
|
|
echo "Initializing AssetManager configuration: $CONFIG_PATH"
|
|
python - "$CONFIG_PATH" <<'PYCFG'
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
from app.config import DEFAULT_CONFIG
|
|
|
|
path = Path(sys.argv[1])
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
try:
|
|
with path.open("x", encoding="utf-8") as handle:
|
|
json.dump(DEFAULT_CONFIG, handle, ensure_ascii=False, indent=2)
|
|
handle.write("\n")
|
|
except FileExistsError:
|
|
# app and callback containers may perform first-start initialization in parallel.
|
|
pass
|
|
PYCFG
|
|
else
|
|
echo "Keeping existing AssetManager configuration: $CONFIG_PATH"
|
|
fi
|
|
|
|
if [ ! -f "$APPINFO_PATH" ]; then
|
|
echo "Initializing AssetManager APPINFO: $APPINFO_PATH"
|
|
# cp is safe when app and callback initialize the same fresh installation.
|
|
cp "$DEFAULT_APPINFO" "$APPINFO_PATH"
|
|
else
|
|
echo "Keeping existing AssetManager APPINFO: $APPINFO_PATH"
|
|
fi
|
|
|
|
exec "$@"
|