Skip to content

Commit ff235ec

Browse files
authored
Merge pull request #8449 from dannyzaken/danny-fixes
fixed get lifecycle conf to support all possible fields
2 parents e4c7b7d + 0186e10 commit ff235ec

File tree

4 files changed

+267
-9
lines changed

4 files changed

+267
-9
lines changed

src/api/common_api.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,9 @@ module.exports = {
211211
filter: {
212212
$ref: '#/definitions/bucket_lifecycle_rule_filter'
213213
},
214+
uses_prefix: {
215+
type: 'boolean'
216+
},
214217
expiration: {
215218
$ref: '#/definitions/bucket_lifecycle_rule_expiration'
216219
},
@@ -1359,7 +1362,9 @@ module.exports = {
13591362

13601363
storage_class_enum: {
13611364
type: 'string',
1362-
enum: ['STANDARD', 'GLACIER', 'GLACIER_IR']
1365+
// added values according to the docs here:
1366+
// https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-noncurrentversiontransition.html#cfn-s3-bucket-noncurrentversiontransition-storageclass
1367+
enum: ['STANDARD', 'GLACIER', 'GLACIER_IR', 'Glacier', 'DEEP_ARCHIVE', 'INTELLIGENT_TIERING', 'ONEZONE_IA', 'STANDARD_IA']
13631368
},
13641369
bucket_logging: {
13651370
type: 'object',

src/endpoint/s3/ops/s3_get_bucket_lifecycle.js

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ async function get_bucket_lifecycle(req) {
1515
};
1616

1717

18-
if (rule.filter.and) {
18+
if (rule.uses_prefix) {
19+
current_rule.Prefix = rule.filter.prefix;
20+
} else if (rule.filter.and) {
1921
current_rule.Filter = {
2022
And: [{
2123
Prefix: rule.filter.prefix,
@@ -40,14 +42,51 @@ async function get_bucket_lifecycle(req) {
4042
}
4143
}
4244

43-
// Generally expiration is optional,
44-
// however NooBaa implements expiration only, so it is expected here.
45-
current_rule.Expiration = {
46-
Days: rule.expiration.days,
47-
};
48-
if (rule.expiration.date) {
49-
current_rule.Expiration.Date = new Date(rule.expiration.date).toISOString();
45+
46+
if (rule.expiration) {
47+
current_rule.Expiration = {
48+
Days: rule.expiration.days,
49+
Date: rule.expiration.date ? new Date(rule.expiration.date).toISOString() : undefined,
50+
};
51+
_.omitBy(current_rule.Expiration, _.isUndefined);
52+
}
53+
54+
if (rule.transition) {
55+
current_rule.Transition = {
56+
Days: rule.transition.days,
57+
Date: rule.transition.date ? new Date(rule.transition.date).toISOString() : undefined,
58+
StorageClass: rule.transition.storage_class,
59+
};
60+
_.omitBy(current_rule.Transition, _.isUndefined);
5061
}
62+
63+
if (rule.noncurrent_version_transition) {
64+
current_rule.NoncurrentVersionTransition = {
65+
NoncurrentDays: rule.noncurrent_version_transition.noncurrent_days,
66+
NewerNoncurrentVersions: rule.noncurrent_version_transition.newer_noncurrent_versions,
67+
StorageClass: rule.noncurrent_version_transition.storage_class,
68+
};
69+
_.omitBy(current_rule.NoncurrentVersionTransition, _.isUndefined);
70+
}
71+
72+
if (rule.noncurrent_version_expiration) {
73+
current_rule.NoncurrentVersionExpiration = {
74+
NoncurrentDays: rule.noncurrent_version_expiration.noncurrent_days,
75+
NewerNoncurrentVersions: rule.noncurrent_version_expiration.newer_noncurrent_versions,
76+
};
77+
_.omitBy(current_rule.NoncurrentVersionExpiration, _.isUndefined);
78+
}
79+
80+
if (rule.abort_incomplete_multipart_upload) {
81+
current_rule.AbortIncompleteMultipartUpload = {
82+
DaysAfterInitiation: rule.abort_incomplete_multipart_upload.days_after_initiation,
83+
};
84+
_.omitBy(current_rule.AbortIncompleteMultipartUpload, _.isUndefined);
85+
}
86+
87+
88+
89+
5190
return { Rule: current_rule };
5291
});
5392

src/endpoint/s3/ops/s3_put_bucket_lifecycle.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ async function put_bucket_lifecycle(req) {
9999
throw new S3Error(S3Error.InvalidArgument);
100100
}
101101
current_rule.filter.prefix = rule.Prefix[0];
102+
current_rule.uses_prefix = true;
102103

103104
} else {
104105
if (rule.Filter?.length !== 1) {

src/test/unit_tests/test_s3_ops.js

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,219 @@ mocha.describe('s3_ops', function() {
195195
// cleanup
196196
await rpc_client.account.delete_account({ email: "obc-account@noobaa.io" });
197197
});
198+
199+
200+
mocha.describe('bucket-lifecycle', function() {
201+
202+
mocha.before(async function() {
203+
await s3.createBucket({ Bucket: "lifecycle-bucket" });
204+
});
205+
206+
mocha.it('should put and get bucket lifecycle with Prefix', async function() {
207+
208+
// put bucket lifecycle
209+
const params = {
210+
Bucket: "lifecycle-bucket",
211+
LifecycleConfiguration: {
212+
Rules: [{
213+
ID: 'rule1',
214+
Status: 'Enabled',
215+
Prefix: 'prefix1-prefix',
216+
Expiration: {
217+
Days: 1
218+
}
219+
}]
220+
}
221+
};
222+
await s3.putBucketLifecycleConfiguration(params);
223+
224+
// get` bucket lifecycle
225+
const res = await s3.getBucketLifecycleConfiguration({ Bucket: "lifecycle-bucket" });
226+
assert.strictEqual(res.Rules.length, 1);
227+
assert.strictEqual(res.Rules[0].ID, 'rule1');
228+
assert.strictEqual(res.Rules[0].Status, 'Enabled');
229+
assert.strictEqual(res.Rules[0].Prefix, 'prefix1-prefix');
230+
assert.strictEqual(res.Rules[0].Expiration.Days, 1);
231+
});
232+
233+
mocha.it('should put and get bucket lifecycle with Filter', async function() {
234+
// put bucket lifecycle
235+
const params = {
236+
Bucket: "lifecycle-bucket",
237+
LifecycleConfiguration: {
238+
Rules: [{
239+
ID: 'rule1',
240+
Status: 'Enabled',
241+
Filter: {
242+
And: {
243+
Prefix: 'prefix1',
244+
Tags: [{
245+
Key: 'key1',
246+
Value: 'value1'
247+
}]
248+
}
249+
},
250+
Expiration: {
251+
Days: 1
252+
}
253+
}]
254+
}
255+
};
256+
await s3.putBucketLifecycleConfiguration(params);
257+
258+
// get bucket lifecycle
259+
const res = await s3.getBucketLifecycleConfiguration({ Bucket: "lifecycle-bucket" });
260+
assert.strictEqual(res.Rules.length, 1);
261+
assert.strictEqual(res.Rules[0].ID, 'rule1');
262+
assert.strictEqual(res.Rules[0].Status, 'Enabled');
263+
assert.strictEqual(res.Rules[0].Filter.And.Prefix, 'prefix1');
264+
assert.strictEqual(res.Rules[0].Filter.And.Tags[0].Key, 'key1');
265+
assert.strictEqual(res.Rules[0].Filter.And.Tags[0].Value, 'value1');
266+
assert.strictEqual(res.Rules[0].Expiration.Days, 1);
267+
});
268+
269+
mocha.it('should put and get bucket lifecycle with Transitions', async function() {
270+
// put bucket lifecycle
271+
const params = {
272+
Bucket: "lifecycle-bucket",
273+
LifecycleConfiguration: {
274+
Rules: [{
275+
ID: 'rule1',
276+
Status: 'Enabled',
277+
Prefix: 'prefix1-transition',
278+
Transitions: [{
279+
Days: 1,
280+
StorageClass: 'STANDARD_IA'
281+
}]
282+
}]
283+
}
284+
};
285+
await s3.putBucketLifecycleConfiguration(params);
286+
287+
// get bucket lifecycle
288+
const res = await s3.getBucketLifecycleConfiguration({ Bucket: "lifecycle-bucket" });
289+
assert.strictEqual(res.Rules.length, 1);
290+
assert.strictEqual(res.Rules[0].ID, 'rule1');
291+
assert.strictEqual(res.Rules[0].Status, 'Enabled');
292+
assert.strictEqual(res.Rules[0].Prefix, 'prefix1-transition');
293+
assert.strictEqual(res.Rules[0].Transitions[0].Days, 1);
294+
assert.strictEqual(res.Rules[0].Transitions[0].StorageClass, 'STANDARD_IA');
295+
});
296+
297+
mocha.it('should put and get bucket lifecycle with NoncurrentVersionTransition', async function() {
298+
// put bucket lifecycle
299+
const params = {
300+
Bucket: "lifecycle-bucket",
301+
LifecycleConfiguration: {
302+
Rules: [{
303+
ID: 'rule1',
304+
Status: 'Enabled',
305+
Prefix: 'prefix1-noncurrent-version-transition',
306+
NoncurrentVersionTransitions: [{
307+
NoncurrentDays: 1,
308+
StorageClass: 'STANDARD_IA'
309+
}]
310+
}]
311+
}
312+
};
313+
await s3.putBucketLifecycleConfiguration(params);
314+
315+
// get bucket lifecycle
316+
const res = await s3.getBucketLifecycleConfiguration({ Bucket: "lifecycle-bucket" });
317+
assert.strictEqual(res.Rules.length, 1);
318+
assert.strictEqual(res.Rules[0].ID, 'rule1');
319+
assert.strictEqual(res.Rules[0].Status, 'Enabled');
320+
assert.strictEqual(res.Rules[0].Prefix, 'prefix1-noncurrent-version-transition');
321+
assert.strictEqual(res.Rules[0].NoncurrentVersionTransitions[0].NoncurrentDays, 1);
322+
assert.strictEqual(res.Rules[0].NoncurrentVersionTransitions[0].StorageClass, 'STANDARD_IA');
323+
});
324+
325+
mocha.it('should put and get bucket lifecycle with AbortIncompleteMultipartUpload', async function() {
326+
// put bucket lifecycle
327+
const params = {
328+
Bucket: "lifecycle-bucket",
329+
LifecycleConfiguration: {
330+
Rules: [{
331+
ID: 'rule1',
332+
Status: 'Enabled',
333+
Prefix: 'prefix1-abort-incomplete',
334+
AbortIncompleteMultipartUpload: {
335+
DaysAfterInitiation: 1
336+
}
337+
}]
338+
}
339+
};
340+
await s3.putBucketLifecycleConfiguration(params);
341+
342+
// get bucket lifecycle
343+
const res = await s3.getBucketLifecycleConfiguration({ Bucket: "lifecycle-bucket" });
344+
assert.strictEqual(res.Rules.length, 1);
345+
assert.strictEqual(res.Rules[0].ID, 'rule1');
346+
assert.strictEqual(res.Rules[0].Status, 'Enabled');
347+
assert.strictEqual(res.Rules[0].Prefix, 'prefix1-abort-incomplete');
348+
assert.strictEqual(res.Rules[0].AbortIncompleteMultipartUpload.DaysAfterInitiation, 1);
349+
350+
});
351+
352+
mocha.it('should put and get bucket lifecycle with Expiration', async function() {
353+
// put bucket lifecycle
354+
const params = {
355+
Bucket: "lifecycle-bucket",
356+
LifecycleConfiguration: {
357+
Rules: [{
358+
ID: 'rule1',
359+
Status: 'Enabled',
360+
Prefix: 'prefix1-expiration',
361+
Expiration: {
362+
Days: 1
363+
}
364+
}]
365+
}
366+
};
367+
await s3.putBucketLifecycleConfiguration(params);
368+
369+
// get bucket lifecycle
370+
const res = await s3.getBucketLifecycleConfiguration({ Bucket: "lifecycle-bucket" });
371+
assert.strictEqual(res.Rules.length, 1);
372+
assert.strictEqual(res.Rules[0].ID, 'rule1');
373+
assert.strictEqual(res.Rules[0].Status, 'Enabled');
374+
assert.strictEqual(res.Rules[0].Prefix, 'prefix1-expiration');
375+
assert.strictEqual(res.Rules[0].Expiration.Days, 1);
376+
});
377+
378+
mocha.it('should put and get bucket lifecycle with NoncurrentVersionExpiration', async function() {
379+
// put bucket lifecycle
380+
const params = {
381+
Bucket: "lifecycle-bucket",
382+
LifecycleConfiguration: {
383+
Rules: [{
384+
ID: 'rule1',
385+
Status: 'Enabled',
386+
Filter: {
387+
Prefix: 'prefix1-noncurrent-version-expiration'
388+
},
389+
NoncurrentVersionExpiration: {
390+
NoncurrentDays: 1
391+
}
392+
}]
393+
}
394+
};
395+
await s3.putBucketLifecycleConfiguration(params);
396+
397+
// get bucket lifecycle
398+
const res = await s3.getBucketLifecycleConfiguration({ Bucket: "lifecycle-bucket" });
399+
assert.strictEqual(res.Rules.length, 1);
400+
assert.strictEqual(res.Rules[0].ID, 'rule1');
401+
assert.strictEqual(res.Rules[0].Status, 'Enabled');
402+
assert.strictEqual(res.Rules[0].Filter.Prefix, 'prefix1-noncurrent-version-expiration');
403+
assert.strictEqual(res.Rules[0].NoncurrentVersionExpiration.NoncurrentDays, 1);
404+
});
405+
406+
mocha.after(async function() {
407+
await s3.deleteBucket({ Bucket: "lifecycle-bucket" });
408+
});
409+
410+
});
198411
});
199412

200413
async function test_object_ops(bucket_name, bucket_type, caching, remote_endpoint_options) {

0 commit comments

Comments
 (0)