ilm: fix x-amz-expiration header evaluation (#16029)

This commit is contained in:
Krishnan Parthasarathi 2022-11-09 04:20:34 -08:00 committed by GitHub
parent 7b7356f04c
commit 7ba281728f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 6 deletions

View File

@ -358,7 +358,7 @@ func (lc Lifecycle) Eval(obj ObjectOpts, now time.Time) Event {
// Specifying the Days tag will automatically perform ExpiredObjectDeleteMarker cleanup
// once delete markers are old enough to satisfy the age criteria.
// https://docs.aws.amazon.com/AmazonS3/latest/userguide/lifecycle-configuration-examples.html
if expectedExpiry := ExpectedExpiryTime(obj.ModTime, int(rule.Expiration.Days)); now.After(expectedExpiry) {
if expectedExpiry := ExpectedExpiryTime(obj.ModTime, int(rule.Expiration.Days)); now.IsZero() || now.After(expectedExpiry) {
events = append(events, Event{
Action: DeleteVersionAction,
RuleID: rule.ID,
@ -380,7 +380,7 @@ func (lc Lifecycle) Eval(obj ObjectOpts, now time.Time) Event {
if !obj.IsLatest && !rule.NoncurrentVersionExpiration.IsDaysNull() {
// Non current versions should be deleted 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 expectedExpiry := ExpectedExpiryTime(obj.SuccessorModTime, int(rule.NoncurrentVersionExpiration.NoncurrentDays)); now.After(expectedExpiry) {
if expectedExpiry := ExpectedExpiryTime(obj.SuccessorModTime, int(rule.NoncurrentVersionExpiration.NoncurrentDays)); now.IsZero() || now.After(expectedExpiry) {
events = append(events, Event{
Action: DeleteVersionAction,
RuleID: rule.ID,
@ -393,7 +393,7 @@ func (lc Lifecycle) Eval(obj ObjectOpts, now time.Time) Event {
if !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 due, ok := rule.NoncurrentVersionTransition.NextDue(obj); ok && now.After(due) {
if due, ok := rule.NoncurrentVersionTransition.NextDue(obj); ok && (now.IsZero() || now.After(due)) {
events = append(events, Event{
Action: TransitionVersionAction,
RuleID: rule.ID,
@ -408,7 +408,7 @@ func (lc Lifecycle) Eval(obj ObjectOpts, now time.Time) Event {
if obj.IsLatest && !obj.DeleteMarker {
switch {
case !rule.Expiration.IsDateNull():
if time.Now().UTC().After(rule.Expiration.Date.Time) {
if now.IsZero() || now.After(rule.Expiration.Date.Time) {
events = append(events, Event{
Action: DeleteAction,
RuleID: rule.ID,
@ -416,7 +416,7 @@ func (lc Lifecycle) Eval(obj ObjectOpts, now time.Time) Event {
})
}
case !rule.Expiration.IsDaysNull():
if expectedExpiry := ExpectedExpiryTime(obj.ModTime, int(rule.Expiration.Days)); now.After(expectedExpiry) {
if expectedExpiry := ExpectedExpiryTime(obj.ModTime, int(rule.Expiration.Days)); now.IsZero() || now.After(expectedExpiry) {
events = append(events, Event{
Action: DeleteAction,
RuleID: rule.ID,
@ -426,7 +426,7 @@ func (lc Lifecycle) Eval(obj ObjectOpts, now time.Time) Event {
}
if obj.TransitionStatus != TransitionComplete {
if due, ok := rule.Transition.NextDue(obj); ok && now.After(due) {
if due, ok := rule.Transition.NextDue(obj); ok && (now.IsZero() || now.After(due)) {
events = append(events, Event{
Action: TransitionAction,
RuleID: rule.ID,

View File

@ -932,3 +932,69 @@ func TestParseLifecycleConfigWithID(t *testing.T) {
}
}
}
func TestFilterAndSetPredictionHeaders(t *testing.T) {
lc := Lifecycle{
Rules: []Rule{
{
ID: "rule-1",
Status: "Enabled",
Filter: Filter{
set: true,
Prefix: Prefix{
string: "folder1/folder1/exp_dt=2022-",
set: true,
},
},
Expiration: Expiration{
Days: 1,
set: true,
},
},
},
}
tests := []struct {
opts ObjectOpts
lc Lifecycle
want int
}{
{
opts: ObjectOpts{
Name: "folder1/folder1/exp_dt=2022-08-01/obj-1",
ModTime: time.Now().UTC().Add(-10 * 24 * time.Hour),
VersionID: "",
IsLatest: true,
NumVersions: 1,
},
want: 1,
lc: lc,
},
{
opts: ObjectOpts{
Name: "folder1/folder1/exp_dt=9999-01-01/obj-1",
ModTime: time.Now().UTC().Add(-10 * 24 * time.Hour),
VersionID: "",
IsLatest: true,
NumVersions: 1,
},
want: 0,
lc: lc,
},
}
for i, tc := range tests {
t.Run(fmt.Sprintf("test-%d", i+1), func(t *testing.T) {
if got := tc.lc.FilterRules(tc.opts); len(got) != tc.want {
t.Fatalf("Expected %d rules to match but got %d", tc.want, len(got))
}
w := httptest.NewRecorder()
tc.lc.SetPredictionHeaders(w, tc.opts)
expHdr, ok := w.Header()[xhttp.AmzExpiration]
switch {
case ok && tc.want == 0:
t.Fatalf("Expected no rule to match but found x-amz-expiration header set: %v", expHdr)
case !ok && tc.want > 0:
t.Fatal("Expected x-amz-expiration header to be set but not found")
}
})
}
}