Ensure end time is recorded for unsuccessful runs too (#62)

* Ensure end time is also recorded for unsuccessful runs

* Clean up integration tests
This commit is contained in:
Frederik Ring 2022-02-13 09:41:36 +01:00 committed by GitHub
parent 0e248010a8
commit 3e17d1b123
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 53 additions and 50 deletions

View File

@ -88,8 +88,6 @@ func main() {
s.must(s.encryptBackup()) s.must(s.encryptBackup())
s.must(s.copyBackup()) s.must(s.copyBackup())
s.must(s.pruneOldBackups()) s.must(s.pruneOldBackups())
s.stats.EndTime = time.Now()
s.stats.TookTime = s.stats.EndTime.Sub(s.stats.EndTime)
} }
// script holds all the stateful information required to orchestrate a // script holds all the stateful information required to orchestrate a
@ -191,8 +189,6 @@ type Config struct {
WebdavPassword string `split_words:"true"` WebdavPassword string `split_words:"true"`
} }
var msgBackupFailed = "backup run failed"
// newScript creates all resources needed for the script to perform actions against // newScript creates all resources needed for the script to perform actions against
// remote resources like the Docker engine or remote storage locations. All // remote resources like the Docker engine or remote storage locations. All
// reading from env vars or other configuration sources is expected to happen // reading from env vars or other configuration sources is expected to happen
@ -214,6 +210,12 @@ func newScript() (*script, error) {
}, },
} }
s.registerHook(hookLevelPlumbing, func(error) error {
s.stats.EndTime = time.Now()
s.stats.TookTime = s.stats.EndTime.Sub(s.stats.EndTime)
return nil
})
if err := envconfig.Process("", s.c); err != nil { if err := envconfig.Process("", s.c); err != nil {
return nil, fmt.Errorf("newScript: failed to process configuration values: %w", err) return nil, fmt.Errorf("newScript: failed to process configuration values: %w", err)
} }

View File

@ -7,6 +7,8 @@ cd $(dirname $0)
docker network create test_network docker network create test_network
docker volume create backup_data docker volume create backup_data
docker volume create app_data docker volume create app_data
# This volume is created to test whether empty directories are handled
# correctly. It is not supposed to hold any data.
docker volume create empty_data docker volume create empty_data
docker run -d \ docker run -d \
@ -48,8 +50,10 @@ docker run --rm -it \
-v backup_data:/data alpine \ -v backup_data:/data alpine \
ash -c 'tar -xvf /data/backup/test.tar.gz && test -f /backup/app_data/offen.db && test -d /backup/empty_data' ash -c 'tar -xvf /data/backup/test.tar.gz && test -f /backup/app_data/offen.db && test -d /backup/empty_data'
echo "[TEST:PASS] Found relevant files in untared backup." echo "[TEST:PASS] Found relevant files in untared remote backup."
# This test does not stop containers during backup. This is happening on
# purpose in order to cover this setup as well.
if [ "$(docker ps -q | wc -l)" != "2" ]; then if [ "$(docker ps -q | wc -l)" != "2" ]; then
echo "[TEST:FAIL] Expected all containers to be running post backup, instead seen:" echo "[TEST:FAIL] Expected all containers to be running post backup, instead seen:"
docker ps docker ps

View File

