68 lines
5.6 KiB
Bash
68 lines
5.6 KiB
Bash
#!/usr/bin/env bash
|
|
# R-1105 Part 1/2: restic 0.14.0 vs 0.18.1 on throwaway LOCAL repos (scratchpad only). No real store is touched.
|
|
# Usage: semantics.sh <out-dir>
|
|
set -u
|
|
S=<scratch>
|
|
OUT=${1:?out dir}; mkdir -p "$OUT"
|
|
W=$S/work; rm -rf "$W"; mkdir -p "$W"
|
|
export RESTIC_PASSWORD_FILE=$W/pw; head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n' > "$RESTIC_PASSWORD_FILE"
|
|
export RESTIC_CACHE_DIR=$W/cache
|
|
export TZ=UTC
|
|
# data: a unit-like tree + one 300 MB file so --json emits status lines mid-run
|
|
mkdir -p $W/src/unit/db-dumps $W/src/unit/volume-dumps $W/src/data
|
|
echo "select 1;" > $W/src/unit/db-dumps/app.sql; echo '{"v":1}' > $W/src/unit/manifest.json
|
|
head -c 300M /dev/urandom > $W/src/unit/volume-dumps/big.tar
|
|
echo hello > $W/src/data/file.txt; echo secret > $W/src/data/noread.txt; chmod 000 $W/src/data/noread.txt
|
|
|
|
for V in 0.14.0 0.18.1; do
|
|
R="$S/bin/restic-$V"; REPO=$W/repo-$V; O=$OUT/$V; mkdir -p $O
|
|
rr() { "$R" -r "$REPO" "$@"; }
|
|
{ echo "== $V"; "$R" version; } > $O/00-version.txt
|
|
rr init > $O/01-init.txt 2>&1; echo "rc=$?" >> $O/01-init.txt
|
|
rr init > $O/02-init-again.txt 2>&1; echo "rc=$?" >> $O/02-init-again.txt
|
|
# T2 --json progress (full stream kept; the big file forces mid-run status lines)
|
|
rr backup --tag felhom-offbox --tag app1 $W/src/unit --json > $O/10-backup-json.stdout 2> $O/10-backup-json.stderr; echo "rc=$?" > $O/10-backup-json.rc
|
|
# T1 a missing source path beside an existing one; a missing path alone; an unreadable file
|
|
rr backup --tag felhom-offbox --tag app1 $W/src/unit $W/src/nope > $O/11-missing-one.txt 2>&1; echo "rc=$?" >> $O/11-missing-one.txt
|
|
rr backup --tag felhom-offbox --tag app2 $W/src/nope > $O/12-missing-all.txt 2>&1; echo "rc=$?" >> $O/12-missing-all.txt
|
|
rr backup --tag felhom-offbox --tag app3 $W/src/data > $O/13-unreadable.txt 2>&1; echo "rc=$?" >> $O/13-unreadable.txt
|
|
# nightly (non-json) output of a normal run, combined — what resticStep sees
|
|
rr backup --tag felhom-offbox --tag app1 $W/src/unit > $O/14-backup-plain.txt 2>&1; echo "rc=$?" >> $O/14-backup-plain.txt
|
|
# T4 snapshots --json, combined stdout+stderr EXACTLY as the runner reads it; latest --tag
|
|
rr snapshots --json > $O/20-snapshots-json.combined 2>&1; echo "rc=$?" > $O/20.rc
|
|
rr snapshots latest --tag app1 --json > $O/21-snapshots-latest-tag.combined 2>&1; echo "rc=$?" > $O/21.rc
|
|
ID=$(rr snapshots latest --tag app1 --json 2>/dev/null | python3 -c 'import json,sys;print(json.load(sys.stdin)[0]["short_id"])')
|
|
# T5 stats
|
|
rr stats "$ID" --json > $O/22-stats-id.combined 2>&1; echo "rc=$?" > $O/22.rc
|
|
rr stats --mode raw-data --json > $O/23-stats-raw.combined 2>&1; echo "rc=$?" > $O/23.rc
|
|
# T6 restore --include --no-lock on a READ-ONLY repo (proves nothing is written); layout under target
|
|
chmod -R a-w "$REPO"
|
|
rr restore "$ID" --target $W/rs-$V --include $W/src/unit --no-lock > $O/30-restore-nolock-ro.txt 2>&1; echo "rc=$?" >> $O/30-restore-nolock-ro.txt
|
|
chmod -R u+w "$REPO"
|
|
(cd $W/rs-$V && find . -type f | sort; sha256sum .$W/src/unit/volume-dumps/big.tar $W/src/unit/volume-dumps/big.tar) > $O/31-restore-layout.txt 2>&1
|
|
rm -rf $W/rs-$V
|
|
rr restore latest --tag app1 --target $W/rl-$V > $O/32-restore-latest-tag.txt 2>&1; echo "rc=$?" >> $O/32-restore-latest-tag.txt
|
|
ls -la $REPO/locks >> $O/32-restore-latest-tag.txt; rm -rf $W/rl-$V
|
|
# T7 error texts: wrong password, no repo, lock held by a live (stopped) exclusive op
|
|
RESTIC_PASSWORD_FILE= RESTIC_PASSWORD=wrong rr cat config > $O/40-wrong-password.txt 2>&1 < /dev/null; echo "rc=$?" >> $O/40-wrong-password.txt
|
|
"$R" -r $W/does-not-exist cat config > $O/41-no-repo.txt 2>&1; echo "rc=$?" >> $O/41-no-repo.txt
|
|
rr prune > $O/42-prune-holder.txt 2>&1 & P=$!; for i in $(seq 1 50); do ls $REPO/locks 2>/dev/null | grep -q . && break; sleep 0.1; done; kill -STOP $P
|
|
rr backup --tag felhom-offbox --tag app1 $W/src/unit > $O/43-locked.txt 2>&1; echo "rc=$?" >> $O/43-locked.txt
|
|
rr unlock > $O/44-unlock-stale-only.txt 2>&1; echo "rc=$?" >> $O/44-unlock-stale-only.txt; ls $REPO/locks | wc -l >> $O/44-unlock-stale-only.txt
|
|
kill -CONT $P; wait $P; echo "rc=$?" >> $O/42-prune-holder.txt
|
|
# transport: sftp to a closed port; sftp with a refused key; rclone program over a dead ssh
|
|
"$R" -r sftp:nobody@127.0.0.1:/x -o sftp.command="ssh nobody@127.0.0.1 -p 1 -oBatchMode=yes -oConnectTimeout=3 -s sftp" cat config > $O/45-sftp-refused-port.txt 2>&1; echo "rc=$?" >> $O/45-sftp-refused-port.txt
|
|
ssh-keygen -q -t ed25519 -N '' -f $W/k-$V
|
|
"$R" -r sftp:nobody@127.0.0.1:/x -o sftp.command="ssh nobody@127.0.0.1 -p 22 -oBatchMode=yes -oConnectTimeout=3 -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oIdentitiesOnly=yes -i $W/k-$V -s sftp" cat config > $O/46-sftp-refused-key.txt 2>&1; echo "rc=$?" >> $O/46-sftp-refused-key.txt
|
|
"$R" -r rclone:x -o rclone.program="ssh -p 1 -oBatchMode=yes -oConnectTimeout=3 nobody@127.0.0.1 rclone" cat config > $O/47-rclone-dead-ssh.txt 2>&1; echo "rc=$?" >> $O/47-rclone-dead-ssh.txt
|
|
"$R" -r sftp:nobody@10.255.255.1:/x -o sftp.command="ssh nobody@10.255.255.1 -p 22 -oBatchMode=yes -oConnectTimeout=3 -s sftp" cat config > $O/48-sftp-unreachable.txt 2>&1; echo "rc=$?" >> $O/48-sftp-unreachable.txt
|
|
# T8 check: healthy, then one damaged pack, --read-data
|
|
rr check > $O/50-check-ok.txt 2>&1; echo "rc=$?" >> $O/50-check-ok.txt
|
|
cp -a $REPO $W/dmg-$V; PK=$(find $W/dmg-$V/data -type f -size +1M | head -1); chmod u+w "$PK"
|
|
printf 'XXXXXXXXXXXXXXXX' | dd of="$PK" bs=1 seek=4096 conv=notrunc 2>/dev/null
|
|
"$R" -r $W/dmg-$V check --read-data > $O/51-check-damaged.txt 2>&1; echo "rc=$?" >> $O/51-check-damaged.txt
|
|
chmod -R u+w $W/dmg-$V; rm -rf $W/dmg-$V
|
|
done
|
|
chmod -R u+w $W
|
|
echo done
|