Skip to content

Commit

Permalink
Add support for DelMarkerExpiration element (#1959)
Browse files Browse the repository at this point in the history
pkg/lifecycle:
- Add marshal/unmarshal support for DelMarkerExpiration action

pkg/notification:
- Add bucket event type for deletion of all versions of an object with
  DEL marker for current version
  "s3:LifecycleDelMarkerExpiration:Delete"
  • Loading branch information
krisis authored May 2, 2024
1 parent 88c389d commit 95db455
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 0 deletions.
25 changes: 25 additions & 0 deletions pkg/lifecycle/lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,11 +414,32 @@ func (e Expiration) MarshalXML(en *xml.Encoder, startElement xml.StartElement) e
return en.EncodeElement(expirationWrapper(e), startElement)
}

// DelMarkerExpiration represents DelMarkerExpiration actions element in an ILM policy
type DelMarkerExpiration struct {
XMLName xml.Name `xml:"DelMarkerExpiration" json:"-"`
Days int `xml:"Days,omitempty" json:"Days,omitempty"`
}

// IsNull returns true if Days isn't specified and false otherwise.
func (de DelMarkerExpiration) IsNull() bool {
return de.Days == 0
}

// MarshalXML avoids serializing an empty DelMarkerExpiration element
func (de DelMarkerExpiration) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if de.IsNull() {
return nil
}
type delMarkerExp DelMarkerExpiration
return enc.EncodeElement(delMarkerExp(de), start)
}

// MarshalJSON customizes json encoding by omitting empty values
func (r Rule) MarshalJSON() ([]byte, error) {
type rule struct {
AbortIncompleteMultipartUpload *AbortIncompleteMultipartUpload `json:"AbortIncompleteMultipartUpload,omitempty"`
Expiration *Expiration `json:"Expiration,omitempty"`
DelMarkerExpiration *DelMarkerExpiration `json:"DelMarkerExpiration,omitempty"`
ID string `json:"ID"`
RuleFilter *Filter `json:"Filter,omitempty"`
NoncurrentVersionExpiration *NoncurrentVersionExpiration `json:"NoncurrentVersionExpiration,omitempty"`
Expand All @@ -442,6 +463,9 @@ func (r Rule) MarshalJSON() ([]byte, error) {
if !r.Expiration.IsNull() {
newr.Expiration = &r.Expiration
}
if !r.DelMarkerExpiration.IsNull() {
newr.DelMarkerExpiration = &r.DelMarkerExpiration
}
if !r.Transition.IsNull() {
newr.Transition = &r.Transition
}
Expand All @@ -460,6 +484,7 @@ type Rule struct {
XMLName xml.Name `xml:"Rule,omitempty" json:"-"`
AbortIncompleteMultipartUpload AbortIncompleteMultipartUpload `xml:"AbortIncompleteMultipartUpload,omitempty" json:"AbortIncompleteMultipartUpload,omitempty"`
Expiration Expiration `xml:"Expiration,omitempty" json:"Expiration,omitempty"`
DelMarkerExpiration DelMarkerExpiration `xml:"DelMarkerExpiration,omitempty" json:"DelMarkerExpiration,omitempty"`
ID string `xml:"ID" json:"ID"`
RuleFilter Filter `xml:"Filter,omitempty" json:"Filter,omitempty"`
NoncurrentVersionExpiration NoncurrentVersionExpiration `xml:"NoncurrentVersionExpiration,omitempty" json:"NoncurrentVersionExpiration,omitempty"`
Expand Down
21 changes: 21 additions & 0 deletions pkg/lifecycle/lifecycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,13 @@ func TestLifecycleJSONRoundtrip(t *testing.T) {
ID: "rule-6",
Status: "Enabled",
},
{
DelMarkerExpiration: DelMarkerExpiration{
Days: 10,
},
ID: "rule-7",
Status: "Enabled",
},
},
}

Expand All @@ -290,6 +297,9 @@ func TestLifecycleJSONRoundtrip(t *testing.T) {
if lc.Rules[i].Expiration != got.Rules[i].Expiration {
t.Fatalf("expected %#v got %#v", lc.Rules[i].Expiration, got.Rules[i].Expiration)
}
if !lc.Rules[i].DelMarkerExpiration.equals(got.Rules[i].DelMarkerExpiration) {
t.Fatalf("expected %#v got %#v", lc.Rules[i].DelMarkerExpiration, got.Rules[i].DelMarkerExpiration)
}
}
}

Expand Down Expand Up @@ -335,6 +345,13 @@ func TestLifecycleXMLRoundtrip(t *testing.T) {
NewerNoncurrentVersions: 5,
},
},
{
ID: "delmarker-expiration",
Status: "Enabled",
DelMarkerExpiration: DelMarkerExpiration{
Days: 5,
},
},
},
}

Expand Down Expand Up @@ -368,6 +385,10 @@ func (t Transition) equals(u Transition) bool {
return t.Days == u.Days && t.Date.Equal(u.Date.Time) && t.StorageClass == u.StorageClass
}

func (a DelMarkerExpiration) equals(b DelMarkerExpiration) bool {
return a.Days == b.Days
}

func TestExpiredObjectDeleteMarker(t *testing.T) {
expected := []byte(`{"Rules":[{"Expiration":{"ExpiredObjectDeleteMarker":true},"ID":"expired-object-delete-marker","Status":"Enabled"}]}`)
lc := Configuration{
Expand Down
1 change: 1 addition & 0 deletions pkg/notification/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const (
ObjectRemovedAll EventType = "s3:ObjectRemoved:*"
ObjectRemovedDelete EventType = "s3:ObjectRemoved:Delete"
ObjectRemovedDeleteMarkerCreated EventType = "s3:ObjectRemoved:DeleteMarkerCreated"
ILMDelMarkerExpirationDelete EventType = "s3:LifecycleDelMarkerExpiration:Delete"
ObjectReducedRedundancyLostObject EventType = "s3:ReducedRedundancyLostObject"
ObjectTransitionAll EventType = "s3:ObjectTransition:*"
ObjectTransitionFailed EventType = "s3:ObjectTransition:Failed"
Expand Down

0 comments on commit 95db455

Please sign in to comment.