quality / changes (push) Successful in 7s
quality / commitlint (push) Skipped
quality / openapi (push) Successful in 27s
quality / web (push) Successful in 48s
quality / api (push) Successful in 1m13s
quality / linux-agent-smoke (push) Successful in 22s
quality / docker-check (push) Successful in 4m43s
CD / quality (push) Successful in 7m42s
CD / publish (push) Successful in 5m17s
52 lines
3.2 KiB
Bash
52 lines
3.2 KiB
Bash
#!/usr/bin/env sh
|
|
# No Docker daemon: verify actual restore transport, guards and exit propagation.
|
|
set -eu
|
|
wrapper="$(pwd)/deploy/docker/restore.sh"
|
|
tmp="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp"' EXIT HUP INT TERM
|
|
mkdir "$tmp/bin"
|
|
backup="$tmp/input backup.db"
|
|
printf 'synthetic backup' >"$backup"
|
|
cat >"$tmp/bin/docker" <<'DOCKER'
|
|
#!/usr/bin/env sh
|
|
set -eu
|
|
printf '%s\n' "$*" >>"$FAKE_LOG"
|
|
case "$1" in
|
|
volume) [ "$2" = inspect ]; exit 0 ;;
|
|
ps)
|
|
count=0; [ ! -f "$FAKE_COUNT" ] || count="$(cat "$FAKE_COUNT")"
|
|
count=$((count + 1)); printf '%s' "$count" >"$FAKE_COUNT"
|
|
if [ "$FAKE_CASE" = ps-initial-failure ] || { [ "$FAKE_CASE" = ps-later-failure ] && [ "$count" = 2 ]; }; then exit 29; fi
|
|
if [ "$FAKE_CASE" = live-initial ] || { [ "$FAKE_CASE" = live-later ] && [ "$count" = 2 ]; }; then printf 'other-writer\n'; fi ;;
|
|
create) printf 'helper-id\n' ;;
|
|
cp) [ "$2" = "$FAKE_BACKUP" ]; [ "$FAKE_CASE" != cp-failure ] || exit 17 ;;
|
|
start) [ "$FAKE_CASE" != start-failure ] || exit 19 ;;
|
|
wait) if [ "$FAKE_CASE" = restore-failure ]; then printf '23\n'; else printf '0\n'; fi ;;
|
|
rm) exit 0 ;;
|
|
*) echo 'Unexpected Docker operation in restore' >&2; exit 98 ;;
|
|
esac
|
|
DOCKER
|
|
chmod +x "$tmp/bin/docker"
|
|
for scenario in success cp-failure start-failure restore-failure live-initial live-later ps-initial-failure ps-later-failure; do
|
|
log="$tmp/$scenario.log"
|
|
if PATH="$tmp/bin:$PATH" FAKE_LOG="$log" FAKE_COUNT="$tmp/$scenario.count" FAKE_CASE="$scenario" FAKE_BACKUP="$backup" sh "$wrapper" image:immutable target-named-volume "$backup"; then actual=0; else actual=$?; fi
|
|
case "$scenario" in success) expected=0;; cp-failure) expected=17;; start-failure) expected=19;; restore-failure) expected=23;; ps-*-failure) expected=29;; *) expected=1;; esac
|
|
[ "$actual" = "$expected" ] || { echo "Unexpected status for $scenario: $actual" >&2; exit 1; }
|
|
grep -F 'volume inspect target-named-volume' "$log" >/dev/null
|
|
if grep -E -- '(type=bind|--privileged|--network host|docker.sock|^volume rm)' "$log" >/dev/null; then echo 'Restore must not use a host bind or remove the target volume' >&2; exit 1; fi
|
|
if [ "$scenario" = live-initial ] || [ "$scenario" = ps-initial-failure ]; then
|
|
if grep -E '^(create|cp|start) ' "$log" >/dev/null; then echo 'Active target must fail before helper creation' >&2; exit 1; fi
|
|
continue
|
|
fi
|
|
grep -E '^create --name evofw-restore-[^ ]+ --network none --cap-drop ALL --security-opt no-new-privileges:true --mount type=volume,src=target-named-volume,dst=/data --entrypoint node image:immutable tools/sqlite-backup.mjs restore /tmp/evofw-restore-input.db /data/app.db --offline$' "$log" >/dev/null
|
|
grep -E '^cp .*input backup.db evofw-restore-[^ ]+:/tmp/evofw-restore-input.db$' "$log" >/dev/null
|
|
grep -E '^rm -fv evofw-restore-' "$log" >/dev/null
|
|
if [ "$scenario" = cp-failure ] || [ "$scenario" = live-later ] || [ "$scenario" = ps-later-failure ]; then
|
|
if grep -E '^start ' "$log" >/dev/null; then echo 'Incomplete input or newly active target must never start restore' >&2; exit 1; fi
|
|
elif [ "$scenario" != start-failure ]; then
|
|
grep -E '^wait evofw-restore-' "$log" >/dev/null
|
|
[ "$(cat "$tmp/$scenario.count")" = 2 ]
|
|
fi
|
|
done
|
|
echo 'Restore wrapper regression passed (remote copy, offline guards, failures, cleanup)'
|