From 09033f4bc940148f6ad78c20baa72fde500645ac Mon Sep 17 00:00:00 2001 From: Luke Policinski Date: Sun, 1 Nov 2026 06:53:28 -0500 Subject: [PATCH] feature: update.sh can be run by the 5Stack service - labels the node with the release version when there is no .git - stops instead of waiting when it would ask for a Steam key with no terminal - leaves Vault to the 5Stack service when it runs update.sh - lets the 5Stack service check each rendered overlay before it is applied --- .github/workflows/panel-scripts.yml | 1 + tests/scripts/apply_overlay_test.sh | 68 +++++++++++++++++++++++++++++ tests/scripts/setup_env_test.sh | 46 +++++++++++++++++++ update.sh | 2 +- utils/apply_overlay.sh | 7 +++ utils/setup-env.sh | 3 +- utils/setup_steam_web_api_key.sh | 4 +- 7 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 tests/scripts/apply_overlay_test.sh diff --git a/.github/workflows/panel-scripts.yml b/.github/workflows/panel-scripts.yml index d3090c6..6571065 100644 --- a/.github/workflows/panel-scripts.yml +++ b/.github/workflows/panel-scripts.yml @@ -42,6 +42,7 @@ jobs: - uses: actions/checkout@v4 - run: shellcheck -x utils/ensure_auth_cookie_domain.sh utils/ensure_node_ip.sh utils/dev_game_server.sh utils/gpu_nodes.sh tests/scripts/*.sh tests/scripts/stub/kubectl - run: bash tests/scripts/setup_env_test.sh + - run: bash tests/scripts/apply_overlay_test.sh - run: bash tests/scripts/debug_test.sh - run: bash tests/scripts/startup_probe_test.sh - run: bash tests/scripts/system_upgrade_test.sh diff --git a/tests/scripts/apply_overlay_test.sh b/tests/scripts/apply_overlay_test.sh new file mode 100644 index 0000000..c446755 --- /dev/null +++ b/tests/scripts/apply_overlay_test.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# shellcheck source=tests/scripts/lib.sh +source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" + +RENDERED='apiVersion: v1 +kind: ConfigMap +metadata: + name: example' + +setup_stubs() { + PANEL_DIR="$WORK_DIR/panel" + mkdir -p "$PANEL_DIR/overlay" "$WORK_DIR/bin" + printf '#!/bin/sh\ncat <"$PANEL_DIR/kustomize" + cat >"$WORK_DIR/bin/kubectl" <>"$WORK_DIR/kubectl-calls" +if [ "\$1" = apply ]; then cp "\$3" "$WORK_DIR/applied"; fi +EOF + chmod +x "$PANEL_DIR/kustomize" "$WORK_DIR/bin/kubectl" + export PATH="$WORK_DIR/bin:$PATH" PANEL_DIR KUBECONFIG="" +} + +hook() { + cat >"$WORK_DIR/pre-apply" <"$WORK_DIR/output" 2>&1 +} + +test_an_apply_without_the_5stack_service_goes_straight_to_kubectl() { + setup_stubs + run_apply || fail "apply_overlay exited $?: $(cat "$WORK_DIR/output")" + assert_eq "$(cat "$WORK_DIR/applied")" "$RENDERED" +} + +test_the_5stack_service_sees_the_rendered_overlay_before_it_is_applied() { + setup_stubs + hook 0 "no rollout without zero downtime" + run_apply || fail "apply_overlay exited $?: $(cat "$WORK_DIR/output")" + assert_eq "$(cat "$WORK_DIR/checked")" "$RENDERED" + assert_eq "$(cat "$WORK_DIR/applied")" "$RENDERED" +} + +test_the_5stack_service_can_stop_an_apply() { + setup_stubs + hook 1 "the panel did not drain within 30 minutes" + run_apply && fail "apply_overlay carried on after the 5Stack service refused" + [ ! -e "$WORK_DIR/kubectl-calls" ] || fail "kubectl ran: $(cat "$WORK_DIR/kubectl-calls")" + assert_contains "$(cat "$WORK_DIR/output")" "the 5Stack service stopped overlay from being applied" + assert_contains "$(cat "$WORK_DIR/output")" "the panel did not drain within 30 minutes" +} + +run_tests diff --git a/tests/scripts/setup_env_test.sh b/tests/scripts/setup_env_test.sh index 1761362..36b2229 100644 --- a/tests/scripts/setup_env_test.sh +++ b/tests/scripts/setup_env_test.sh @@ -181,4 +181,50 @@ test_custom_ports_move_from_nginx_config_env_to_traefik_config_env() { [ ! -e "$PANEL/overlays/config/nginx-config.env" ] || fail "nginx-config.env was left behind" } +test_a_missing_steam_key_with_no_terminal_stops_instead_of_waiting() { + make_panel + set_sibling_domains + set_env overlays/local-secrets/steam-secrets.env STEAM_WEB_API_KEY "" + bash -c 'source "$1/utils/utils.sh"' _ "$PANEL" "$WORK_DIR/setup-output" 2>&1 & + local pid=$! ticks=0 status + while kill -0 "$pid" 2>/dev/null; do + if [ "$ticks" -ge 100 ]; then + kill "$pid" + fail "setup-env.sh kept waiting for a Steam key with nothing to read from" + fi + sleep 0.1 + ticks=$((ticks + 1)) + done + wait "$pid" + status=$? + [ "$status" -ne 0 ] || fail "setup-env.sh carried on without a Steam key" + assert_contains "$(cat "$WORK_DIR/setup-output")" "has no STEAM_WEB_API_KEY" +} + +use_vault() { + sed 's/^VAULT_MANAGER=false$/VAULT_MANAGER=true/' "$PANEL/.5stack-env.config" >"$PANEL/.5stack-env.config.tmp" + mv "$PANEL/.5stack-env.config.tmp" "$PANEL/.5stack-env.config" + mkdir -p "$WORK_DIR/bin" + printf '#!/bin/sh\necho "$*" >>"%s/vault-calls"\nexit 1\n' "$WORK_DIR" >"$WORK_DIR/bin/vault" + chmod +x "$WORK_DIR/bin/vault" + export PATH="$WORK_DIR/bin:$PATH" +} + +test_the_5stack_service_runs_a_vault_install_without_the_vault_cli() { + make_panel + set_sibling_domains + use_vault + FIVESTACK_RELEASE=2026.11.1.1 run_setup_env + [ ! -e "$WORK_DIR/vault-calls" ] || fail "setup-env.sh called vault: $(cat "$WORK_DIR/vault-calls")" +} + +test_update_sh_on_a_vault_install_still_checks_the_vault_login() { + make_panel + set_sibling_domains + use_vault + bash -c 'source "$1/utils/utils.sh"' _ "$PANEL" "$WORK_DIR/setup-output" 2>&1 && fail "setup-env.sh carried on without a Vault login" + assert_contains "$(cat "$WORK_DIR/vault-calls")" "status" + assert_contains "$(cat "$WORK_DIR/setup-output")" "Not logged into vault" +} + run_tests diff --git a/update.sh b/update.sh index 53d9135..fdea13a 100755 --- a/update.sh +++ b/update.sh @@ -135,7 +135,7 @@ step "Updating the TimescaleDB extension" update_timescaledb_extension finish_timescaledb_major_upgrade -GIT_SHA=$(git rev-parse HEAD) +GIT_SHA="${FIVESTACK_RELEASE:-$(git rev-parse HEAD)}" kubectl --kubeconfig=$KUBECONFIG label node $(kubectl --kubeconfig=$KUBECONFIG get nodes --selector='node-role.kubernetes.io/control-plane' -o jsonpath='{.items[0].metadata.name}') 5stack-panel-version=$GIT_SHA --overwrite diff --git a/utils/apply_overlay.sh b/utils/apply_overlay.sh index 2c9ff35..1090a8d 100644 --- a/utils/apply_overlay.sh +++ b/utils/apply_overlay.sh @@ -125,6 +125,13 @@ apply_overlay() { return 1 fi + # Set by the 5Stack service: it checks what this apply changes and may hold new matches first. + if [ -n "${FIVESTACK_PRE_APPLY:-}" ] && ! output="$("$FIVESTACK_PRE_APPLY" "$rendered" 2>&1)"; then + err "the 5Stack service stopped $overlay from being applied:" + echo "$output" | sed 's/^/ /' >&2 + return 1 + fi + for ((attempt = 1; attempt <= attempts; attempt++)); do if output="$(kubectl "${kc[@]}" apply -f "$rendered" 2>&1)"; then if [ "$DEBUG" = true ]; then diff --git a/utils/setup-env.sh b/utils/setup-env.sh index 9d26405..f8786a4 100755 --- a/utils/setup-env.sh +++ b/utils/setup-env.sh @@ -351,7 +351,8 @@ fi setup_steam_web_api_key "overlays/local-secrets/steam-secrets.env" -if [ "$VAULT_MANAGER" = true ]; then +# The 5Stack service sets FIVESTACK_RELEASE and handles Vault itself; it asks before writing to it. +if [ "$VAULT_MANAGER" = true ] && [ -z "${FIVESTACK_RELEASE:-}" ]; then if ! command -v vault &> /dev/null; then echo "Error: vault CLI is not installed. Please install it first (https://developer.hashicorp.com/vault/install)." exit 1 diff --git a/utils/setup_steam_web_api_key.sh b/utils/setup_steam_web_api_key.sh index ad34bef..8f90202 100644 --- a/utils/setup_steam_web_api_key.sh +++ b/utils/setup_steam_web_api_key.sh @@ -12,7 +12,9 @@ setup_steam_web_api_key() { while [ -z "$STEAM_WEB_API_KEY" ]; do echo "Please enter your Steam Web API key (required for Steam authentication). Get one at: https://steamcommunity.com/dev/apikey" - read STEAM_WEB_API_KEY + if ! read -r STEAM_WEB_API_KEY; then + die "$secrets_file has no STEAM_WEB_API_KEY and there is no terminal to ask for one. Add it to that file and run this again." + fi done update_env_var "$secrets_file" "STEAM_WEB_API_KEY" "$STEAM_WEB_API_KEY"