1import ./make-test-python.nix (
2 { pkgs, ... }:
3
4 let
5 remoteRepository = "/root/restic-backup";
6 remoteFromFileRepository = "/root/restic-backup-from-file";
7 remoteNoInitRepository = "/root/restic-backup-no-init";
8 rcloneRepository = "rclone:local:/root/restic-rclone-backup";
9
10 backupPrepareCommand = ''
11 touch /root/backupPrepareCommand
12 test ! -e /root/backupCleanupCommand
13 '';
14
15 backupCleanupCommand = ''
16 rm /root/backupPrepareCommand
17 touch /root/backupCleanupCommand
18 '';
19
20 testDir = pkgs.stdenvNoCC.mkDerivation {
21 name = "test-files-to-backup";
22 unpackPhase = "true";
23 installPhase = ''
24 mkdir $out
25 echo some_file > $out/some_file
26 echo some_other_file > $out/some_other_file
27 mkdir $out/a_dir
28 echo a_file > $out/a_dir/a_file
29 '';
30 };
31
32 passwordFile = "${pkgs.writeText "password" "correcthorsebatterystaple"}";
33 paths = [ "/opt" ];
34 exclude = [ "/opt/excluded_file_*" ];
35 pruneOpts = [
36 "--keep-daily 2"
37 "--keep-weekly 1"
38 "--keep-monthly 1"
39 "--keep-yearly 99"
40 ];
41 in
42 {
43 name = "restic";
44
45 meta = with pkgs.lib.maintainers; {
46 maintainers = [ bbigras i077 ];
47 };
48
49 nodes = {
50 server =
51 { pkgs, ... }:
52 {
53 services.restic.backups = {
54 remotebackup = {
55 inherit passwordFile paths exclude pruneOpts backupPrepareCommand backupCleanupCommand;
56 repository = remoteRepository;
57 initialize = true;
58 timerConfig = null; # has no effect here, just checking that it doesn't break the service
59 };
60 remote-from-file-backup = {
61 inherit passwordFile exclude pruneOpts;
62 initialize = true;
63 repositoryFile = pkgs.writeText "repositoryFile" remoteFromFileRepository;
64 paths = [ "/opt/a_dir" ];
65 dynamicFilesFrom = ''
66 find /opt -mindepth 1 -maxdepth 1 ! -name a_dir # all files in /opt except for a_dir
67 '';
68 };
69 remote-noinit-backup = {
70 inherit passwordFile exclude pruneOpts paths;
71 initialize = false;
72 repository = remoteNoInitRepository;
73 };
74 rclonebackup = {
75 inherit passwordFile paths exclude pruneOpts;
76 initialize = true;
77 repository = rcloneRepository;
78 rcloneConfig = {
79 type = "local";
80 one_file_system = true;
81 };
82
83 # This gets overridden by rcloneConfig.type
84 rcloneConfigFile = pkgs.writeText "rclone.conf" ''
85 [local]
86 type=ftp
87 '';
88 };
89 remoteprune = {
90 inherit passwordFile;
91 repository = remoteRepository;
92 pruneOpts = [ "--keep-last 1" ];
93 };
94 custompackage = {
95 inherit passwordFile paths;
96 repository = "some-fake-repository";
97 package = pkgs.writeShellScriptBin "restic" ''
98 echo "$@" >> /root/fake-restic.log;
99 '';
100
101 pruneOpts = [ "--keep-last 1" ];
102 checkOpts = [ "--some-check-option" ];
103 };
104 };
105
106 environment.sessionVariables.RCLONE_CONFIG_LOCAL_TYPE = "local";
107 };
108 };
109
110 testScript = ''
111 server.start()
112 server.wait_for_unit("dbus.socket")
113 server.fail(
114 "restic-remotebackup snapshots",
115 'restic-remote-from-file-backup snapshots"',
116 "restic-rclonebackup snapshots",
117 "grep 'backup.* /opt' /root/fake-restic.log",
118 )
119 server.succeed(
120 # set up
121 "cp -rT ${testDir} /opt",
122 "touch /opt/excluded_file_1 /opt/excluded_file_2",
123 "mkdir -p /root/restic-rclone-backup",
124 "restic-remote-noinit-backup init",
125
126 # test that remotebackup runs custom commands and produces a snapshot
127 "timedatectl set-time '2016-12-13 13:45'",
128 "systemctl start restic-backups-remotebackup.service",
129 "rm /root/backupCleanupCommand",
130 'restic-remotebackup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
131
132 # test that restoring that snapshot produces the same directory
133 "mkdir /tmp/restore-1",
134 "restic-remotebackup restore latest -t /tmp/restore-1",
135 "diff -ru ${testDir} /tmp/restore-1/opt",
136
137 # test that remote-from-file-backup produces a snapshot
138 "systemctl start restic-backups-remote-from-file-backup.service",
139 'restic-remote-from-file-backup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
140
141 # test that remote-noinit-backup produces a snapshot
142 "systemctl start restic-backups-remote-noinit-backup.service",
143 'restic-remote-noinit-backup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
144
145 # test that restoring that snapshot produces the same directory
146 "mkdir /tmp/restore-2",
147 "${pkgs.restic}/bin/restic -r ${remoteRepository} -p ${passwordFile} restore latest -t /tmp/restore-2",
148 "diff -ru ${testDir} /tmp/restore-2/opt",
149
150 # test that rclonebackup produces a snapshot
151 "systemctl start restic-backups-rclonebackup.service",
152 'restic-rclonebackup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
153
154 # test that custompackage runs both `restic backup` and `restic check` with reasonable commandlines
155 "systemctl start restic-backups-custompackage.service",
156 "grep 'backup' /root/fake-restic.log",
157 "grep 'check.* --some-check-option' /root/fake-restic.log",
158
159 # test that we can create four snapshots in remotebackup and rclonebackup
160 "timedatectl set-time '2017-12-13 13:45'",
161 "systemctl start restic-backups-remotebackup.service",
162 "rm /root/backupCleanupCommand",
163 "systemctl start restic-backups-rclonebackup.service",
164
165 "timedatectl set-time '2018-12-13 13:45'",
166 "systemctl start restic-backups-remotebackup.service",
167 "rm /root/backupCleanupCommand",
168 "systemctl start restic-backups-rclonebackup.service",
169
170 "timedatectl set-time '2018-12-14 13:45'",
171 "systemctl start restic-backups-remotebackup.service",
172 "rm /root/backupCleanupCommand",
173 "systemctl start restic-backups-rclonebackup.service",
174
175 "timedatectl set-time '2018-12-15 13:45'",
176 "systemctl start restic-backups-remotebackup.service",
177 "rm /root/backupCleanupCommand",
178 "systemctl start restic-backups-rclonebackup.service",
179
180 "timedatectl set-time '2018-12-16 13:45'",
181 "systemctl start restic-backups-remotebackup.service",
182 "rm /root/backupCleanupCommand",
183 "systemctl start restic-backups-rclonebackup.service",
184
185 'restic-remotebackup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 4"',
186 'restic-rclonebackup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 4"',
187
188 # test that remoteprune brings us back to 1 snapshot in remotebackup
189 "systemctl start restic-backups-remoteprune.service",
190 'restic-remotebackup snapshots --json | ${pkgs.jq}/bin/jq "length | . == 1"',
191
192 )
193 '';
194 }
195)