2019-12-04 16:08:03 +01:00
use failure ::* ;
use std ::path ::PathBuf ;
use proxmox_backup ::backup ::* ;
fn get_prune_list (
list : Vec < BackupInfo > ,
2019-12-05 19:01:51 +01:00
return_kept : bool ,
2019-12-06 08:56:27 +01:00
options : & PruneOptions ,
2019-12-04 16:08:03 +01:00
) -> Vec < PathBuf > {
2019-12-06 08:56:27 +01:00
let mut prune_info = compute_prune_info ( list , options ) . unwrap ( ) ;
2019-12-04 16:08:03 +01:00
2019-12-05 13:13:30 +01:00
prune_info . reverse ( ) ;
2019-12-05 19:01:51 +01:00
2019-12-05 13:13:30 +01:00
prune_info
2019-12-04 16:08:03 +01:00
. iter ( )
2019-12-05 13:13:30 +01:00
. filter_map ( | ( info , keep ) | {
2019-12-05 19:01:51 +01:00
if * keep ! = return_kept {
2019-12-05 13:13:30 +01:00
None
} else {
Some ( info . backup_dir . relative_path ( ) )
}
} )
2019-12-04 16:08:03 +01:00
. collect ( )
}
2019-12-05 16:47:08 +01:00
fn create_info (
snapshot : & str ,
partial : bool ,
) -> BackupInfo {
let backup_dir = BackupDir ::parse ( snapshot ) . unwrap ( ) ;
let mut files = Vec ::new ( ) ;
if ! partial {
files . push ( String ::from ( MANIFEST_BLOB_NAME ) ) ;
}
2019-12-05 19:01:51 +01:00
2019-12-05 16:47:08 +01:00
BackupInfo { backup_dir , files }
}
2019-12-06 08:56:27 +01:00
2019-12-05 19:01:51 +01:00
#[ test ]
2019-12-07 11:23:33 +01:00
fn test_prune_hourly ( ) -> Result < ( ) , Error > {
let mut orig_list = Vec ::new ( ) ;
orig_list . push ( create_info ( " host/elsa/2019-11-15T09:39:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-11-15T10:49:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-11-15T10:59:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-11-15T11:39:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-11-15T11:49:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-11-15T11:59:15Z " , false ) ) ;
let list = orig_list . clone ( ) ;
let options = PruneOptions ::new ( ) . keep_hourly ( Some ( 3 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-11-15T10:49:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-11-15T11:39:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-11-15T11:49:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
let list = orig_list . clone ( ) ;
let options = PruneOptions ::new ( ) . keep_hourly ( Some ( 2 ) ) ;
let remove_list = get_prune_list ( list , true , & options ) ;
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-11-15T10:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-11-15T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
Ok ( ( ) )
}
#[ test ]
2019-12-05 19:01:51 +01:00
fn test_prune_simple2 ( ) -> Result < ( ) , Error > {
let mut orig_list = Vec ::new ( ) ;
orig_list . push ( create_info ( " host/elsa/2018-11-15T11:59:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-11-15T11:59:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-11-21T11:59:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-11-22T11:59:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-11-29T11:59:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-12-01T11:59:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-12-02T11:59:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-12-03T11:59:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-12-04T11:59:15Z " , false ) ) ;
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_daily ( Some ( 1 ) ) ;
let remove_list = get_prune_list ( list , true , & options ) ;
2019-12-05 19:01:51 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_last ( Some ( 1 ) ) . keep_daily ( Some ( 1 ) ) ;
let remove_list = get_prune_list ( list , true , & options ) ;
2019-12-05 19:01:51 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-03T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_daily ( Some ( 1 ) ) . keep_weekly ( Some ( 1 ) ) ;
let remove_list = get_prune_list ( list , true , & options ) ;
2019-12-05 19:01:51 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-01T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_daily ( Some ( 1 ) ) . keep_weekly ( Some ( 1 ) ) . keep_monthly ( Some ( 1 ) ) ;
let remove_list = get_prune_list ( list , true , & options ) ;
2019-12-05 19:01:51 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-11-22T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-01T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_monthly ( Some ( 1 ) ) . keep_yearly ( Some ( 1 ) ) ;
let remove_list = get_prune_list ( list , true , & options ) ;
2019-12-05 19:01:51 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2018-11-15T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
Ok ( ( ) )
}
2019-12-05 16:47:08 +01:00
2019-12-04 16:08:03 +01:00
#[ test ]
fn test_prune_simple ( ) -> Result < ( ) , Error > {
2019-12-05 16:47:08 +01:00
let mut orig_list = Vec ::new ( ) ;
2019-12-04 16:08:03 +01:00
2019-12-05 16:47:08 +01:00
orig_list . push ( create_info ( " host/elsa/2019-12-02T11:59:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-12-03T11:59:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-12-04T11:59:15Z " , false ) ) ;
orig_list . push ( create_info ( " host/elsa/2019-12-04T12:59:15Z " , false ) ) ;
2019-12-04 16:08:03 +01:00
// keep-last tests
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_last ( Some ( 4 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-04 16:08:03 +01:00
let expect : Vec < PathBuf > = Vec ::new ( ) ;
assert_eq! ( remove_list , expect ) ;
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_last ( Some ( 3 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-04 16:08:03 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-02T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_last ( Some ( 2 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-04 16:08:03 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-02T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-03T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_last ( Some ( 1 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-04 16:08:03 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-02T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-03T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_last ( Some ( 0 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-04 16:08:03 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-02T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-03T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-04T12:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
// keep-last, keep-daily mixed
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_last ( Some ( 2 ) ) . keep_daily ( Some ( 2 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-05 08:55:19 +01:00
let expect : Vec < PathBuf > = vec! [ ] ;
2019-12-04 16:08:03 +01:00
assert_eq! ( remove_list , expect ) ;
// keep-daily test
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_daily ( Some ( 3 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-04 16:08:03 +01:00
let expect : Vec < PathBuf > = vec! [ PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ] ;
assert_eq! ( remove_list , expect ) ;
// keep-daily test
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_daily ( Some ( 2 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-04 16:08:03 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-02T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
// keep-weekly
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_weekly ( Some ( 5 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-05 08:55:19 +01:00
// all backup are within the same week, so we only keep a single file
2019-12-04 16:08:03 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-02T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-03T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
2019-12-05 08:55:19 +01:00
// keep-daily + keep-weekly
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_daily ( Some ( 1 ) ) . keep_weekly ( Some ( 5 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-05 08:55:19 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-02T11:59:15Z " ) ,
2019-12-05 18:41:28 +01:00
PathBuf ::from ( " host/elsa/2019-12-03T11:59:15Z " ) ,
2019-12-05 08:55:19 +01:00
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
// keep-monthly
2019-12-04 16:08:03 +01:00
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_monthly ( Some ( 6 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-05 08:55:19 +01:00
// all backup are within the same month, so we only keep a single file
2019-12-04 16:08:03 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-02T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-03T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
2019-12-05 08:55:19 +01:00
// keep-yearly
2019-12-04 16:08:03 +01:00
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_yearly ( Some ( 7 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-05 08:55:19 +01:00
// all backup are within the same year, so we only keep a single file
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-02T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-03T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
// keep-weekly + keep-monthly + keep-yearly
let list = orig_list . clone ( ) ;
2019-12-06 08:56:27 +01:00
let options = PruneOptions ::new ( ) . keep_weekly ( Some ( 5 ) ) . keep_monthly ( Some ( 6 ) ) . keep_yearly ( Some ( 7 ) ) ;
let remove_list = get_prune_list ( list , false , & options ) ;
2019-12-05 08:55:19 +01:00
// all backup are within one week, so we only keep a single file
2019-12-04 16:08:03 +01:00
let expect : Vec < PathBuf > = vec! [
PathBuf ::from ( " host/elsa/2019-12-02T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-03T11:59:15Z " ) ,
PathBuf ::from ( " host/elsa/2019-12-04T11:59:15Z " ) ,
] ;
assert_eq! ( remove_list , expect ) ;
Ok ( ( ) )
}