Skip to content

Commit

Permalink
warn on check failure - fixes #43
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronhurt committed Aug 31, 2024
1 parent 4ca0684 commit 9accb04
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 41 deletions.
116 changes: 89 additions & 27 deletions test/test.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env dash
# shellcheck disable=SC2030,SC2031
# shellcheck disable=SC2030,SC2031,SC2034
## ^^ tests are intentionally run in subshells
## variables that appear unused here are used by main script

## test.sh contains zfs-replicate test cases
set -eu ## fail on errors and undefined variables
Expand All @@ -16,7 +17,6 @@ SCRIPT_PATH="${0%/*}"
_fail() {
line=$1
match=$2
## verbose testing
## hack to match blank lines
if [ "$match" = "null" ] && [ -n "$line" ]; then
printf "FAILED '%s' != ''\n" "$line" && exit 1
Expand All @@ -30,44 +30,35 @@ _fail() {

_testZFSReplicate() {
## wrapper for easy matching
export ECHO="echo"
## define test conditions
export FIND="${SCRIPT_PATH}/find.sh"
export ZFS="${SCRIPT_PATH}/zfs.sh"
export SSH="${SCRIPT_PATH}/ssh.sh"
export HOST_CHECK="${ECHO} %HOST%"
export SYSLOG=0
REPLICATE_SETS="srcPool0/srcFS0:dstPool0/dstFS0"
REPLICATE_SETS="${REPLICATE_SETS} srcPool1/srcFS1/subFS1:dstPool1/dstFS1@dstHost1"
REPLICATE_SETS="${REPLICATE_SETS} srcPool2/srcFS2:dstPool2/dstFS2@dstHost2"
REPLICATE_SETS="${REPLICATE_SETS} srcPool3/srcFS3@srcHost3:dstPool3/dstFS3"
REPLICATE_SETS="${REPLICATE_SETS} srcPool4/srcFS4@srcHost4:dstPool4/dstFS4@dstHost4"
ECHO="echo"
## disable syslog for tests
SYSLOG=0

## test loadConfig
(
## source script functions
# shellcheck source=/dev/null
. ../zfs-replicate.sh
printf "_testSetsNoConfig/loadConfig\n" ## we expect no output and clean exit
printf "_testZFSReplicate/loadConfigWithError\n"
loadConfig | awk '{ print NR-1, $0 }' | while read -r idx line; do
printf "%d %s\n" "$idx" "$line"
case $idx in
*)
_fail "$line" "null"
0)
_fail "$line" "missing required setting REPLICATE_SETS"
;;
esac
done
)

## test config override
## test config override of script defaults
(
## likely default values at script load time
FIND="/usr/bin/find"
ZFS="/sbin/zfs"
SSH="/usr/sbin/ssh"
## source script functions
REPLICATE_SETS="fakeSource:fakeDest"
# shellcheck source=/dev/null
. ../zfs-replicate.sh
printf "_testSetsNoConfig/loadConfigOverrideDefaults\n"
printf "_testZFSReplicate/loadConfigOverrideDefaults\n"
_fail "/usr/sbin/ssh %HOST% /sbin/zfs receive -vFd" "$DEST_PIPE_WITH_HOST"
_fail "/sbin/zfs receive -vFd" "$DEST_PIPE_WITHOUT_HOST"
## generate config
Expand All @@ -81,12 +72,21 @@ _testZFSReplicate() {
_fail "myZFS receive -vFd" "$DEST_PIPE_WITHOUT_HOST"
)

## test snapCreate
## test snapCreate with different set combinations
(
## source script functions
## configure test parameters
FIND="${SCRIPT_PATH}/find.sh"
ZFS="${SCRIPT_PATH}/zfs.sh"
SSH="${SCRIPT_PATH}/ssh.sh"
HOST_CHECK="${ECHO} %HOST%"
REPLICATE_SETS="srcPool0/srcFS0:dstPool0/dstFS0"
REPLICATE_SETS="${REPLICATE_SETS} srcPool1/srcFS1/subFS1:dstPool1/dstFS1@dstHost1"
REPLICATE_SETS="${REPLICATE_SETS} srcPool2/srcFS2:dstPool2/dstFS2@dstHost2"
REPLICATE_SETS="${REPLICATE_SETS} srcPool3/srcFS3@srcHost3:dstPool3/dstFS3"
REPLICATE_SETS="${REPLICATE_SETS} srcPool4/srcFS4@srcHost4:dstPool4/dstFS4@dstHost4"
# shellcheck source=/dev/null
. ../zfs-replicate.sh && loadConfig
printf "_testSetsNoConfig/snapCreate\n"
printf "_testZFSReplicate/snapCreateWithoutErrors\n"
snapCreate | awk '{ print NR-1, $0 }' | while read -r idx line; do
match=""
printf "%d %s\n" "$idx" "$line"
Expand Down Expand Up @@ -221,24 +221,86 @@ _testZFSReplicate() {
done
)

## test exitClean
## test snapCreate with host check errors
(
## configure test parameters
FIND="${SCRIPT_PATH}/find.sh"
ZFS="${SCRIPT_PATH}/zfs.sh"
SSH="${SCRIPT_PATH}/ssh.sh"
HOST_CHECK="false"
REPLICATE_SETS="srcPool0/srcFS0:dstPool0/dstFS0"
REPLICATE_SETS="${REPLICATE_SETS} srcPool1/srcFS1/subFS1:dstPool1/dstFS1@dstHost1"
REPLICATE_SETS="${REPLICATE_SETS} srcPool2/srcFS2:dstPool2/dstFS2@dstHost2"
REPLICATE_SETS="${REPLICATE_SETS} srcPool3/srcFS3@srcHost3:dstPool3/dstFS3"
REPLICATE_SETS="${REPLICATE_SETS} srcPool4/srcFS4@srcHost4:dstPool4/dstFS4@dstHost4"
# shellcheck source=/dev/null
. ../zfs-replicate.sh && loadConfig
printf "_testZFSReplicate/snapCreateWithHostCheckErrors\n"
snapCreate | awk '{ print NR-1, $0 }' | while read -r idx line; do
match=""
printf "%d %s\n" "$idx" "$line"
case $idx in
17)
match="source or destination host check failed"
;;
19)
match="source or destination host check failed"
;;
21)
match="source or destination host check failed"
;;
23)
match="source or destination host check failed"
;;
esac
_fail "$line" "$match"
done
)

