From 45d145a823a72f8da718e8b2256db8a3942851e5 Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Mon, 18 Oct 2021 19:24:30 -0500 Subject: [PATCH] fix: immediate tiering for NoncurrentVersionTransition (#13464) --- internal/bucket/lifecycle/lifecycle.go | 3 +- internal/bucket/lifecycle/lifecycle_test.go | 42 ++++++++++++++------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/internal/bucket/lifecycle/lifecycle.go b/internal/bucket/lifecycle/lifecycle.go index 8ae8d729e..9e1f43ec8 100644 --- a/internal/bucket/lifecycle/lifecycle.go +++ b/internal/bucket/lifecycle/lifecycle.go @@ -316,10 +316,9 @@ func (lc Lifecycle) ComputeAction(obj ObjectOpts) Action { if obj.VersionID != "" && !obj.IsLatest && !obj.SuccessorModTime.IsZero() && !obj.DeleteMarker && obj.TransitionStatus != TransitionComplete { // Non current versions should be transitioned if their age exceeds non current days configuration // https://docs.aws.amazon.com/AmazonS3/latest/dev/intro-lifecycle-rules.html#intro-lifecycle-rules-actions - if time.Now().After(ExpectedExpiryTime(obj.SuccessorModTime, int(rule.NoncurrentVersionTransition.NoncurrentDays))) { + if due, ok := rule.NoncurrentVersionTransition.NextDue(obj); ok && time.Now().UTC().After(due) { return TransitionVersionAction } - } } diff --git a/internal/bucket/lifecycle/lifecycle_test.go b/internal/bucket/lifecycle/lifecycle_test.go index f0d4f67bb..4c011047a 100644 --- a/internal/bucket/lifecycle/lifecycle_test.go +++ b/internal/bucket/lifecycle/lifecycle_test.go @@ -27,6 +27,7 @@ import ( "testing" "time" + "github.com/google/uuid" xhttp "github.com/minio/minio/internal/http" ) @@ -216,12 +217,15 @@ func TestExpectedExpiryTime(t *testing.T) { func TestComputeActions(t *testing.T) { testCases := []struct { - inputConfig string - objectName string - objectTags string - objectModTime time.Time - isExpiredDelMarker bool - expectedAction Action + inputConfig string + objectName string + objectTags string + objectModTime time.Time + isExpiredDelMarker bool + expectedAction Action + isNoncurrent bool + objectSuccessorModTime time.Time + versionID string }{ // Empty object name (unexpected case) should always return NoneAction { @@ -386,13 +390,23 @@ func TestComputeActions(t *testing.T) { isExpiredDelMarker: true, expectedAction: DeleteVersionAction, }, - // Should not delete expired marker if its time has not come yet + // Should transition immediately when Transition days is zero { inputConfig: `Enabled0S3TIER-1`, objectName: "foodir/fooobject", objectModTime: time.Now().UTC(), // Created now expectedAction: TransitionAction, }, + // Should transition immediately when NoncurrentVersion Transition days is zero + { + inputConfig: `Enabled0S3TIER-1`, + objectName: "foodir/fooobject", + objectModTime: time.Now().UTC(), // Created now + expectedAction: TransitionVersionAction, + isNoncurrent: true, + objectSuccessorModTime: time.Now().UTC(), + versionID: uuid.New().String(), + }, } for _, tc := range testCases { @@ -403,12 +417,14 @@ func TestComputeActions(t *testing.T) { t.Fatalf("Got unexpected error: %v", err) } if resultAction := lc.ComputeAction(ObjectOpts{ - Name: tc.objectName, - UserTags: tc.objectTags, - ModTime: tc.objectModTime, - DeleteMarker: tc.isExpiredDelMarker, - NumVersions: 1, - IsLatest: true, + Name: tc.objectName, + UserTags: tc.objectTags, + ModTime: tc.objectModTime, + DeleteMarker: tc.isExpiredDelMarker, + NumVersions: 1, + IsLatest: !tc.isNoncurrent, + SuccessorModTime: tc.objectSuccessorModTime, + VersionID: tc.versionID, }); resultAction != tc.expectedAction { t.Fatalf("Expected action: `%v`, got: `%v`", tc.expectedAction, resultAction) }