1/* 2 * MinIO Go Library for Amazon S3 Compatible Cloud Storage 3 * Copyright 2020 MinIO, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package minio 19 20import ( 21 "bytes" 22 "context" 23 "encoding/xml" 24 "io/ioutil" 25 "net/http" 26 "net/url" 27 28 "github.com/minio/minio-go/v7/pkg/lifecycle" 29 "github.com/minio/minio-go/v7/pkg/s3utils" 30) 31 32// SetBucketLifecycle set the lifecycle on an existing bucket. 33func (c Client) SetBucketLifecycle(ctx context.Context, bucketName string, config *lifecycle.Configuration) error { 34 // Input validation. 35 if err := s3utils.CheckValidBucketName(bucketName); err != nil { 36 return err 37 } 38 39 // If lifecycle is empty then delete it. 40 if config.Empty() { 41 return c.removeBucketLifecycle(ctx, bucketName) 42 } 43 44 buf, err := xml.Marshal(config) 45 if err != nil { 46 return err 47 } 48 49 // Save the updated lifecycle. 50 return c.putBucketLifecycle(ctx, bucketName, buf) 51} 52 53// Saves a new bucket lifecycle. 54func (c Client) putBucketLifecycle(ctx context.Context, bucketName string, buf []byte) error { 55 // Get resources properly escaped and lined up before 56 // using them in http request. 57 urlValues := make(url.Values) 58 urlValues.Set("lifecycle", "") 59 60 // Content-length is mandatory for put lifecycle request 61 reqMetadata := requestMetadata{ 62 bucketName: bucketName, 63 queryValues: urlValues, 64 contentBody: bytes.NewReader(buf), 65 contentLength: int64(len(buf)), 66 contentMD5Base64: sumMD5Base64(buf), 67 } 68 69 // Execute PUT to upload a new bucket lifecycle. 70 resp, err := c.executeMethod(ctx, http.MethodPut, reqMetadata) 71 defer closeResponse(resp) 72 if err != nil { 73 return err 74 } 75 if resp != nil { 76 if resp.StatusCode != http.StatusOK { 77 return httpRespToErrorResponse(resp, bucketName, "") 78 } 79 } 80 return nil 81} 82 83// Remove lifecycle from a bucket. 84func (c Client) removeBucketLifecycle(ctx context.Context, bucketName string) error { 85 // Get resources properly escaped and lined up before 86 // using them in http request. 87 urlValues := make(url.Values) 88 urlValues.Set("lifecycle", "") 89 90 // Execute DELETE on objectName. 91 resp, err := c.executeMethod(ctx, http.MethodDelete, requestMetadata{ 92 bucketName: bucketName, 93 queryValues: urlValues, 94 contentSHA256Hex: emptySHA256Hex, 95 }) 96 defer closeResponse(resp) 97 if err != nil { 98 return err 99 } 100 return nil 101} 102 103// GetBucketLifecycle fetch bucket lifecycle configuration 104func (c Client) GetBucketLifecycle(ctx context.Context, bucketName string) (*lifecycle.Configuration, error) { 105 // Input validation. 106 if err := s3utils.CheckValidBucketName(bucketName); err != nil { 107 return nil, err 108 } 109 110 bucketLifecycle, err := c.getBucketLifecycle(ctx, bucketName) 111 if err != nil { 112 return nil, err 113 } 114 115 config := lifecycle.NewConfiguration() 116 if err = xml.Unmarshal(bucketLifecycle, config); err != nil { 117 return nil, err 118 } 119 return config, nil 120} 121 122// Request server for current bucket lifecycle. 123func (c Client) getBucketLifecycle(ctx context.Context, bucketName string) ([]byte, error) { 124 // Get resources properly escaped and lined up before 125 // using them in http request. 126 urlValues := make(url.Values) 127 urlValues.Set("lifecycle", "") 128 129 // Execute GET on bucket to get lifecycle. 130 resp, err := c.executeMethod(ctx, http.MethodGet, requestMetadata{ 131 bucketName: bucketName, 132 queryValues: urlValues, 133 }) 134 135 defer closeResponse(resp) 136 if err != nil { 137 return nil, err 138 } 139 140 if resp != nil { 141 if resp.StatusCode != http.StatusOK { 142 return nil, httpRespToErrorResponse(resp, bucketName, "") 143 } 144 } 145 146 return ioutil.ReadAll(resp.Body) 147} 148