From 765a8923a472a1ab4ca590bc390a90b8a0cdb62a Mon Sep 17 00:00:00 2001 From: Lemon-miaow Date: Wed, 23 Sep 2026 19:05:54 +0800 Subject: [PATCH] fix(bootstrap): re-runs keep the operator's [registry] overrides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit §15's upgrade path is "re-run the installer", but write_felis_toml rewrote the [registry] table from scratch — url + build_namespace only. Everything else an operator put there (the §8e build-lane executor mirrors, the resource caps, the uploads backend stamped by the storage wizard, [registry.s3]) was silently reverted on every re-run: builds went back to the denied upstream executors and an S3-backed install flipped to local storage, with nothing pointing at why. Found while landing the registry-hosting work, which depends on those same keys surviving. - persisted_registry_block carries the operator-owned [registry] keys and the [registry.s3] subtable forward, same first-readable-file rule as persisted_smtp_block; url/build_namespace stay installer-owned (they must match REGISTRY_URL/BUILD_NS, so a stale value must NOT survive). - The s3 subtable header is re-emitted with its keys, so nothing carried lands as an unknown key under [registry]. - bootstrap_test.sh pins the carry, the installer-owned exclusion, and idempotence (a second re-run writes a byte-identical file). --- deploy/bootstrap.sh | 39 +++++++++++++++++++++++-- deploy/bootstrap_test.sh | 63 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/deploy/bootstrap.sh b/deploy/bootstrap.sh index 9901185..b518d1e 100644 --- a/deploy/bootstrap.sh +++ b/deploy/bootstrap.sh @@ -2129,17 +2129,50 @@ persisted_auth_source_blocks() { 'url = "https://littleskin.cn/api/yggdrasil/sessionserver/session/minecraft/hasJoined"' } +# persisted_registry_block echoes the operator-owned [registry] keys an earlier run +# left behind — the build-lane executor mirrors, the resource caps, the uploads +# backend and its [registry.s3] subtable — so §15's upgrade path (re-run the +# installer) does not silently revert them. Nothing in this script's inputs +# derives these: they are hand-written per docs/troubleshooting.md §8e or stamped +# by the storage wizard. url and build_namespace are NOT carried: this script +# owns them (they must match REGISTRY_URL / BUILD_NS). Same first-readable-file +# rule as persisted_smtp_block. +persisted_registry_block() { + local f out + for f in "${STATE_DIR}/felis.host.toml" "${STATE_DIR}/felis.pod.toml"; do + [ -r "$f" ] || continue + out="$(awk ' + /^[[:space:]]*\[/ { sect = $0; next } + sect ~ /^[[:space:]]*\[registry\][[:space:]]*$/ && + /^[[:space:]]*(kaniko_image|trivy_image|trivy_db_repository|build_cpu_limit|build_mem_limit|user_uploads_context)[[:space:]]*=/ { print } + sect ~ /^[[:space:]]*\[registry\.s3\][[:space:]]*$/ && /^[[:space:]]*[A-Za-z_]+[[:space:]]*=/ { + if (!s3hdr) { printf "[registry.s3]\n"; s3hdr = 1 } + print + } + ' "$f")" + [ -n "$out" ] || continue + printf '%s\n' "$out" + return 0 + done +} + write_felis_toml() { - local target="$1" db_host="$2" smtp_block auth_source_blocks + local target="$1" db_host="$2" smtp_block auth_source_blocks registry_block smtp_block="$(persisted_smtp_block)" if [ -n "$smtp_block" ]; then log "carrying forward the configured [smtp] relay" smtp_block="${smtp_block}"$'\n' # keep a blank line before the next section fi auth_source_blocks="$(persisted_auth_source_blocks)" + registry_block="$(persisted_registry_block)" + if [ -n "$registry_block" ]; then + log "carrying forward the configured [registry] overrides" + registry_block="${registry_block}"$'\n' # keep a blank line before the next section + fi cat > "$target" < "$fnfile" + +rdir="$(mktemp -d)" +cat > "$rdir/felis.host.toml" <<'TOML' +[registry] +url = "stale.invalid:5000" +build_namespace = "stale-ns" +kaniko_image = "registry.felis.svc:5000/mirror/kaniko-executor:v1.24.0" +trivy_db_repository = "registry.felis.svc:5000/mirror/trivy-db:2" + +[registry.s3] +endpoint = "https://s3.example" +region = "us-east-1" +TOML + +run_write() { # out-file + STATE_DIR="$rdir" OUT_TOML="$1" FNFILE="$fnfile" bash -c ' + log() { :; } + persisted_smtp_block() { :; } + persisted_auth_source_blocks() { :; } + . "$FNFILE" + FELIS_ROOT_DOMAIN=r.example.com DB_USER=u DB_PASSWORD=p DB_NAME=d MINECRAFT_NS=minecraft \ + FELIS_EGRESS_MODE=nodeport FELIS_LIMBO_IMAGE=li FELIS_LOBBY_IMAGE=lo \ + REGISTRY_URL=registry.felis.svc:5000 BUILD_NS=felis-build FELIS_ARCHIVE_LOCAL_PATH=/a \ + write_felis_toml "$OUT_TOML" 127.0.0.1' +} + +run_write "$rdir/out.toml" +out="$(cat "$rdir/out.toml")" +expect "a re-run carries the build-lane executor mirrors" \ + 'kaniko_image = "registry.felis.svc:5000/mirror/kaniko-executor:v1.24.0"' "$out" +expect "a re-run carries the [registry.s3] uploads subtable" "[registry.s3]" "$out" +expect "the carried subtable keeps its keys" 'endpoint = "https://s3.example"' "$out" +expect "url stays installer-owned" 'url = "registry.felis.svc:5000"' "$out" +case "$out" in + *stale.invalid* | *stale-ns*) echo "FAIL: stale installer-owned registry values survived the re-run"; fails=$((fails + 1)) ;; +esac + +cp "$rdir/out.toml" "$rdir/felis.host.toml" +run_write "$rdir/out2.toml" +if cmp -s "$rdir/out.toml" "$rdir/out2.toml"; then + echo "PASS a carried-forward config converges (the second re-run is a no-op)" +else + echo "FAIL: carrying [registry] overrides is not idempotent" + diff "$rdir/out.toml" "$rdir/out2.toml" | head + fails=$((fails + 1)) +fi + +rm -f "$fnfile" + # --------------------------------------------------------------------------------------- if [ "$fails" -eq 0 ]; then echo "ALL PASS"