Files
ThothII/scripts/test-vector-backup-restore-safety.sh
T

109 lines
4.0 KiB
Bash
Executable File

#!/bin/sh
set -eu
cd "$(dirname "$0")/.."
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT HUP INT TERM
fakebin="$tmp/bin"
mkdir "$fakebin"
project="thoth-task8"
volume_name="${project}_qdrant-data"
mountpoint="$tmp/docker-volumes/$volume_name/_data"
mkdir -p "$mountpoint/collections/demo"
printf '%s' before-backup >"$mountpoint/collections/demo/state.json"
cat >"$fakebin/docker" <<'SH'
#!/bin/sh
set -eu
log_file=${DOCKER_LOG:?}
printf '%s\n' "$*" >>"$log_file"
if [ "$1" = volume ] && [ "$2" = ls ]; then
if [ "${VOLUME_LS_OUTPUT:-}" = multiple ]; then
printf '%s\n%s\n' "${PROJECT_NAME}_qdrant-data" "${PROJECT_NAME}_qdrant-data-copy"
exit 0
fi
printf '%s\n' "${PROJECT_NAME}_qdrant-data"
exit 0
fi
if [ "$1" = volume ] && [ "$2" = inspect ]; then
printf '%s\n' "${MOUNTPOINT:?}"
exit 0
fi
if [ "$1" = compose ] && [ "$2" = --project-name ]; then
case "$4" in
ps)
if [ "${QDRANT_RUNNING:-1}" = 1 ]; then
printf '%s\n' qdrant-container
fi
exit 0
;;
stop)
exit 0
;;
start)
exit 0
;;
esac
fi
exit 0
SH
chmod 0755 "$fakebin/docker"
backup_output="$tmp/qdrant-backup.tar"
docker_log="$tmp/docker.log"
PATH="$fakebin:$PATH" DOCKER_LOG="$docker_log" PROJECT_NAME="$project" MOUNTPOINT="$mountpoint" \
./scripts/vector-backup.sh --project-name "$project" --output "$backup_output" >/dev/null
test -s "$backup_output"
tar -tf "$backup_output" | grep -q '^./collections/demo/state.json$'
grep -q "volume ls --filter label=com.docker.compose.project=$project --filter label=com.docker.compose.volume=qdrant-data" "$docker_log"
grep -q "compose --project-name $project ps --status running -q qdrant" "$docker_log"
grep -q "compose --project-name $project stop qdrant" "$docker_log"
grep -q "compose --project-name $project start qdrant" "$docker_log"
existing="$tmp/existing.tar"
printf '%s' sentinel >"$existing"
if PATH="$fakebin:$PATH" DOCKER_LOG="$tmp/existing.log" PROJECT_NAME="$project" MOUNTPOINT="$mountpoint" \
./scripts/vector-backup.sh --project-name "$project" --output "$existing" >"$tmp/existing.out" 2>"$tmp/existing.err"; then
echo "backup overwrote an existing archive" >&2
exit 1
fi
test "$(cat "$existing")" = sentinel
if PATH="$fakebin:$PATH" DOCKER_LOG="$tmp/ambiguous.log" PROJECT_NAME="$project" MOUNTPOINT="$mountpoint" VOLUME_LS_OUTPUT=multiple \
./scripts/vector-backup.sh --project-name "$project" --output "$tmp/ambiguous.tar" >"$tmp/ambiguous.out" 2>"$tmp/ambiguous.err"; then
echo "backup accepted an ambiguous qdrant-data target" >&2
exit 1
fi
grep -q 'exactly one qdrant-data volume' "$tmp/ambiguous.err"
restore_input="$tmp/restore.tar"
restore_source="$tmp/restore-source"
mkdir -p "$restore_source/collections/demo"
printf '%s' restored >"$restore_source/collections/demo/state.json"
tar -C "$restore_source" -cf "$restore_input" .
if PATH="$fakebin:$PATH" DOCKER_LOG="$tmp/restore-refuse.log" PROJECT_NAME="$project" MOUNTPOINT="$mountpoint" \
./scripts/vector-restore.sh --project-name "$project" --input "$restore_input" --confirm-project wrong-project \
>"$tmp/restore-refuse.out" 2>"$tmp/restore-refuse.err"; then
echo "restore skipped explicit project confirmation" >&2
exit 1
fi
grep -q 'confirmation must match --project-name exactly' "$tmp/restore-refuse.err"
test "$(cat "$mountpoint/collections/demo/state.json")" = before-backup
printf '%s' modified-live >"$mountpoint/collections/demo/state.json"
restore_log="$tmp/restore-ok.log"
PATH="$fakebin:$PATH" DOCKER_LOG="$restore_log" PROJECT_NAME="$project" MOUNTPOINT="$mountpoint" \
./scripts/vector-restore.sh --project-name "$project" --input "$restore_input" --confirm-project "$project" >/dev/null
test "$(cat "$mountpoint/collections/demo/state.json")" = restored
grep -q "compose --project-name $project stop qdrant" "$restore_log"
grep -q "compose --project-name $project start qdrant" "$restore_log"
grep -q "volume inspect --format {{ .Mountpoint }} $volume_name" "$restore_log"
echo "qdrant backup/restore target resolution, refusal, and service-state contracts passed."