mirror of
https://github.com/minio/minio.git
synced 2025-01-11 15:03:22 -05:00
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:
parent
3e063cca5c
commit
9b3b04ecec
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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
|
@ -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()
|
||||
}
|
@ -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.
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
@ -218,7 +218,7 @@ var (
|
||||
|
||||
globalBucketObjectLockConfig = objectlock.NewBucketObjectLockConfig()
|
||||
|
||||
globalBucketQuotaSys = NewBucketQuotaSys()
|
||||
globalBucketQuotaSys *BucketQuotaSys
|
||||
globalBucketStorageCache bucketStorageCache
|
||||
|
||||
// Disk cache drives
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user