diff --git a/cmd/bucket-encryption-handlers.go b/cmd/bucket-encryption-handlers.go index e4f9ae488..da2348cff 100644 --- a/cmd/bucket-encryption-handlers.go +++ b/cmd/bucket-encryption-handlers.go @@ -18,6 +18,7 @@ package cmd import ( "encoding/xml" + "fmt" "io" "net/http" @@ -69,7 +70,12 @@ func (api objectAPIHandlers) PutBucketEncryptionHandler(w http.ResponseWriter, r // Parse bucket encryption xml encConfig, err := validateBucketSSEConfig(io.LimitReader(r.Body, maxBucketSSEConfigSize)) if err != nil { - writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrMalformedXML), r.URL, guessIsBrowserReq(r)) + apiErr := APIError{ + Code: "MalformedXML", + Description: fmt.Sprintf("%s (%s)", errorCodes[ErrMalformedXML].Description, err), + HTTPStatusCode: errorCodes[ErrMalformedXML].HTTPStatusCode, + } + writeErrorResponse(ctx, w, apiErr, r.URL, guessIsBrowserReq(r)) return } @@ -86,7 +92,7 @@ func (api objectAPIHandlers) PutBucketEncryptionHandler(w http.ResponseWriter, r } // Update the in-memory bucket encryption cache - globalBucketSSEConfigSys.Set(bucket, *encConfig) + globalBucketSSEConfigSys.Set(bucket, encConfig) // Update peer MinIO servers of the updated bucket encryption config globalNotificationSys.SetBucketSSEConfig(ctx, bucket, encConfig) @@ -174,6 +180,7 @@ func (api objectAPIHandlers) DeleteBucketEncryptionHandler(w http.ResponseWriter // Remove entry from the in-memory bucket encryption cache globalBucketSSEConfigSys.Remove(bucket) + // Update peer MinIO servers of the updated bucket encryption config globalNotificationSys.RemoveBucketSSEConfig(ctx, bucket) diff --git a/cmd/bucket-encryption.go b/cmd/bucket-encryption.go index 365087d4f..b6c77a6aa 100644 --- a/cmd/bucket-encryption.go +++ b/cmd/bucket-encryption.go @@ -31,13 +31,13 @@ import ( // BucketSSEConfigSys - in-memory cache of bucket encryption config type BucketSSEConfigSys struct { sync.RWMutex - bucketSSEConfigMap map[string]bucketsse.BucketSSEConfig + bucketSSEConfigMap map[string]*bucketsse.BucketSSEConfig } // NewBucketSSEConfigSys - Creates an empty in-memory bucket encryption configuration cache func NewBucketSSEConfigSys() *BucketSSEConfigSys { return &BucketSSEConfigSys{ - bucketSSEConfigMap: make(map[string]bucketsse.BucketSSEConfig), + bucketSSEConfigMap: make(map[string]*bucketsse.BucketSSEConfig), } } @@ -47,11 +47,12 @@ func (sys *BucketSSEConfigSys) load(buckets []BucketInfo, objAPI ObjectLayer) er config, err := objAPI.GetBucketSSEConfig(GlobalContext, bucket.Name) if err != nil { if _, ok := err.(BucketSSEConfigNotFound); ok { - sys.Remove(bucket.Name) + continue } - continue + // Quorum errors should be returned. + return err } - sys.Set(bucket.Name, *config) + sys.Set(bucket.Name, config) } return nil @@ -73,7 +74,7 @@ func (sys *BucketSSEConfigSys) Init(buckets []BucketInfo, objAPI ObjectLayer) er } // Get - gets bucket encryption config for the given bucket. -func (sys *BucketSSEConfigSys) Get(bucket string) (config bucketsse.BucketSSEConfig, ok bool) { +func (sys *BucketSSEConfigSys) Get(bucket string) (config *bucketsse.BucketSSEConfig, ok bool) { // We don't cache bucket encryption config in gateway mode. if globalIsGateway { objAPI := newObjectLayerWithoutSafeModeFn() @@ -85,7 +86,7 @@ func (sys *BucketSSEConfigSys) Get(bucket string) (config bucketsse.BucketSSECon if err != nil { return } - return *cfg, true + return cfg, true } sys.Lock() @@ -95,7 +96,7 @@ func (sys *BucketSSEConfigSys) Get(bucket string) (config bucketsse.BucketSSECon } // Set - sets bucket encryption config to given bucket name. -func (sys *BucketSSEConfigSys) Set(bucket string, config bucketsse.BucketSSEConfig) { +func (sys *BucketSSEConfigSys) Set(bucket string, config *bucketsse.BucketSSEConfig) { // We don't cache bucket encryption config in gateway mode. if globalIsGateway { return @@ -146,8 +147,8 @@ func removeBucketSSEConfig(ctx context.Context, objAPI ObjectLayer, bucket strin // Path to bucket-encryption.xml for the given bucket. configFile := path.Join(bucketConfigPrefix, bucket, bucketSSEConfig) - if err := objAPI.DeleteObject(ctx, minioMetaBucket, configFile); err != nil { - if _, ok := err.(ObjectNotFound); ok { + if err := deleteConfig(ctx, objAPI, configFile); err != nil { + if err == errConfigNotFound { return BucketSSEConfigNotFound{Bucket: bucket} } return err diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index 74dd17b9f..2a3c12189 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -589,8 +589,9 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req return } if objectLockEnabled { - globalBucketObjectLockConfig.Set(bucket, objectlock.Retention{}) - globalNotificationSys.PutBucketObjectLockConfig(ctx, bucket, objectlock.Retention{}) + ret := &objectlock.Retention{} + globalBucketObjectLockConfig.Set(bucket, ret) + globalNotificationSys.PutBucketObjectLockConfig(ctx, bucket, ret) } } @@ -1069,8 +1070,8 @@ func (api objectAPIHandlers) PutBucketObjectLockConfigHandler(w http.ResponseWri globalBucketObjectLockConfig.Set(bucket, retention) globalNotificationSys.PutBucketObjectLockConfig(ctx, bucket, retention) } else { - globalBucketObjectLockConfig.Remove(bucket) - globalNotificationSys.RemoveBucketObjectLockConfig(ctx, bucket) + globalBucketObjectLockConfig.Set(bucket, &objectlock.Retention{}) + globalNotificationSys.PutBucketObjectLockConfig(ctx, bucket, &objectlock.Retention{}) } // Write success response. diff --git a/cmd/bucket-lifecycle-handler.go b/cmd/bucket-lifecycle-handler.go index 10ea678ae..285968058 100644 --- a/cmd/bucket-lifecycle-handler.go +++ b/cmd/bucket-lifecycle-handler.go @@ -77,7 +77,7 @@ func (api objectAPIHandlers) PutBucketLifecycleHandler(w http.ResponseWriter, r return } - globalLifecycleSys.Set(bucket, *bucketLifecycle) + globalLifecycleSys.Set(bucket, bucketLifecycle) globalNotificationSys.SetBucketLifecycle(ctx, bucket, bucketLifecycle) // Success. diff --git a/cmd/lifecycle.go b/cmd/bucket-lifecycle.go similarity index 87% rename from cmd/lifecycle.go rename to cmd/bucket-lifecycle.go index 8e780c617..b1784184a 100644 --- a/cmd/lifecycle.go +++ b/cmd/bucket-lifecycle.go @@ -35,11 +35,11 @@ const ( // LifecycleSys - Bucket lifecycle subsystem. type LifecycleSys struct { sync.RWMutex - bucketLifecycleMap map[string]lifecycle.Lifecycle + bucketLifecycleMap map[string]*lifecycle.Lifecycle } // Set - sets lifecycle config to given bucket name. -func (sys *LifecycleSys) Set(bucketName string, lifecycle lifecycle.Lifecycle) { +func (sys *LifecycleSys) Set(bucketName string, lifecycle *lifecycle.Lifecycle) { if globalIsGateway { // no-op return @@ -52,7 +52,7 @@ func (sys *LifecycleSys) Set(bucketName string, lifecycle lifecycle.Lifecycle) { } // Get - gets lifecycle config associated to a given bucket name. -func (sys *LifecycleSys) Get(bucketName string) (lc lifecycle.Lifecycle, ok bool) { +func (sys *LifecycleSys) Get(bucketName string) (lc *lifecycle.Lifecycle, ok bool) { if globalIsGateway { // When gateway is enabled, no cached value // is used to validate life cycle policies. @@ -65,7 +65,7 @@ func (sys *LifecycleSys) Get(bucketName string) (lc lifecycle.Lifecycle, ok bool if err != nil { return } - return *l, true + return l, true } sys.Lock() @@ -104,8 +104,8 @@ func removeLifecycleConfig(ctx context.Context, objAPI ObjectLayer, bucketName s // 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 { + if err := deleteConfig(ctx, objAPI, configFile); err != nil { + if err == errConfigNotFound { return BucketLifecycleNotFound{Bucket: bucketName} } return err @@ -116,7 +116,7 @@ func removeLifecycleConfig(ctx context.Context, objAPI ObjectLayer, bucketName s // NewLifecycleSys - creates new lifecycle system. func NewLifecycleSys() *LifecycleSys { return &LifecycleSys{ - bucketLifecycleMap: make(map[string]lifecycle.Lifecycle), + bucketLifecycleMap: make(map[string]*lifecycle.Lifecycle), } } @@ -139,15 +139,16 @@ func (sys *LifecycleSys) Init(buckets []BucketInfo, objAPI ObjectLayer) error { // Loads lifecycle policies for all buckets into LifecycleSys. func (sys *LifecycleSys) load(buckets []BucketInfo, objAPI ObjectLayer) error { for _, bucket := range buckets { - config, err := objAPI.GetBucketLifecycle(GlobalContext, bucket.Name) + config, err := getLifecycleConfig(objAPI, bucket.Name) if err != nil { if _, ok := err.(BucketLifecycleNotFound); ok { - sys.Remove(bucket.Name) + continue } - continue + // Quorum errors should be returned. + return err } - sys.Set(bucket.Name, *config) + sys.Set(bucket.Name, config) } return nil diff --git a/cmd/object-lock.go b/cmd/bucket-object-lock.go similarity index 99% rename from cmd/object-lock.go rename to cmd/bucket-object-lock.go index 0e240089a..552bff319 100644 --- a/cmd/object-lock.go +++ b/cmd/bucket-object-lock.go @@ -398,7 +398,7 @@ func initBucketObjectLockConfig(buckets []BucketInfo, objAPI ObjectLayer) error configData, err := readConfig(ctx, objAPI, configFile) if err != nil { if errors.Is(err, errConfigNotFound) { - globalBucketObjectLockConfig.Set(bucket.Name, objectlock.Retention{}) + globalBucketObjectLockConfig.Set(bucket.Name, &objectlock.Retention{}) continue } return err @@ -408,7 +408,7 @@ func initBucketObjectLockConfig(buckets []BucketInfo, objAPI ObjectLayer) error if err != nil { return err } - retention := objectlock.Retention{} + retention := &objectlock.Retention{} if config.Rule != nil { retention = config.ToRetention() } diff --git a/cmd/bucket-policy-handlers.go b/cmd/bucket-policy-handlers.go index 49516b39c..245c16cf6 100644 --- a/cmd/bucket-policy-handlers.go +++ b/cmd/bucket-policy-handlers.go @@ -92,7 +92,7 @@ func (api objectAPIHandlers) PutBucketPolicyHandler(w http.ResponseWriter, r *ht return } - globalPolicySys.Set(bucket, *bucketPolicy) + globalPolicySys.Set(bucket, bucketPolicy) globalNotificationSys.SetBucketPolicy(ctx, bucket, bucketPolicy) // Success. diff --git a/cmd/policy.go b/cmd/bucket-policy.go similarity index 96% rename from cmd/policy.go rename to cmd/bucket-policy.go index be626a564..7745e64a6 100644 --- a/cmd/policy.go +++ b/cmd/bucket-policy.go @@ -39,11 +39,11 @@ import ( // PolicySys - policy subsystem. type PolicySys struct { sync.RWMutex - bucketPolicyMap map[string]policy.Policy + bucketPolicyMap map[string]*policy.Policy } // Set - sets policy to given bucket name. If policy is empty, existing policy is removed. -func (sys *PolicySys) Set(bucketName string, policy policy.Policy) { +func (sys *PolicySys) Set(bucketName string, policy *policy.Policy) { if globalIsGateway { // Set policy is a non-op under gateway mode. return @@ -97,12 +97,12 @@ func (sys *PolicySys) IsAllowed(args policy.Args) bool { // Loads policies for all buckets into PolicySys. func (sys *PolicySys) load(buckets []BucketInfo, objAPI ObjectLayer) error { for _, bucket := range buckets { - config, err := objAPI.GetBucketPolicy(GlobalContext, bucket.Name) + config, err := getPolicyConfig(objAPI, bucket.Name) if err != nil { if _, ok := err.(BucketPolicyNotFound); ok { - sys.Remove(bucket.Name) + continue } - continue + return err } // This part is specifically written to handle migration // when the Version string is empty, this was allowed @@ -118,7 +118,7 @@ func (sys *PolicySys) load(buckets []BucketInfo, objAPI ObjectLayer) error { return err } } - sys.Set(bucket.Name, *config) + sys.Set(bucket.Name, config) } return nil } @@ -126,7 +126,7 @@ func (sys *PolicySys) load(buckets []BucketInfo, objAPI ObjectLayer) error { // Init - initializes policy system from policy.json of all buckets. func (sys *PolicySys) Init(buckets []BucketInfo, objAPI ObjectLayer) error { if objAPI == nil { - return errInvalidArgument + return errServerNotInitialized } // In gateway mode, we don't need to load the policies @@ -142,7 +142,7 @@ func (sys *PolicySys) Init(buckets []BucketInfo, objAPI ObjectLayer) error { // NewPolicySys - creates new policy system. func NewPolicySys() *PolicySys { return &PolicySys{ - bucketPolicyMap: make(map[string]policy.Policy), + bucketPolicyMap: make(map[string]*policy.Policy), } } diff --git a/cmd/quota.go b/cmd/bucket-quota.go similarity index 90% rename from cmd/quota.go rename to cmd/bucket-quota.go index 0beebf368..6f7103573 100644 --- a/cmd/quota.go +++ b/cmd/bucket-quota.go @@ -60,23 +60,50 @@ func (sys *BucketQuotaSys) Remove(bucketName string) { sys.Unlock() } -// Exists - bucketName has Quota config set -func (sys *BucketQuotaSys) Exists(bucketName string) bool { - sys.RLock() - _, ok := sys.quotaMap[bucketName] - sys.RUnlock() - return ok -} - -// Keys - list of buckets with quota configuration -func (sys *BucketQuotaSys) Keys() []string { +// Buckets - list of buckets with quota configuration +func (sys *BucketQuotaSys) Buckets() []string { sys.RLock() defer sys.RUnlock() - var keys []string + var buckets []string for k := range sys.quotaMap { - keys = append(keys, k) + buckets = append(buckets, k) } - return keys + return buckets +} + +// Init initialize bucket quota sys configuration with all buckets. +func (sys *BucketQuotaSys) Init(buckets []BucketInfo, objAPI ObjectLayer) error { + if objAPI == nil { + return errServerNotInitialized + } + + // 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 + } + + return sys.load(buckets, objAPI) +} + +func (sys *BucketQuotaSys) load(buckets []BucketInfo, objAPI ObjectLayer) error { + for _, bucket := range buckets { + ctx := logger.SetReqInfo(GlobalContext, &logger.ReqInfo{BucketName: bucket.Name}) + configFile := path.Join(bucketConfigPrefix, bucket.Name, bucketQuotaConfigFile) + configData, err := readConfig(ctx, objAPI, configFile) + if err != nil { + if errors.Is(err, errConfigNotFound) { + continue + } + return err + } + quotaCfg, err := parseBucketQuota(configData) + if err != nil { + return err + } + globalBucketQuotaSys.Set(bucket.Name, quotaCfg) + } + return nil } // NewBucketQuotaSys returns initialized BucketQuotaSys @@ -131,26 +158,6 @@ func enforceBucketQuota(ctx context.Context, bucket string, size int64) error { return globalBucketStorageCache.check(ctx, q, bucket, size) } -func initBucketQuotaSys(buckets []BucketInfo, objAPI ObjectLayer) error { - for _, bucket := range buckets { - ctx := logger.SetReqInfo(GlobalContext, &logger.ReqInfo{BucketName: bucket.Name}) - configFile := path.Join(bucketConfigPrefix, bucket.Name, bucketQuotaConfigFile) - configData, err := readConfig(ctx, objAPI, configFile) - if err != nil { - if errors.Is(err, errConfigNotFound) { - continue - } - return err - } - quotaCfg, err := parseBucketQuota(configData) - if err != nil { - return err - } - globalBucketQuotaSys.Set(bucket.Name, quotaCfg) - } - return nil -} - const ( bgQuotaInterval = 1 * time.Hour ) @@ -182,7 +189,7 @@ func enforceFIFOQuota(ctx context.Context, objectAPI ObjectLayer) error { if env.Get(envDataUsageCrawlConf, config.EnableOn) == config.EnableOff { return nil } - for _, bucket := range globalBucketQuotaSys.Keys() { + for _, bucket := range globalBucketQuotaSys.Buckets() { // Check if the current bucket has quota restrictions, if not skip it cfg, ok := globalBucketQuotaSys.Get(bucket) if !ok { diff --git a/cmd/globals.go b/cmd/globals.go index 0bbf7164d..a2bb93743 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -218,7 +218,7 @@ var ( globalBucketObjectLockConfig = objectlock.NewBucketObjectLockConfig() - globalBucketQuotaSys = NewBucketQuotaSys() + globalBucketQuotaSys *BucketQuotaSys globalBucketStorageCache bucketStorageCache // Disk cache drives diff --git a/cmd/notification.go b/cmd/notification.go index 2eb726357..d1ed32a35 100644 --- a/cmd/notification.go +++ b/cmd/notification.go @@ -771,7 +771,7 @@ func (sys *NotificationSys) load(buckets []BucketInfo, objAPI ObjectLayer) error // Init - initializes notification system from notification.xml and listener.json of all buckets. func (sys *NotificationSys) Init(buckets []BucketInfo, objAPI ObjectLayer) error { if objAPI == nil { - return errInvalidArgument + return errServerNotInitialized } // In gateway mode, notifications are not supported. @@ -905,7 +905,7 @@ func (sys *NotificationSys) Send(args eventArgs) { } // PutBucketObjectLockConfig - put bucket object lock configuration to all peers. -func (sys *NotificationSys) PutBucketObjectLockConfig(ctx context.Context, bucketName string, retention objectlock.Retention) { +func (sys *NotificationSys) PutBucketObjectLockConfig(ctx context.Context, bucketName string, retention *objectlock.Retention) { g := errgroup.WithNErrs(len(sys.peerClients)) for index, client := range sys.peerClients { if client == nil { diff --git a/cmd/peer-rest-client.go b/cmd/peer-rest-client.go index bd0b105b1..d2a3c306f 100644 --- a/cmd/peer-rest-client.go +++ b/cmd/peer-rest-client.go @@ -656,12 +656,12 @@ func (client *peerRESTClient) PutBucketNotification(bucket string, rulesMap even } // PutBucketObjectLockConfig - PUT bucket object lock configuration. -func (client *peerRESTClient) PutBucketObjectLockConfig(bucket string, retention objectlock.Retention) error { +func (client *peerRESTClient) PutBucketObjectLockConfig(bucket string, retention *objectlock.Retention) error { values := make(url.Values) values.Set(peerRESTBucket, bucket) var reader bytes.Buffer - err := gob.NewEncoder(&reader).Encode(&retention) + err := gob.NewEncoder(&reader).Encode(retention) if err != nil { return err } diff --git a/cmd/peer-rest-server.go b/cmd/peer-rest-server.go index 071915b3a..032999c92 100644 --- a/cmd/peer-rest-server.go +++ b/cmd/peer-rest-server.go @@ -675,13 +675,14 @@ func (s *peerRESTServer) SetBucketPolicyHandler(w http.ResponseWriter, r *http.R s.writeErrorResponse(w, errors.New("Bucket name is missing")) return } - var policyData policy.Policy + if r.ContentLength < 0 { s.writeErrorResponse(w, errInvalidArgument) return } - err := gob.NewDecoder(r.Body).Decode(&policyData) + var policyData = &policy.Policy{} + err := gob.NewDecoder(r.Body).Decode(policyData) if err != nil { s.writeErrorResponse(w, err) return @@ -716,13 +717,13 @@ func (s *peerRESTServer) SetBucketLifecycleHandler(w http.ResponseWriter, r *htt s.writeErrorResponse(w, errors.New("Bucket name is missing")) return } - var lifecycleData lifecycle.Lifecycle if r.ContentLength < 0 { s.writeErrorResponse(w, errInvalidArgument) return } - err := gob.NewDecoder(r.Body).Decode(&lifecycleData) + var lifecycleData = &lifecycle.Lifecycle{} + err := gob.NewDecoder(r.Body).Decode(lifecycleData) if err != nil { s.writeErrorResponse(w, err) return @@ -758,13 +759,13 @@ func (s *peerRESTServer) SetBucketSSEConfigHandler(w http.ResponseWriter, r *htt return } - var encConfig bucketsse.BucketSSEConfig if r.ContentLength < 0 { s.writeErrorResponse(w, errInvalidArgument) return } - err := gob.NewDecoder(r.Body).Decode(&encConfig) + var encConfig = &bucketsse.BucketSSEConfig{} + err := gob.NewDecoder(r.Body).Decode(encConfig) if err != nil { s.writeErrorResponse(w, err) return @@ -860,13 +861,13 @@ func (s *peerRESTServer) PutBucketObjectLockConfigHandler(w http.ResponseWriter, return } - var retention objectlock.Retention if r.ContentLength < 0 { s.writeErrorResponse(w, errInvalidArgument) return } - err := gob.NewDecoder(r.Body).Decode(&retention) + var retention = &objectlock.Retention{} + err := gob.NewDecoder(r.Body).Decode(retention) if err != nil { s.writeErrorResponse(w, err) return diff --git a/cmd/policy_test.go b/cmd/policy_test.go index 487d6034a..378fd8741 100644 --- a/cmd/policy_test.go +++ b/cmd/policy_test.go @@ -41,10 +41,10 @@ func TestPolicySysSet(t *testing.T) { }, } case1Result := NewPolicySys() - case1Result.bucketPolicyMap["mybucket"] = case1Policy + case1Result.bucketPolicyMap["mybucket"] = &case1Policy case2PolicySys := NewPolicySys() - case2PolicySys.bucketPolicyMap["mybucket"] = case1Policy + case2PolicySys.bucketPolicyMap["mybucket"] = &case1Policy case2Policy := policy.Policy{ Version: policy.DefaultVersion, Statements: []policy.Statement{ @@ -58,10 +58,10 @@ func TestPolicySysSet(t *testing.T) { }, } case2Result := NewPolicySys() - case2Result.bucketPolicyMap["mybucket"] = case2Policy + case2Result.bucketPolicyMap["mybucket"] = &case2Policy case3PolicySys := NewPolicySys() - case3PolicySys.bucketPolicyMap["mybucket"] = case2Policy + case3PolicySys.bucketPolicyMap["mybucket"] = &case2Policy case3Policy := policy.Policy{ ID: "MyPolicyForMyBucket", Version: policy.DefaultVersion, @@ -81,7 +81,7 @@ func TestPolicySysSet(t *testing.T) { for i, testCase := range testCases { result := testCase.policySys - result.Set(testCase.bucketName, testCase.bucketPolicy) + result.Set(testCase.bucketName, &testCase.bucketPolicy) if !reflect.DeepEqual(result, testCase.expectedResult) { t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) @@ -103,7 +103,7 @@ func TestPolicySysRemove(t *testing.T) { }, } case1PolicySys := NewPolicySys() - case1PolicySys.bucketPolicyMap["mybucket"] = case1Policy + case1PolicySys.bucketPolicyMap["mybucket"] = &case1Policy case1Result := NewPolicySys() case2Policy := policy.Policy{ @@ -119,9 +119,9 @@ func TestPolicySysRemove(t *testing.T) { }, } case2PolicySys := NewPolicySys() - case2PolicySys.bucketPolicyMap["mybucket"] = case2Policy + case2PolicySys.bucketPolicyMap["mybucket"] = &case2Policy case2Result := NewPolicySys() - case2Result.bucketPolicyMap["mybucket"] = case2Policy + case2Result.bucketPolicyMap["mybucket"] = &case2Policy case3PolicySys := NewPolicySys() case3Result := NewPolicySys() @@ -148,7 +148,7 @@ func TestPolicySysRemove(t *testing.T) { func TestPolicySysIsAllowed(t *testing.T) { policySys := NewPolicySys() - policySys.Set("mybucket", policy.Policy{ + policySys.Set("mybucket", &policy.Policy{ Version: policy.DefaultVersion, Statements: []policy.Statement{ policy.NewStatement( diff --git a/cmd/server-main.go b/cmd/server-main.go index 058b52929..1e090ebc5 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -155,6 +155,9 @@ func newAllSubsystems() { // Create new bucket encryption subsystem globalBucketSSEConfigSys = NewBucketSSEConfigSys() + + // Create new bucket quota subsystem + globalBucketQuotaSys = NewBucketQuotaSys() } func initSafeMode(buckets []BucketInfo) (err error) { @@ -275,10 +278,6 @@ func initAllSubsystems(buckets []BucketInfo, newObject ObjectLayer) (err error) if err = initBucketObjectLockConfig(buckets, newObject); err != nil { return fmt.Errorf("Unable to initialize object lock system: %w", err) } - // Initialize bucket quota system. - if err = initBucketQuotaSys(buckets, newObject); err != nil { - return fmt.Errorf("Unable to initialize bucket quota system: %w", err) - } // Initialize lifecycle system. if err = globalLifecycleSys.Init(buckets, newObject); err != nil { @@ -290,6 +289,11 @@ func initAllSubsystems(buckets []BucketInfo, newObject ObjectLayer) (err error) return fmt.Errorf("Unable to initialize bucket encryption subsystem: %w", err) } + // Initialize bucket quota system. + if err = globalBucketQuotaSys.Init(buckets, newObject); err != nil { + return fmt.Errorf("Unable to initialize bucket quota system: %w", err) + } + return nil } diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index d62eb2808..57f616c70 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -1750,7 +1750,7 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, obj ObjectLayer, testName, bucketN if err := obj.SetBucketPolicy(context.Background(), bucketName, bucketPolicy); err != nil { t.Fatalf("unexpected error. %v", err) } - globalPolicySys.Set(bucketName, *bucketPolicy) + globalPolicySys.Set(bucketName, bucketPolicy) defer globalPolicySys.Remove(bucketName) // now call the handler again with the unsigned/anonymous request, it should be accepted. diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go index 0d1453c8a..91a5511e7 100644 --- a/cmd/web-handlers.go +++ b/cmd/web-handlers.go @@ -1904,7 +1904,7 @@ func (web *webAPIHandlers) SetBucketPolicy(r *http.Request, args *SetBucketPolic return toJSONError(ctx, err, args.BucketName) } - globalPolicySys.Set(args.BucketName, *bucketPolicy) + globalPolicySys.Set(args.BucketName, bucketPolicy) globalNotificationSys.SetBucketPolicy(ctx, args.BucketName, bucketPolicy) } diff --git a/cmd/web-handlers_test.go b/cmd/web-handlers_test.go index a0a167349..c98c8e2e2 100644 --- a/cmd/web-handlers_test.go +++ b/cmd/web-handlers_test.go @@ -548,7 +548,7 @@ func testListObjectsWebHandler(obj ObjectLayer, instanceType string, t TestErrHa if err = obj.SetBucketPolicy(context.Background(), bucketName, bucketPolicy); err != nil { t.Fatalf("unexpected error. %v", err) } - globalPolicySys.Set(bucketName, *bucketPolicy) + globalPolicySys.Set(bucketName, bucketPolicy) defer globalPolicySys.Remove(bucketName) // Unauthenticated ListObjects with READ bucket policy should succeed. @@ -906,7 +906,7 @@ func testUploadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler if err := obj.SetBucketPolicy(context.Background(), bucketName, bucketPolicy); err != nil { t.Fatalf("unexpected error. %v", err) } - globalPolicySys.Set(bucketName, *bucketPolicy) + globalPolicySys.Set(bucketName, bucketPolicy) defer globalPolicySys.Remove(bucketName) // Unauthenticated upload with WRITE policy should succeed. @@ -1025,7 +1025,7 @@ func testDownloadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandl if err := obj.SetBucketPolicy(context.Background(), bucketName, bucketPolicy); err != nil { t.Fatalf("unexpected error. %v", err) } - globalPolicySys.Set(bucketName, *bucketPolicy) + globalPolicySys.Set(bucketName, bucketPolicy) defer globalPolicySys.Remove(bucketName) // Unauthenticated download with READ policy should succeed. diff --git a/pkg/bucket/object/lock/lock.go b/pkg/bucket/object/lock/lock.go index 372680105..fafd4acf3 100644 --- a/pkg/bucket/object/lock/lock.go +++ b/pkg/bucket/object/lock/lock.go @@ -161,18 +161,18 @@ func (r Retention) Retain(created time.Time) bool { // BucketObjectLockConfig - map of bucket and retention configuration. type BucketObjectLockConfig struct { sync.RWMutex - retentionMap map[string]Retention + retentionMap map[string]*Retention } // Set - set retention configuration. -func (config *BucketObjectLockConfig) Set(bucketName string, retention Retention) { +func (config *BucketObjectLockConfig) Set(bucketName string, retention *Retention) { config.Lock() config.retentionMap[bucketName] = retention config.Unlock() } // Get - Get retention configuration. -func (config *BucketObjectLockConfig) Get(bucketName string) (r Retention, ok bool) { +func (config *BucketObjectLockConfig) Get(bucketName string) (r *Retention, ok bool) { config.RLock() defer config.RUnlock() r, ok = config.retentionMap[bucketName] @@ -189,7 +189,7 @@ func (config *BucketObjectLockConfig) Remove(bucketName string) { // NewBucketObjectLockConfig returns initialized BucketObjectLockConfig func NewBucketObjectLockConfig() *BucketObjectLockConfig { return &BucketObjectLockConfig{ - retentionMap: map[string]Retention{}, + retentionMap: make(map[string]*Retention), } } @@ -280,7 +280,8 @@ func (config *Config) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error } // ToRetention - convert to Retention type. -func (config *Config) ToRetention() (r Retention) { +func (config *Config) ToRetention() (r *Retention) { + r = &Retention{} if config.Rule != nil { r.Mode = config.Rule.DefaultRetention.Mode