## test exitClean code=0 and extra message
(
FIND="fakeFIND"
ZFS="fakeZFS"
SSH="fakeSSH"
REPLICATE_SETS="fakeSource:fakeDest"
## source script functions
# shellcheck source=/dev/null
. ../zfs-replicate.sh && loadConfig
printf "_testSetsNoConfig/exitClean\n"
printf "_testZFSReplicate/exitCleanSuccess\n"
exitClean 0 "test message" | awk '{ print NR-1, $0 }' | while read -r idx line; do
printf "%d %s\n" "$idx" "$line"
case $idx in
0)
match="success total sets 0 skipped 0: test message"
match="success total sets 0 skipped 0: test message" ## counts in test are always zero
_fail "$line" "$match"
;;
esac
done
)

## test exitClean code=99 with error message
(
FIND="fakeFIND"
ZFS="fakeZFS"
SSH="fakeSSH"
REPLICATE_SETS="fakeSource:fakeDest"
## source script functions
# shellcheck source=/dev/null
. ../zfs-replicate.sh && loadConfig
printf "_testZFSReplicate/exitCleanError\n"
exitClean 99 "error message" | awk '{ print NR-1, $0 }' | while read -r idx line; do
printf "%d %s\n" "$idx" "$line"
case $idx in
0)
match="operation exited unexpectedly: code=99 msg=error message"
_fail "$line" "$match"
;;
esac
done
)

## yay, tests completed!
printf "Tests Complete: No Error!\n"
return 0
}

