Add stackctl for running stacks by hand on a host
One shared script installed into /srv/stacks on every host, with per-host groups in server/<host>/stack-groups. Tested in check.sh. Also two new common mistakes in the adding-a-stack skill. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d28494d21f
commit
35b1378080
Executable
+115
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Tests for server/shared/components/stackctl, against a throwaway stack root and a stub
|
||||
# `docker` that records what it was asked to do instead of doing it.
|
||||
#
|
||||
# scripts/test-stackctl.sh
|
||||
#
|
||||
# Run by scripts/check.sh. Needs nothing but bash.
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
work="$(mktemp -d)"
|
||||
trap 'rm -rf "$work"' EXIT
|
||||
|
||||
root="$work/stacks"
|
||||
bin="$work/bin"
|
||||
log="$work/calls"
|
||||
mkdir -p "$root" "$bin"
|
||||
cp "$repo_root/server/shared/components/stackctl" "$root/stackctl"
|
||||
|
||||
for s in reverse-proxy openbao webapp grafana prometheus static-site wiki; do
|
||||
mkdir -p "$root/$s"
|
||||
touch "$root/$s/docker-compose.yml"
|
||||
done
|
||||
mkdir -p "$root/not-a-stack"
|
||||
|
||||
cat > "$root/stack-groups" <<'EOF'
|
||||
# a comment
|
||||
order: reverse-proxy openbao
|
||||
confirm: openbao
|
||||
|
||||
system: openbao webapp
|
||||
monitoring: grafana prometheus
|
||||
monitoring: ghost
|
||||
sites: static-site
|
||||
EOF
|
||||
|
||||
# Records "<stack> <args>" and fails for any stack named in $FAIL.
|
||||
cat > "$bin/docker" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
stack="$(basename "$PWD")"
|
||||
echo "$stack $*" >> "$STACKCTL_TEST_LOG"
|
||||
case " ${FAIL:-} " in *" $stack "*) exit 1 ;; esac
|
||||
if [ "$2" = ps ]; then printf 'running\nexited\n'; fi
|
||||
EOF
|
||||
chmod +x "$bin/docker"
|
||||
|
||||
export PATH="$bin:$PATH" STACKCTL_TEST_LOG="$log"
|
||||
|
||||
failures=0
|
||||
run() { : > "$log"; set +e; out="$("$root/stackctl" "$@" 2>&1 </dev/null)"; status=$?; set -e; }
|
||||
calls() { cut -d' ' -f1-3 "$log" | paste -sd, -; }
|
||||
check() {
|
||||
local name="$1" want="$2" got="$3"
|
||||
if [ "$want" = "$got" ]; then
|
||||
printf 'ok %s\n' "$name"
|
||||
else
|
||||
printf 'FAIL %s\n want: %s\n got: %s\n' "$name" "$want" "$got"
|
||||
failures=$((failures + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
run up all
|
||||
check "up all runs order first, then alphabetical" \
|
||||
"reverse-proxy compose up,openbao compose up,grafana compose up,prometheus compose up,static-site compose up,webapp compose up,wiki compose up" \
|
||||
"$(calls)"
|
||||
check "up all succeeds" 0 "$status"
|
||||
|
||||
run -y down all
|
||||
check "down reverses the order" \
|
||||
"wiki compose down,webapp compose down,static-site compose down,prometheus compose down,grafana compose down,openbao compose down,reverse-proxy compose down" \
|
||||
"$(calls)"
|
||||
|
||||
run up monitoring sites
|
||||
check "groups expand, and repeated lines append" \
|
||||
"grafana compose up,prometheus compose up,static-site compose up" "$(calls)"
|
||||
check "a missing group member is warned about" yes \
|
||||
"$(grep -q 'ghost' <<<"$out" && echo yes || echo no)"
|
||||
|
||||
run up grafana nope
|
||||
check "an unknown target runs nothing" "" "$(calls)"
|
||||
check "an unknown target fails" 2 "$status"
|
||||
|
||||
run up order
|
||||
check "reserved names are not targets" 2 "$status"
|
||||
|
||||
run down system
|
||||
check "down of a confirm stack without a TTY runs nothing" "" "$(calls)"
|
||||
check "down of a confirm stack without a TTY fails" 1 "$status"
|
||||
|
||||
run -y down system
|
||||
check "-y allows it" "webapp compose down,openbao compose down" "$(calls)"
|
||||
|
||||
run up openbao
|
||||
check "up of a confirm stack needs no confirmation" "openbao compose up" "$(calls)"
|
||||
|
||||
FAIL=webapp run up system
|
||||
check "a failing stack does not stop the rest" \
|
||||
"openbao compose up,webapp compose up" "$(calls)"
|
||||
check "a failing stack fails the run" 1 "$status"
|
||||
check "a failing stack is named at the end" yes \
|
||||
"$(tail -n1 <<<"$out" | grep -q webapp && echo yes || echo no)"
|
||||
|
||||
run logs grafana prometheus
|
||||
check "logs takes exactly one stack" 2 "$status"
|
||||
|
||||
run ps grafana
|
||||
check "ps counts running containers" yes \
|
||||
"$(grep -Eq 'grafana +1/2' <<<"$out" && echo yes || echo no)"
|
||||
|
||||
run frobnicate all
|
||||
check "an unknown command fails" 2 "$status"
|
||||
|
||||
[ "$failures" -eq 0 ] || { echo "$failures failed"; exit 1; }
|
||||
echo "all stackctl tests passed"
|
||||
Reference in New Issue
Block a user