From f4b9383c2a8622fc8dcf8c7a7c3e09c59d2bf390 Mon Sep 17 00:00:00 2001 From: ViViDboarder Date: Mon, 28 Jan 2019 11:58:58 -0800 Subject: [PATCH 1/3] Fix arm test target typo --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ee895db..5a37e72 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ test-x86: build-x86 .PHONY: test-arm test-arm: build-arm - cd tests && .test.sh $(DOCKER_TAG):raspbian + cd tests && ./test.sh $(DOCKER_TAG):raspbian .PHONY: test-all test-all: test-x86 test-arm From b2fd9d4259785b8604efbd8a00943bf12209c33c Mon Sep 17 00:00:00 2001 From: ViViDboarder Date: Thu, 27 Sep 2018 17:32:55 -0700 Subject: [PATCH 2/3] Add support for pre/post scripts Allows adding scripts to a directory to be executed before backups and after restorating. This can allow backing up a mysql dump or something. Using these could (and probably does) break verify checks Fixes #8 --- Dockerfile.raspbian | 6 ++ Dockerfile.ubuntu | 6 ++ Makefile | 2 + backup.sh | 15 ++++ restore.sh | 15 ++++ tests/test-pre-scripts.sh | 71 +++++++++++++++++++ .../backup/after/post-backup.sh | 6 ++ .../backup/before/pre-backup.sh | 6 ++ tests/test-pre-scripts/create-test-data.sql | 7 ++ .../restore/after/post-restore.sh | 6 ++ .../restore/before/pre-restore.sh | 3 + 11 files changed, 143 insertions(+) create mode 100755 tests/test-pre-scripts.sh create mode 100755 tests/test-pre-scripts/backup/after/post-backup.sh create mode 100755 tests/test-pre-scripts/backup/before/pre-backup.sh create mode 100644 tests/test-pre-scripts/create-test-data.sql create mode 100755 tests/test-pre-scripts/restore/after/post-restore.sh create mode 100755 tests/test-pre-scripts/restore/before/pre-restore.sh diff --git a/Dockerfile.raspbian b/Dockerfile.raspbian index c94ac05..9e039be 100644 --- a/Dockerfile.raspbian +++ b/Dockerfile.raspbian @@ -43,6 +43,12 @@ ENV CRON_SCHEDULE="" ENV FULL_CRON_SCHEDULE="" ENV VERIFY_CRON_SCHEDULE="" +# Create script dirs +RUN mkdir -p /scripts/backup/before +RUN mkdir -p /scripts/backup/after +RUN mkdir -p /scripts/restore/before +RUN mkdir -p /scripts/restore/after + ADD backup.sh / ADD restore.sh / ADD start.sh / diff --git a/Dockerfile.ubuntu b/Dockerfile.ubuntu index 05a030f..dce74a7 100644 --- a/Dockerfile.ubuntu +++ b/Dockerfile.ubuntu @@ -43,6 +43,12 @@ ENV CRON_SCHEDULE="" ENV FULL_CRON_SCHEDULE="" ENV VERIFY_CRON_SCHEDULE="" +# Create script dirs +RUN mkdir -p /scripts/backup/before +RUN mkdir -p /scripts/backup/after +RUN mkdir -p /scripts/restore/before +RUN mkdir -p /scripts/restore/after + ADD backup.sh / ADD restore.sh / ADD start.sh / diff --git a/Makefile b/Makefile index 5a37e72..1816e8c 100644 --- a/Makefile +++ b/Makefile @@ -20,10 +20,12 @@ build-all: build-x86 build-arm .PHONY: test-x86 test-x86: build-x86 cd tests && ./test.sh $(DOCKER_TAG):ubuntu + cd tests && ./test-pre-scripts.sh $(DOCKER_TAG):ubuntu .PHONY: test-arm test-arm: build-arm cd tests && ./test.sh $(DOCKER_TAG):raspbian + cd tests && ./test-pre-scripts.sh $(DOCKER_TAG):raspbian .PHONY: test-all test-all: test-x86 test-arm diff --git a/backup.sh b/backup.sh index 4473a4d..9115891 100755 --- a/backup.sh +++ b/backup.sh @@ -7,6 +7,13 @@ set -e exit 1 fi + # Run pre-backup scripts + for f in /scripts/backup/before/*; do + if [ -f $f -a -x $f ]; then + bash $f + fi + done + duplicity \ $1 \ --asynchronous-upload \ @@ -22,4 +29,12 @@ set -e --name $BACKUP_NAME \ $BACKUP_DEST fi + + # Run post-backup scripts + for f in /scripts/backup/after/*; do + if [ -f $f -a -x $f ]; then + bash $f + fi + done + ) 200>/var/lock/duplicity/.duplicity.lock diff --git a/restore.sh b/restore.sh index eec941f..fc2dec7 100755 --- a/restore.sh +++ b/restore.sh @@ -7,6 +7,13 @@ set -e exit 1 fi + # Run pre-restore scripts + for f in /scripts/restore/before/*; do + if [ -f $f -a -x $f ]; then + bash $f + fi + done + duplicity restore \ --force \ --log-file /root/duplicity.log \ @@ -15,4 +22,12 @@ set -e $@ \ $BACKUP_DEST \ $PATH_TO_BACKUP + + # Run post-restore scripts + for f in /scripts/restore/after/*; do + if [ -f $f -a -x $f ]; then + bash $f + fi + done + ) 200>/var/lock/duplicity/.duplicity.lock diff --git a/tests/test-pre-scripts.sh b/tests/test-pre-scripts.sh new file mode 100755 index 0000000..8482406 --- /dev/null +++ b/tests/test-pre-scripts.sh @@ -0,0 +1,71 @@ +#! /bin/bash +set -e + +image=$1 + +if [ "$IN_CONTAINER" != "true" ] ; then + # Run the test script within the container + docker run --rm \ + -e IN_CONTAINER=true \ + -e SKIP_ON_START=true \ + -v "$(pwd)/test-pre-scripts.sh:/test.sh" \ + -v "$(pwd)/test-pre-scripts:/scripts" \ + $image \ + bash -c "/test.sh" +else + echo "Performing backup tests" + + echo "Verify cron and crontab exist" + type cron + type crontab + + echo "Install sqlite3" + apt-get update + apt-get install -y --no-install-recommends sqlite3 + + echo "Create test data..." + mkdir -p /data + touch /data/test_database.db + sqlite3 /data/test_database.db < /scripts/create-test-data.sql + + echo "Making backup..." + /backup.sh + + echo "Verify intermediary file is gone" + test -f /data/test_database.db.bak && exit 1 || echo "Gone" + + echo "Delete test data..." + rm -fr /data/* + + echo "Verify deleted..." + test -f /data/test_database.db && exit 1 || echo "Gone" + + echo "Restore backup..." + /restore.sh + + echo "Verify restored files exist..." + test -f /data/test_database.db + test -f /data/test_database.db.bak && exit 1 || echo "Gone" + sqlite3 /data/test_database.db "select data from test_table where id = 1" + + echo "Delete test data again..." + rm -fr /data/* + + echo "Verify deleted..." + test -f /data/test_database.db && exit 1 || echo "Gone" + + echo "Simulate a restart with RESTORE_ON_EMPTY_START..." + RESTORE_ON_EMPTY_START=true /start.sh + + echo "Verify restore happened..." + test -f /data/test_database.db + test -f /data/test_database.db.bak && exit 1 || echo "Gone" + sqlite3 /data/test_database.db "select data from test_table where id = 1" + + echo "Delete test data..." + rm -fr /data/* + + echo "Verify restore with incorrect passphrase fails..." + echo "Fail to restore backup..." + PASSPHRASE=Incorrect.Mule.Solar.Paperclip /restore.sh && exit 1 || echo "OK" +fi diff --git a/tests/test-pre-scripts/backup/after/post-backup.sh b/tests/test-pre-scripts/backup/after/post-backup.sh new file mode 100755 index 0000000..a606858 --- /dev/null +++ b/tests/test-pre-scripts/backup/after/post-backup.sh @@ -0,0 +1,6 @@ +set -e + +cd /data + +# Remove backed up copy +rm test_database.db.bak diff --git a/tests/test-pre-scripts/backup/before/pre-backup.sh b/tests/test-pre-scripts/backup/before/pre-backup.sh new file mode 100755 index 0000000..b0da835 --- /dev/null +++ b/tests/test-pre-scripts/backup/before/pre-backup.sh @@ -0,0 +1,6 @@ +set -e + +cd /data + +# Dump the SQLite database +sqlite3 test_database.db ".backup test_database.db.bak" diff --git a/tests/test-pre-scripts/create-test-data.sql b/tests/test-pre-scripts/create-test-data.sql new file mode 100644 index 0000000..0d63db8 --- /dev/null +++ b/tests/test-pre-scripts/create-test-data.sql @@ -0,0 +1,7 @@ +CREATE TABLE test_table ( + id integer PRIMARY KEY, + data text NOT NULL +); + +INSERT INTO test_table (data) +VALUES ("Test row"); diff --git a/tests/test-pre-scripts/restore/after/post-restore.sh b/tests/test-pre-scripts/restore/after/post-restore.sh new file mode 100755 index 0000000..7ede126 --- /dev/null +++ b/tests/test-pre-scripts/restore/after/post-restore.sh @@ -0,0 +1,6 @@ +set -e + +cd /data + +# Restore the backedup database +mv test_database.db.bak test_database.db diff --git a/tests/test-pre-scripts/restore/before/pre-restore.sh b/tests/test-pre-scripts/restore/before/pre-restore.sh new file mode 100755 index 0000000..ea3e3e4 --- /dev/null +++ b/tests/test-pre-scripts/restore/before/pre-restore.sh @@ -0,0 +1,3 @@ +set -e + +# Don't really need to do anything here From fa9c0f979848478ac8b1f2c56a9637e5dbbaf902 Mon Sep 17 00:00:00 2001 From: ViViDboarder Date: Fri, 1 Feb 2019 13:48:00 -0800 Subject: [PATCH 3/3] Add healthcheck to Docker image --- Dockerfile.raspbian | 12 ++++++++---- Dockerfile.ubuntu | 12 ++++++++---- cron-exec.sh | 10 ++++++++++ healthcheck.sh | 5 +++++ start.sh | 14 +++++++------- tests/test.sh | 13 +++++++++---- 6 files changed, 47 insertions(+), 19 deletions(-) create mode 100755 cron-exec.sh create mode 100755 healthcheck.sh diff --git a/Dockerfile.raspbian b/Dockerfile.raspbian index 9e039be..d5cec48 100644 --- a/Dockerfile.raspbian +++ b/Dockerfile.raspbian @@ -49,9 +49,13 @@ RUN mkdir -p /scripts/backup/after RUN mkdir -p /scripts/restore/before RUN mkdir -p /scripts/restore/after -ADD backup.sh / -ADD restore.sh / -ADD start.sh / -ADD verify.sh / +COPY backup.sh / +COPY restore.sh / +COPY start.sh / +COPY verify.sh / +COPY healthcheck.sh / +COPY cron-exec.sh / + +HEALTHCHECK CMD /healthcheck.sh CMD [ "/start.sh" ] diff --git a/Dockerfile.ubuntu b/Dockerfile.ubuntu index dce74a7..1f3ffd8 100644 --- a/Dockerfile.ubuntu +++ b/Dockerfile.ubuntu @@ -49,9 +49,13 @@ RUN mkdir -p /scripts/backup/after RUN mkdir -p /scripts/restore/before RUN mkdir -p /scripts/restore/after -ADD backup.sh / -ADD restore.sh / -ADD start.sh / -ADD verify.sh / +COPY backup.sh / +COPY restore.sh / +COPY start.sh / +COPY verify.sh / +COPY healthcheck.sh / +COPY cron-exec.sh / + +HEALTHCHECK CMD /healthcheck.sh CMD [ "/start.sh" ] diff --git a/cron-exec.sh b/cron-exec.sh new file mode 100755 index 0000000..ed4667f --- /dev/null +++ b/cron-exec.sh @@ -0,0 +1,10 @@ +#! /bin/bash + +ENV=/env +LOG=/cron.log +HEALTH_FILE=/unhealthy + +test -f $ENV || echo NO_ENV=true > $ENV + +# Execute command and write output to log +env `cat $ENV | xargs` $@ 2>> $LOG && rm -f $HEALTH_FILE || { touch $HEALTH_FILE; exit 1; } diff --git a/healthcheck.sh b/healthcheck.sh new file mode 100755 index 0000000..b7052a1 --- /dev/null +++ b/healthcheck.sh @@ -0,0 +1,5 @@ +#! /bin/bash + +HEALTH_FILE=/unhealthy + +test -f $HEALTH_FILE || exit 0 && exit 1 diff --git a/start.sh b/start.sh index 1480490..4b65f1f 100755 --- a/start.sh +++ b/start.sh @@ -18,34 +18,34 @@ fi # If set to restore on start, restore if the data volume is empty if [ "$RESTORE_ON_EMPTY_START" == "true" -a -z "$(ls -A $PATH_TO_BACKUP)" ]; then - /restore.sh + /cron-exec.sh /restore.sh fi # Unless explicitly skipping, take a backup on startup if [ "$SKIP_ON_START" != "true" ]; then - /backup.sh + /cron-exec.sh /backup.sh fi if [ -n "$CRON_SCHEDULE" ]; then # Export the environment to a file so it can be loaded from cron - env | sed 's/^\(.*\)=\(.*\)$/export \1="\2"/g' > /env.sh + env > /env # Remove some vars we don't want to keep - sed -i '/\(HOSTNAME\|affinity\|SHLVL\|PWD\)/d' /env.sh + sed -i '/\(HOSTNAME\|affinity\|SHLVL\|PWD\)/d' /env # Use bash for cron echo "SHELL=/bin/bash" > /crontab.conf # Schedule the backups - echo "$CRON_SCHEDULE source /env.sh && /backup.sh 2>> /cron.log" >> /crontab.conf + echo "$CRON_SCHEDULE /cron-exec.sh /backup.sh" >> /crontab.conf echo "Backups scheduled as $CRON_SCHEDULE" if [ -n "$FULL_CRON_SCHEDULE" ]; then - echo "$FULL_CRON_SCHEDULE source /env.sh && /backup.sh full 2>> /cron.log" >> /crontab.conf + echo "$FULL_CRON_SCHEDULE /cron-exec.sh /backup.sh full" >> /crontab.conf echo "Full backup scheduled as $VERIFY_CRON_SCHEDULE" fi if [ -n "$VERIFY_CRON_SCHEDULE" ]; then - echo "$VERIFY_CRON_SCHEDULE source /env.sh && /verify.sh 2>> /cron.log" >> /crontab.conf + echo "$VERIFY_CRON_SCHEDULE /cron-exec.sh /verify.sh" >> /crontab.conf echo "Verify scheduled as $VERIFY_CRON_SCHEDULE" fi diff --git a/tests/test.sh b/tests/test.sh index 84546dc..8ebf31f 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -22,10 +22,10 @@ else mkdir -p /data && echo Test > /data/test.txt echo "Making backup..." - /backup.sh + /cron-exec.sh /backup.sh echo "Verify backup..." - /verify.sh + /cron-exec.sh /verify.sh echo "Delete test data..." rm -fr /data/* @@ -34,7 +34,8 @@ else test -f /data/test.txt && exit 1 || echo "Gone" echo "Restore backup..." - /restore.sh + /cron-exec.sh /restore.sh + /healthcheck.sh echo "Verify restore..." test -f /data/test.txt @@ -51,6 +52,7 @@ else echo "Simulate a restart with RESTORE_ON_EMPTY_START..." RESTORE_ON_EMPTY_START=true /start.sh + /healthcheck.sh echo "Verify restore happened..." test -f /data/test.txt @@ -58,5 +60,8 @@ else echo "Verify restore with incorrect passphrase fails..." echo "Fail to restore backup..." - PASSPHRASE=Incorrect.Mule.Solar.Paperclip /restore.sh && exit 1 || echo "OK" + PASSPHRASE=Incorrect.Mule.Solar.Paperclip /cron-exec.sh /restore.sh && exit 1 || echo "OK" + + echo "Verify failed healthcheck" + /healthcheck.sh && exit 1 || echo "OK" fi