Skip to content

Commit 37429af

Browse files
authored
Merge pull request #8300 from dannyzaken/danny-nc-lifecycle
Added lifecycle configuration support in bucketspace_fs
2 parents 8c93a87 + 8906f86 commit 37429af

File tree

8 files changed

+217
-170
lines changed

8 files changed

+217
-170
lines changed

.jsbeautifyrc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
2-
"indent_size": 4,
3-
"indent_char": " ",
4-
"indent_level": 0,
5-
"indent_with_tabs": false,
6-
"brace_style": "collapse,preserve-inline",
7-
"preserve_newlines": true,
8-
"max_preserve_newlines": 10,
9-
"end_with_newline": true
2+
"indent_size": 4,
3+
"indent_char": " ",
4+
"indent_level": 0,
5+
"indent_with_tabs": false,
6+
"brace_style": "collapse,preserve-inline",
7+
"preserve_newlines": true,
8+
"max_preserve_newlines": 10,
9+
"end_with_newline": true
1010
}

docs/NooBaaNonContainerized/S3Ops.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ The following lists describe the bucket and object operations available in NooBa
2525
- S3 DeleteBucketPolicy
2626
- S3 GetBucketPolicy
2727
- S3 GetBucketPolicyStatus
28+
- S3 PutBucketLifecycleConfiguration
29+
- S3 GetBucketLifecycleConfiguration
30+
- S3 DeleteBucketLifecycle
31+
2832

2933
### Supported S3 Object Operations
3034

src/api/bucket_api.js

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -599,12 +599,7 @@ module.exports = {
599599
type: 'object',
600600
properties: {
601601
name: { $ref: 'common_api#/definitions/bucket_name' },
602-
rules: {
603-
type: 'array',
604-
items: {
605-
$ref: 'common_api#/definitions/bucket_lifecycle_rule'
606-
},
607-
}
602+
rules: { $ref: 'common_api#/definitions/bucket_lifecycle_configuration' }
608603
}
609604
},
610605
auth: {
@@ -620,12 +615,7 @@ module.exports = {
620615
name: { $ref: 'common_api#/definitions/bucket_name' },
621616
}
622617
},
623-
reply: {
624-
type: 'array',
625-
items: {
626-
$ref: 'common_api#/definitions/bucket_lifecycle_rule'
627-
}
628-
},
618+
reply: { $ref: 'common_api#/definitions/bucket_lifecycle_configuration' },
629619
auth: {
630620
system: 'admin'
631621
}
@@ -1385,7 +1375,7 @@ module.exports = {
13851375
type: 'object',
13861376
properties: {
13871377
prefix: { type: 'string' },
1388-
// s3 support also tag or and operator of 2 tags/ tag and prefix
1378+
// s3 support also tag or and operator of 2 tags/ tag and prefix
13891379
}
13901380
},
13911381
sync_deletions: { type: 'boolean' },

