| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | /* | 
					
						
							|  |  |  |  * MinIO Cloud Storage, (C) 2019 MinIO, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"encoding/xml" | 
					
						
							|  |  |  | 	"path" | 
					
						
							|  |  |  | 	"sync" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 06:12:34 +08:00
										 |  |  | 	"github.com/minio/minio/pkg/bucket/lifecycle" | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Disabled means the lifecycle rule is inactive
 | 
					
						
							|  |  |  | 	Disabled = "Disabled" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // LifecycleSys - Bucket lifecycle subsystem.
 | 
					
						
							|  |  |  | type LifecycleSys struct { | 
					
						
							|  |  |  | 	sync.RWMutex | 
					
						
							|  |  |  | 	bucketLifecycleMap map[string]lifecycle.Lifecycle | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Set - sets lifecycle config to given bucket name.
 | 
					
						
							|  |  |  | func (sys *LifecycleSys) Set(bucketName string, lifecycle lifecycle.Lifecycle) { | 
					
						
							| 
									
										
										
										
											2019-10-02 08:05:02 +08:00
										 |  |  | 	if globalIsGateway { | 
					
						
							|  |  |  | 		// no-op
 | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sys.bucketLifecycleMap[bucketName] = lifecycle | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-10 01:02:41 +08:00
										 |  |  | // Get - gets lifecycle config associated to a given bucket name.
 | 
					
						
							| 
									
										
										
										
											2020-02-05 17:42:34 +08:00
										 |  |  | func (sys *LifecycleSys) Get(bucketName string) (lc lifecycle.Lifecycle, ok bool) { | 
					
						
							| 
									
										
										
										
											2019-10-02 08:05:02 +08:00
										 |  |  | 	if globalIsGateway { | 
					
						
							|  |  |  | 		// When gateway is enabled, no cached value
 | 
					
						
							|  |  |  | 		// is used to validate life cycle policies.
 | 
					
						
							| 
									
										
										
										
											2019-11-10 01:27:23 +08:00
										 |  |  | 		objAPI := newObjectLayerWithoutSafeModeFn() | 
					
						
							| 
									
										
										
										
											2019-10-02 08:05:02 +08:00
										 |  |  | 		if objAPI == nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-02-05 17:42:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-10 00:30:02 +08:00
										 |  |  | 		l, err := objAPI.GetBucketLifecycle(GlobalContext, bucketName) | 
					
						
							| 
									
										
										
										
											2020-02-05 17:42:34 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return *l, true | 
					
						
							| 
									
										
										
										
											2019-10-02 08:05:02 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-05 17:42:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-10 01:02:41 +08:00
										 |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							| 
									
										
										
										
											2020-02-05 17:42:34 +08:00
										 |  |  | 	lc, ok = sys.bucketLifecycleMap[bucketName] | 
					
						
							|  |  |  | 	return | 
					
						
							| 
									
										
										
										
											2019-08-10 01:02:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | func saveLifecycleConfig(ctx context.Context, objAPI ObjectLayer, bucketName string, bucketLifecycle *lifecycle.Lifecycle) error { | 
					
						
							|  |  |  | 	data, err := xml.Marshal(bucketLifecycle) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Construct path to lifecycle.xml for the given bucket.
 | 
					
						
							|  |  |  | 	configFile := path.Join(bucketConfigPrefix, bucketName, bucketLifecycleConfig) | 
					
						
							|  |  |  | 	return saveConfig(ctx, objAPI, configFile, data) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // getLifecycleConfig - get lifecycle config for given bucket name.
 | 
					
						
							|  |  |  | func getLifecycleConfig(objAPI ObjectLayer, bucketName string) (*lifecycle.Lifecycle, error) { | 
					
						
							|  |  |  | 	// Construct path to lifecycle.xml for the given bucket.
 | 
					
						
							|  |  |  | 	configFile := path.Join(bucketConfigPrefix, bucketName, bucketLifecycleConfig) | 
					
						
							| 
									
										
										
										
											2020-04-10 00:30:02 +08:00
										 |  |  | 	configData, err := readConfig(GlobalContext, objAPI, configFile) | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		if err == errConfigNotFound { | 
					
						
							|  |  |  | 			err = BucketLifecycleNotFound{Bucket: bucketName} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return lifecycle.ParseLifecycleConfig(bytes.NewReader(configData)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func removeLifecycleConfig(ctx context.Context, objAPI ObjectLayer, bucketName string) error { | 
					
						
							|  |  |  | 	// Construct path to lifecycle.xml for the given bucket.
 | 
					
						
							|  |  |  | 	configFile := path.Join(bucketConfigPrefix, bucketName, bucketLifecycleConfig) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := objAPI.DeleteObject(ctx, minioMetaBucket, configFile); err != nil { | 
					
						
							|  |  |  | 		if _, ok := err.(ObjectNotFound); ok { | 
					
						
							|  |  |  | 			return BucketLifecycleNotFound{Bucket: bucketName} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewLifecycleSys - creates new lifecycle system.
 | 
					
						
							|  |  |  | func NewLifecycleSys() *LifecycleSys { | 
					
						
							|  |  |  | 	return &LifecycleSys{ | 
					
						
							|  |  |  | 		bucketLifecycleMap: make(map[string]lifecycle.Lifecycle), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Init - initializes lifecycle system from lifecycle.xml of all buckets.
 | 
					
						
							| 
									
										
										
										
											2019-10-02 08:05:02 +08:00
										 |  |  | func (sys *LifecycleSys) Init(buckets []BucketInfo, objAPI ObjectLayer) error { | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | 	if objAPI == nil { | 
					
						
							|  |  |  | 		return errServerNotInitialized | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-02 08:05:02 +08:00
										 |  |  | 	// In gateway mode, we always fetch the bucket lifecycle configuration from the gateway backend.
 | 
					
						
							|  |  |  | 	// So, this is a no-op for gateway servers.
 | 
					
						
							|  |  |  | 	if globalIsGateway { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 09:07:43 +08:00
										 |  |  | 	// Load LifecycleSys once during boot.
 | 
					
						
							|  |  |  | 	return sys.load(buckets, objAPI) | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-02 08:05:02 +08:00
										 |  |  | // Loads lifecycle policies for all buckets into LifecycleSys.
 | 
					
						
							|  |  |  | func (sys *LifecycleSys) load(buckets []BucketInfo, objAPI ObjectLayer) error { | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | 	for _, bucket := range buckets { | 
					
						
							| 
									
										
										
										
											2020-04-10 00:30:02 +08:00
										 |  |  | 		config, err := objAPI.GetBucketLifecycle(GlobalContext, bucket.Name) | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			if _, ok := err.(BucketLifecycleNotFound); ok { | 
					
						
							|  |  |  | 				sys.Remove(bucket.Name) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		sys.Set(bucket.Name, *config) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-05 17:42:34 +08:00
										 |  |  | // Remove - removes lifecycle config for given bucket name.
 | 
					
						
							| 
									
										
										
										
											2019-07-20 04:20:33 +08:00
										 |  |  | func (sys *LifecycleSys) Remove(bucketName string) { | 
					
						
							|  |  |  | 	sys.Lock() | 
					
						
							|  |  |  | 	defer sys.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	delete(sys.bucketLifecycleMap, bucketName) | 
					
						
							|  |  |  | } |