From 3c4ef4338fdfba4e2540a602abccc7f0f115c699 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sat, 8 Oct 2022 13:11:00 -0700 Subject: [PATCH] marshal retention XML in expected format (#15821) --- internal/bucket/object/lock/lock.go | 21 ++++++--- internal/bucket/object/lock/lock_test.go | 58 ++++++++++++++++-------- 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/internal/bucket/object/lock/lock.go b/internal/bucket/object/lock/lock.go index e8546f1eb..d40bf71b8 100644 --- a/internal/bucket/object/lock/lock.go +++ b/internal/bucket/object/lock/lock.go @@ -309,9 +309,12 @@ func (rDate *RetentionDate) UnmarshalXML(d *xml.Decoder, startElement xml.StartE // While AWS documentation mentions that the date specified // must be present in ISO 8601 format, in reality they allow // users to provide RFC 3339 compliant dates. - retDate, err := time.Parse(time.RFC3339, dateStr) + retDate, err := time.Parse(iso8601TimeFormat, dateStr) if err != nil { - return ErrInvalidRetentionDate + retDate, err = time.Parse(time.RFC3339, dateStr) + if err != nil { + return ErrInvalidRetentionDate + } } *rDate = RetentionDate{retDate} @@ -321,10 +324,10 @@ func (rDate *RetentionDate) UnmarshalXML(d *xml.Decoder, startElement xml.StartE // MarshalXML encodes expiration date if it is non-zero and encodes // empty string otherwise func (rDate *RetentionDate) MarshalXML(e *xml.Encoder, startElement xml.StartElement) error { - if *rDate == (RetentionDate{time.Time{}}) { + if rDate.IsZero() { return nil } - return e.EncodeElement(rDate.Format(time.RFC3339), startElement) + return e.EncodeElement(rDate.Format(iso8601TimeFormat), startElement) } // ObjectRetention specified in @@ -414,9 +417,12 @@ func ParseObjectLockRetentionHeaders(h http.Header) (rmode RetMode, r RetentionD // While AWS documentation mentions that the date specified // must be present in ISO 8601 format, in reality they allow // users to provide RFC 3339 compliant dates. - retDate, err = time.Parse(time.RFC3339, dateStr) + retDate, err = time.Parse(iso8601TimeFormat, dateStr) if err != nil { - return rmode, r, ErrInvalidRetentionDate + retDate, err = time.Parse(time.RFC3339, dateStr) + if err != nil { + return rmode, r, ErrInvalidRetentionDate + } } _, replReq := h[textproto.CanonicalMIMEHeaderKey(xhttp.MinIOSourceReplicationRequest)] @@ -459,6 +465,9 @@ func GetObjectRetentionMeta(meta map[string]string) ObjectRetention { if t, e := time.Parse(iso8601TimeFormat, tillStr); e == nil { retainTill = RetentionDate{t.UTC()} } + if t, e := time.Parse(time.RFC3339, tillStr); e == nil { + retainTill = RetentionDate{t.UTC()} + } } return ObjectRetention{XMLNS: "http://s3.amazonaws.com/doc/2006-03-01/", Mode: mode, RetainUntilDate: retainTill} } diff --git a/internal/bucket/object/lock/lock_test.go b/internal/bucket/object/lock/lock_test.go index 7add6d48a..5884c2b73 100644 --- a/internal/bucket/object/lock/lock_test.go +++ b/internal/bucket/object/lock/lock_test.go @@ -174,17 +174,20 @@ func TestParseObjectLockConfig(t *testing.T) { }, } for _, tt := range tests { - _, err := ParseObjectLockConfig(strings.NewReader(tt.value)) - //nolint:gocritic - if tt.expectedErr == nil { - if err != nil { - t.Fatalf("error: expected = , got = %v", err) + tt := tt + t.Run("", func(t *testing.T) { + _, err := ParseObjectLockConfig(strings.NewReader(tt.value)) + //nolint:gocritic + if tt.expectedErr == nil { + if err != nil { + t.Fatalf("error: expected = , got = %v", err) + } + } else if err == nil { + t.Fatalf("error: expected = %v, got = ", tt.expectedErr) + } else if tt.expectedErr.Error() != err.Error() { + t.Fatalf("error: expected = %v, got = %v", tt.expectedErr, err) } - } else if err == nil { - t.Fatalf("error: expected = %v, got = ", tt.expectedErr) - } else if tt.expectedErr.Error() != err.Error() { - t.Fatalf("error: expected = %v, got = %v", tt.expectedErr, err) - } + }) } } @@ -209,19 +212,27 @@ func TestParseObjectRetention(t *testing.T) { expectedErr: nil, expectErr: false, }, + { + value: `GOVERNANCE2057-01-02T15:04:05.000Z`, + expectedErr: nil, + expectErr: false, + }, } for _, tt := range tests { - _, err := ParseObjectRetention(strings.NewReader(tt.value)) - //nolint:gocritic - if tt.expectedErr == nil { - if err != nil { - t.Fatalf("error: expected = , got = %v", err) + tt := tt + t.Run("", func(t *testing.T) { + _, err := ParseObjectRetention(strings.NewReader(tt.value)) + //nolint:gocritic + if tt.expectedErr == nil { + if err != nil { + t.Fatalf("error: expected = , got = %v", err) + } + } else if err == nil { + t.Fatalf("error: expected = %v, got = ", tt.expectedErr) + } else if tt.expectedErr.Error() != err.Error() { + t.Fatalf("error: expected = %v, got = %v", tt.expectedErr, err) } - } else if err == nil { - t.Fatalf("error: expected = %v, got = ", tt.expectedErr) - } else if tt.expectedErr.Error() != err.Error() { - t.Fatalf("error: expected = %v, got = %v", tt.expectedErr, err) - } + }) } } @@ -367,6 +378,13 @@ func TestParseObjectLockRetentionHeaders(t *testing.T) { }, expectedErr: nil, }, + { + header: http.Header{ + xhttp.AmzObjectLockMode: []string{"governance"}, + xhttp.AmzObjectLockRetainUntilDate: []string{"2087-01-02T15:04:05.000Z"}, + }, + expectedErr: nil, + }, } for i, tt := range tests {