mirror of https://github.com/minio/minio.git
Add updatedAt for GetBucketLifecycleConfig (#17271)
This commit is contained in:
parent
d0a0eb9738
commit
62df731006
|
@ -460,7 +460,7 @@ func (a adminAPIHandlers) ExportBucketMetadataHandler(w http.ResponseWriter, r *
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case bucketLifecycleConfig:
|
case bucketLifecycleConfig:
|
||||||
config, err := globalBucketMetadataSys.GetLifecycleConfig(bucket)
|
config, _, err := globalBucketMetadataSys.GetLifecycleConfig(bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, BucketLifecycleNotFound{Bucket: bucket}) {
|
if errors.Is(err, BucketLifecycleNotFound{Bucket: bucket}) {
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -253,6 +253,7 @@ const (
|
||||||
ErrInvalidObjectName
|
ErrInvalidObjectName
|
||||||
ErrInvalidObjectNamePrefixSlash
|
ErrInvalidObjectNamePrefixSlash
|
||||||
ErrInvalidResourceName
|
ErrInvalidResourceName
|
||||||
|
ErrInvalidLifecycleQueryParameter
|
||||||
ErrServerNotInitialized
|
ErrServerNotInitialized
|
||||||
ErrOperationTimedOut
|
ErrOperationTimedOut
|
||||||
ErrClientDisconnected
|
ErrClientDisconnected
|
||||||
|
@ -1255,6 +1256,11 @@ var errorCodes = errorCodeMap{
|
||||||
Description: "The JSON you provided was not well-formed or did not validate against our published format.",
|
Description: "The JSON you provided was not well-formed or did not validate against our published format.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
|
ErrInvalidLifecycleQueryParameter: {
|
||||||
|
Code: "XMinioInvalidLifecycleParameter",
|
||||||
|
Description: "The boolean value provided for withUpdatedAt query parameter was invalid.",
|
||||||
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
|
},
|
||||||
ErrAdminNoSuchUser: {
|
ErrAdminNoSuchUser: {
|
||||||
Code: "XMinioAdminNoSuchUser",
|
Code: "XMinioAdminNoSuchUser",
|
||||||
Description: "The specified user does not exist.",
|
Description: "The specified user does not exist.",
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -21,6 +21,7 @@ import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/minio/minio/internal/bucket/lifecycle"
|
"github.com/minio/minio/internal/bucket/lifecycle"
|
||||||
xhttp "github.com/minio/minio/internal/http"
|
xhttp "github.com/minio/minio/internal/http"
|
||||||
|
@ -115,6 +116,16 @@ func (api objectAPIHandlers) GetBucketLifecycleHandler(w http.ResponseWriter, r
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
bucket := vars["bucket"]
|
bucket := vars["bucket"]
|
||||||
|
|
||||||
|
var withUpdatedAt bool
|
||||||
|
if updatedAtStr := r.Form.Get("withUpdatedAt"); updatedAtStr != "" {
|
||||||
|
var err error
|
||||||
|
withUpdatedAt, err = strconv.ParseBool(updatedAtStr)
|
||||||
|
if err != nil {
|
||||||
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrInvalidLifecycleQueryParameter), r.URL)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketLifecycleAction, bucket, ""); s3Error != ErrNone {
|
if s3Error := checkRequestAuthType(ctx, r, policy.GetBucketLifecycleAction, bucket, ""); s3Error != ErrNone {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL)
|
||||||
return
|
return
|
||||||
|
@ -126,7 +137,7 @@ func (api objectAPIHandlers) GetBucketLifecycleHandler(w http.ResponseWriter, r
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := globalBucketMetadataSys.GetLifecycleConfig(bucket)
|
config, updatedAt, err := globalBucketMetadataSys.GetLifecycleConfig(bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
|
@ -138,6 +149,9 @@ func (api objectAPIHandlers) GetBucketLifecycleHandler(w http.ResponseWriter, r
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if withUpdatedAt {
|
||||||
|
w.Header().Set(xhttp.MinIOLifecycleCfgUpdatedAt, updatedAt.Format(iso8601Format))
|
||||||
|
}
|
||||||
// Write lifecycle configuration to client.
|
// Write lifecycle configuration to client.
|
||||||
writeSuccessResponseXML(w, configData)
|
writeSuccessResponseXML(w, configData)
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,8 @@ type LifecycleSys struct{}
|
||||||
|
|
||||||
// Get - gets lifecycle config associated to a given bucket name.
|
// Get - gets lifecycle config associated to a given bucket name.
|
||||||
func (sys *LifecycleSys) Get(bucketName string) (lc *lifecycle.Lifecycle, err error) {
|
func (sys *LifecycleSys) Get(bucketName string) (lc *lifecycle.Lifecycle, err error) {
|
||||||
return globalBucketMetadataSys.GetLifecycleConfig(bucketName)
|
lc, _, err = globalBucketMetadataSys.GetLifecycleConfig(bucketName)
|
||||||
|
return lc, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLifecycleSys - creates new lifecycle system.
|
// NewLifecycleSys - creates new lifecycle system.
|
||||||
|
|
|
@ -121,6 +121,7 @@ func (sys *BucketMetadataSys) updateAndParse(ctx context.Context, bucket string,
|
||||||
meta.NotificationConfigXML = configData
|
meta.NotificationConfigXML = configData
|
||||||
case bucketLifecycleConfig:
|
case bucketLifecycleConfig:
|
||||||
meta.LifecycleConfigXML = configData
|
meta.LifecycleConfigXML = configData
|
||||||
|
meta.LifecycleConfigUpdatedAt = updatedAt
|
||||||
case bucketSSEConfig:
|
case bucketSSEConfig:
|
||||||
meta.EncryptionConfigXML = configData
|
meta.EncryptionConfigXML = configData
|
||||||
meta.EncryptionConfigUpdatedAt = updatedAt
|
meta.EncryptionConfigUpdatedAt = updatedAt
|
||||||
|
@ -246,18 +247,18 @@ func (sys *BucketMetadataSys) GetObjectLockConfig(bucket string) (*objectlock.Co
|
||||||
|
|
||||||
// GetLifecycleConfig returns configured lifecycle config
|
// GetLifecycleConfig returns configured lifecycle config
|
||||||
// The returned object may not be modified.
|
// The returned object may not be modified.
|
||||||
func (sys *BucketMetadataSys) GetLifecycleConfig(bucket string) (*lifecycle.Lifecycle, error) {
|
func (sys *BucketMetadataSys) GetLifecycleConfig(bucket string) (*lifecycle.Lifecycle, time.Time, error) {
|
||||||
meta, _, err := sys.GetConfig(GlobalContext, bucket)
|
meta, _, err := sys.GetConfig(GlobalContext, bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, errConfigNotFound) {
|
if errors.Is(err, errConfigNotFound) {
|
||||||
return nil, BucketLifecycleNotFound{Bucket: bucket}
|
return nil, time.Time{}, BucketLifecycleNotFound{Bucket: bucket}
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, time.Time{}, err
|
||||||
}
|
}
|
||||||
if meta.lifecycleConfig == nil {
|
if meta.lifecycleConfig == nil {
|
||||||
return nil, BucketLifecycleNotFound{Bucket: bucket}
|
return nil, time.Time{}, BucketLifecycleNotFound{Bucket: bucket}
|
||||||
}
|
}
|
||||||
return meta.lifecycleConfig, nil
|
return meta.lifecycleConfig, meta.LifecycleConfigUpdatedAt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNotificationConfig returns configured notification config
|
// GetNotificationConfig returns configured notification config
|
||||||
|
|
|
@ -88,6 +88,7 @@ type BucketMetadata struct {
|
||||||
QuotaConfigUpdatedAt time.Time
|
QuotaConfigUpdatedAt time.Time
|
||||||
ReplicationConfigUpdatedAt time.Time
|
ReplicationConfigUpdatedAt time.Time
|
||||||
VersioningConfigUpdatedAt time.Time
|
VersioningConfigUpdatedAt time.Time
|
||||||
|
LifecycleConfigUpdatedAt time.Time
|
||||||
|
|
||||||
// Unexported fields. Must be updated atomically.
|
// Unexported fields. Must be updated atomically.
|
||||||
policyConfig *policy.Policy
|
policyConfig *policy.Policy
|
||||||
|
@ -427,6 +428,10 @@ func (b *BucketMetadata) defaultTimestamps() {
|
||||||
if b.VersioningConfigUpdatedAt.IsZero() {
|
if b.VersioningConfigUpdatedAt.IsZero() {
|
||||||
b.VersioningConfigUpdatedAt = b.Created
|
b.VersioningConfigUpdatedAt = b.Created
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b.LifecycleConfigUpdatedAt.IsZero() {
|
||||||
|
b.LifecycleConfigUpdatedAt = b.Created
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save config to supplied ObjectLayer api.
|
// Save config to supplied ObjectLayer api.
|
||||||
|
|
|
@ -150,6 +150,12 @@ func (z *BucketMetadata) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||||
err = msgp.WrapError(err, "VersioningConfigUpdatedAt")
|
err = msgp.WrapError(err, "VersioningConfigUpdatedAt")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
case "LifecycleConfigUpdatedAt":
|
||||||
|
z.LifecycleConfigUpdatedAt, err = dc.ReadTime()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "LifecycleConfigUpdatedAt")
|
||||||
|
return
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
err = dc.Skip()
|
err = dc.Skip()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -163,9 +169,9 @@ func (z *BucketMetadata) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||||
|
|
||||||
// EncodeMsg implements msgp.Encodable
|
// EncodeMsg implements msgp.Encodable
|
||||||
func (z *BucketMetadata) EncodeMsg(en *msgp.Writer) (err error) {
|
func (z *BucketMetadata) EncodeMsg(en *msgp.Writer) (err error) {
|
||||||
// map header, size 21
|
// map header, size 22
|
||||||
// write "Name"
|
// write "Name"
|
||||||
err = en.Append(0xde, 0x0, 0x15, 0xa4, 0x4e, 0x61, 0x6d, 0x65)
|
err = en.Append(0xde, 0x0, 0x16, 0xa4, 0x4e, 0x61, 0x6d, 0x65)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -374,15 +380,25 @@ func (z *BucketMetadata) EncodeMsg(en *msgp.Writer) (err error) {
|
||||||
err = msgp.WrapError(err, "VersioningConfigUpdatedAt")
|
err = msgp.WrapError(err, "VersioningConfigUpdatedAt")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// write "LifecycleConfigUpdatedAt"
|
||||||
|
err = en.Append(0xb8, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = en.WriteTime(z.LifecycleConfigUpdatedAt)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "LifecycleConfigUpdatedAt")
|
||||||
|
return
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalMsg implements msgp.Marshaler
|
// MarshalMsg implements msgp.Marshaler
|
||||||
func (z *BucketMetadata) MarshalMsg(b []byte) (o []byte, err error) {
|
func (z *BucketMetadata) MarshalMsg(b []byte) (o []byte, err error) {
|
||||||
o = msgp.Require(b, z.Msgsize())
|
o = msgp.Require(b, z.Msgsize())
|
||||||
// map header, size 21
|
// map header, size 22
|
||||||
// string "Name"
|
// string "Name"
|
||||||
o = append(o, 0xde, 0x0, 0x15, 0xa4, 0x4e, 0x61, 0x6d, 0x65)
|
o = append(o, 0xde, 0x0, 0x16, 0xa4, 0x4e, 0x61, 0x6d, 0x65)
|
||||||
o = msgp.AppendString(o, z.Name)
|
o = msgp.AppendString(o, z.Name)
|
||||||
// string "Created"
|
// string "Created"
|
||||||
o = append(o, 0xa7, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64)
|
o = append(o, 0xa7, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64)
|
||||||
|
@ -444,6 +460,9 @@ func (z *BucketMetadata) MarshalMsg(b []byte) (o []byte, err error) {
|
||||||
// string "VersioningConfigUpdatedAt"
|
// string "VersioningConfigUpdatedAt"
|
||||||
o = append(o, 0xb9, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74)
|
o = append(o, 0xb9, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74)
|
||||||
o = msgp.AppendTime(o, z.VersioningConfigUpdatedAt)
|
o = msgp.AppendTime(o, z.VersioningConfigUpdatedAt)
|
||||||
|
// string "LifecycleConfigUpdatedAt"
|
||||||
|
o = append(o, 0xb8, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74)
|
||||||
|
o = msgp.AppendTime(o, z.LifecycleConfigUpdatedAt)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,6 +610,12 @@ func (z *BucketMetadata) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||||
err = msgp.WrapError(err, "VersioningConfigUpdatedAt")
|
err = msgp.WrapError(err, "VersioningConfigUpdatedAt")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
case "LifecycleConfigUpdatedAt":
|
||||||
|
z.LifecycleConfigUpdatedAt, bts, err = msgp.ReadTimeBytes(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "LifecycleConfigUpdatedAt")
|
||||||
|
return
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
bts, err = msgp.Skip(bts)
|
bts, err = msgp.Skip(bts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -605,6 +630,6 @@ func (z *BucketMetadata) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||||
|
|
||||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||||
func (z *BucketMetadata) Msgsize() (s int) {
|
func (z *BucketMetadata) Msgsize() (s int) {
|
||||||
s = 3 + 5 + msgp.StringPrefixSize + len(z.Name) + 8 + msgp.TimeSize + 12 + msgp.BoolSize + 17 + msgp.BytesPrefixSize + len(z.PolicyConfigJSON) + 22 + msgp.BytesPrefixSize + len(z.NotificationConfigXML) + 19 + msgp.BytesPrefixSize + len(z.LifecycleConfigXML) + 20 + msgp.BytesPrefixSize + len(z.ObjectLockConfigXML) + 20 + msgp.BytesPrefixSize + len(z.VersioningConfigXML) + 20 + msgp.BytesPrefixSize + len(z.EncryptionConfigXML) + 17 + msgp.BytesPrefixSize + len(z.TaggingConfigXML) + 16 + msgp.BytesPrefixSize + len(z.QuotaConfigJSON) + 21 + msgp.BytesPrefixSize + len(z.ReplicationConfigXML) + 24 + msgp.BytesPrefixSize + len(z.BucketTargetsConfigJSON) + 28 + msgp.BytesPrefixSize + len(z.BucketTargetsConfigMetaJSON) + 22 + msgp.TimeSize + 26 + msgp.TimeSize + 26 + msgp.TimeSize + 23 + msgp.TimeSize + 21 + msgp.TimeSize + 27 + msgp.TimeSize + 26 + msgp.TimeSize
|
s = 3 + 5 + msgp.StringPrefixSize + len(z.Name) + 8 + msgp.TimeSize + 12 + msgp.BoolSize + 17 + msgp.BytesPrefixSize + len(z.PolicyConfigJSON) + 22 + msgp.BytesPrefixSize + len(z.NotificationConfigXML) + 19 + msgp.BytesPrefixSize + len(z.LifecycleConfigXML) + 20 + msgp.BytesPrefixSize + len(z.ObjectLockConfigXML) + 20 + msgp.BytesPrefixSize + len(z.VersioningConfigXML) + 20 + msgp.BytesPrefixSize + len(z.EncryptionConfigXML) + 17 + msgp.BytesPrefixSize + len(z.TaggingConfigXML) + 16 + msgp.BytesPrefixSize + len(z.QuotaConfigJSON) + 21 + msgp.BytesPrefixSize + len(z.ReplicationConfigXML) + 24 + msgp.BytesPrefixSize + len(z.BucketTargetsConfigJSON) + 28 + msgp.BytesPrefixSize + len(z.BucketTargetsConfigMetaJSON) + 22 + msgp.TimeSize + 26 + msgp.TimeSize + 26 + msgp.TimeSize + 23 + msgp.TimeSize + 21 + msgp.TimeSize + 27 + msgp.TimeSize + 26 + msgp.TimeSize + 25 + msgp.TimeSize
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,8 +211,8 @@ const (
|
||||||
// Header indiicates last rtention update time on source
|
// Header indiicates last rtention update time on source
|
||||||
MinIOSourceObjectLegalHoldTimestamp = "X-Minio-Source-Replication-LegalHold-Timestamp"
|
MinIOSourceObjectLegalHoldTimestamp = "X-Minio-Source-Replication-LegalHold-Timestamp"
|
||||||
// predicted date/time of transition
|
// predicted date/time of transition
|
||||||
MinIOTransition = "X-Minio-Transition"
|
MinIOTransition = "X-Minio-Transition"
|
||||||
|
MinIOLifecycleCfgUpdatedAt = "X-Minio-LifecycleConfig-UpdatedAt"
|
||||||
// MinIOCompressed is returned when object is compressed
|
// MinIOCompressed is returned when object is compressed
|
||||||
MinIOCompressed = "X-Minio-Compressed"
|
MinIOCompressed = "X-Minio-Compressed"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue