@@ -37,13 +37,15 @@ const TagValue2 = 'tagvalue2';
37
37
const object_io = new ObjectIO ( ) ;
38
38
object_io . set_verification_mode ( ) ;
39
39
40
-
40
+ // eslint-disable-next-line max-lines-per-function
41
41
mocha . describe ( 'lifecycle' , ( ) => {
42
42
43
43
let s3 ;
44
44
mocha . before ( async function ( ) {
45
45
this . timeout ( 60000 ) ;
46
46
47
+ config . LIFECYCLE_SCHEDULE_MIN = 0 ;
48
+ config . LIFECYCLE_INTERVAL = 0 ;
47
49
const account_info = await rpc_client . account . read_account ( { email : EMAIL , } ) ;
48
50
s3 = new S3 ( {
49
51
endpoint : coretest . get_http_address ( ) ,
@@ -347,9 +349,6 @@ mocha.describe('lifecycle', () => {
347
349
const size = num_parts * part_size ;
348
350
const data = generator . update ( Buffer . alloc ( size ) ) ;
349
351
const { obj_id } = await rpc_client . object . create_object_upload ( { bucket, key, content_type } ) ;
350
- const mp_list_before = await rpc_client . object . list_multiparts ( { obj_id, bucket, key } ) ;
351
- coretest . log ( 'list_multiparts before' , mp_list_before ) ;
352
- assert . strictEqual ( mp_list_before . multiparts . length , 0 ) ;
353
352
const multiparts_ids = [ ] ;
354
353
355
354
const get_part_slice = i => data . slice ( i * part_size , ( i + 1 ) * part_size ) ;
@@ -381,15 +380,65 @@ mocha.describe('lifecycle', () => {
381
380
await MDStore . instance ( ) . update_object_by_id ( obj_id , update ) ;
382
381
383
382
const mp_list_after = await rpc_client . object . list_multiparts ( { obj_id, bucket, key } ) ;
384
- coretest . log ( ' mp_list_after after' , mp_list_after ) ;
385
- assert . strictEqual ( mp_list_after . multiparts . length , num_parts ) ;
383
+ assert . strictEqual ( mp_list_after . multiparts . length , num_parts ,
384
+ `list_multiparts actual ${ mp_list_after . multiparts . length } !== ${ num_parts } ` ) ;
386
385
387
386
return obj_id ;
388
387
}
389
388
390
- mocha . it ( 'lifecyle - listMultiPart verify' , async ( ) => {
391
- await create_mock_multipart_upload ( 'test-lifecycle-multipart' , multipart_bucket , 3 , 45 , 7 ) ;
389
+ mocha . it ( 'lifecycle - delete multipart after 30 days' , async ( ) => {
390
+ const days = 30 ;
391
+ const multi_bucket_key = 'test-lifecycle-multipart1' ;
392
+ const obj_id = await create_mock_multipart_upload ( multi_bucket_key , multipart_bucket , days , 45 , 7 ) ;
393
+ const putLifecycleParams = commonTests . multipart_lifecycle_configuration ( multipart_bucket , multi_bucket_key , days ) ;
394
+
395
+ await s3 . putBucketLifecycleConfiguration ( putLifecycleParams ) ;
396
+ await lifecycle . background_worker ( ) ;
397
+ await verify_multipart_deleted ( obj_id , multi_bucket_key , 0 ) ;
398
+ } ) ;
399
+
400
+ mocha . it ( 'lifecycle - should not delete multipart after 30 days, before expiration' , async ( ) => {
401
+ const days = 30 ;
402
+ const multi_bucket_key = 'test-lifecycle-multipart2' ;
403
+ // create_time updated to 29 days and expire is 30 days, do not delete any multipart
404
+ const obj_id = await create_mock_multipart_upload ( multi_bucket_key , multipart_bucket , days - 1 , 45 , 7 ) ;
405
+ const putLifecycleParams = commonTests . multipart_lifecycle_configuration ( multipart_bucket , multi_bucket_key , days ) ;
406
+
407
+ await s3 . putBucketLifecycleConfiguration ( putLifecycleParams ) ;
408
+ await lifecycle . background_worker ( ) ;
409
+ await verify_multipart_deleted ( obj_id , multi_bucket_key , 7 ) ;
392
410
} ) ;
411
+
412
+ mocha . it ( 'lifecycle - delete multipart after 30 days, with prfix' , async ( ) => {
413
+ const days = 30 ;
414
+ const multi_bucket_key_prefix = 'prefix-test-lifecycle-multipart3' ;
415
+ const multi_bucket_key = 'test-lifecycle-multipart3' ;
416
+ // create_time updated to days + 1(31 days) and expire is 30 days,
417
+ const obj_id1 = await create_mock_multipart_upload ( multi_bucket_key_prefix , multipart_bucket , days + 1 , 45 , 7 ) ;
418
+ const obj_id2 = await create_mock_multipart_upload ( multi_bucket_key , multipart_bucket , days + 1 , 45 , 7 ) ;
419
+ const putLifecycleParams = commonTests . multipart_lifecycle_configuration ( multipart_bucket , multi_bucket_key_prefix , days ) ;
420
+
421
+ await s3 . putBucketLifecycleConfiguration ( putLifecycleParams ) ;
422
+ await lifecycle . background_worker ( ) ;
423
+ // delete only those multipart with prefix `prefix-test-lifecycle-multipart3` not others
424
+ await verify_multipart_deleted ( obj_id1 , multi_bucket_key_prefix , 0 ) ;
425
+ await verify_multipart_deleted ( obj_id2 , multi_bucket_key , 7 ) ;
426
+ } ) ;
427
+
428
+ async function verify_multipart_deleted ( obj_id , key , expected_length ) {
429
+ try {
430
+ const mp_list = await rpc_client . object . list_multiparts ( { obj_id, bucket : multipart_bucket , key } ) ;
431
+ console . log ( 'verify_multipart_deleted : multipart upload objects :' , mp_list ) ;
432
+ const actual_length = mp_list . objects . length ;
433
+ console . log ( 'list_objects_admin objects: ' , util . inspect ( mp_list . objects ) ) ;
434
+ assert . strictEqual ( actual_length , expected_length , `listObjectResult actual ${ actual_length } !== ${ expected_length } ` ) ;
435
+ } catch ( err ) {
436
+ console . log ( 'verify_multipart_deleted error is :' , err ) ;
437
+ if ( err . code === 'NO_SUCH_UPLOAD' && expected_length === 0 ) {
438
+ assert . ok ( true ) ;
439
+ }
440
+ }
441
+ }
393
442
} ) ;
394
443
395
444
mocha . describe ( 'bucket-lifecycle-version' , function ( ) {
@@ -553,16 +602,16 @@ mocha.describe('lifecycle', () => {
553
602
const update = {
554
603
create_time : moment ( ) . subtract ( age , 'days' ) . toDate ( ) ,
555
604
} ;
556
- console . log ( 'blow_version_objects : bucket' , bucket , 'multiparts_ids ' , obj_upload_ids , " obj_upload_ids length: " , obj_upload_ids . length , "update :" , update ) ;
605
+ console . log ( 'create_mock_version : bucket' , bucket , 'obj_upload_ids: ' , obj_upload_ids , " obj_upload_ids length: " , obj_upload_ids . length , "update :" , update ) ;
557
606
const update_result = await MDStore . instance ( ) . update_objects_by_ids ( obj_upload_ids , update ) ;
558
- console . log ( 'blow_version_objects : update_objects_by_ids' , update_result ) ;
607
+ console . log ( 'create_mock_version : update_objects_by_ids: ' , update_result ) ;
559
608
}
560
609
}
561
610
562
611
mocha . it ( 'lifecyle - version object expired' , async ( ) => {
563
612
const age = 30 ;
564
613
const version_count = 10 ;
565
- const version_bucket_key = 'test-lifecycle-version1' ;
614
+ const version_bucket_key = 'test-lifecycle-version1-1 ' ;
566
615
await create_mock_version ( version_bucket_key , version_bucket , age , version_count , true ) ;
567
616
const putLifecycleParams = commonTests . days_lifecycle_configuration ( version_bucket , version_bucket_key ) ;
568
617
await s3 . putBucketLifecycleConfiguration ( putLifecycleParams ) ;
@@ -574,7 +623,7 @@ mocha.describe('lifecycle', () => {
574
623
mocha . it ( 'lifecyle - version object not expired' , async ( ) => {
575
624
const age = 5 ;
576
625
const version_count = 10 ;
577
- const version_bucket_key = 'test-lifecycle-version2' ;
626
+ const version_bucket_key = 'test-lifecycle-version2-0 ' ;
578
627
await create_mock_version ( version_bucket_key , version_bucket , age , version_count , true ) ;
579
628
const putLifecycleParams = commonTests . days_lifecycle_configuration ( version_bucket , version_bucket_key ) ;
580
629
await s3 . putBucketLifecycleConfiguration ( putLifecycleParams ) ;
@@ -583,7 +632,141 @@ mocha.describe('lifecycle', () => {
583
632
await verify_version_deleted ( version_count , version_bucket_key ) ;
584
633
} ) ;
585
634
586
- async function verify_version_deleted ( expected_length , key ) {
635
+ mocha . it ( 'lifecyle - version not expiration' , async ( ) => {
636
+ const days = 30 ;
637
+ const version_count = 10 ;
638
+ const newnon_current_version = 1 ;
639
+ const noncurrent_days = 15 ;
640
+ const version_bucket_key = 'test-lifecycle-version2-1' ;
641
+ // create_time updated to 29 days and expire is 30 days and noncurrent expire in 15
642
+ await create_mock_version ( version_bucket_key , version_bucket , days - 1 , version_count ) ;
643
+ const putLifecycleParams = commonTests . version_lifecycle_configuration ( version_bucket ,
644
+ version_bucket_key , days , newnon_current_version , noncurrent_days ) ;
645
+
646
+ await s3 . putBucketLifecycleConfiguration ( putLifecycleParams ) ;
647
+ await lifecycle . background_worker ( ) ;
648
+ // remove all the noncurrent versions expect one( newnon_current_version = 1) once 15 days passed
649
+ // current version has not expired. In that case, list will return 2 objects
650
+ await verify_version_deleted ( 2 , version_bucket_key ) ;
651
+ } ) ;
652
+
653
+ mocha . it ( 'lifecyle - version expiration - only NewerNoncurrentVersions exceeded' , async ( ) => {
654
+ const days = 35 ;
655
+ const version_count = 10 ;
656
+ const newnon_current_version = 5 ;
657
+ const noncurrent_days = 30 ;
658
+ const version_bucket_key = 'test-lifecycle-version1-1' ;
659
+ // create_time updated to 36 days and expire is 35 days
660
+ await create_mock_version ( version_bucket_key , version_bucket , days + 1 , version_count , true ) ;
661
+ const putLifecycleParams = commonTests . version_lifecycle_configuration ( version_bucket ,
662
+ version_bucket_key , days , newnon_current_version , noncurrent_days ) ;
663
+
664
+ await s3 . putBucketLifecycleConfiguration ( putLifecycleParams ) ;
665
+ await lifecycle . background_worker ( ) ;
666
+ // object will expire, noncurrent version count(5) + deleted current version(1) + delete marker(1)
667
+ await verify_version_deleted ( 7 , version_bucket_key ) ;
668
+ } ) ;
669
+
670
+ mocha . it ( 'lifecyle - version expiration - only NoncurrentDays exceeded' , async ( ) => {
671
+ const days = 45 ;
672
+ const version_count = 10 ;
673
+ const newnon_current_version = 100 ;
674
+ const noncurrent_days = 30 ;
675
+ const version_bucket_key = 'test-lifecycle-version3' ;
676
+ // create_time updated to 45+30+1= 76 days and expire is 45 days
677
+ await create_mock_version ( version_bucket_key , version_bucket , days + noncurrent_days + 1 , version_count , true ) ;
678
+ const putLifecycleParams = commonTests . version_lifecycle_configuration ( version_bucket ,
679
+ version_bucket_key , days , newnon_current_version , noncurrent_days ) ;
680
+
681
+ await s3 . putBucketLifecycleConfiguration ( putLifecycleParams ) ;
682
+ await lifecycle . background_worker ( ) ;
683
+ // dekete only current version, do not delete noncurrent version because newnon_current_version = 100
684
+ // noncurrent version count + delete marker(1)
685
+ await verify_version_deleted ( 11 , version_bucket_key ) ;
686
+ } ) ;
687
+
688
+ mocha . it ( 'lifecyle - version expiration - both NoncurrentDays and NewerNoncurrentVersions exceeded' , async ( ) => {
689
+ const days = 30 ;
690
+ const version_count = 10 ;
691
+ const newnon_current_version = 1 ;
692
+ const noncurrent_days = 15 ;
693
+ const version_bucket_key = 'test-lifecycle-version4' ;
694
+ // create_time updated to 46 days and expire is 30 days
695
+ await create_mock_version ( version_bucket_key , version_bucket , days + noncurrent_days + 1 , version_count ) ;
696
+ const putLifecycleParams = commonTests . version_lifecycle_configuration ( version_bucket ,
697
+ version_bucket_key , days , newnon_current_version , noncurrent_days ) ;
698
+
699
+ await s3 . putBucketLifecycleConfiguration ( putLifecycleParams ) ;
700
+ await lifecycle . background_worker ( ) ;
701
+ // newnon_current_version count + current version
702
+ await verify_version_deleted ( 2 , version_bucket_key ) ;
703
+ } ) ;
704
+
705
+ mocha . it ( 'lifecyle - version not expiration - delete marker true' , async ( ) => {
706
+ const days = 30 ;
707
+ const version_count = 10 ;
708
+ const newnon_current_version = 0 ;
709
+ const noncurrent_days = 15 ;
710
+ const version_bucket_key = 'test-lifecycle-version5' ;
711
+ // create_time updated to 29 days and expire is 30 days,
712
+ await create_mock_version ( version_bucket_key , version_bucket , days - 1 , version_count , true ) ;
713
+ const putLifecycleParams = commonTests . version_lifecycle_configuration ( version_bucket ,
714
+ version_bucket_key , days , newnon_current_version , noncurrent_days ) ;
715
+
716
+ await s3 . putBucketLifecycleConfiguration ( putLifecycleParams ) ;
717
+ await lifecycle . background_worker ( ) ;
718
+ // remove all the noncurrent version because the noncurrent_days is 15(< 30) and
719
+ // newnon_current_version is 0. Only current version exists
720
+ await verify_version_deleted ( 1 , version_bucket_key ) ;
721
+ } ) ;
722
+
723
+ mocha . it ( 'lifecyle - version expiration all - delete marker true' , async ( ) => {
724
+ const days = 30 ;
725
+ const version_count = 10 ;
726
+ const newnon_current_version = 0 ;
727
+ const noncurrent_days = 15 ;
728
+ const version_bucket_key = 'test-lifecycle-version6' ;
729
+ await create_mock_version ( version_bucket_key , version_bucket , days + noncurrent_days + 1 , version_count , true ) ;
730
+ const putLifecycleParams = commonTests . version_lifecycle_configuration ( version_bucket ,
731
+ version_bucket_key , days , newnon_current_version , noncurrent_days ) ;
732
+ await s3 . putBucketLifecycleConfiguration ( putLifecycleParams ) ;
733
+ await lifecycle . background_worker ( ) ;
734
+ await verify_version_deleted ( 2 , version_bucket_key ) ;
735
+ // add a delay between two worker run
736
+ await P . delay ( 100 ) ; // 0.1sec
737
+ // Complete deletion will happen in two lifecycle run,
738
+ // First delete all the noncurrent version and current version to noncurrent version
739
+ // last noncurrent version( current in first step ) and delete marker
740
+ await age_object ( days + noncurrent_days + 1 , version_bucket_key ) ;
741
+ await lifecycle . background_worker ( ) ;
742
+ await verify_version_deleted ( 1 , version_bucket_key ) ;
743
+
744
+ const putDeleteMarkerLifecycleParams = commonTests . marker_lifecycle_configuration ( version_bucket , version_bucket_key ) ;
745
+ await s3 . putBucketLifecycleConfiguration ( putDeleteMarkerLifecycleParams ) ;
746
+ await lifecycle . background_worker ( ) ;
747
+ await verify_version_deleted ( 0 , version_bucket_key ) ;
748
+ } ) ;
749
+
750
+ async function age_object ( age , key = '' ) {
751
+ const obj_params = {
752
+ bucket : version_bucket ,
753
+ prefix : key ,
754
+ } ;
755
+ const obj_ids = [ ] ;
756
+ const { objects} = await rpc_client . object . list_object_versions ( obj_params ) ;
757
+ for ( const object of objects ) {
758
+ obj_ids . push ( object . obj_id ) ;
759
+ }
760
+ if ( age > 0 ) {
761
+ const update = {
762
+ create_time : moment ( ) . subtract ( age , 'days' ) . toDate ( ) ,
763
+ } ;
764
+ console . log ( 'age_object: bucket' , version_bucket , 'obj_ids' , obj_ids , " obj_upload_ids length: " , obj_ids . length , "update :" , update ) ;
765
+ await MDStore . instance ( ) . update_objects_by_ids ( obj_ids , update ) ;
766
+ }
767
+ }
768
+
769
+ async function verify_version_deleted ( expected_length , key = '' ) {
587
770
const obj_params = {
588
771
bucket : version_bucket ,
589
772
prefix : key ,
0 commit comments