git.iko.soy/typeable/nixpkgs
on master help sign in
nixos/postgresqlBackup: Only replace backup when successful

Previously, a failed backup would always overwrite ${db}.sql.gz, because the bash `>` redirect truncates the file; even if the backup was going to fail. On the next run, the ${db}.prev.sql.gz backup would be overwritten by the bad ${db}.sql.gz. Now, if the backup fails, the ${db}.in-progress.sql.gz is in an unknown state, but ${db}.sql.gz will not be written. On the next run, ${db}.prev.sql.gz (our only good backup) will not be overwritten because ${db}.sql.gz does not exist.

commit81c8189a841728a813bcde8604b80427fcf33522 authorRobert Hensing <robert@roberthensing.nl> dateFri 4 Jun 2021, 17:34 (5 years ago) parentc586e42
2 files changed+27−1
nixos/modules/services/backup/postgresql-backup.nix+5−1 nixos/tests/postgresql.nix+22
nixos/modules/services/backup/postgresql-backup.nix+5−1
@@ -17,6 +17,8 @@ let
1717 path = [ pkgs.coreutils pkgs.gzip config.services.postgresql.package ];
1818
1919 script = ''
20+ set -e -o pipefail
21+
2022 umask 0077 # ensure backup is only readable by postgres user
2123
2224 if [ -e ${cfg.location}/${db}.sql.gz ]; then
@@ -24,7 +26,9 @@ let
2426 fi
2527
2628 ${dumpCmd} | \
27− gzip -c > ${cfg.location}/${db}.sql.gz
29+ gzip -c > ${cfg.location}/${db}.in-progress.sql.gz
30+
31+ mv ${cfg.location}/${db}.in-progress.sql.gz ${cfg.location}/${db}.sql.gz
2832 '';
2933
3034 serviceConfig = {
nixos/tests/postgresql.nix+22
@@ -73,8 +73,30 @@ let
7373 machine.succeed(
7474 "systemctl start ${backupService}.service",
7575 "zcat /var/backup/postgresql/${backupName}.sql.gz | grep '<test>ok</test>'",
76+ "ls -hal /var/backup/postgresql/ >/dev/console",
7677 "stat -c '%a' /var/backup/postgresql/${backupName}.sql.gz | grep 600",
7778 )
79+ with subtest("Backup service fails gracefully"):
80+ # Sabotage the backup process
81+ machine.succeed("rm /run/postgresql/.s.PGSQL.5432")
82+ machine.fail(
83+ "systemctl start ${backupService}.service",
84+ )
85+ machine.succeed(
86+ "ls -hal /var/backup/postgresql/ >/dev/console",
87+ "zcat /var/backup/postgresql/${backupName}.prev.sql.gz | grep '<test>ok</test>'",
88+ "stat /var/backup/postgresql/${backupName}.in-progress.sql.gz",
89+ )
90+ # In a previous version, the second run would overwrite prev.sql.gz,
91+ # so we test a second run as well.
92+ machine.fail(
93+ "systemctl start ${backupService}.service",
94+ )
95+ machine.succeed(
96+ "stat /var/backup/postgresql/${backupName}.in-progress.sql.gz",
97+ "zcat /var/backup/postgresql/${backupName}.prev.sql.gz | grep '<test>ok</test>'",
98+ )
99+
78100
79101 with subtest("Initdb works"):
80102 machine.succeed("sudo -u postgres initdb -D /tmp/testpostgres2")