readonly EX_OK=0 readonly EX_GENERAL=1 readonly EX_USAGE=2 readonly EX_CONFIG=3 readonly EX_DEPENDENCY=4 readonly EX_PERMISSION=5 readonly EX_NOT_FOUND=6 readonly EX_COMMAND_FAILED=10 readonly EX_K8S=20 readonly EX_DB=30 readonly EX_BACKUP=40 # ERR_MSG="" # ERR_CODE=0 # err_set() { # ERR_CODE="$1" # ERR_MSG="$2" # return "$ERR_CODE" # } # err_clear() { # ERR_CODE=0 # ERR_MSG="" # } # m_a_riadbStatus() { # err_clear # local out err # if ! run out appError kubectl get pods -n mariadb; then # err_set 30 "Cannot get MariaDB pods: $err" # return $ERR_CODE # fi # log_table "$out" # } # Print an error message to stderr. # $1 (message): error message text. function appError() { printf '%s\n' "$*" >&2 } # Print a fatal error message and exit the script. # [$1] (code): optional numeric exit code (defaults to 1); if omitted, $1 is the message. # $1 (message): error message text (all remaining args when code is provided). function appFailure() { local code=1 if [[ "${1:-}" =~ ^[0-9]+$ ]]; then code="$1" shift fi printf '%b\n' "\033[0;91mCrash: $*\033[0m" exit "$code" } # Source a shell file, exiting with failure if the file does not exist. # $1 (file): path to the shell file to load. function appLoadFile() { local file="$1" [[ -f "$file" ]] || appFailure 3 "File not found: $file" . "$file" } # Validate all required configuration variables and abort on any missing or malformed value. function appCheckConfig() { local value local -a values=('hostName' 'hostIp' 'hostUuid' 'hostSalt' 'k3sNamespace' 'redisKube' 'mariadbKube' 'olsKube' 'postfixKube' 'workerKube' 'redisFileUsersAcl' 'postfixIp' 'postfixHost' 'postfixPostmaster' 'postfixDkimSelector' 'workerApiUrl' 'workerName' 'backupType' 'backupFirstDir') for value in "${values[@]}"; do [[ -n "${!value-}" ]] || appFailure 4 "$value: not specified" done values=('appAssetsPath' 'appDataPath' 'basePath' 'olsVhostsPath' 'domainsList' 'k3sCmd' 'redisPath' 'mariadbMasterPath' 'mariadbSlavePath' 'olsPath' 'olsAdminPath' 'olsPhpIniPath' 'olsLogsPath' 'olsConfigFile' 'olsPrivatePath' 'olsPublicPath' 'olsVhostsConfigPath' 'postfixPath' 'postfixDkimPath' 'workerPath' 'workerAgentPath' 'workerTasksPath' 'workerFilesPath' 'logPath' 'logFile' 'backupDailyPath' 'backupArchivePath' 'storagePath' 'rsyncPath' 'ftpPath' 'sshPath') for value in "${values[@]}"; do [[ "${!value-}" == /* ]] || appFailure 4 "$value: a variable must begin with /" [[ "${!value-}" != */ ]] || appFailure 4 "$value: a variable cannot end in /" done values=('backupParallelJobs' 'k3sReadyRetries' 'k3sReadySleep' 'workerApiGettingPause' 'workerApiSendingPause' 'backupDailyKeep' 'backupArchiveInterval' 'storageDailyKeep' 'storageArchiveKeep' 'olsQuotaBlockLimit' 'olsQuotaInodeLimit') for value in "${values[@]}"; do [[ "${!value-}" =~ ^[0-9]+$ ]] && (( ${!value} >= 1 )) || appFailure 4 "$value: incorrect number value" done if [[ "$backupDailySuffix" == "$backupArchiveSuffix" ]]; then appFailure 4 "backupDailySuffix = backupArchiveSuffix" fi } # Initialize the application by loading core libraries, config, modules, and commands. function appBootstrap() { local file [[ "$EUID" -eq 0 ]] || appFailure 2 "You must run this script as root" # Core for file in \ "$appPath/libs/main.sh" \ "$appPath/libs/print.sh" \ "$appPath/libs/file.sh" do appLoadFile "$file" done # Config appLoadFile "$appPath/config.sh" appCheckConfig # Modules for file in "$appPath/libs/modules/"*.sh; do appLoadFile "$file" done # Commands for file in "$appPath/libs/commands/"*.sh; do appLoadFile "$file" done } # Dispatch execution to the appropriate router based on the APP_MODE environment variable. function appRouter() { local mode="${APP_MODE:-cmd}" case "$mode" in api) apiRouter "$@" ;; cmd|*) cmdRouter "$@" ;; esac }