Loading deploy/bootstrap.sh +16 −1 Changes for deploy/bootstrap.sh: 16 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -2364,6 +2364,21 @@ atomic_install_file() { mv -fT "$staged" "$target" } # install_if_changed is atomic_install_file that leaves a target with the same bytes in # place, fixing only its mode and owner, so the target's mtime keeps meaning "the content # changed". felis domain check reads a proxy started before felis-link.properties' mtime # as one still on the old names, and a re-run that rewrote the same bytes made every # install look behind (and `felis domain set` restart the proxy for nothing). install_if_changed() { local source="$1" target="$2" mode="$3" owner="$4" group="$5" if [ -f "$target" ] && [ ! -L "$target" ] && cmp -s "$source" "$target"; then chown "${owner}:${group}" "$target" chmod "$mode" "$target" return 0 fi atomic_install_file "$@" } # build_velocity_plugin compiles plugins/velocity in the same gradle image the two # Dockerfiles use, and drops the jar where Velocity will look for it. Docker is the # toolchain here on purpose: the host needs no JDK and no gradle, only a JRE. Gradle Loading Loading @@ -2728,7 +2743,7 @@ EOF atomic_install_file "${tmp}/forwarding.secret" "${VELOCITY_DIR}/forwarding.secret" 0640 root "$VELOCITY_USER" atomic_install_file "${tmp}/velocity.toml" "${VELOCITY_DIR}/velocity.toml" 0640 "$VELOCITY_USER" "$VELOCITY_USER" atomic_install_file "${tmp}/felis-link.properties" \ install_if_changed "${tmp}/felis-link.properties" \ "${VELOCITY_DIR}/plugins/felis-link/felis-link.properties" 0640 root "$VELOCITY_USER" ok "velocity.toml + forwarding secret + felis-link.properties written (${VELOCITY_DIR})" } Loading deploy/bootstrap_test.sh +37 −3 Changes for deploy/bootstrap_test.sh: 37 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -1541,9 +1541,10 @@ panel_hostname = "console.r.example.com" # The proxy's link properties and the panel certificate take the carried names. wvblock="$(awk '/^write_velocity_config\(\) \{/,/^}/' "$BS")" ptblock="$(awk '/^ensure_panel_tls_cert\(\) \{/,/^}/' "$BS")" { [ -n "$wvblock" ] && [ -n "$ptblock" ]; } \ || { echo "FAIL: write_velocity_config / ensure_panel_tls_cert not found in $BS"; exit 1; } printf '%s\n' "$wvblock" "$ptblock" >> "$fnfile" iicblock="$(awk '/^install_if_changed\(\) \{/,/^}/' "$BS")" { [ -n "$wvblock" ] && [ -n "$ptblock" ] && [ -n "$iicblock" ]; } \ || { echo "FAIL: write_velocity_config / ensure_panel_tls_cert / install_if_changed not found in $BS"; exit 1; } printf '%s\n' "$iicblock" "$wvblock" "$ptblock" >> "$fnfile" cat > "$adir/felis.host.toml" <<'TOML' [auth] admin_hostname = "ops.example.org" Loading Loading @@ -1601,6 +1602,39 @@ else echo "FAIL: reading a long [auth] printed:"; printf '%s\n' "$err" | head -5; fails=$((fails + 1)) fi # A re-run that writes the same felis-link.properties leaves the file alone: felis domain # check reads a proxy started before the file's mtime as still on the old names. run_link() { # velocity-dir [root-domain] VD="$1" RD="${2:-r.example.com}" TMPDIR="$1" FNFILE="$fnfile" bash -c ' set -Eeuo pipefail log() { :; }; ok() { :; }; remember_temp() { :; } felis_internal_ip() { printf 10.43.0.1; } prepare_velocity_layout() { :; } atomic_install_file() { echo "REPLACED $(basename "$2")"; cp "$1" "$2"; } chown() { echo "CHOWN $*"; }; chmod() { echo "CHMOD $*"; } . "$FNFILE" STATE_DIR="$VD" FELIS_ROOT_DOMAIN="$RD" FORWARDING_SECRET=f SERVICE_TOKEN=t LOGIN_SERVER=login \ LOBBY_SERVER=lobby FELIS_GAME_PORT=25565 VELOCITY_DIR="$VD" VELOCITY_USER=v NODE_IP=10.0.0.5 write_velocity_config' 2>&1 } ldir2="$(mktemp -d)" mkdir -p "$ldir2/plugins/felis-link" lprops="$ldir2/plugins/felis-link/felis-link.properties" expect "a first write installs felis-link.properties" "REPLACED felis-link.properties" "$(run_link "$ldir2")" touch -t 202001010000 "$lprops" before="$(ls -l --time-style=+%s "$lprops" 2>/dev/null || stat -f '%m' "$lprops")" out="$(run_link "$ldir2")" case "$out" in *"REPLACED felis-link.properties"*) echo "FAIL: a re-run with the same names replaced felis-link.properties"; fails=$((fails + 1)) ;; *) echo "PASS a re-run with the same names leaves felis-link.properties in place" ;; esac expect "the re-run still fixes the owner" "CHOWN root:v $lprops" "$out" expect "the re-run still fixes the mode" "CHMOD 0640 $lprops" "$out" expect "the kept file keeps its mtime" "$before" "$(ls -l --time-style=+%s "$lprops" 2>/dev/null || stat -f '%m' "$lprops")" expect "a re-run on other names replaces felis-link.properties" "REPLACED felis-link.properties" "$(run_link "$ldir2" other.example.net)" expect "the replaced file has the new root domain" "root-domain=other.example.net" "$(grep '^root-domain=' "$lprops")" rm -rf "$ldir2" # A different FELIS_ROOT_DOMAIN on an installed host is refused with the way through. dnblock="$(awk '/^detect_node_ip\(\) \{/,/^}/' "$BS")" prdblock="$(awk '/^persisted_root_domain\(\) \{/,/^}/' "$BS")" Loading docs/operations.md +6 −0 Changes for docs/operations.md: 6 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -506,3 +506,9 @@ names afterwards. A second `set -yes` changed and restarted nothing; the install with the old `FELIS_ROOT_DOMAIN` stopped at its first check; a full installer re-run kept the moved domain and left `check` clean; moving back restored every surface **[VM-VERIFIED]**. `check` reads the proxy as behind when `felis-velocity` started before `felis-link.properties` last changed. Installers before this command rewrote that file on every run, so a host upgraded from one can show that line once with the file already on the names; `sudo systemctl restart felis-velocity` clears it. The installer now leaves the file alone when its content is the same. Loading
deploy/bootstrap.sh +16 −1 Changes for deploy/bootstrap.sh: 16 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -2364,6 +2364,21 @@ atomic_install_file() { mv -fT "$staged" "$target" } # install_if_changed is atomic_install_file that leaves a target with the same bytes in # place, fixing only its mode and owner, so the target's mtime keeps meaning "the content # changed". felis domain check reads a proxy started before felis-link.properties' mtime # as one still on the old names, and a re-run that rewrote the same bytes made every # install look behind (and `felis domain set` restart the proxy for nothing). install_if_changed() { local source="$1" target="$2" mode="$3" owner="$4" group="$5" if [ -f "$target" ] && [ ! -L "$target" ] && cmp -s "$source" "$target"; then chown "${owner}:${group}" "$target" chmod "$mode" "$target" return 0 fi atomic_install_file "$@" } # build_velocity_plugin compiles plugins/velocity in the same gradle image the two # Dockerfiles use, and drops the jar where Velocity will look for it. Docker is the # toolchain here on purpose: the host needs no JDK and no gradle, only a JRE. Gradle Loading Loading @@ -2728,7 +2743,7 @@ EOF atomic_install_file "${tmp}/forwarding.secret" "${VELOCITY_DIR}/forwarding.secret" 0640 root "$VELOCITY_USER" atomic_install_file "${tmp}/velocity.toml" "${VELOCITY_DIR}/velocity.toml" 0640 "$VELOCITY_USER" "$VELOCITY_USER" atomic_install_file "${tmp}/felis-link.properties" \ install_if_changed "${tmp}/felis-link.properties" \ "${VELOCITY_DIR}/plugins/felis-link/felis-link.properties" 0640 root "$VELOCITY_USER" ok "velocity.toml + forwarding secret + felis-link.properties written (${VELOCITY_DIR})" } Loading
deploy/bootstrap_test.sh +37 −3 Changes for deploy/bootstrap_test.sh: 37 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -1541,9 +1541,10 @@ panel_hostname = "console.r.example.com" # The proxy's link properties and the panel certificate take the carried names. wvblock="$(awk '/^write_velocity_config\(\) \{/,/^}/' "$BS")" ptblock="$(awk '/^ensure_panel_tls_cert\(\) \{/,/^}/' "$BS")" { [ -n "$wvblock" ] && [ -n "$ptblock" ]; } \ || { echo "FAIL: write_velocity_config / ensure_panel_tls_cert not found in $BS"; exit 1; } printf '%s\n' "$wvblock" "$ptblock" >> "$fnfile" iicblock="$(awk '/^install_if_changed\(\) \{/,/^}/' "$BS")" { [ -n "$wvblock" ] && [ -n "$ptblock" ] && [ -n "$iicblock" ]; } \ || { echo "FAIL: write_velocity_config / ensure_panel_tls_cert / install_if_changed not found in $BS"; exit 1; } printf '%s\n' "$iicblock" "$wvblock" "$ptblock" >> "$fnfile" cat > "$adir/felis.host.toml" <<'TOML' [auth] admin_hostname = "ops.example.org" Loading Loading @@ -1601,6 +1602,39 @@ else echo "FAIL: reading a long [auth] printed:"; printf '%s\n' "$err" | head -5; fails=$((fails + 1)) fi # A re-run that writes the same felis-link.properties leaves the file alone: felis domain # check reads a proxy started before the file's mtime as still on the old names. run_link() { # velocity-dir [root-domain] VD="$1" RD="${2:-r.example.com}" TMPDIR="$1" FNFILE="$fnfile" bash -c ' set -Eeuo pipefail log() { :; }; ok() { :; }; remember_temp() { :; } felis_internal_ip() { printf 10.43.0.1; } prepare_velocity_layout() { :; } atomic_install_file() { echo "REPLACED $(basename "$2")"; cp "$1" "$2"; } chown() { echo "CHOWN $*"; }; chmod() { echo "CHMOD $*"; } . "$FNFILE" STATE_DIR="$VD" FELIS_ROOT_DOMAIN="$RD" FORWARDING_SECRET=f SERVICE_TOKEN=t LOGIN_SERVER=login \ LOBBY_SERVER=lobby FELIS_GAME_PORT=25565 VELOCITY_DIR="$VD" VELOCITY_USER=v NODE_IP=10.0.0.5 write_velocity_config' 2>&1 } ldir2="$(mktemp -d)" mkdir -p "$ldir2/plugins/felis-link" lprops="$ldir2/plugins/felis-link/felis-link.properties" expect "a first write installs felis-link.properties" "REPLACED felis-link.properties" "$(run_link "$ldir2")" touch -t 202001010000 "$lprops" before="$(ls -l --time-style=+%s "$lprops" 2>/dev/null || stat -f '%m' "$lprops")" out="$(run_link "$ldir2")" case "$out" in *"REPLACED felis-link.properties"*) echo "FAIL: a re-run with the same names replaced felis-link.properties"; fails=$((fails + 1)) ;; *) echo "PASS a re-run with the same names leaves felis-link.properties in place" ;; esac expect "the re-run still fixes the owner" "CHOWN root:v $lprops" "$out" expect "the re-run still fixes the mode" "CHMOD 0640 $lprops" "$out" expect "the kept file keeps its mtime" "$before" "$(ls -l --time-style=+%s "$lprops" 2>/dev/null || stat -f '%m' "$lprops")" expect "a re-run on other names replaces felis-link.properties" "REPLACED felis-link.properties" "$(run_link "$ldir2" other.example.net)" expect "the replaced file has the new root domain" "root-domain=other.example.net" "$(grep '^root-domain=' "$lprops")" rm -rf "$ldir2" # A different FELIS_ROOT_DOMAIN on an installed host is refused with the way through. dnblock="$(awk '/^detect_node_ip\(\) \{/,/^}/' "$BS")" prdblock="$(awk '/^persisted_root_domain\(\) \{/,/^}/' "$BS")" Loading
docs/operations.md +6 −0 Changes for docs/operations.md: 6 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -506,3 +506,9 @@ names afterwards. A second `set -yes` changed and restarted nothing; the install with the old `FELIS_ROOT_DOMAIN` stopped at its first check; a full installer re-run kept the moved domain and left `check` clean; moving back restored every surface **[VM-VERIFIED]**. `check` reads the proxy as behind when `felis-velocity` started before `felis-link.properties` last changed. Installers before this command rewrote that file on every run, so a host upgraded from one can show that line once with the file already on the names; `sudo systemctl restart felis-velocity` clears it. The installer now leaves the file alone when its content is the same.