allow lifecycle rules with overlapping prefixes (#10053)

master
findmyname666 4 years ago committed by GitHub
parent 7b14e9b660
commit 48aebf2d9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      pkg/bucket/lifecycle/lifecycle.go
  2. 47
      pkg/bucket/lifecycle/lifecycle_test.go

@ -24,9 +24,9 @@ import (
) )
var ( var (
errLifecycleTooManyRules = Errorf("Lifecycle configuration allows a maximum of 1000 rules") errLifecycleTooManyRules = Errorf("Lifecycle configuration allows a maximum of 1000 rules")
errLifecycleNoRule = Errorf("Lifecycle configuration should have at least one rule") errLifecycleNoRule = Errorf("Lifecycle configuration should have at least one rule")
errLifecycleOverlappingPrefix = Errorf("Lifecycle configuration has rules with overlapping prefix") errLifecycleDuplicateID = Errorf("Lifecycle configuration has rule with the same ID. Rule ID must be unique.")
) )
// Action represents a delete action or other transition // Action represents a delete action or other transition
@ -115,17 +115,15 @@ func (lc Lifecycle) Validate() error {
return err return err
} }
} }
// Compare every rule's prefix with every other rule's prefix // Make sure Rule ID is unique
for i := range lc.Rules { for i := range lc.Rules {
if i == len(lc.Rules)-1 { if i == len(lc.Rules)-1 {
break break
} }
// N B Empty prefixes overlap with all prefixes
otherRules := lc.Rules[i+1:] otherRules := lc.Rules[i+1:]
for _, otherRule := range otherRules { for _, otherRule := range otherRules {
if strings.HasPrefix(lc.Rules[i].Prefix(), otherRule.Prefix()) || if lc.Rules[i].ID == otherRule.ID {
strings.HasPrefix(otherRule.Prefix(), lc.Rules[i].Prefix()) { return errLifecycleDuplicateID
return errLifecycleOverlappingPrefix
} }
} }
} }

@ -27,11 +27,12 @@ import (
func TestParseAndValidateLifecycleConfig(t *testing.T) { func TestParseAndValidateLifecycleConfig(t *testing.T) {
// Test for lifecycle config with more than 1000 rules // Test for lifecycle config with more than 1000 rules
var manyRules []Rule var manyRules []Rule
rule := Rule{
Status: "Enabled",
Expiration: Expiration{Days: ExpirationDays(3)},
}
for i := 0; i < 1001; i++ { for i := 0; i < 1001; i++ {
rule := Rule{
ID: fmt.Sprintf("toManyRule%d", i),
Status: "Enabled",
Expiration: Expiration{Days: ExpirationDays(i)},
}
manyRules = append(manyRules, rule) manyRules = append(manyRules, rule)
} }
@ -42,6 +43,7 @@ func TestParseAndValidateLifecycleConfig(t *testing.T) {
// Test for lifecycle config with rules containing overlapping prefixes // Test for lifecycle config with rules containing overlapping prefixes
rule1 := Rule{ rule1 := Rule{
ID: "rule1",
Status: "Enabled", Status: "Enabled",
Expiration: Expiration{Days: ExpirationDays(3)}, Expiration: Expiration{Days: ExpirationDays(3)},
Filter: Filter{ Filter: Filter{
@ -49,6 +51,7 @@ func TestParseAndValidateLifecycleConfig(t *testing.T) {
}, },
} }
rule2 := Rule{ rule2 := Rule{
ID: "rule2",
Status: "Enabled", Status: "Enabled",
Expiration: Expiration{Days: ExpirationDays(3)}, Expiration: Expiration{Days: ExpirationDays(3)},
Filter: Filter{ Filter: Filter{
@ -63,6 +66,31 @@ func TestParseAndValidateLifecycleConfig(t *testing.T) {
t.Fatal("Failed to marshal lifecycle config with rules having overlapping prefix") t.Fatal("Failed to marshal lifecycle config with rules having overlapping prefix")
} }
// Test for lifecycle rules with duplicate IDs
rule3 := Rule{
ID: "duplicateID",
Status: "Enabled",
Expiration: Expiration{Days: ExpirationDays(3)},
Filter: Filter{
Prefix: "/a/b",
},
}
rule4 := Rule{
ID: "duplicateID",
Status: "Enabled",
Expiration: Expiration{Days: ExpirationDays(4)},
Filter: Filter{
And: And{
Prefix: "/x/z",
},
},
}
duplicateIDRules := []Rule{rule3, rule4}
duplicateIDLcConfig, err := xml.Marshal(Lifecycle{Rules: duplicateIDRules})
if err != nil {
t.Fatal("Failed to marshal lifecycle config of rules with duplicate ID.")
}
testCases := []struct { testCases := []struct {
inputConfig string inputConfig string
expectedParsingErr error expectedParsingErr error
@ -70,7 +98,8 @@ func TestParseAndValidateLifecycleConfig(t *testing.T) {
}{ }{
{ // Valid lifecycle config { // Valid lifecycle config
inputConfig: `<LifecycleConfiguration> inputConfig: `<LifecycleConfiguration>
<Rule> <Rule>
<ID>testRule1</ID>
<Filter> <Filter>
<Prefix>prefix</Prefix> <Prefix>prefix</Prefix>
</Filter> </Filter>
@ -78,6 +107,7 @@ func TestParseAndValidateLifecycleConfig(t *testing.T) {
<Expiration><Days>3</Days></Expiration> <Expiration><Days>3</Days></Expiration>
</Rule> </Rule>
<Rule> <Rule>
<ID>testRule2</ID>
<Filter> <Filter>
<Prefix>another-prefix</Prefix> <Prefix>another-prefix</Prefix>
</Filter> </Filter>
@ -114,7 +144,12 @@ func TestParseAndValidateLifecycleConfig(t *testing.T) {
{ // lifecycle config with rules having overlapping prefix { // lifecycle config with rules having overlapping prefix
inputConfig: string(overlappingLcConfig), inputConfig: string(overlappingLcConfig),
expectedParsingErr: nil, expectedParsingErr: nil,
expectedValidationErr: errLifecycleOverlappingPrefix, expectedValidationErr: nil,
},
{ // lifecycle config with rules having overlapping prefix
inputConfig: string(duplicateIDLcConfig),
expectedParsingErr: nil,
expectedValidationErr: errLifecycleDuplicateID,
}, },
} }

Loading…
Cancel
Save