]>
Commit | Line | Data |
---|---|---|
0c875cf3 DM |
1 | use std::path::PathBuf; |
2 | ||
6ef1b649 WB |
3 | use anyhow::Error; |
4 | ||
89725197 | 5 | use pbs_api_types::PruneOptions; |
42dad3ab | 6 | use pbs_datastore::manifest::MANIFEST_BLOB_NAME; |
89725197 | 7 | use pbs_datastore::prune::compute_prune_info; |
42dad3ab | 8 | use pbs_datastore::{BackupDir, BackupInfo}; |
0c875cf3 | 9 | |
0c875cf3 DM |
10 | fn get_prune_list( |
11 | list: Vec<BackupInfo>, | |
a096eecb | 12 | return_kept: bool, |
9b783521 | 13 | options: &PruneOptions, |
0c875cf3 DM |
14 | ) -> Vec<PathBuf> { |
15 | ||
9b783521 | 16 | let mut prune_info = compute_prune_info(list, options).unwrap(); |
0c875cf3 | 17 | |
8f0b4c1f | 18 | prune_info.reverse(); |
a096eecb | 19 | |
8f0b4c1f | 20 | prune_info |
0c875cf3 | 21 | .iter() |
8f0b4c1f | 22 | .filter_map(|(info, keep)| { |
a096eecb | 23 | if *keep != return_kept { |
8f0b4c1f DM |
24 | None |
25 | } else { | |
26 | Some(info.backup_dir.relative_path()) | |
27 | } | |
28 | }) | |
0c875cf3 DM |
29 | .collect() |
30 | } | |
31 | ||
659da6c9 DM |
32 | fn create_info( |
33 | snapshot: &str, | |
34 | partial: bool, | |
35 | ) -> BackupInfo { | |
36 | ||
0cf2b644 | 37 | let backup_dir: BackupDir = snapshot.parse().unwrap(); |
659da6c9 DM |
38 | |
39 | let mut files = Vec::new(); | |
40 | ||
41 | if !partial { | |
42 | files.push(String::from(MANIFEST_BLOB_NAME)); | |
43 | } | |
a096eecb | 44 | |
92c5cf42 | 45 | BackupInfo { backup_dir, files, protected: false } |
659da6c9 | 46 | } |
9b783521 | 47 | |
a096eecb | 48 | #[test] |
102d8d41 DM |
49 | fn test_prune_hourly() -> Result<(), Error> { |
50 | ||
51 | let mut orig_list = Vec::new(); | |
52 | ||
53 | orig_list.push(create_info("host/elsa/2019-11-15T09:39:15Z", false)); | |
54 | orig_list.push(create_info("host/elsa/2019-11-15T10:49:15Z", false)); | |
55 | orig_list.push(create_info("host/elsa/2019-11-15T10:59:15Z", false)); | |
56 | orig_list.push(create_info("host/elsa/2019-11-15T11:39:15Z", false)); | |
57 | orig_list.push(create_info("host/elsa/2019-11-15T11:49:15Z", false)); | |
58 | orig_list.push(create_info("host/elsa/2019-11-15T11:59:15Z", false)); | |
59 | ||
60 | let list = orig_list.clone(); | |
89725197 DM |
61 | let mut options = PruneOptions::default(); |
62 | options.keep_hourly = Some(3); | |
102d8d41 DM |
63 | let remove_list = get_prune_list(list, false, &options); |
64 | let expect: Vec<PathBuf> = vec![ | |
65 | PathBuf::from("host/elsa/2019-11-15T10:49:15Z"), | |
66 | PathBuf::from("host/elsa/2019-11-15T11:39:15Z"), | |
67 | PathBuf::from("host/elsa/2019-11-15T11:49:15Z"), | |
68 | ]; | |
69 | assert_eq!(remove_list, expect); | |
70 | ||
44288184 | 71 | let list = orig_list; |
89725197 DM |
72 | let mut options = PruneOptions::default(); |
73 | options.keep_hourly = Some(2); | |
102d8d41 DM |
74 | let remove_list = get_prune_list(list, true, &options); |
75 | let expect: Vec<PathBuf> = vec![ | |
76 | PathBuf::from("host/elsa/2019-11-15T10:59:15Z"), | |
77 | PathBuf::from("host/elsa/2019-11-15T11:59:15Z"), | |
78 | ]; | |
79 | assert_eq!(remove_list, expect); | |
80 | ||
81 | Ok(()) | |
82 | } | |
83 | ||
89725197 | 84 | #[test] |
a096eecb DM |
85 | fn test_prune_simple2() -> Result<(), Error> { |
86 | ||
87 | let mut orig_list = Vec::new(); | |
88 | ||
89 | orig_list.push(create_info("host/elsa/2018-11-15T11:59:15Z", false)); | |
90 | orig_list.push(create_info("host/elsa/2019-11-15T11:59:15Z", false)); | |
91 | orig_list.push(create_info("host/elsa/2019-11-21T11:59:15Z", false)); | |
92 | orig_list.push(create_info("host/elsa/2019-11-22T11:59:15Z", false)); | |
93 | orig_list.push(create_info("host/elsa/2019-11-29T11:59:15Z", false)); | |
94 | orig_list.push(create_info("host/elsa/2019-12-01T11:59:15Z", false)); | |
95 | orig_list.push(create_info("host/elsa/2019-12-02T11:59:15Z", false)); | |
96 | orig_list.push(create_info("host/elsa/2019-12-03T11:59:15Z", false)); | |
97 | orig_list.push(create_info("host/elsa/2019-12-04T11:59:15Z", false)); | |
98 | ||
99 | let list = orig_list.clone(); | |
89725197 DM |
100 | let mut options = PruneOptions::default(); |
101 | options.keep_daily = Some(1); | |
9b783521 | 102 | let remove_list = get_prune_list(list, true, &options); |
a096eecb DM |
103 | let expect: Vec<PathBuf> = vec![ |
104 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
105 | ]; | |
106 | assert_eq!(remove_list, expect); | |
107 | ||
108 | let list = orig_list.clone(); | |
89725197 DM |
109 | let mut options = PruneOptions::default(); |
110 | options.keep_last = Some(1); | |
111 | options.keep_daily = Some(1); | |
9b783521 | 112 | let remove_list = get_prune_list(list, true, &options); |
a096eecb DM |
113 | let expect: Vec<PathBuf> = vec![ |
114 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
115 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
116 | ]; | |
117 | assert_eq!(remove_list, expect); | |
118 | ||
119 | let list = orig_list.clone(); | |
89725197 DM |
120 | let mut options = PruneOptions::default(); |
121 | options.keep_daily = Some(1); | |
122 | options.keep_weekly = Some(1); | |
9b783521 | 123 | let remove_list = get_prune_list(list, true, &options); |
a096eecb DM |
124 | let expect: Vec<PathBuf> = vec![ |
125 | PathBuf::from("host/elsa/2019-12-01T11:59:15Z"), | |
126 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
127 | ]; | |
128 | assert_eq!(remove_list, expect); | |
129 | ||
130 | let list = orig_list.clone(); | |
89725197 DM |
131 | let mut options = PruneOptions::default(); |
132 | options.keep_daily = Some(1); | |
133 | options.keep_weekly = Some(1); | |
134 | options.keep_monthly = Some(1); | |
9b783521 | 135 | let remove_list = get_prune_list(list, true, &options); |
a096eecb DM |
136 | let expect: Vec<PathBuf> = vec![ |
137 | PathBuf::from("host/elsa/2019-11-22T11:59:15Z"), | |
138 | PathBuf::from("host/elsa/2019-12-01T11:59:15Z"), | |
139 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
140 | ]; | |
141 | assert_eq!(remove_list, expect); | |
142 | ||
44288184 | 143 | let list = orig_list; |
89725197 DM |
144 | let mut options = PruneOptions::default(); |
145 | options.keep_monthly = Some(1); | |
146 | options.keep_yearly = Some(1); | |
9b783521 | 147 | let remove_list = get_prune_list(list, true, &options); |
a096eecb DM |
148 | let expect: Vec<PathBuf> = vec![ |
149 | PathBuf::from("host/elsa/2018-11-15T11:59:15Z"), | |
150 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
151 | ]; | |
152 | assert_eq!(remove_list, expect); | |
153 | ||
154 | Ok(()) | |
155 | } | |
659da6c9 | 156 | |
0c875cf3 DM |
157 | #[test] |
158 | fn test_prune_simple() -> Result<(), Error> { | |
159 | ||
659da6c9 | 160 | let mut orig_list = Vec::new(); |
0c875cf3 | 161 | |
659da6c9 DM |
162 | orig_list.push(create_info("host/elsa/2019-12-02T11:59:15Z", false)); |
163 | orig_list.push(create_info("host/elsa/2019-12-03T11:59:15Z", false)); | |
164 | orig_list.push(create_info("host/elsa/2019-12-04T11:59:15Z", false)); | |
165 | orig_list.push(create_info("host/elsa/2019-12-04T12:59:15Z", false)); | |
166 | ||
0c875cf3 DM |
167 | // keep-last tests |
168 | ||
169 | let list = orig_list.clone(); | |
89725197 DM |
170 | let mut options = PruneOptions::default(); |
171 | options.keep_last = Some(4); | |
9b783521 | 172 | let remove_list = get_prune_list(list, false, &options); |
0c875cf3 DM |
173 | let expect: Vec<PathBuf> = Vec::new(); |
174 | assert_eq!(remove_list, expect); | |
175 | ||
176 | let list = orig_list.clone(); | |
89725197 DM |
177 | let mut options = PruneOptions::default(); |
178 | options.keep_last = Some(3); | |
9b783521 | 179 | let remove_list = get_prune_list(list, false, &options); |
0c875cf3 DM |
180 | let expect: Vec<PathBuf> = vec![ |
181 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
182 | ]; | |
183 | assert_eq!(remove_list, expect); | |
184 | ||
185 | let list = orig_list.clone(); | |
89725197 DM |
186 | let mut options = PruneOptions::default(); |
187 | options.keep_last = Some(2); | |
9b783521 | 188 | let remove_list = get_prune_list(list, false, &options); |
0c875cf3 DM |
189 | let expect: Vec<PathBuf> = vec![ |
190 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
191 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
192 | ]; | |
193 | assert_eq!(remove_list, expect); | |
194 | ||
195 | let list = orig_list.clone(); | |
89725197 DM |
196 | let mut options = PruneOptions::default(); |
197 | options.keep_last = Some(1); | |
9b783521 | 198 | let remove_list = get_prune_list(list, false, &options); |
0c875cf3 DM |
199 | let expect: Vec<PathBuf> = vec![ |
200 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
201 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
202 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
203 | ]; | |
204 | assert_eq!(remove_list, expect); | |
205 | ||
206 | let list = orig_list.clone(); | |
89725197 DM |
207 | let mut options = PruneOptions::default(); |
208 | options.keep_last = Some(0); | |
9b783521 | 209 | let remove_list = get_prune_list(list, false, &options); |
0c875cf3 DM |
210 | let expect: Vec<PathBuf> = vec![ |
211 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
212 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
213 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
214 | PathBuf::from("host/elsa/2019-12-04T12:59:15Z"), | |
215 | ]; | |
216 | assert_eq!(remove_list, expect); | |
217 | ||
218 | // keep-last, keep-daily mixed | |
219 | let list = orig_list.clone(); | |
89725197 DM |
220 | let mut options = PruneOptions::default(); |
221 | options.keep_last = Some(2); | |
222 | options.keep_daily = Some(2); | |
9b783521 | 223 | let remove_list = get_prune_list(list, false, &options); |
2c034f8d | 224 | let expect: Vec<PathBuf> = vec![]; |
0c875cf3 DM |
225 | assert_eq!(remove_list, expect); |
226 | ||
227 | // keep-daily test | |
0c875cf3 | 228 | let list = orig_list.clone(); |
89725197 DM |
229 | let mut options = PruneOptions::default(); |
230 | options.keep_daily = Some(3); | |
9b783521 | 231 | let remove_list = get_prune_list(list, false, &options); |
0c875cf3 DM |
232 | let expect: Vec<PathBuf> = vec![PathBuf::from("host/elsa/2019-12-04T11:59:15Z")]; |
233 | assert_eq!(remove_list, expect); | |
234 | ||
235 | // keep-daily test | |
0c875cf3 | 236 | let list = orig_list.clone(); |
89725197 DM |
237 | let mut options = PruneOptions::default(); |
238 | options.keep_daily = Some(2); | |
9b783521 | 239 | let remove_list = get_prune_list(list, false, &options); |
0c875cf3 DM |
240 | let expect: Vec<PathBuf> = vec![ |
241 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
242 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
243 | ]; | |
244 | assert_eq!(remove_list, expect); | |
245 | ||
246 | // keep-weekly | |
247 | let list = orig_list.clone(); | |
89725197 DM |
248 | let mut options = PruneOptions::default(); |
249 | options.keep_weekly = Some(5); | |
9b783521 | 250 | let remove_list = get_prune_list(list, false, &options); |
2c034f8d | 251 | // all backup are within the same week, so we only keep a single file |
0c875cf3 DM |
252 | let expect: Vec<PathBuf> = vec![ |
253 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
254 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
255 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
256 | ]; | |
257 | assert_eq!(remove_list, expect); | |
258 | ||
2c034f8d DM |
259 | // keep-daily + keep-weekly |
260 | let list = orig_list.clone(); | |
89725197 DM |
261 | let mut options = PruneOptions::default(); |
262 | options.keep_daily = Some(1); | |
263 | options.keep_weekly = Some(5); | |
9b783521 | 264 | let remove_list = get_prune_list(list, false, &options); |
2c034f8d DM |
265 | let expect: Vec<PathBuf> = vec![ |
266 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
6f47dd8a | 267 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), |
2c034f8d DM |
268 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), |
269 | ]; | |
270 | assert_eq!(remove_list, expect); | |
271 | ||
272 | // keep-monthly | |
0c875cf3 | 273 | let list = orig_list.clone(); |
89725197 DM |
274 | let mut options = PruneOptions::default(); |
275 | options.keep_monthly = Some(6); | |
9b783521 | 276 | let remove_list = get_prune_list(list, false, &options); |
2c034f8d | 277 | // all backup are within the same month, so we only keep a single file |
0c875cf3 DM |
278 | let expect: Vec<PathBuf> = vec![ |
279 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
280 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
281 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
282 | ]; | |
283 | assert_eq!(remove_list, expect); | |
284 | ||
2c034f8d | 285 | // keep-yearly |
0c875cf3 | 286 | let list = orig_list.clone(); |
89725197 DM |
287 | let mut options = PruneOptions::default(); |
288 | options.keep_yearly = Some(7); | |
9b783521 | 289 | let remove_list = get_prune_list(list, false, &options); |
2c034f8d DM |
290 | // all backup are within the same year, so we only keep a single file |
291 | let expect: Vec<PathBuf> = vec![ | |
292 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
293 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
294 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
295 | ]; | |
296 | assert_eq!(remove_list, expect); | |
297 | ||
298 | // keep-weekly + keep-monthly + keep-yearly | |
44288184 | 299 | let list = orig_list; |
89725197 DM |
300 | let mut options = PruneOptions::default(); |
301 | options.keep_weekly = Some(5); | |
302 | options.keep_monthly = Some(6); | |
303 | options.keep_yearly = Some(7); | |
9b783521 | 304 | let remove_list = get_prune_list(list, false, &options); |
2c034f8d | 305 | // all backup are within one week, so we only keep a single file |
0c875cf3 DM |
306 | let expect: Vec<PathBuf> = vec![ |
307 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
308 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
309 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
310 | ]; | |
311 | assert_eq!(remove_list, expect); | |
312 | ||
313 | Ok(()) | |
314 | } |