feat(cli): apply coordinated updates during maintenance

This commit is contained in:
Lemon-miaow committed 2026-10-04 17:36:21 +08:00
1 parent cb3ed94026
commit 4d8e9af240
21 files changed
+990 -457

No files matched your search

+6 -1
View File
@@ -69,6 +69,7 @@
# FELIS_CLOUDFLARED_VERSION / FELIS_CLOUDFLARED_SHA256 cloudflared release installed
# when none is present (default: 2026.9.1, digests pinned); the
# sha256 is REQUIRED for any other version
# FELIS_FORCE_UPDATE=1 reinstalls the binary even when its version already matches.
# FELIS_UPGRADE_DEPS 1 moves an installed k3s and cloudflared to the versions above
# (k3s one minor version at a time; neither is ever downgraded) and
# restarts cloudflared-felis onto the new binary (default: 0)
@@ -2612,7 +2613,7 @@ download_release_binary() {
# Convergence check, and the cheapest one available: no API call, no download, and it asks
# the exact question that matters. Reruns are the common case for this installer.
if [ -x "$HOST_BIN" ] && [ "$("$HOST_BIN" version 2>/dev/null | head -n 1)" = "felis ${FELIS_REF}" ]; then
if [ "${FELIS_FORCE_UPDATE:-0}" != 1 ] && [ -x "$HOST_BIN" ] && [ "$("$HOST_BIN" version 2>/dev/null | head -n 1)" = "felis ${FELIS_REF}" ]; then
HAVE_PREBUILT_BINARY=1
ok "host binary is already ${FELIS_REF}; skipping the download"
return 0
@@ -6287,6 +6288,10 @@ main() {
# Before the first change to the host: a problem found here costs a rerun, one found
# halfway through costs an install to unwind.
preflight
check_postgres_major
if [ "$FELIS_UPGRADE_DEPS" = 1 ] && [ -x "$K3S_BIN" ]; then
k3s_upgrade_allowed "$("$K3S_BIN" --version 2>/dev/null | awk 'NR == 1 { print $3 }')" "$FELIS_K3S_VERSION" || true
fi
quiet_watchdog
pause_package_background_timers
ensure_swap
+47 -1
View File
@@ -1085,9 +1085,10 @@ dsum="$(sha256sum <"$ddir/asset" | cut -d' ' -f1)"
# command inside fetch_source. The log lands in $ddir/log; stdout says what the caller did.
run_download() {
rm -f "$ddir/bin/felis"
if [ "${ALREADY_INSTALLED:-0}" = 1 ]; then cp "$ddir/asset" "$ddir/bin/felis"; chmod +x "$ddir/bin/felis"; fi
: > "$ddir/log"
SUMS="$1" ENTRY="${2:-acquire_felis_binary}" ASSET="$ddir/asset" LOG="$ddir/log" FELIS_REF=v9.9.9 \
HOST_BIN="$ddir/bin/felis" TMPDIR="$sdir" INSTALL_FAILS="${INSTALL_FAILS:-}" FETCH_FAILS="${FETCH_FAILS:-}" bash -c '
HOST_BIN="$ddir/bin/felis" TMPDIR="$sdir" FELIS_FORCE_UPDATE="${FELIS_FORCE_UPDATE:-0}" INSTALL_FAILS="${INSTALL_FAILS:-}" FETCH_FAILS="${FETCH_FAILS:-}" bash -c '
set -Eeuo pipefail
ok() { printf "OK: %s\n" "$*" >> "$LOG"; }
warn() { printf "WARN: %s\n" "$*" >> "$LOG"; }
@@ -1143,6 +1144,15 @@ same_log "the release binary is hashed before it is first executed" "$(printf '%
"OK: installed felis-linux-amd64 v9.9.9 at $ddir/bin/felis")"
if cmp -s "$ddir/asset" "$ddir/bin/felis"; then echo "PASS the installed binary is the download"; else echo "FAIL the installed binary is not the download"; fails=$((fails + 1)); fi
out="$(ALREADY_INSTALLED=1 run_download "")"
same_out "the matching host binary skips download" "PREBUILT[1]" $?
out="$(FELIS_FORCE_UPDATE=1 ALREADY_INSTALLED=1 run_download "$(printf '%s felis-linux-amd64\n' "$dsum")")"
same_out "force reinstalls the matching verified binary" "PREBUILT[1]" $?
same_log "force verifies the download before executing it" "$(printf '%s\n' \
"OK: felis-linux-amd64 matches release v9.9.9's SHA256SUMS" \
"RAN: version" \
"OK: installed felis-linux-amd64 v9.9.9 at $ddir/bin/felis")"
out="$(run_download "$(printf '%s felis-linux-amd64\n' deadbeef)")"
same_out "a mismatched release binary asks for the source build" "FETCH_SOURCE
PREBUILT[]" $?
@@ -5222,6 +5232,42 @@ case "$out" in
esac
rm -rf "$credir" "$credcalls"
# Existing clusters must pass compatibility before the install changes the host.
compatdir="$(mktemp -d)"
mkdir -p "$compatdir/pg/18/docker"
printf '18' > "$compatdir/pg/18/docker/PG_VERSION"
printf '#!/bin/sh\necho "k3s version v1.36.4+k3s1 (example)"\n' > "$compatdir/k3s"
chmod +x "$compatdir/k3s"
run_compatibility_guard() {
PG_DATA_DIR="$compatdir/pg" K3S_BIN="$compatdir/k3s" WANT_PG="$1" FELIS_K3S_VERSION="$2" FELIS_UPGRADE_DEPS=1 bash -c '
set -Eeuo pipefail
die() { echo "DIE: $*"; exit 1; }
ok() { :; }
version_newer() { return 1; }
postgres_image_major() { echo "$WANT_PG"; }
acquire_run_lock() { :; }
ensure_k3s_on_path() { :; }
resolve_nano_listen() { :; }
validate_settings() { :; }
detect_os() { :; }
prompt_install_mode() { INSTALL_MODE=full; }
detect_node_ip() { :; }
preflight() { :; }
quiet_watchdog() { echo HOST_CHANGE; exit 0; }
'"$(bsfn check_postgres_major)"'
'"$(bsfn k3s_upgrade_allowed)"'
'"$(bsfn main)"'
main
' 2>&1
}
out="$(run_compatibility_guard 19 v1.37.1+k3s1)"
expect "PostgreSQL major mismatch is refused before host changes" 'holds a PostgreSQL 18 cluster' "$out"
case "$out" in *HOST_CHANGE*) echo "FAIL PostgreSQL refusal came after a host change"; fails=$((fails + 1));; esac
out="$(run_compatibility_guard 18 v1.38.1+k3s1)"
expect "k3s minor skip is refused before host changes" 'skips a minor version' "$out"
case "$out" in *HOST_CHANGE*) echo "FAIL k3s refusal came after a host change"; fails=$((fails + 1));; esac
rm -rf "$compatdir"
# Worker admission reuses the installer but must never enter host control-plane setup.
before "distributed host firewall runs the newly built binary" \
' build_image' '"$HOST_BIN" node firewall --controller' "$(bsfn main)"