src/api/common_api.js

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ module.exports = {
195195
}
196196
}
197197
},
198+
bucket_lifecycle_configuration: {
199+
type: 'array',
200+
items: {
201+
$ref: '#/definitions/bucket_lifecycle_rule'
202+
}
203+
},
198204
bucket_lifecycle_rule: {
199205
type: 'object',
200206
required: ['id', 'filter', 'expiration', 'status'],
@@ -259,27 +265,26 @@ module.exports = {
259265

260266
bucket_policy_principal: {
261267
anyOf: [{
262-
wrapper: SensitiveString
263-
}, {
264-
type: 'object',
265-
required: ['AWS'],
266-
properties: {
267-
AWS: {
268-
anyOf: [{
269-
wrapper: SensitiveString
270-
}, {
271-
type: 'array',
272-
items: {
273-
wrapper: SensitiveString
274-
}
275-
}]
276-
}
268+
wrapper: SensitiveString
269+
}, {
270+
type: 'object',
271+
required: ['AWS'],
272+
properties: {
273+
AWS: {
274+
anyOf: [{
275+
wrapper: SensitiveString
276+
}, {
277+
type: 'array',
278+
items: {
279+
wrapper: SensitiveString
280+
}
281+
}]
277282
}
278283
}
279-
]},
284+
}]
285+
},
280286
string_or_string_array: {
281-
anyOf: [
282-
{
287+
anyOf: [{
283288
type: 'string'
284289
},
285290
{
@@ -288,7 +293,7 @@ module.exports = {
288293
type: 'string'
289294
}
290295
}
291-
]
296+
]
292297
},
293298

294299
bucket_policy_string_condition: {
@@ -314,8 +319,7 @@ module.exports = {
314319
Statement: {
315320
type: 'array',
316321
items: {
317-
allOf: [
318-
{
322+
allOf: [{
319323
type: 'object',
320324
required: ['Effect'],
321325
properties: {
@@ -378,8 +382,7 @@ module.exports = {
378382
// the schema above. these schemas are only here to validate the mutually exclusive required fields
379383
// they should be replaced once we support allOf for individual fields
380384
{
381-
oneOf: [
382-
{
385+
oneOf: [{
383386
type: 'object',
384387
required: ["Principal"],
385388
additionalProperties: true,
@@ -394,8 +397,7 @@ module.exports = {
394397
],
395398
},
396399
{
397-
oneOf: [
398-
{
400+
oneOf: [{
399401
type: 'object',
400402
required: ["Action"],
401403
additionalProperties: true,
@@ -407,11 +409,10 @@ module.exports = {
407409
additionalProperties: true,
408410
properties: {}
409411
}
410-
],
412+
],
411413
},
412414
{
413-
oneOf: [
414-
{
415+
oneOf: [{
415416
type: 'object',
416417
required: ["Resource"],
417418
additionalProperties: true,
@@ -1270,7 +1271,7 @@ module.exports = {
12701271
}
12711272
},
12721273

1273-
// nsfs
1274+
// nsfs
12741275

12751276
fs_backend: {
12761277
type: 'string',
@@ -1301,7 +1302,7 @@ module.exports = {
13011302
}
13021303
}, {
13031304
type: 'object',
1304-
required: [ 'distinguished_name', 'new_buckets_path', 'nsfs_only'],
1305+
required: ['distinguished_name', 'new_buckets_path', 'nsfs_only'],
13051306
properties: {
13061307
distinguished_name: { wrapper: SensitiveString },
13071308
new_buckets_path: { type: 'string' },

src/sdk/bucketspace_fs.js

Lines changed: 59 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,25 @@ const { ConfigFS, JSON_SUFFIX, CONFIG_TYPES } = require('./config_fs');
1919
const mongo_utils = require('../util/mongo_utils');
2020

2121
const KeysSemaphore = require('../util/keys_semaphore');
22-
const { get_umasked_mode, validate_bucket_creation, get_bucket_tmpdir_full_path, folder_delete,
23-
entity_enum, translate_error_codes, get_process_fs_context} = require('../util/native_fs_utils');
22+
const {
23+
get_umasked_mode,
24+
validate_bucket_creation,
25+
get_bucket_tmpdir_full_path,
26+
folder_delete,
27+
entity_enum,
28+
translate_error_codes,
29+
get_process_fs_context
30+
} = require('../util/native_fs_utils');
2431
const NoobaaEvent = require('../manage_nsfs/manage_nsfs_events_utils').NoobaaEvent;
2532
const { anonymous_access_key } = require('./object_sdk');
2633

2734
const dbg = require('../util/debug_module')(__filename);
2835
const bucket_semaphore = new KeysSemaphore(1);
2936

3037

31-
3238
class BucketSpaceFS extends BucketSpaceSimpleFS {
33-
constructor({config_root}, stats) {
34-
super({ fs_root: ''});
39+
constructor({ config_root }, stats) {
40+
super({ fs_root: '' });
3541
this.config_root = config_root;
3642
this.stats = stats;
3743
this.fs_context = get_process_fs_context(
@@ -85,7 +91,7 @@ class BucketSpaceFS extends BucketSpaceSimpleFS {
8591
throw new RpcError('NO_SUCH_ACCOUNT', `Account with access_key not found.`, err);
8692
}
8793
//account access failed
88-
new NoobaaEvent(NoobaaEvent.ACCOUNT_NOT_FOUND).create_event(access_key, {access_key: access_key}, err);
94+
new NoobaaEvent(NoobaaEvent.ACCOUNT_NOT_FOUND).create_event(access_key, { access_key: access_key }, err);
8995
throw new RpcError('NO_SUCH_ACCOUNT', err.message);
9096
}
9197
}
@@ -154,7 +160,7 @@ class BucketSpaceFS extends BucketSpaceSimpleFS {
154160
} catch (err) {
155161
const rpc_error = translate_error_codes(err, entity_enum.BUCKET);
156162
if (err.rpc_code === 'INVALID_SCHEMA') err.rpc_code = 'INVALID_BUCKET_STATE';
157-
new NoobaaEvent(NoobaaEvent[rpc_error.rpc_code]).create_event(name, {bucket_name: name}, err);
163+
new NoobaaEvent(NoobaaEvent[rpc_error.rpc_code]).create_event(name, { bucket_name: name }, err);
158164
throw rpc_error;
159165
}
160166
}
@@ -237,7 +243,7 @@ class BucketSpaceFS extends BucketSpaceSimpleFS {
237243
}
238244
// currently we do not allow IAM account to create a bucket (temporary)
239245
if (sdk.requesting_account.owner !== undefined) {
240-
dbg.warn('create_bucket: account is IAM account (currently not allowed to create buckets)');
246+
dbg.warn('create_bucket: account is IAM account (currently not allowed to create buckets)');
241247
throw new RpcError('UNAUTHORIZED', 'Not allowed to create new buckets');
242248
}
243249
if (!sdk.requesting_account.nsfs_account_config || !sdk.requesting_account.nsfs_account_config.new_buckets_path) {
@@ -271,17 +277,18 @@ class BucketSpaceFS extends BucketSpaceSimpleFS {
271277
nsfs_schema_utils.validate_bucket_schema(bucket_to_validate);
272278
await this.config_fs.create_bucket_config_file(name, bucket_config);
273279
} catch (err) {
274-
new NoobaaEvent(NoobaaEvent.BUCKET_CREATION_FAILED).create_event(name, {bucket_name: name}, err);
280+
new NoobaaEvent(NoobaaEvent.BUCKET_CREATION_FAILED).create_event(name, { bucket_name: name }, err);
275281
throw translate_error_codes(err, entity_enum.BUCKET);
276282
}
277283

278284
// create bucket's underlying storage directory
279285
try {
280286
await nb_native().fs.mkdir(fs_context, bucket_storage_path, get_umasked_mode(config.BASE_MODE_DIR));
281-
new NoobaaEvent(NoobaaEvent.BUCKET_CREATED).create_event(name, {bucket_name: name});
287+
new NoobaaEvent(NoobaaEvent.BUCKET_CREATED).create_event(name, { bucket_name: name });
282288
} catch (err) {
283289
dbg.error('BucketSpaceFS: create_bucket could not create underlying directory - nsfs, deleting bucket', err);
284-
new NoobaaEvent(NoobaaEvent.BUCKET_DIR_CREATION_FAILED).create_event(name, {bucket: name, path: bucket_storage_path}, err);
290+
new NoobaaEvent(NoobaaEvent.BUCKET_DIR_CREATION_FAILED)
291+
.create_event(name, { bucket: name, path: bucket_storage_path }, err);
285292
await nb_native().fs.unlink(this.fs_context, bucket_config_path);
286293
throw translate_error_codes(err, entity_enum.BUCKET);
287294
}
@@ -358,8 +365,8 @@ class BucketSpaceFS extends BucketSpaceSimpleFS {
358365
new NoobaaEvent(NoobaaEvent.BUCKET_DELETE).create_event(name, { bucket_name: name });
359366
} catch (err) {
360367
dbg.error('BucketSpaceFS: delete_bucket: bucket name', name, 'error', err);
361-
new NoobaaEvent(NoobaaEvent.BUCKET_DELETE_FAILED).create_event(name,
362-
{ bucket_name: name, bucket_path: bucket_config_path }, err);
368+
new NoobaaEvent(NoobaaEvent.BUCKET_DELETE_FAILED)
369+
.create_event(name, { bucket_name: name, bucket_path: bucket_config_path }, err);
363370
throw translate_error_codes(err, entity_enum.BUCKET);
364371
}
365372
});
@@ -371,15 +378,41 @@ class BucketSpaceFS extends BucketSpaceSimpleFS {
371378
//////////////////////
372379

373380
async get_bucket_lifecycle_configuration_rules(params) {
374-
// TODO
381+
try {
382+
const { name } = params;
383+
dbg.log0('BucketSpaceFS.get_bucket_lifecycle_configuration_rules: Bucket name', name);
384+
const bucket = await this.config_fs.get_bucket_by_name(name);
385+
return bucket.lifecycle_configuration_rules || [];
386+
} catch (error) {
387+
throw translate_error_codes(error, entity_enum.BUCKET);
388+
}
375389
}
376390

377391
async set_bucket_lifecycle_configuration_rules(params) {
378-
// TODO
392+
try {
393+
const { name, rules } = params;
394+
dbg.log0('BucketSpaceFS.set_bucket_lifecycle_configuration_rules: Bucket name, rules', name, rules);
395+
const bucket = await this.config_fs.get_bucket_by_name(name);
396+
bucket.lifecycle_configuration_rules = rules;
397+
nsfs_schema_utils.validate_bucket_schema(bucket);
398+
const update_bucket = JSON.stringify(bucket);
399+
await this.config_fs.update_bucket_config_file(name, update_bucket);
400+
} catch (err) {
401+
throw translate_error_codes(err, entity_enum.BUCKET);
402+
}
379403
}
380404

381405
async delete_bucket_lifecycle(params) {
382-
// TODO
406+
try {
407+
const { name } = params;
408+
dbg.log0('BucketSpaceFS.delete_bucket_lifecycle: Bucket name', name);
409+
const bucket = await this.config_fs.get_bucket_by_name(name);
410+
delete bucket.lifecycle_configuration_rules;
411+
nsfs_schema_utils.validate_bucket_schema(bucket);
412+
await this.config_fs.update_bucket_config_file(name, JSON.stringify(bucket));
413+
} catch (error) {
414+
throw translate_error_codes(error, entity_enum.BUCKET);
415+
}
383416
}
384417

385418
///////////////////////
@@ -517,7 +550,7 @@ class BucketSpaceFS extends BucketSpaceSimpleFS {
517550
// in case it is algorithm: 'AES256', the property would be undefined
518551
const bucket_to_validate = _.omitBy(bucket, _.isUndefined);
519552
dbg.log2("put_bucket_encryption: bucket properties before validate_bucket_schema",
520-
bucket_to_validate);
553+
bucket_to_validate);
521554
nsfs_schema_utils.validate_bucket_schema(bucket_to_validate);
522555
const update_bucket = JSON.stringify(bucket);
523556
await this.config_fs.update_bucket_config_file(name, update_bucket);
@@ -565,7 +598,7 @@ class BucketSpaceFS extends BucketSpaceSimpleFS {
565598
bucket.website = website;
566599
const bucket_to_validate = _.omitBy(bucket, _.isUndefined);
567600
dbg.log2("put_bucket_website: bucket properties before validate_bucket_schema",
568-
bucket_to_validate);
601+
bucket_to_validate);
569602
nsfs_schema_utils.validate_bucket_schema(bucket_to_validate);
570603
const update_bucket = JSON.stringify(bucket);
571604
await this.config_fs.update_bucket_config_file(name, update_bucket);
@@ -591,9 +624,9 @@ class BucketSpaceFS extends BucketSpaceSimpleFS {
591624
}
592625

593626
/**
594-
* @param {object} params
595-
* @returns {Promise<object>}
596-
*/
627+
* @param {object} params
628+
* @returns {Promise<object>}
629+
*/
597630
async get_bucket_website(params) {
598631
try {
599632
const { name } = params;
@@ -620,7 +653,7 @@ class BucketSpaceFS extends BucketSpaceSimpleFS {
620653
dbg.log2('put_bucket_policy: bucket properties before validate_bucket_schema', bucket_to_validate);
621654
nsfs_schema_utils.validate_bucket_schema(bucket_to_validate);
622655
await bucket_policy_utils.validate_s3_policy(bucket.s3_policy, bucket.name, async principal =>
623-
this.config_fs.get_account_by_name(principal, { silent_if_missing: true }));
656+
this.config_fs.get_account_by_name(principal, { silent_if_missing: true }));
624657
const update_bucket = JSON.stringify(bucket);
625658
await this.config_fs.update_bucket_config_file(name, update_bucket);
626659
} catch (err) {
@@ -686,10 +719,10 @@ class BucketSpaceFS extends BucketSpaceSimpleFS {
686719
const bucket_policy = bucket.s3_policy;
687720

688721
if (!bucket_policy) {
689-
// in case we do not have bucket policy
690-
// we allow IAM account to access a bucket that that is owned by their root account
691-
const is_iam_and_same_root_account_owner = account.owner !== undefined &&
692-
account.owner === bucket.owner_account.id;
722+
// in case we do not have bucket policy
723+
// we allow IAM account to access a bucket that that is owned by their root account
724+
const is_iam_and_same_root_account_owner = account.owner !== undefined &&
725+
account.owner === bucket.owner_account.id;
693726
return is_owner || is_iam_and_same_root_account_owner;
694727
}
695728
if (!action) {

src/server/system_services/schemas/bucket_schema.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,7 @@ module.exports = {
201201

202202
//lifecycle rules if exist
203203
lifecycle_configuration_rules: {
204-
type: 'array',
205-
items: {
206-
$ref: 'common_api#/definitions/bucket_lifecycle_rule'
207-
}
204+
$ref: 'common_api#/definitions/bucket_lifecycle_configuration'
208205
},
209206
tagging: {
210207
$ref: 'common_api#/definitions/tagging',

0 commit comments

Comments
 (0)