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