mirror of
https://github.com/minio/minio.git
synced 2025-11-21 02:09:08 -05:00
Fix evaluation of NewerNoncurrentVersions (#21096)
- Move VersionPurgeStatus into replication package - ilm: Evaluate policy w/ obj retention/replication - lifecycle: Use Evaluator to enforce ILM in scanner - Unit tests covering ILM, replication and retention - Simplify NewEvaluator constructor
This commit is contained in:
committed by
GitHub
parent
07f31e574c
commit
01447d2438
177
internal/bucket/lifecycle/evaluator_test.go
Normal file
177
internal/bucket/lifecycle/evaluator_test.go
Normal file
@@ -0,0 +1,177 @@
|
||||
// Copyright (c) 2015-2025 MinIO, Inc.
|
||||
//
|
||||
// This file is part of MinIO Object Storage stack
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package lifecycle
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func TestNewerNoncurrentVersions(t *testing.T) {
|
||||
prepLifecycleCfg := func(tagKeys []string, retainVersions []int) Lifecycle {
|
||||
var lc Lifecycle
|
||||
for i := range retainVersions {
|
||||
ruleID := fmt.Sprintf("rule-%d", i)
|
||||
tag := Tag{
|
||||
Key: tagKeys[i],
|
||||
Value: "minio",
|
||||
}
|
||||
lc.Rules = append(lc.Rules, Rule{
|
||||
ID: ruleID,
|
||||
Status: "Enabled",
|
||||
Filter: Filter{
|
||||
Tag: tag,
|
||||
set: true,
|
||||
},
|
||||
NoncurrentVersionExpiration: NoncurrentVersionExpiration{
|
||||
NewerNoncurrentVersions: retainVersions[i],
|
||||
set: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
return lc
|
||||
}
|
||||
|
||||
lc := prepLifecycleCfg([]string{"tag3", "tag4", "tag5"}, []int{3, 4, 5})
|
||||
evaluator := NewEvaluator(lc)
|
||||
tagKeys := []string{"tag3", "tag3", "tag3", "tag4", "tag4", "tag5", "tag5"}
|
||||
verIDs := []string{
|
||||
"0NdAikoUVNGEpCUuB9vl.XyoMftMXCSg", "19M6Z405yFZuYygnnU9jKzsOBamTZK_7", "0PmlJdFWi_9d6l_dAkWrrhP.bBgtFk6V", // spellchecker:disable-line
|
||||
".MmRalFNNJyOLymgCtQ3.qsdoYpy8qkB", "Bjb4OlMW9Agx.Nrggh15iU6frGu2CLde", "ngBmUd_cVl6ckONI9XsKGpJjzimohrzZ", // spellchecker:disable-line
|
||||
"T6m1heTHLUtnByW2IOWJ3zM4JP9xXt2O", // spellchecker:disable-line
|
||||
}
|
||||
wantEvents := []Event{
|
||||
{Action: NoneAction},
|
||||
{Action: NoneAction},
|
||||
{Action: NoneAction},
|
||||
{Action: NoneAction},
|
||||
{Action: NoneAction},
|
||||
{Action: NoneAction},
|
||||
{Action: DeleteVersionAction},
|
||||
}
|
||||
var objs []ObjectOpts
|
||||
curModTime := time.Date(2025, time.February, 10, 23, 0, 0, 0, time.UTC)
|
||||
for i := range tagKeys {
|
||||
obj := ObjectOpts{
|
||||
Name: "obj",
|
||||
VersionID: verIDs[i],
|
||||
ModTime: curModTime.Add(time.Duration(-i) * time.Second),
|
||||
UserTags: fmt.Sprintf("%s=minio", tagKeys[i]),
|
||||
NumVersions: len(verIDs),
|
||||
}
|
||||
if i == 0 {
|
||||
obj.IsLatest = true
|
||||
} else {
|
||||
obj.SuccessorModTime = curModTime.Add(time.Duration(-i+1) * time.Second)
|
||||
}
|
||||
objs = append(objs, obj)
|
||||
}
|
||||
now := time.Date(2025, time.February, 10, 23, 0, 0, 0, time.UTC)
|
||||
gotEvents := evaluator.eval(objs, now)
|
||||
for i := range wantEvents {
|
||||
if gotEvents[i].Action != wantEvents[i].Action {
|
||||
t.Fatalf("got %v, want %v", gotEvents[i], wantEvents[i])
|
||||
}
|
||||
}
|
||||
|
||||
lc = prepLifecycleCfg([]string{"tag3", "tag4", "tag5"}, []int{1, 2, 3})
|
||||
objs = objs[:len(objs)-1]
|
||||
wantEvents = []Event{
|
||||
{Action: NoneAction},
|
||||
{Action: NoneAction},
|
||||
{Action: DeleteVersionAction},
|
||||
{Action: NoneAction},
|
||||
{Action: DeleteVersionAction},
|
||||
{Action: NoneAction},
|
||||
}
|
||||
evaluator = NewEvaluator(lc)
|
||||
gotEvents = evaluator.eval(objs, now)
|
||||
for i := range wantEvents {
|
||||
if gotEvents[i].Action != wantEvents[i].Action {
|
||||
t.Fatalf("test-%d: got %v, want %v", i+1, gotEvents[i], wantEvents[i])
|
||||
}
|
||||
}
|
||||
|
||||
lc = Lifecycle{
|
||||
Rules: []Rule{
|
||||
{
|
||||
ID: "AllVersionsExpiration",
|
||||
Status: "Enabled",
|
||||
Filter: Filter{},
|
||||
Expiration: Expiration{
|
||||
Days: 1,
|
||||
DeleteAll: Boolean{
|
||||
val: true,
|
||||
set: true,
|
||||
},
|
||||
set: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
now = time.Date(2025, time.February, 12, 23, 0, 0, 0, time.UTC)
|
||||
evaluator = NewEvaluator(lc)
|
||||
gotEvents = evaluator.eval(objs, now)
|
||||
wantEvents = []Event{
|
||||
{Action: DeleteAllVersionsAction},
|
||||
{Action: NoneAction},
|
||||
{Action: NoneAction},
|
||||
{Action: NoneAction},
|
||||
{Action: NoneAction},
|
||||
{Action: NoneAction},
|
||||
}
|
||||
for i := range wantEvents {
|
||||
if gotEvents[i].Action != wantEvents[i].Action {
|
||||
t.Fatalf("test-%d: got %v, want %v", i+1, gotEvents[i], wantEvents[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyEvaluator(t *testing.T) {
|
||||
var objs []ObjectOpts
|
||||
curModTime := time.Date(2025, time.February, 10, 23, 0, 0, 0, time.UTC)
|
||||
for i := range 5 {
|
||||
obj := ObjectOpts{
|
||||
Name: "obj",
|
||||
VersionID: uuid.New().String(),
|
||||
ModTime: curModTime.Add(time.Duration(-i) * time.Second),
|
||||
NumVersions: 5,
|
||||
}
|
||||
if i == 0 {
|
||||
obj.IsLatest = true
|
||||
} else {
|
||||
obj.SuccessorModTime = curModTime.Add(time.Duration(-i+1) * time.Second)
|
||||
}
|
||||
objs = append(objs, obj)
|
||||
}
|
||||
|
||||
evaluator := NewEvaluator(Lifecycle{})
|
||||
events, err := evaluator.Eval(objs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, event := range events {
|
||||
if event.Action != NoneAction {
|
||||
t.Fatalf("got %v, want %v", event.Action, NoneAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user