lifecycle: Iterate over all rules until actionable expiry is found (#9725)

This commit is contained in:
Anis Elleuch 2020-05-28 18:55:48 +01:00 committed by GitHub
parent 7214a0160a
commit 231c5cf6de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 28 deletions

View File

@ -93,49 +93,54 @@ func (lc Lifecycle) Validate() error {
return nil return nil
} }
// FilterRuleActions returns the expiration and transition from the object name // FilterActionableRules returns the rules actions that need to be executed
// after evaluating all rules. // after evaluating prefix/tag filtering
func (lc Lifecycle) FilterRuleActions(objName, objTags string) (string, Expiration, Transition) { func (lc Lifecycle) FilterActionableRules(objName, objTags string) []Rule {
if objName == "" { if objName == "" {
return "", Expiration{}, Transition{} return nil
} }
var rules []Rule
for _, rule := range lc.Rules { for _, rule := range lc.Rules {
if rule.Status == Disabled { if rule.Status == Disabled {
continue continue
} }
tags := rule.Tags()
if strings.HasPrefix(objName, rule.Prefix()) { if strings.HasPrefix(objName, rule.Prefix()) {
tags := rule.Tags()
if tags != "" { if tags != "" {
if strings.Contains(objTags, tags) { if strings.Contains(objTags, tags) {
return rule.ID, rule.Expiration, Transition{} rules = append(rules, rule)
} }
} else { } else {
return rule.ID, rule.Expiration, Transition{} rules = append(rules, rule)
} }
} }
} }
return "", Expiration{}, Transition{} return rules
} }
// ComputeAction returns the action to perform by evaluating all lifecycle rules // ComputeAction returns the action to perform by evaluating all lifecycle rules
// against the object name and its modification time. // against the object name and its modification time.
func (lc Lifecycle) ComputeAction(objName, objTags string, modTime time.Time) Action { func (lc Lifecycle) ComputeAction(objName, objTags string, modTime time.Time) (action Action) {
var action = NoneAction action = NoneAction
if modTime.IsZero() { if modTime.IsZero() {
return action return
} }
_, exp, _ := lc.FilterRuleActions(objName, objTags) rules := lc.FilterActionableRules(objName, objTags)
if !exp.IsDateNull() { for _, rule := range rules {
if time.Now().After(exp.Date.Time) { if !rule.Expiration.IsDateNull() {
action = DeleteAction if time.Now().After(rule.Expiration.Date.Time) {
action = DeleteAction
return
}
}
if !rule.Expiration.IsDaysNull() {
if time.Now().After(expectedExpiryTime(modTime, rule.Expiration.Days)) {
action = DeleteAction
return
}
} }
} }
if !exp.IsDaysNull() { return
if time.Now().After(expectedExpiryTime(modTime, exp.Days)) {
action = DeleteAction
}
}
return action
} }
// expectedExpiryTime calculates the expiry date/time based on a object modtime. // expectedExpiryTime calculates the expiry date/time based on a object modtime.
@ -149,13 +154,27 @@ func expectedExpiryTime(modTime time.Time, days ExpirationDays) time.Time {
} }
// PredictExpiryTime returns the expiry date/time of a given object // PredictExpiryTime returns the expiry date/time of a given object
// after evaluting the current lifecycle document.
func (lc Lifecycle) PredictExpiryTime(objName, objTags string) (string, time.Time) { func (lc Lifecycle) PredictExpiryTime(objName, objTags string) (string, time.Time) {
ruleID, exp, _ := lc.FilterRuleActions(objName, objTags) var finalExpiryDate time.Time
if !exp.IsDateNull() { var finalExpiryRuleID string
return ruleID, exp.Date.Time
// Iterate over all actionable rules and find the earliest
// expiration date and its associated rule ID.
for _, rule := range lc.FilterActionableRules(objName, objTags) {
if !rule.Expiration.IsDateNull() {
if finalExpiryDate.IsZero() || finalExpiryDate.After(rule.Expiration.Date.Time) {
finalExpiryRuleID = rule.ID
finalExpiryDate = rule.Expiration.Date.Time
}
}
if !rule.Expiration.IsDaysNull() {
expectedExpiry := expectedExpiryTime(time.Now(), rule.Expiration.Days)
if finalExpiryDate.IsZero() || finalExpiryDate.After(expectedExpiry) {
finalExpiryRuleID = rule.ID
finalExpiryDate = expectedExpiry
}
}
} }
if !exp.IsDaysNull() { return finalExpiryRuleID, finalExpiryDate
return ruleID, expectedExpiryTime(time.Now(), exp.Days)
}
return "", time.Time{}
} }

View File

@ -298,6 +298,13 @@ func TestComputeActions(t *testing.T) {
objectModTime: time.Now().UTC().Add(-24 * time.Hour), // Created 1 day ago objectModTime: time.Now().UTC().Add(-24 * time.Hour), // Created 1 day ago
expectedAction: NoneAction, expectedAction: NoneAction,
}, },
// Should remove, the second rule has expiration kicked in
{
inputConfig: `<LifecycleConfiguration><Rule><Status>Enabled</Status><Expiration><Date>` + time.Now().Truncate(24*time.Hour).UTC().Add(24*time.Hour).Format(time.RFC3339) + `</Date></Expiration></Rule><Rule><Filter><Prefix>foxdir/</Prefix></Filter><Status>Enabled</Status><Expiration><Date>` + time.Now().Truncate(24*time.Hour).UTC().Add(-24*time.Hour).Format(time.RFC3339) + `</Date></Expiration></Rule></LifecycleConfiguration>`,
objectName: "foxdir/fooobject",
objectModTime: time.Now().UTC().Add(-24 * time.Hour), // Created 1 day ago
expectedAction: DeleteAction,
},
} }
for i, tc := range testCases { for i, tc := range testCases {