allow retries for bucket encryption/policy quorum reloads (#9513)

We should allow quorum errors to be send upwards
such that caller can retry while reading bucket
encryption/policy configs when server is starting
up, this allows distributed setups to load the
configuration properly.

Current code didn't facilitate this and would have
never loaded the actual configs during rolling,
server restarts.
This commit is contained in:
Harshavardhana 2020-05-04 09:42:58 -07:00 committed by GitHub
parent 3e063cca5c
commit 9b3b04ecec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 132 additions and 109 deletions

View file

@ -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)

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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()
}

View file

@ -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.

View file

@ -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),
}
}

View file

@ -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 {

View file

@ -218,7 +218,7 @@ var (
globalBucketObjectLockConfig = objectlock.NewBucketObjectLockConfig()
globalBucketQuotaSys = NewBucketQuotaSys()
globalBucketQuotaSys *BucketQuotaSys
globalBucketStorageCache bucketStorageCache
// Disk cache drives

View file

@ -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 {

View file

@ -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
}

View file

@ -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

View file

@ -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(

View file

@ -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
}

View file

@ -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.

View file

@ -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)
}

View file

@ -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.

View file

@ -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