@@ -26,12 +26,16 @@ const { TMP_PATH, generate_s3_policy } = require('../system_tests/test_utils');
26
26
const { CONFIG_SUBDIRS , JSON_SUFFIX } = require ( '../../sdk/config_fs' ) ;
27
27
const nc_mkm = require ( '../../manage_nsfs/nc_master_key_manager' ) . get_instance ( ) ;
28
28
29
+ const XATTR_INTERNAL_NOOBAA_PREFIX = 'user.noobaa.' ;
30
+ const XATTR_VERSION_ID = XATTR_INTERNAL_NOOBAA_PREFIX + 'version_id' ;
31
+ const XATTR_DELETE_MARKER = XATTR_INTERNAL_NOOBAA_PREFIX + 'delete_marker' ;
29
32
30
33
const test_bucket = 'bucket1' ;
31
34
const test_bucket2 = 'bucket2' ;
32
35
const test_not_empty_bucket = 'notemptybucket' ;
33
36
const test_bucket_temp_dir = 'buckettempdir' ;
34
37
const test_bucket_invalid = 'bucket_invalid' ;
38
+ const test_bucket_delete_marker = 'deletemarkerbucket' ;
35
39
const test_bucket_iam_account = 'bucket-iam-account-can-access' ;
36
40
37
41
const tmp_fs_path = path . join ( TMP_PATH , 'test_bucketspace_fs' ) ;
@@ -217,6 +221,39 @@ function make_dummy_object_sdk() {
217
221
} ;
218
222
}
219
223
224
+ function make_versioning_object_sdk ( ) {
225
+ const versioning_object_sdk = make_dummy_object_sdk ( ) ;
226
+ versioning_object_sdk . nsfs = { } ;
227
+ versioning_object_sdk . _get_bucket_namespace = name => {
228
+ if ( _ . isUndefined ( versioning_object_sdk . nsfs [ name ] ) ) {
229
+ const buck_path = path . join ( new_buckets_path , name ) ;
230
+ versioning_object_sdk . nsfs [ name ] = new NamespaceFS ( {
231
+ bucket_path : buck_path ,
232
+ bucket_id : '1' ,
233
+ namespace_resource_id : undefined ,
234
+ access_mode : undefined ,
235
+ versioning : undefined ,
236
+ force_md5_etag : undefined ,
237
+ stats : undefined
238
+ } ) ;
239
+ }
240
+ return versioning_object_sdk . nsfs [ name ] ;
241
+ } ;
242
+ versioning_object_sdk . read_bucket_full_info = async function ( name ) {
243
+ const ns = this . _get_bucket_namespace ( name ) ;
244
+ const bucket = ( await bucketspace_fs . read_bucket_sdk_info ( { name } ) ) ;
245
+ if ( name === test_bucket_temp_dir ) {
246
+ bucket . namespace . should_create_underlying_storage = false ;
247
+ } else {
248
+ bucket . namespace . should_create_underlying_storage = true ;
249
+ }
250
+ return { ns, bucket} ;
251
+ } ;
252
+
253
+ return versioning_object_sdk ;
254
+ }
255
+
256
+
220
257
// account_user2 (copied from the dummy sdk)
221
258
// is the root account of account_iam_user1
222
259
const account_iam_user1 = {
@@ -637,7 +674,34 @@ mocha.describe('bucketspace_fs', function() {
637
674
await bucketspace_fs . delete_bucket ( param , dummy_object_sdk ) ;
638
675
await fs_utils . file_must_not_exist ( bucket_config_path ) ;
639
676
} ) ;
677
+
678
+ mocha . it ( 'delete_bucket with delete marker' , async function ( ) {
679
+ const versioning_sdk = make_versioning_object_sdk ( ) ;
680
+ const param = { name : test_bucket_delete_marker } ;
681
+ await create_bucket ( param . name ) ;
682
+
683
+ await bucketspace_fs . set_bucket_versioning ( { name : param . name , versioning : 'ENABLED' } , versioning_sdk ) ;
684
+ const version_dir = path . join ( new_buckets_path , param . name , '.versions' ) ;
685
+ await nb_native ( ) . fs . mkdir ( ACCOUNT_FS_CONFIG , version_dir ) ;
686
+
687
+ const versioned_path = path . join ( version_dir , 'dummy_mtime-crkfjum9883k-ino-guu7' ) ;
688
+ await create_versioned_object ( versioned_path , Buffer . from ( JSON . stringify ( "data" ) ) , 'mtime-crkfjum9883k-ino-guu7' , false ) ;
689
+
690
+ const delete_marker_path = path . join ( version_dir , 'dummy_mtime-crkfjx1hui2o-ino-guu9' ) ;
691
+ const delete_marker_obj = await create_versioned_object ( delete_marker_path , Buffer . from ( JSON . stringify ( "data" ) ) , 'mtime-crkfjx1hui2o-ino-guu9' , true ) ;
692
+ const xattr_delete_marker = { [ XATTR_DELETE_MARKER ] : 'true' } ;
693
+ delete_marker_obj . replacexattr ( DEFAULT_FS_CONFIG , xattr_delete_marker ) ;
694
+
695
+ try {
696
+ await bucketspace_fs . delete_bucket ( param , versioning_sdk ) ;
697
+ assert . fail ( 'should have failed with NOT EMPTY' ) ;
698
+ } catch ( err ) {
699
+ assert . strictEqual ( err . rpc_code , 'NOT_EMPTY' ) ;
700
+ assert . equal ( err . message , 'underlying directory has files in it' ) ;
701
+ }
702
+ } ) ;
640
703
} ) ;
704
+
641
705
mocha . describe ( 'set_bucket_versioning' , function ( ) {
642
706
mocha . before ( async function ( ) {
643
707
await create_bucket ( test_bucket ) ;
@@ -900,6 +964,18 @@ async function create_bucket(bucket_name) {
900
964
assert . equal ( stat1 . nlink , 1 ) ;
901
965
}
902
966
967
+ async function create_versioned_object ( object_path , data , version_id , return_fd ) {
968
+ console . log ( object_path ) ;
969
+ const target_file = await nb_native ( ) . fs . open ( ACCOUNT_FS_CONFIG , object_path , 'w+' ) ;
970
+ await fs . promises . writeFile ( object_path , data ) ;
971
+ if ( version_id !== 'null' ) {
972
+ const xattr_version_id = { [ XATTR_VERSION_ID ] : `${ version_id } ` } ;
973
+ await target_file . replacexattr ( ACCOUNT_FS_CONFIG , xattr_version_id ) ;
974
+ }
975
+ if ( return_fd ) return target_file ;
976
+ await target_file . close ( ACCOUNT_FS_CONFIG ) ;
977
+ }
978
+
903
979
904
980
function get_config_file_path ( config_type_path , file_name ) {
905
981
return path . join ( config_root , config_type_path , file_name + JSON_SUFFIX ) ;
0 commit comments