Files
imagefind/scripts/smoke-fnos-upgrade.sh
T

123 lines
5.5 KiB
Bash
Executable File

#!/bin/sh
set -eu
PROJECT_ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
OLD_PACKAGE="${1:-$PROJECT_ROOT/dist/imagefind-0.3.9-x86_64.fpk}"
NEW_APP_ROOT="${2:-$PROJECT_ROOT/.build-fnos/imagefind/app}"
PORT="${3:-18766}"
NEW_PACKAGE_ROOT="${4:-$PROJECT_ROOT/fnos}"
PYTHON_PATH="${5:-${IMAGEFIND_PYTHON_PATH:-}}"
PASSWORD="imagefind-upgrade-smoke-password"
[ -f "$OLD_PACKAGE" ] || { printf 'missing previous package: %s\n' "$OLD_PACKAGE" >&2; exit 1; }
[ -f "$NEW_APP_ROOT/runtime/VERSION" ] && [ -d "$NEW_APP_ROOT/runtime/wheels" ] || {
printf 'missing new packaged Python runtime: %s\n' "$NEW_APP_ROOT/runtime" >&2
exit 1
}
OLD_PACKAGE=$(CDPATH= cd -- "$(dirname -- "$OLD_PACKAGE")" && pwd)/$(basename -- "$OLD_PACKAGE")
NEW_APP_ROOT=$(CDPATH= cd -- "$NEW_APP_ROOT" && pwd)
NEW_PACKAGE_ROOT=$(CDPATH= cd -- "$NEW_PACKAGE_ROOT" && pwd)
WORK_ROOT=$(mktemp -d "$PROJECT_ROOT/.upgrade-smoke.XXXXXX")
OLD_PACKAGE_ROOT="$WORK_ROOT/old-package"
ACTIVE_APP_ROOT="$WORK_ROOT/app"
OLD_APP_ROOT="$WORK_ROOT/old-app"
DATA_ROOT="$WORK_ROOT/var"
LIFECYCLE_LOG="$WORK_ROOT/fnos-upgrade.log"
COOKIE_JAR="$WORK_ROOT/cookie.txt"
OLD_CONTROL="$OLD_PACKAGE_ROOT/cmd/main"
NEW_CONTROL="$NEW_PACKAGE_ROOT/cmd/main"
cleanup() {
set +e
if [ -x "$NEW_CONTROL" ]; then
IMAGEFIND_PYTHON_PATH="$PYTHON_PATH" TRIM_APPDEST="$ACTIVE_APP_ROOT" TRIM_PKGVAR="$DATA_ROOT" \
"$NEW_CONTROL" stop >/dev/null 2>&1
fi
if [ -x "$OLD_CONTROL" ]; then
TRIM_APPDEST="$ACTIVE_APP_ROOT" TRIM_PKGVAR="$DATA_ROOT" "$OLD_CONTROL" stop >/dev/null 2>&1
fi
if [ "${IMAGEFIND_KEEP_UPGRADE_SMOKE:-false}" = "true" ]; then
printf 'upgrade smoke workspace preserved at %s\n' "$WORK_ROOT" >&2
return
fi
case "$WORK_ROOT" in
"$PROJECT_ROOT"/.upgrade-smoke.*) rm -rf -- "$WORK_ROOT" ;;
*) printf 'refusing to clear unexpected upgrade smoke path: %s\n' "$WORK_ROOT" >&2 ;;
esac
}
trap cleanup EXIT HUP INT TERM
mkdir -p "$OLD_PACKAGE_ROOT" "$ACTIVE_APP_ROOT"
tar xzf "$OLD_PACKAGE" -C "$OLD_PACKAGE_ROOT" cmd manifest
tar xOf "$OLD_PACKAGE" app.tgz | tar xzf - -C "$ACTIVE_APP_ROOT"
OLD_VERSION=$(sed -n 's/^version[[:space:]]*=[[:space:]]*//p' "$OLD_PACKAGE_ROOT/manifest" | head -n 1)
NEW_VERSION=$(sed -n 's/^version[[:space:]]*=[[:space:]]*//p' "$NEW_PACKAGE_ROOT/manifest" | head -n 1)
[ -n "$OLD_VERSION" ] && [ -n "$NEW_VERSION" ] || { printf 'unable to read package versions\n' >&2; exit 1; }
[ "$OLD_VERSION" != "$NEW_VERSION" ] || { printf 'upgrade smoke requires two different versions\n' >&2; exit 1; }
wait_for_version() {
EXPECTED="$1"
ATTEMPT=0
while [ "$ATTEMPT" -lt 90 ]; do
STATUS=$(curl -fsS "http://127.0.0.1:$PORT/api/v1/status" 2>/dev/null || true)
case "$STATUS" in
*'"configured":true'*'"version":"'"$EXPECTED"'"'*) return 0 ;;
esac
ATTEMPT=$((ATTEMPT + 1))
sleep 1
done
printf 'version %s did not become ready; lifecycle log follows:\n' "$EXPECTED" >&2
tail -100 "$DATA_ROOT/log/imagefind.log" >&2 || true
return 1
}
IMAGEFIND_PYTHON_PATH="$PYTHON_PATH" TRIM_APPDEST="$ACTIVE_APP_ROOT" TRIM_PKGVAR="$DATA_ROOT" \
TRIM_TEMP_LOGFILE="$LIFECYCLE_LOG" \
wizard_admin_password="$PASSWORD" wizard_admin_password_confirm="$PASSWORD" \
"$OLD_PACKAGE_ROOT/cmd/install_callback"
TRIM_PKGVAR="$DATA_ROOT" wizard_direct_access=true wizard_direct_port="$PORT" \
"$OLD_PACKAGE_ROOT/cmd/config_callback"
# A 0.3.15 PyInstaller service can be precisely what is broken on the target
# NAS. Upgrade verification must therefore begin from its persisted data and
# lifecycle callbacks, not require the old HTTP listener to become healthy.
if [ "${IMAGEFIND_SMOKE_START_OLD:-false}" = "true" ]; then
IMAGEFIND_PYTHON_PATH="$PYTHON_PATH" TRIM_APPDEST="$ACTIVE_APP_ROOT" TRIM_PKGVAR="$DATA_ROOT" \
"$OLD_CONTROL" start
wait_for_version "$OLD_VERSION"
fi
printf '%s\n' 'preserve-across-upgrade' >"$DATA_ROOT/data/upgrade-smoke-marker"
IMAGEFIND_PYTHON_PATH="$PYTHON_PATH" TRIM_APPDEST="$ACTIVE_APP_ROOT" TRIM_PKGVAR="$DATA_ROOT" \
"$OLD_CONTROL" stop
TRIM_APPDEST="$ACTIVE_APP_ROOT" TRIM_PKGVAR="$DATA_ROOT" TRIM_TEMP_LOGFILE="$LIFECYCLE_LOG" \
"$NEW_PACKAGE_ROOT/cmd/upgrade_init"
mv "$ACTIVE_APP_ROOT" "$OLD_APP_ROOT"
ln -s "$NEW_APP_ROOT" "$ACTIVE_APP_ROOT"
# Deliberately pass stale mismatched values from the previous wizard.
# The upgrade must preserve the existing password and still succeed.
TRIM_APPDEST="$ACTIVE_APP_ROOT" TRIM_PKGVAR="$DATA_ROOT" TRIM_TEMP_LOGFILE="$LIFECYCLE_LOG" \
IMAGEFIND_PYTHON_PATH="$PYTHON_PATH" \
wizard_admin_password=placeholder wizard_admin_password_confirm=different \
"$NEW_PACKAGE_ROOT/cmd/upgrade_callback"
IMAGEFIND_PYTHON_PATH="$PYTHON_PATH" TRIM_APPDEST="$ACTIVE_APP_ROOT" TRIM_PKGVAR="$DATA_ROOT" \
"$NEW_CONTROL" start
wait_for_version "$NEW_VERSION"
[ "$(sed -n '1p' "$DATA_ROOT/data/upgrade-smoke-marker")" = "preserve-across-upgrade" ] || {
printf 'upgrade did not preserve application data\n' >&2
exit 1
}
LOGIN=$(curl -fsS -c "$COOKIE_JAR" -H 'Content-Type: application/json' \
--data "{\"password\":\"$PASSWORD\",\"remember_device\":false}" \
"http://127.0.0.1:$PORT/api/v1/auth/login")
case "$LOGIN" in
*'"csrf_token"'*) ;;
*) printf 'upgrade did not preserve the administrator password\n' >&2; exit 1 ;;
esac
grep -q '升级准备完成' "$LIFECYCLE_LOG"
grep -q '升级数据检查完成' "$LIFECYCLE_LOG"
printf 'fnOS upgrade smoke passed: %s -> %s; data, access settings and password preserved\n' \
"$OLD_VERSION" "$NEW_VERSION"