Skip to content

Commit

Permalink
Add header for lifecycle config expiry to ignore replication (#1999)
Browse files Browse the repository at this point in the history
  • Loading branch information
poornas authored Sep 20, 2024
1 parent 100ddb4 commit 2a9a820
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 14 deletions.
31 changes: 19 additions & 12 deletions api-bucket-lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,30 +41,36 @@ func (c *Client) SetBucketLifecycle(ctx context.Context, bucketName string, conf
if config.Empty() {
return c.removeBucketLifecycle(ctx, bucketName)
}

expAfterRepl := config.ExpireAfterReplication
config.ExpireAfterReplication = ""
buf, err := xml.Marshal(config)
if err != nil {
return err
}

// Save the updated lifecycle.
return c.putBucketLifecycle(ctx, bucketName, buf)
return c.putBucketLifecycle(ctx, bucketName, buf, expAfterRepl)
}

// Saves a new bucket lifecycle.
func (c *Client) putBucketLifecycle(ctx context.Context, bucketName string, buf []byte) error {
func (c *Client) putBucketLifecycle(ctx context.Context, bucketName string, buf []byte, expAfterRepl string) error {
// Get resources properly escaped and lined up before
// using them in http request.
urlValues := make(url.Values)
urlValues.Set("lifecycle", "")

var cheaders http.Header
if expAfterRepl != "" {
cheaders = make(http.Header)
cheaders.Set(minioLifecycleExpiryAfterReplication, expAfterRepl)
}
// Content-length is mandatory for put lifecycle request
reqMetadata := requestMetadata{
bucketName: bucketName,
queryValues: urlValues,
contentBody: bytes.NewReader(buf),
contentLength: int64(len(buf)),
contentMD5Base64: sumMD5Base64(buf),
customHeader: cheaders,
}

// Execute PUT to upload a new bucket lifecycle.
Expand Down Expand Up @@ -114,7 +120,7 @@ func (c *Client) GetBucketLifecycleWithInfo(ctx context.Context, bucketName stri
return nil, time.Time{}, err
}

bucketLifecycle, updatedAt, err := c.getBucketLifecycle(ctx, bucketName)
bucketLifecycle, updatedAt, expAfterRepl, err := c.getBucketLifecycle(ctx, bucketName)
if err != nil {
return nil, time.Time{}, err
}
Expand All @@ -123,11 +129,12 @@ func (c *Client) GetBucketLifecycleWithInfo(ctx context.Context, bucketName stri
if err = xml.Unmarshal(bucketLifecycle, config); err != nil {
return nil, time.Time{}, err
}
config.ExpireAfterReplication = expAfterRepl
return config, updatedAt, nil
}

// Request server for current bucket lifecycle.
func (c *Client) getBucketLifecycle(ctx context.Context, bucketName string) ([]byte, time.Time, error) {
func (c *Client) getBucketLifecycle(ctx context.Context, bucketName string) ([]byte, time.Time, string, error) {
// Get resources properly escaped and lined up before
// using them in http request.
urlValues := make(url.Values)
Expand All @@ -142,28 +149,28 @@ func (c *Client) getBucketLifecycle(ctx context.Context, bucketName string) ([]b

defer closeResponse(resp)
if err != nil {
return nil, time.Time{}, err
return nil, time.Time{}, "", err
}

if resp != nil {
if resp.StatusCode != http.StatusOK {
return nil, time.Time{}, httpRespToErrorResponse(resp, bucketName, "")
return nil, time.Time{}, "", httpRespToErrorResponse(resp, bucketName, "")
}
}

lcBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, time.Time{}, err
return nil, time.Time{}, "", err
}

const minIOLifecycleCfgUpdatedAt = "X-Minio-LifecycleConfig-UpdatedAt"
var updatedAt time.Time
if timeStr := resp.Header.Get(minIOLifecycleCfgUpdatedAt); timeStr != "" {
updatedAt, err = time.Parse(iso8601DateFormat, timeStr)
if err != nil {
return nil, time.Time{}, err
return nil, time.Time{}, "", err
}
}

return lcBytes, updatedAt, nil
expAfterRepl := resp.Header.Get(minioLifecycleExpiryAfterReplication)
return lcBytes, updatedAt, expAfterRepl, nil
}
2 changes: 2 additions & 0 deletions api-put-object.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ const (
ReplicationStatusFailed ReplicationStatus = "FAILED"
// ReplicationStatusReplica indicates object is a replica of a source
ReplicationStatusReplica ReplicationStatus = "REPLICA"
// ReplicationStatusReplicaEdge indicates object is a replica of a edge source
ReplicationStatusReplicaEdge ReplicationStatus = "REPLICA-EDGE"
)

// Empty returns true if no replication status set.
Expand Down
3 changes: 3 additions & 0 deletions constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,7 @@ const (
minioTgtReplicationReady = "X-Minio-Replication-Ready"
// Header asks if delete marker replication request can be sent by source now.
isMinioTgtReplicationReady = "X-Minio-Check-Replication-Ready"

// Header indicating if ilm expiry ignores replication status
minioLifecycleExpiryAfterReplication = "X-Minio-Lifecycle-Expiry-After-Replication"
)
5 changes: 3 additions & 2 deletions pkg/lifecycle/lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -496,8 +496,9 @@ type Rule struct {

// Configuration is a collection of Rule objects.
type Configuration struct {
XMLName xml.Name `xml:"LifecycleConfiguration,omitempty" json:"-"`
Rules []Rule `xml:"Rule"`
XMLName xml.Name `xml:"LifecycleConfiguration,omitempty" json:"-"`
Rules []Rule `xml:"Rule"`
ExpireAfterReplication string `xml:"-" json:"-"`
}

// Empty check if lifecycle configuration is empty
Expand Down

0 comments on commit 2a9a820

Please sign in to comment.