#!/usr/bin/env bash set -Eeuo pipefail ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) WORK=$(mktemp -d) EXECUTION_MARKER=/tmp/kaidi-baota-fixture-executed-$$ trap 'rm -rf "$WORK" "$EXECUTION_MARKER"' EXIT fail() { printf 'Baota start fixture failed: %s\n' "$1" >&2 [ ! -f "$WORK/java.log" ] || sed -n '1,40p' "$WORK/java.log" >&2 exit 1 } RELEASE="$WORK/release" mkdir -p "$RELEASE/ops" "$RELEASE/public" "$WORK/files" "$WORK/tmp" "$WORK/state" "$WORK/mock-bin" RELEASE_PHYSICAL=$(cd "$RELEASE" && pwd -P) printf 'fixture jar\n' > "$RELEASE/app.jar" printf '\n' > "$RELEASE/public/index.html" printf '1.0.0-preview.25\n' > "$RELEASE/VERSION" cp "$ROOT/deploy/baota-start.sh" "$RELEASE/ops/baota-start.sh" chmod 0755 "$RELEASE/ops/baota-start.sh" cat > "$WORK/mock-bin/awk" <<'SH' #!/usr/bin/env bash case "${2:-}" in /proc/*/stat) printf '424242\n' ;; *) exec /usr/bin/awk "$@" ;; esac SH chmod 0755 "$WORK/mock-bin/awk" cat > "$WORK/base.env" < "$WORK/runtime.env" < "$WORK/java" <<'SH' #!/usr/bin/env bash set -Eeuo pipefail if [ "${1:-}" = -version ]; then printf 'openjdk version "17-fixture"\n' >&2 exit 0 fi { printf 'cwd=%s\n' "$PWD" printf 'args=%s\n' "$*" printf 'version=%s\n' "$APP_VERSION" printf 'address=%s\n' "$SERVER_ADDRESS" printf 'port=%s\n' "$SERVER_PORT" printf 'update=%s\n' "$FINANCE_UPDATE_ENABLED" printf 'static=%s\n' "$FINANCE_STATIC_LOCATIONS" printf 'username=%s\n' "$DB_USERNAME" printf 'password=%s\n' "$DB_PASSWORD" printf 'pid-record=%s\n' "$(cat "$KAIDI_PID_FILE")" printf 'self-pid=%s\n' "$$" } > "$MOCK_JAVA_LOG" SH chmod 0755 "$WORK/java" MOCK_JAVA_LOG="$WORK/java.log" \ PATH="$WORK/mock-bin:$PATH" \ KAIDI_JAVA_BIN="$WORK/java" \ KAIDI_CONFIG_FILE="$WORK/base.env" \ KAIDI_RUNTIME_ENV_FILE="$WORK/runtime.env" \ DB_URL='' DB_USERNAME='' DB_PASSWORD='' \ "$RELEASE/ops/baota-start.sh" grep -Fqx "cwd=$RELEASE_PHYSICAL" "$WORK/java.log" || fail 'launcher did not use the physical release directory' grep -Fqx "args=-XX:MaxRAMPercentage=70 -Dfile.encoding=UTF-8 -Dkaidi.release.path=$RELEASE_PHYSICAL -Dkaidi.release.version=1.0.0-preview.25 -jar $RELEASE_PHYSICAL/app.jar" "$WORK/java.log" \ || fail 'launcher did not identify and execute the packaged Spring Boot release' grep -Fqx 'version=1.0.0-preview.25' "$WORK/java.log" || fail 'launcher did not read VERSION' grep -Fqx 'address=127.0.0.1' "$WORK/java.log" || fail 'launcher did not default to loopback' grep -Fqx 'port=19090' "$WORK/java.log" || fail 'runtime environment did not override the base port' grep -Fqx 'update=true' "$WORK/java.log" || fail 'launcher did not keep online update enabled' grep -Fqx "static=file:$RELEASE_PHYSICAL/public/" "$WORK/java.log" \ || fail 'launcher did not bind static resources to the release directory' grep -Fqx 'username=fixture-user' "$WORK/java.log" || fail 'launcher did not load setup database values' grep -Fqx "password=\$(touch $EXECUTION_MARKER)" "$WORK/java.log" \ || fail 'launcher changed a literal password while parsing the protected environment' [ ! -e "$EXECUTION_MARKER" ] || fail 'launcher executed command syntax from a database password' PID_RECORD=$(sed -n 's/^pid-record=//p' "$WORK/java.log") SELF_PID=$(sed -n 's/^self-pid=//p' "$WORK/java.log") [ "$PID_RECORD" = "$SELF_PID 424242" ] || fail 'PID file did not bind the PID to its proc start time' # systemd reads the root-only EnvironmentFile before dropping to User=kaidi. # The launcher must therefore be able to start with those files intentionally # unreadable by the service user. chmod 000 "$WORK/base.env" "$WORK/runtime.env" MOCK_JAVA_LOG="$WORK/preloaded.log" \ PATH="$WORK/mock-bin:$PATH" \ KAIDI_ENV_PRELOADED=true \ KAIDI_JAVA_BIN="$WORK/java" \ SPRING_PROFILES_ACTIVE=production \ SERVER_ADDRESS=127.0.0.1 \ SERVER_PORT=21000 \ DB_URL='jdbc:mysql://db.fixture/kaidi_finance' \ DB_USERNAME=fixture-user \ DB_PASSWORD='fixture-password' \ FIELD_ENCRYPTION_KEY=fixture-field-key \ FILE_STORAGE_ROOT="$WORK/files" \ FILE_STORAGE_TEMP="$WORK/tmp" \ FINANCE_SETUP_ENABLED=false \ FINANCE_UPDATE_ENABLED=true \ FILE_SCANNER_ENABLED=false \ KAIDI_PID_FILE="$WORK/state/preloaded.pid" \ KAIDI_CONFIG_FILE="$WORK/base.env" \ KAIDI_RUNTIME_ENV_FILE="$WORK/runtime.env" \ "$RELEASE/ops/baota-start.sh" grep -Fqx 'port=21000' "$WORK/preloaded.log" \ || fail 'launcher still depended on the root-only configuration files under systemd' chmod 0644 "$WORK/base.env" "$WORK/runtime.env" MOCK_JAVA_LOG="$WORK/explicit.log" \ PATH="$WORK/mock-bin:$PATH" \ KAIDI_JAVA_BIN="$WORK/java" \ KAIDI_CONFIG_FILE="$WORK/base.env" \ KAIDI_RUNTIME_ENV_FILE="$WORK/runtime.env" \ SERVER_PORT=20000 \ "$RELEASE/ops/baota-start.sh" grep -Fqx 'port=20000' "$WORK/explicit.log" || fail 'non-empty Baota environment did not take precedence' cat > "$WORK/missing-db.env" < "$WORK/missing-db.out" 2>&1; then fail 'launcher accepted a production configuration without DB_URL' fi grep -Fq '受保护的 Kaidi 配置缺少:DB_URL' "$WORK/missing-db.out" \ || fail 'launcher did not report the missing database URL' [ ! -e "$WORK/missing-db.log" ] || fail 'launcher started Java after configuration validation failed' printf 'Baota Spring Boot launcher configuration, PID identity, and injection fixtures passed\n'