fix(install): backups exist on a default install; retention resolves real world dirs (#6)
Three faces of one gap, all on the supported install path: - Backup/restore answered 503 out of the box: nothing ever rendered the archive PVC, so FELIS_BACKUP_PVC was unset. The bundle now renders the PVC (Minecraft namespace, RWO 10Gi, cluster default class) and 'felis manifests' names it by default (--backup-pvc= is the explicit no-store shape); bootstrap passes it through so the generated felis.toml [archive] local_path and the jobs' mount path come from one variable. - Retention was unreachable: bootstrap never passed the reaper flags. It now forwards FELIS_WORLDS_HOST_PATH/FELIS_ARCHIVE_LOCAL_PATH, so one env enables the daily CronJob; unset keeps today's fail-safe (no reaper, nothing deleted). - Even when enabled it could not find a world on a stock install: resolveWorldDir now also resolves the exact local-path directory <pv-name>_<ns>_<pvc-name> read from the live PVC's volumeName (never a glob, so a stale deleted PV's bytes can't be archived in place of the current world). Reaper Role gains persistentvolumeclaims:get (weaker than the delete it already held). README (zh/en) stops promising automatic/scheduled backups and states retention is opt-in. bootstrap_test covers the env->flag contract.
This commit is contained in:
14 files changed
+394
-82
No files matched your search
+42
-6
@@ -63,6 +63,15 @@
|
||||
# FELIS_ROOT_DOMAIN deployment root domain (default: <node-ip>.nip.io)
|
||||
# FELIS_PANEL_NODEPORT local HTTPS panel/API NodePort (default: 30443)
|
||||
# FELIS_EGRESS_MODE loadbalancer|nodeport (default: nodeport — no MetalLB on a demo box)
|
||||
# FELIS_BACKUP_PVC world-archive PVC the installer renders and felis-api hands to its
|
||||
# backup/restore Jobs (default: felis-backups; empty string disables
|
||||
# backups — the endpoints answer 503)
|
||||
# FELIS_ARCHIVE_LOCAL_PATH path that PVC is mounted at inside those Jobs; written into
|
||||
# felis.toml [archive] local_path (default: /var/lib/felis/archives)
|
||||
# FELIS_WORLDS_HOST_PATH node directory holding the world volumes (on the k3s this
|
||||
# installer provisions: /var/lib/rancher/k3s/storage). Setting it
|
||||
# enables the daily retention reaper, which archives and then deletes
|
||||
# worlds idle beyond the retention window (default: unset = no reaper)
|
||||
# PKG_LOCK_TIMEOUT seconds to wait for package-manager locks (default: 900)
|
||||
# APT_LOCK_TIMEOUT legacy alias for PKG_LOCK_TIMEOUT
|
||||
set -Eeuo pipefail
|
||||
@@ -106,6 +115,18 @@ FELIS_VERSION_BASE=""
|
||||
FELIS_IMAGE="${FELIS_IMAGE:-felis:demo}"
|
||||
FELIS_EGRESS_MODE="${FELIS_EGRESS_MODE:-nodeport}"
|
||||
FELIS_PANEL_NODEPORT="${FELIS_PANEL_NODEPORT:-30443}"
|
||||
# World-archive storage. The installer renders this PVC (minecraft namespace) and felis-api
|
||||
# advertises it to its backup/restore Jobs; emptying it disables backups (503). The archive
|
||||
# path is written into felis.toml so the Jobs' mount and [archive] local_path agree by
|
||||
# construction — a mismatch would leave tarLocal's absolute archive refs unresolvable.
|
||||
FELIS_BACKUP_PVC="${FELIS_BACKUP_PVC:-felis-backups}"
|
||||
FELIS_ARCHIVE_LOCAL_PATH="${FELIS_ARCHIVE_LOCAL_PATH:-/var/lib/felis/archives}"
|
||||
# Retention is opt-in because it DELETES worlds (after a verified archive): point this at the
|
||||
# node directory the world volumes live under. On the k3s this installer provisions that is
|
||||
# /var/lib/rancher/k3s/storage — the reaper resolves each PVC's local-path directory exactly
|
||||
# from its volumeName. Left unset, no reaper CronJob renders and archives accumulate until
|
||||
# the backup PVC fills (then backups fail loudly; nothing is deleted).
|
||||
FELIS_WORLDS_HOST_PATH="${FELIS_WORLDS_HOST_PATH:-}"
|
||||
INSTALL_MODE="${FELIS_INSTALL_MODE:-}"
|
||||
# Loopback by default: hasJoined is an unauthenticated endpoint by protocol (Velocity
|
||||
# sends no token), so a public bind is a free auth relay — anyone can point their own
|
||||
@@ -2047,7 +2068,7 @@ build_namespace = "${BUILD_NS}"
|
||||
|
||||
[archive]
|
||||
store = "tarLocal"
|
||||
local_path = "/var/lib/felis/archives"
|
||||
local_path = "${FELIS_ARCHIVE_LOCAL_PATH}"
|
||||
|
||||
[auth]
|
||||
admin_hostname = "op.console.${FELIS_ROOT_DOMAIN}"
|
||||
@@ -2137,11 +2158,26 @@ deploy_bundle() {
|
||||
--dry-run=client -o yaml | kube apply -f -
|
||||
|
||||
log "rendering + applying the control-plane bundle"
|
||||
"$HOST_BIN" manifests \
|
||||
--felis-image "$FELIS_IMAGE" \
|
||||
--panel-node-port "$FELIS_PANEL_NODEPORT" \
|
||||
--velocity-cidr "${NODE_IP}/32" \
|
||||
| kube apply -f -
|
||||
local -a manifest_args=(
|
||||
--felis-image "$FELIS_IMAGE"
|
||||
--panel-node-port "$FELIS_PANEL_NODEPORT"
|
||||
--velocity-cidr "${NODE_IP}/32"
|
||||
)
|
||||
# Backups are on by default (the renderer's own default names felis-backups); an emptied
|
||||
# FELIS_BACKUP_PVC asks for the no-backup shape explicitly, and a custom name must be
|
||||
# passed through or the api would advertise a PVC the bundle never created.
|
||||
if [ -n "$FELIS_BACKUP_PVC" ]; then
|
||||
manifest_args+=(--backup-pvc "$FELIS_BACKUP_PVC")
|
||||
else
|
||||
manifest_args+=(--backup-pvc=)
|
||||
fi
|
||||
# Retention renders only when the operator names where the worlds live; the archive path
|
||||
# always travels with it because it must equal the [archive] local_path written above.
|
||||
if [ -n "$FELIS_WORLDS_HOST_PATH" ]; then
|
||||
log "retention enabled: the daily reaper will read worlds from ${FELIS_WORLDS_HOST_PATH}"
|
||||
manifest_args+=(--worlds-host-path "$FELIS_WORLDS_HOST_PATH" --archive-local-path "$FELIS_ARCHIVE_LOCAL_PATH")
|
||||
fi
|
||||
"$HOST_BIN" manifests "${manifest_args[@]}" | kube apply -f -
|
||||
restart_existing_control_plane "$had_api" "$had_operator"
|
||||
|
||||
log "waiting for control-plane rollouts"
|
||||
|
||||
@@ -574,6 +574,45 @@ mkdir -p "$sdir/src/.git"
|
||||
expect "a failed fetch into an existing checkout names the token" "set FELIS_GITHUB_TOKEN" \
|
||||
"$(run_fetch "$sdir/src")"
|
||||
|
||||
# --- default install keeps backups, and retention envs reach the renderer ----------------
|
||||
# A default install must render the world-archive PVC (without one, backup/restore answer an
|
||||
# honest 503), and FELIS_WORLDS_HOST_PATH must turn into the reaper's two flags or an
|
||||
# operator's retention enablement silently renders no CronJob. Extracted, not retyped.
|
||||
|
||||
mblock="$(awk '/^ local -a manifest_args=\(/,/kube apply -f -/' "$BS")"
|
||||
[ -n "$mblock" ] || { echo "FAIL: no manifest_args block found in $BS"; exit 1; }
|
||||
[ "$(printf '%s\n' "$mblock" | wc -l)" -lt 30 ] \
|
||||
|| { echo "FAIL: the extracted block is not the manifest_args block -- did it move?"; exit 1; }
|
||||
|
||||
run_bundle_flags() { # backup-pvc worlds-host-path
|
||||
FELIS_IMAGE=reg/felis:test FELIS_PANEL_NODEPORT=30443 NODE_IP=10.0.0.5 \
|
||||
FELIS_BACKUP_PVC="$1" FELIS_WORLDS_HOST_PATH="$2" FELIS_ARCHIVE_LOCAL_PATH=/var/lib/felis/archives \
|
||||
HOST_BIN=myManifests bash -c '
|
||||
log() { :; }
|
||||
kube() { cat; }
|
||||
myManifests() { printf "%s\n" "$@"; }
|
||||
run_bundle() {
|
||||
'"$mblock"'
|
||||
}
|
||||
run_bundle'
|
||||
}
|
||||
|
||||
out="$(run_bundle_flags felis-backups '')"
|
||||
expect "a default install asks the renderer for the archive PVC" "--backup-pvc
|
||||
felis-backups" "$out"
|
||||
case "$out" in
|
||||
*--worlds-host-path*) echo "FAIL: no reaper flags may render without FELIS_WORLDS_HOST_PATH"; fails=$((fails + 1)) ;;
|
||||
esac
|
||||
|
||||
out="$(run_bundle_flags '' '')"
|
||||
expect "an emptied FELIS_BACKUP_PVC is the explicit no-backup shape" "--backup-pvc=" "$out"
|
||||
|
||||
out="$(run_bundle_flags felis-backups /var/lib/rancher/k3s/storage)"
|
||||
expect "enabling retention passes the worlds root" "--worlds-host-path
|
||||
/var/lib/rancher/k3s/storage" "$out"
|
||||
expect "enabling retention passes the archive mount that must match felis.toml" "--archive-local-path
|
||||
/var/lib/felis/archives" "$out"
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
if [ "$fails" -eq 0 ]; then
|
||||
echo "ALL PASS"
|
||||
|
||||
Reference in new issue
Block a user