diff --git a/extensions/lifecycle/util/RulesReducer.js b/extensions/lifecycle/util/RulesReducer.js index b79163a0c..19d2fefd7 100644 --- a/extensions/lifecycle/util/RulesReducer.js +++ b/extensions/lifecycle/util/RulesReducer.js @@ -142,8 +142,7 @@ class RulesReducer { let storageClass; if (r.Expiration) { - // NOTE: Expiration Days cannot be 0. - if (r.Expiration.Days) { + if (r.Expiration.Days !== undefined) { days = this._decrementExpirationDay(r.Expiration.Days); } else if (r.Expiration.Date) { if (r.Expiration.Date <= this._currentDate) { @@ -200,8 +199,8 @@ class RulesReducer { let storageClass; if (r.NoncurrentVersionExpiration) { - // 'NoncurrentDays' for NoncurrentVersionExpiration action is a positive integer - if (r.NoncurrentVersionExpiration.NoncurrentDays) { + // 'NoncurrentDays' for NoncurrentVersionExpiration action is a nonnegative integer + if (r.NoncurrentVersionExpiration.NoncurrentDays !== undefined) { days = this._decrementExpirationDay(r.NoncurrentVersionExpiration.NoncurrentDays); } } @@ -246,7 +245,7 @@ class RulesReducer { // NOTE: When you specify the Days tag, Amazon S3 automatically performs ExpiredObjectDeleteMarker // cleanup when the delete markers are old enough to satisfy the age criteria. if (r.Expiration) { - if (r.Expiration.Days) { + if (r.Expiration.Days !== undefined) { days = this._decrementExpirationDay(r.Expiration.Days); } else if (r.Expiration.Date) { if (r.Expiration.Date <= this._currentDate) { diff --git a/tests/unit/lifecycle/RulesReducer.spec.js b/tests/unit/lifecycle/RulesReducer.spec.js index 0765fb534..49d61d4d2 100644 --- a/tests/unit/lifecycle/RulesReducer.spec.js +++ b/tests/unit/lifecycle/RulesReducer.spec.js @@ -143,6 +143,29 @@ describe('RulesReducer with versioning Disabled', () => { assert.deepStrictEqual(result, expected); }); + it('with Expiration rule using Days set to 0', () => { + const currentDate = Date.now(); + const prefix = ''; + const bucketLCRules = [ + { + Expiration: { Days: 0 }, + ID: '123', + Prefix: prefix, + Status: 'Enabled', + } + ]; + const expected = { + currents: [{ + prefix: '', + days: 0, + }] + }; + const rulesReducer = new RulesReducer(versioningStatus, currentDate, bucketLCRules, options); + const result = rulesReducer.toListings(); + + assert.deepStrictEqual(result, expected); + }); + it('with Expiration rule using Days and prefix', () => { const currentDate = Date.now(); const prefix = 'pre'; diff --git a/tests/unit/lifecycle/RulesReducerWithVersion.spec.js b/tests/unit/lifecycle/RulesReducerWithVersion.spec.js index f7d7f5fa5..b4af02795 100644 --- a/tests/unit/lifecycle/RulesReducerWithVersion.spec.js +++ b/tests/unit/lifecycle/RulesReducerWithVersion.spec.js @@ -121,6 +121,28 @@ describe('RulesReducer with versioning Enabled', () => { assert.deepStrictEqual(result, expected); }); + it('with Expiration rule using Days set to 0', () => { + const currentDate = Date.now(); + const prefix = ''; + const bucketLCRules = [ + { + Expiration: { Days: 0 }, + ID: '123', + Prefix: prefix, + Status: 'Enabled', + } + ]; + const expected = { + currents: [{ prefix: '', days: 0 }], + nonCurrents: [], + orphans: [{ prefix: '', days: 0 }], + }; + const rulesReducer = new RulesReducer(versioningStatus, currentDate, bucketLCRules, options); + const result = rulesReducer.toListings(); + + assert.deepStrictEqual(result, expected); + }); + it('with Expiration rule using Days and prefix', () => { const currentDate = Date.now(); const prefix = 'pre'; @@ -460,6 +482,30 @@ describe('RulesReducer with versioning Enabled', () => { assert.deepStrictEqual(result, expected); }); + it('with NoncurrentVersionExpiration rule using NoncurrentDays set to 0', () => { + const currentDate = Date.now(); + const bucketLCRules = [ + { + NoncurrentVersionExpiration: { NoncurrentDays: 0 }, + ID: '0', + Prefix: '', + Status: 'Enabled', + }, + ]; + const rulesReducer = new RulesReducer(versioningStatus, currentDate, bucketLCRules, options); + const result = rulesReducer.toListings(); + + const expected = { + currents: [], + nonCurrents: [{ + prefix: '', + days: 0, + }], + orphans: [], + }; + assert.deepStrictEqual(result, expected); + }); + it('with NoncurrentVersionTransitions rule', () => { const currentDate = Date.now(); const bucketLCRules = [ diff --git a/tests/unit/lifecycle/rules.spec.js b/tests/unit/lifecycle/rules.spec.js index d31afd9a7..9b9ac31a7 100644 --- a/tests/unit/lifecycle/rules.spec.js +++ b/tests/unit/lifecycle/rules.spec.js @@ -318,6 +318,31 @@ describe('rulesToParams with versioning Disabled', () => { assert.deepStrictEqual(result, expected); }); + it('with Expiration rule using Days set to 0 (no BeforeDate, lists all)', () => { + const currentDate = Date.now(); + const prefix = ''; + const bucketLCRules = [ + { + Expiration: { Days: 0 }, + ID: '123', + Prefix: prefix, + Status: 'Enabled', + } + ]; + const expected = { + params: { + Bucket: bucketName, + Prefix: prefix, + MaxKeys: MAX_KEYS, + }, + listType: 'current', + remainings: [] + }; + + const result = rulesToParams(versioningStatus, currentDate, bucketLCRules, bucketData, options); + assert.deepStrictEqual(result, expected); + }); + it('with Expiration rule using Days and prefix', () => { const currentDate = Date.now(); const prefix = 'pre'; diff --git a/tests/unit/lifecycle/rulesWithVersion.spec.js b/tests/unit/lifecycle/rulesWithVersion.spec.js index c104c2252..537ea53d8 100644 --- a/tests/unit/lifecycle/rulesWithVersion.spec.js +++ b/tests/unit/lifecycle/rulesWithVersion.spec.js @@ -262,6 +262,33 @@ describe('rulesToParams with versioning Enabled', () => { assert.deepStrictEqual(result, expected); }); + it('with Expiration rule using Days set to 0 (no BeforeDate, lists all)', () => { + const currentDate = Date.now(); + const bucketLCRules = [ + { + Expiration: { Days: 0 }, + ID: '123', + Prefix: '', + Status: 'Enabled', + } + ]; + const expected = { + params: { + Bucket: bucketName, + Prefix: '', + MaxKeys: MAX_KEYS, + }, + listType: 'current', + remainings: [{ + listType: 'orphan', + prefix: '', + }] + }; + + const result = rulesToParams(versioningStatus, currentDate, bucketLCRules, bucketData, options); + assert.deepStrictEqual(result, expected); + }); + it('with Expiration rule using Days', () => { const currentDate = Date.now(); const prefix = ''; @@ -731,6 +758,31 @@ describe('rulesToParams with versioning Enabled', () => { assert.deepStrictEqual(result, expected); }); + it('with NoncurrentVersionExpiration rule using NoncurrentDays set to 0 (no BeforeDate)', () => { + const currentDate = Date.now(); + const bucketLCRules = [ + { + NoncurrentVersionExpiration: { NoncurrentDays: 0 }, + ID: '123', + Prefix: '', + Status: 'Enabled', + } + ]; + + const expected = { + params: { + Bucket: bucketName, + Prefix: '', + MaxKeys: MAX_KEYS, + }, + listType: 'noncurrent', + remainings: [] + }; + + const result = rulesToParams(versioningStatus, currentDate, bucketLCRules, bucketData, options); + assert.deepStrictEqual(result, expected); + }); + it('with NoncurrentVersionExpiration and NoncurrentVersionTransitions rules with different prefix', () => { const currentDate = Date.now(); const expectedBeforeDate = (new Date(currentDate - ONE_DAY_IN_SEC)).toISOString();