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)
}