@ -9,9 +9,20 @@ mkdir -p local
docker-compose up -d docker-compose up -d
sleep 5 sleep 5
# A symlink for a known file in the volume is created so the test can check
# whether symlinks are preserved on backup.
docker-compose exec offen ln -s /var/opt/offen/offen.db /var/opt/offen/db.link docker-compose exec offen ln -s /var/opt/offen/offen.db /var/opt/offen/db.link
docker-compose exec backup backup docker-compose exec backup backup
sleep 5
if [ "$(docker-compose ps -q | wc -l)" != "4" ]; then
echo "[TEST:FAIL] Expected all containers to be running post backup, instead seen:"
docker-compose ps
exit 1
fi
echo "[TEST:PASS] All containers running post backup."
docker run --rm -it \ docker run --rm -it \
-v compose_minio_backup_data:/minio_data \ -v compose_minio_backup_data:/minio_data \
-v compose_webdav_backup_data:/webdav_data alpine \ -v compose_webdav_backup_data:/webdav_data alpine \
@ -19,23 +30,17 @@ docker run --rm -it \
echo 1234secret | gpg -d --pinentry-mode loopback --passphrase-fd 0 --yes /minio_data/backup/test-hostnametoken.tar.gz.gpg > /tmp/test-hostnametoken.tar.gz && tar -xf /tmp/test-hostnametoken.tar.gz -C /tmp && test -f /tmp/backup/app_data/offen.db && \ echo 1234secret | gpg -d --pinentry-mode loopback --passphrase-fd 0 --yes /minio_data/backup/test-hostnametoken.tar.gz.gpg > /tmp/test-hostnametoken.tar.gz && tar -xf /tmp/test-hostnametoken.tar.gz -C /tmp && test -f /tmp/backup/app_data/offen.db && \
echo 1234secret | gpg -d --pinentry-mode loopback --passphrase-fd 0 --yes /webdav_data/data/my/new/path/test-hostnametoken.tar.gz.gpg > /tmp/test-hostnametoken.tar.gz && tar -xf /tmp/test-hostnametoken.tar.gz -C /tmp && test -f /tmp/backup/app_data/offen.db' echo 1234secret | gpg -d --pinentry-mode loopback --passphrase-fd 0 --yes /webdav_data/data/my/new/path/test-hostnametoken.tar.gz.gpg > /tmp/test-hostnametoken.tar.gz && tar -xf /tmp/test-hostnametoken.tar.gz -C /tmp && test -f /tmp/backup/app_data/offen.db'
echo "[TEST:PASS] Found relevant files in untared remote backups." echo "[TEST:PASS] Found relevant files in decrypted and untared remote backups."
test -L ./local/test-hostnametoken.latest.tar.gz.gpg
echo 1234secret | gpg -d --yes --passphrase-fd 0 ./local/test-hostnametoken.tar.gz.gpg > ./local/decrypted.tar.gz echo 1234secret | gpg -d --yes --passphrase-fd 0 ./local/test-hostnametoken.tar.gz.gpg > ./local/decrypted.tar.gz
tar -xf ./local/decrypted.tar.gz -C /tmp && test -f /tmp/backup/app_data/offen.db tar -xf ./local/decrypted.tar.gz -C /tmp && test -f /tmp/backup/app_data/offen.db
rm ./local/decrypted.tar.gz rm ./local/decrypted.tar.gz
test -L /tmp/backup/app_data/db.link test -L /tmp/backup/app_data/db.link
echo "[TEST:PASS] Found relevant files in untared local backup." echo "[TEST:PASS] Found relevant files in decrypted and untared local backup."
if [ "$(docker-compose ps -q | wc -l)" != "4" ]; then test -L ./local/test-hostnametoken.latest.tar.gz.gpg
echo "[TEST:FAIL] Expected all containers to be running post backup, instead seen:" echo "[TEST:PASS] Found symlink to latest version in local backup."
docker-compose ps
exit 1
fi
echo "[TEST:PASS] All containers running post backup."
# The second part of this test checks if backups get deleted when the retention # The second part of this test checks if backups get deleted when the retention
# is set to 0 days (which it should not as it would mean all backups get deleted) # is set to 0 days (which it should not as it would mean all backups get deleted)
@ -56,8 +61,8 @@ echo "[TEST:PASS] Remote backups have not been deleted."
if [ "$(find ./local -type f | wc -l)" != "1" ]; then if [ "$(find ./local -type f | wc -l)" != "1" ]; then
echo "[TEST:FAIL] Backups should not have been deleted, instead seen:" echo "[TEST:FAIL] Backups should not have been deleted, instead seen:"
find ./local -type f find ./local -type f
exit 1
fi fi
echo "[TEST:PASS] Local backups have not been deleted." echo "[TEST:PASS] Local backups have not been deleted."
docker-compose down --volumes docker-compose down --volumes

View File

@ -9,7 +9,7 @@ services:
BACKUP_CRON_EXPRESSION: 0 0 5 31 2 ? BACKUP_CRON_EXPRESSION: 0 0 5 31 2 ?
BACKUP_PRUNING_PREFIX: test BACKUP_PRUNING_PREFIX: test
NOTIFICATION_LEVEL: info NOTIFICATION_LEVEL: info
NOTIFICATION_URLS: gotify://gotify/${GOTIFY_TOKEN}?disableTLS=true NOTIFICATION_URLS: ${NOTIFICATION_URLS}
volumes: volumes:
- ./local:/archive - ./local:/archive
- app_data:/backup/app_data:ro - app_data:/backup/app_data:ro

