From 3918a4b11a6c48087216ef499de04d50492da6b7 Mon Sep 17 00:00:00 2001 From: Minseong Choi Date: Tue, 22 Sep 2026 13:52:00 +0900 Subject: [PATCH] fix(bootstrap): install only the full control plane under felis setup prompt_install_mode also runs inside felis setup. Setup then goes on to the Owner and edge setup, which need the control plane, so choosing nano there always ended in a setup error. Under felis setup the mode is now full before any prompt or default is considered, and an explicit FELIS_INSTALL_MODE=nano stops with a message pointing at deploy/bootstrap.sh. That leaves the felis setup branch of acquire_nano_binary unreachable, so it goes. install_embedded_binary stays, since the full install still uses it. --- deploy/bootstrap.sh | 12 ++++++++---- deploy/bootstrap_test.sh | 16 ++++++++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/deploy/bootstrap.sh b/deploy/bootstrap.sh index ac0dd2e..e3faaf2 100644 --- a/deploy/bootstrap.sh +++ b/deploy/bootstrap.sh @@ -2194,6 +2194,14 @@ summary() { # prompt (or FELIS_INSTALL_MODE=nano). # --------------------------------------------------------------------------- prompt_install_mode() { + # felis setup carries on to the Owner and edge setup, which needs the control plane, so + # a nano install under it could only end in a setup error. + if bootstrap_from_tui; then + [ "$INSTALL_MODE" != nano ] || die "felis setup installs the full control plane; for Felis-nano run deploy/bootstrap.sh with FELIS_INSTALL_MODE=nano" + INSTALL_MODE="full" + log "install mode: full (felis setup)" + return 0 + fi case "$INSTALL_MODE" in full|nano) log "install mode: ${INSTALL_MODE} (from FELIS_INSTALL_MODE)"; return 0 ;; "") ;; @@ -2285,10 +2293,6 @@ build_nano_binary() { } acquire_nano_binary() { - if bootstrap_from_tui; then - install_embedded_binary - return 0 - fi # The release channel takes the same prebuilt binary the control plane does. This is the # biggest win on this path: a host that only wants the auth multiplexer stops needing a Go # toolchain and a checkout at all. diff --git a/deploy/bootstrap_test.sh b/deploy/bootstrap_test.sh index 4e0532a..ac000e7 100644 --- a/deploy/bootstrap_test.sh +++ b/deploy/bootstrap_test.sh @@ -280,6 +280,10 @@ pblock="$(awk '/^prompt_install_mode\(\) \{/,/^}/' "$BS")" [ -n "$pblock" ] || { echo "FAIL: no prompt_install_mode found in $BS"; exit 1; } [ "$(printf '%s\n' "$pblock" | wc -l)" -lt 60 ] \ || { echo "FAIL: the extracted block is not the function -- did its closing brace move?"; exit 1; } +tblock="$(awk '/^bootstrap_from_tui\(\) \{/,/^}/' "$BS")" +[ -n "$tblock" ] || { echo "FAIL: no bootstrap_from_tui found in $BS"; exit 1; } +[ "$(printf '%s\n' "$tblock" | wc -l)" -lt 5 ] \ + || { echo "FAIL: the extracted block is not the function -- did its closing brace move?"; exit 1; } # Only the no-terminal path can run unattended, and with a terminal attached the prompt # would sit waiting on it. setsid drops the controlling terminal, as cloud-init and CI have. @@ -288,10 +292,12 @@ if (: /dev/null; then if command -v setsid >/dev/null 2>&1; then notty=setsid; else notty=skip; fi fi -run_mode() { # unit-path done-marker-path [FELIS_INSTALL_MODE] - INSTALL_MODE="${3:-}" NANO_SERVICE="$1" BOOTSTRAP_DONE="$2" $notty bash -c ' +run_mode() { # unit-path done-marker-path [FELIS_INSTALL_MODE [FELIS_BOOTSTRAP_FROM_TUI]] + INSTALL_MODE="${3:-}" FELIS_BOOTSTRAP_FROM_TUI="${4:-}" NANO_SERVICE="$1" BOOTSTRAP_DONE="$2" \ + $notty bash -c ' die() { printf "DIE: %s\n" "$*"; exit 1; } log() { printf "LOG: %s\n" "$*"; } + '"$tblock"' '"$pblock"' prompt_install_mode &1 @@ -307,6 +313,12 @@ else "$(run_mode "$sdir/felis-nano.service" "$sdir/bootstrap.done")" expect "a fresh host defaults to full" "MODE: full" \ "$(run_mode "$sdir/absent.service" "$sdir/absent.done")" + # felis setup goes on to need the control plane, so under it nano is refused, and the + # nano-only default above must not apply either. + expect "felis setup refuses FELIS_INSTALL_MODE=nano" "DIE: felis setup installs the full control plane" \ + "$(run_mode "$sdir/absent.service" "$sdir/absent.done" nano 1)" + expect "felis setup installs full on a nano-only host" "MODE: full" \ + "$(run_mode "$sdir/felis-nano.service" "$sdir/absent.done" "" 1)" fi # ---------------------------------------------------------------------------------------