Expand Down
40 changes: 26 additions & 14 deletions zfs-replicate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ __SKIP_COUNT=0
sortLogs() {
## check if file logging is enabled
if [ -z "$LOG_BASE" ] || [ ! -d "$LOG_BASE" ]; then
return
return 0
fi
## find existing logs
logs=$($FIND "$LOG_BASE" -maxdepth 1 -type f -name 'autorep-*')
Expand Down Expand Up @@ -147,15 +147,19 @@ checkLock() {
checkHost() {
## do we have a host check defined
if [ -z "$HOST_CHECK" ]; then
return
return 0
fi
host=$1
if [ -z "$host" ]; then
return 0
fi
cmd=$(printf "%s\n" "$HOST_CHECK" | sed "s/%HOST%/$host/g")
printf "checking host cmd=%s\n" "$cmd"
## run the check
if ! $cmd > /dev/null 2>&1; then
exitClean 128 "host check failed"
return 1
fi
return 0
}

## ensure dataset exists
Expand All @@ -171,8 +175,9 @@ checkDataset() {
printf "checking dataset cmd=%s\n" "$cmd"
## execute command
if ! $cmd; then
exitClean 128 "failed to list dataset: $set"
return 1
fi
return 0
}

## small wrapper around zfs destroy
Expand Down Expand Up @@ -271,29 +276,36 @@ snapCreate() {
if [ "$ALLOW_ROOT_DATASETS" -ne 1 ]; then
if [ "$dst" = "$(basename "$dst")" ] || [ "$dst" = "$(basename "$dst")/" ]; then
temps="replicating root datasets can lead to data loss - set ALLOW_ROOT_DATASETS=1 to override"
printf "WARNING: %s\n" "$temps"
printf "WARNING: skipping replication set '%s' - %s\n" "$pair" "$temps"
__SKIP_COUNT=$((__SKIP_COUNT + 1))
continue
fi
fi
## init source and destination host in each loop iteration
srcHost=""
dstHost=""
## look for host options on source and check host if found
## look for source host option
if [ "${src#*"@"}" != "$src" ]; then
srcHost=$(printf "%s\n" "$src" | cut -f2 -d@)
checkHost "$srcHost"
src=$(printf "%s\n" "$src" | cut -f1 -d@)
fi
## look for host options on destination and check host if found
## look for destination host option
if [ "${dst#*"@"}" != "$dst" ]; then
dstHost=$(printf "%s\n" "$dst" | cut -f2 -d@)
checkHost "$dstHost"
dst=$(printf "%s\n" "$dst" | cut -f1 -d@)
fi
## check source and destination hosts
if ! checkHost "$srcHost" || ! checkHost "$dstHost"; then
printf "WARNING: skipping replication set '%s' - source or destination host check failed\n" "$pair"
__SKIP_COUNT=$((__SKIP_COUNT + 1))
continue
fi
## check source and destination datasets
checkDataset "$src" "$srcHost"
checkDataset "$dst" "$dstHost"
if ! checkDataset "$src" "$srcHost" || ! checkDataset "$dst" "$dstHost"; then
printf "WARNING: skipping replication set '%s' - source or destination dataset check failed\n" "$pair"
__SKIP_COUNT=$((__SKIP_COUNT + 1))
continue
fi
## get source and destination snapshots
srcSnaps=$(snapList "$src" "$srcHost" 1)
dstSnaps=$(snapList "$dst" "$dstHost" 0)
Expand Down Expand Up @@ -508,9 +520,6 @@ loadConfig() {
if [ -n "$LOG_BASE" ] && [ ! -d "$LOG_BASE" ]; then
mkdir -p "$LOG_BASE"
fi
if [ -z "$FIND" ]; then
writeLog "ERROR: unable to locate system find binary" && exit 1
fi
## we have all we need for status
if [ "$status" -eq 1 ]; then
showStatus
Expand All @@ -525,6 +534,9 @@ loadConfig() {
if [ "$SNAP_KEEP" -lt 2 ]; then
writeLog "ERROR: a minimum of 2 snapshots are required for incremental sending" && exit 1
fi
if [ -z "$FIND" ]; then
writeLog "ERROR: unable to locate system find binary" && exit 1
fi
if [ -z "$SSH" ]; then
writeLog "ERROR: unable to locate system ssh binary" && exit 1
fi
Expand Down

0 comments on commit 9accb04

Please sign in to comment.