View File

@ -10,49 +10,43 @@ docker-compose up -d
sleep 5 sleep 5
GOTIFY_TOKEN=$(curl -sSLX POST -H 'Content-Type: application/json' -d '{"name":"test"}' http://admin:custom@localhost:8080/application | jq -r '.token') GOTIFY_TOKEN=$(curl -sSLX POST -H 'Content-Type: application/json' -d '{"name":"test"}' http://admin:custom@localhost:8080/application | jq -r '.token')
docker-compose down
GOTIFY_TOKEN=$GOTIFY_TOKEN docker-compose up -d
echo "[TEST:INFO] Set up Gotify application using token $GOTIFY_TOKEN" echo "[TEST:INFO] Set up Gotify application using token $GOTIFY_TOKEN"
docker-compose exec backup backup docker-compose exec backup backup
tar -xf ./local/test.tar.gz -C /tmp && test -f /tmp/backup/app_data/offen.db NUM_MESSAGES=$(curl -sSL http://admin:custom@localhost:8080/message | jq -r '.messages | length')
echo "[TEST:PASS] Found relevant files in untared local backup." if [ "$NUM_MESSAGES" != 0 ]; then
echo "[TEST:FAIL] Expected no notifications to be sent when not configured"
if [ "$(docker-compose ps -q | wc -l)" != "3" ]; then
echo "[TEST:FAIL] Expected all containers to be running post backup, instead seen:"
docker-compose ps
exit 1 exit 1
fi fi
echo "[TEST:PASS] No notifications were sent when not configured."
echo "[TEST:PASS] All containers running post backup." docker-compose down
MESSAGE=$(curl -sSL http://admin:custom@localhost:8080/message | jq -r '.messages[0]') NOTIFICATION_URLS="gotify://gotify/${GOTIFY_TOKEN}?disableTLS=true" docker-compose up -d
docker-compose exec backup backup
case "$MESSAGE" in NUM_MESSAGES=$(curl -sSL http://admin:custom@localhost:8080/message | jq -r '.messages | length')
*"Successful test run, yay!"*) if [ "$NUM_MESSAGES" != 1 ]; then
echo "[TEST:PASS] Custom notification title was used" echo "[TEST:FAIL] Expected one notifications to be sent when configured"
;;
*)
echo "[TEST:FAIL] Expected custom title to be used in notification, instead seen:"
echo $MESSAGE
exit 1 exit 1
;; fi
esac echo "[TEST:PASS] Correct number of notifications were sent when configured."
case "$MESSAGE" in MESSAGE_TITLE=$(curl -sSL http://admin:custom@localhost:8080/message | jq -r '.messages[0].title')
*"Backing up /tmp/test.tar.gz succeeded."*) MESSAGE_BODY=$(curl -sSL http://admin:custom@localhost:8080/message | jq -r '.messages[0].message')
echo "[TEST:PASS] Custom notification body was used"
;; if [ "$MESSAGE_TITLE" != "Successful test run, yay!" ]; then
*) echo "[TEST:FAIL] Unexpected notification title $MESSAGE_TITLE"
echo "[TEST:FAIL] Expected custom body to be used in notification, instead seen:"
echo $MESSAGE
exit 1 exit 1
;; fi
esac echo "[TEST:PASS] Custom notification title was used."
if [ "$MESSAGE_BODY" != "Backing up /tmp/test.tar.gz succeeded." ]; then
echo "[TEST:FAIL] Unexpected notification body $MESSAGE_BODY"
exit 1
fi
echo "[TEST:PASS] Custom notification body was used."
docker-compose down --volumes docker-compose down --volumes

View File

@ -29,9 +29,7 @@ if [ "$(docker ps -q | wc -l)" != "5" ]; then
docker ps -a docker ps -a
exit 1 exit 1
fi fi
echo "[TEST:PASS] All containers running post backup." echo "[TEST:PASS] All containers running post backup."
docker stack rm test_stack docker stack rm test_stack
docker swarm leave --force docker swarm leave --force