diff --git a/cmd/bucket-encryption-handlers.go b/cmd/bucket-encryption-handlers.go index ec47f43a2..aa5999485 100644 --- a/cmd/bucket-encryption-handlers.go +++ b/cmd/bucket-encryption-handlers.go @@ -204,7 +204,7 @@ func (api objectAPIHandlers) DeleteBucketEncryptionHandler(w http.ResponseWriter } // Delete bucket encryption config from object layer - updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, nil) + updatedAt, err := globalBucketMetadataSys.Delete(ctx, bucket, bucketSSEConfig) if err != nil { writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) return diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index b0afca206..18ff802d9 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -1618,7 +1618,7 @@ func (api objectAPIHandlers) DeleteBucketTaggingHandler(w http.ResponseWriter, r return } - updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, nil) + updatedAt, err := globalBucketMetadataSys.Delete(ctx, bucket, bucketTaggingConfig) if err != nil { writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) return diff --git a/cmd/bucket-lifecycle-handlers.go b/cmd/bucket-lifecycle-handlers.go index e7a8943cc..77d6432f7 100644 --- a/cmd/bucket-lifecycle-handlers.go +++ b/cmd/bucket-lifecycle-handlers.go @@ -168,7 +168,7 @@ func (api objectAPIHandlers) DeleteBucketLifecycleHandler(w http.ResponseWriter, return } - if _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketLifecycleConfig, nil); err != nil { + if _, err := globalBucketMetadataSys.Delete(ctx, bucket, bucketLifecycleConfig); err != nil { writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) return } diff --git a/cmd/bucket-metadata-sys.go b/cmd/bucket-metadata-sys.go index b4c2c9b8e..b7bc78eed 100644 --- a/cmd/bucket-metadata-sys.go +++ b/cmd/bucket-metadata-sys.go @@ -81,9 +81,7 @@ func (sys *BucketMetadataSys) Set(bucket string, meta BucketMetadata) { } } -// Update update bucket metadata for the specified config file. -// The configData data should not be modified after being sent here. -func (sys *BucketMetadataSys) Update(ctx context.Context, bucket string, configFile string, configData []byte) (updatedAt time.Time, err error) { +func (sys *BucketMetadataSys) updateAndParse(ctx context.Context, bucket string, configFile string, configData []byte, parse bool) (updatedAt time.Time, err error) { objAPI := newObjectLayerFn() if objAPI == nil { return updatedAt, errServerNotInitialized @@ -107,7 +105,7 @@ func (sys *BucketMetadataSys) Update(ctx context.Context, bucket string, configF return updatedAt, errInvalidArgument } - meta, err := loadBucketMetadata(ctx, objAPI, bucket) + meta, err := loadBucketMetadataParse(ctx, objAPI, bucket, parse) if err != nil { if !globalIsErasure && !globalIsDistErasure && errors.Is(err, errVolumeNotFound) { // Only single drive mode needs this fallback. @@ -165,6 +163,18 @@ func (sys *BucketMetadataSys) Update(ctx context.Context, bucket string, configF return updatedAt, nil } +// Delete delete the bucket metadata for the specified bucket. +// must be used by all callers instead of using Update() with nil configData. +func (sys *BucketMetadataSys) Delete(ctx context.Context, bucket string, configFile string) (updatedAt time.Time, err error) { + return sys.updateAndParse(ctx, bucket, configFile, nil, false) +} + +// Update update bucket metadata for the specified bucket. +// The configData data should not be modified after being sent here. +func (sys *BucketMetadataSys) Update(ctx context.Context, bucket string, configFile string, configData []byte) (updatedAt time.Time, err error) { + return sys.updateAndParse(ctx, bucket, configFile, configData, true) +} + // Get metadata for a bucket. // If no metadata exists errConfigNotFound is returned and a new metadata is returned. // Only a shallow copy is returned, so referenced data should not be modified, diff --git a/cmd/bucket-metadata.go b/cmd/bucket-metadata.go index 2d5376bab..2f565d6b5 100644 --- a/cmd/bucket-metadata.go +++ b/cmd/bucket-metadata.go @@ -162,8 +162,7 @@ func (b *BucketMetadata) Load(ctx context.Context, api ObjectLayer, name string) return err } -// loadBucketMetadata loads and migrates to bucket metadata. -func loadBucketMetadata(ctx context.Context, objectAPI ObjectLayer, bucket string) (BucketMetadata, error) { +func loadBucketMetadataParse(ctx context.Context, objectAPI ObjectLayer, bucket string, parse bool) (BucketMetadata, error) { b := newBucketMetadata(bucket) err := b.Load(ctx, objectAPI, b.Name) if err != nil && !errors.Is(err, errConfigNotFound) { @@ -172,8 +171,22 @@ func loadBucketMetadata(ctx context.Context, objectAPI ObjectLayer, bucket strin if err == nil { b.defaultTimestamps() } - // Old bucket without bucket metadata. Hence we migrate existing settings. - if err := b.convertLegacyConfigs(ctx, objectAPI); err != nil { + + configs, err := b.getAllLegacyConfigs(ctx, objectAPI) + if err != nil { + return b, err + } + + if len(configs) == 0 { + if parse { + // nothing to update, parse and proceed. + err = b.parseAllConfigs(ctx, objectAPI) + } + } else { + // Old bucket without bucket metadata. Hence we migrate existing settings. + err = b.convertLegacyConfigs(ctx, objectAPI, configs) + } + if err != nil { return b, err } @@ -185,6 +198,11 @@ func loadBucketMetadata(ctx context.Context, objectAPI ObjectLayer, bucket strin return b, nil } +// loadBucketMetadata loads and migrates to bucket metadata. +func loadBucketMetadata(ctx context.Context, objectAPI ObjectLayer, bucket string) (BucketMetadata, error) { + return loadBucketMetadataParse(ctx, objectAPI, bucket, true) +} + // parseAllConfigs will parse all configs and populate the private fields. // The first error encountered is returned. func (b *BucketMetadata) parseAllConfigs(ctx context.Context, objectAPI ObjectLayer) (err error) { @@ -277,7 +295,7 @@ func (b *BucketMetadata) parseAllConfigs(ctx context.Context, objectAPI ObjectLa return nil } -func (b *BucketMetadata) convertLegacyConfigs(ctx context.Context, objectAPI ObjectLayer) error { +func (b *BucketMetadata) getAllLegacyConfigs(ctx context.Context, objectAPI ObjectLayer) (map[string][]byte, error) { legacyConfigs := []string{ legacyBucketObjectLockEnabledConfigFile, bucketPolicyConfig, @@ -291,7 +309,7 @@ func (b *BucketMetadata) convertLegacyConfigs(ctx context.Context, objectAPI Obj objectLockConfig, } - configs := make(map[string][]byte) + configs := make(map[string][]byte, len(legacyConfigs)) // Handle migration from lockEnabled to newer format. if b.LockEnabled { @@ -316,16 +334,15 @@ func (b *BucketMetadata) convertLegacyConfigs(ctx context.Context, objectAPI Obj continue } - return err + return nil, err } configs[legacyFile] = configData } - if len(configs) == 0 { - // nothing to update, return right away. - return b.parseAllConfigs(ctx, objectAPI) - } + return configs, nil +} +func (b *BucketMetadata) convertLegacyConfigs(ctx context.Context, objectAPI ObjectLayer, configs map[string][]byte) error { for legacyFile, configData := range configs { switch legacyFile { case legacyBucketObjectLockEnabledConfigFile: diff --git a/cmd/bucket-policy-handlers.go b/cmd/bucket-policy-handlers.go index 3b6b5c3df..c1b2cd185 100644 --- a/cmd/bucket-policy-handlers.go +++ b/cmd/bucket-policy-handlers.go @@ -149,7 +149,7 @@ func (api objectAPIHandlers) DeleteBucketPolicyHandler(w http.ResponseWriter, r return } - updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, nil) + updatedAt, err := globalBucketMetadataSys.Delete(ctx, bucket, bucketPolicyConfig) if err != nil { writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) return diff --git a/cmd/bucket-replication-handlers.go b/cmd/bucket-replication-handlers.go index 68d96f641..bb0e8b332 100644 --- a/cmd/bucket-replication-handlers.go +++ b/cmd/bucket-replication-handlers.go @@ -165,7 +165,7 @@ func (api objectAPIHandlers) DeleteBucketReplicationConfigHandler(w http.Respons writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrReplicationDenyEditError), r.URL) return } - if _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketReplicationConfig, nil); err != nil { + if _, err := globalBucketMetadataSys.Delete(ctx, bucket, bucketReplicationConfig); err != nil { writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) return } diff --git a/cmd/site-replication.go b/cmd/site-replication.go index 966c2ea53..b52e7ae50 100644 --- a/cmd/site-replication.go +++ b/cmd/site-replication.go @@ -1361,7 +1361,7 @@ func (c *SiteReplicationSys) PeerBucketPolicyHandler(ctx context.Context, bucket } // Delete the bucket policy - _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, nil) + _, err := globalBucketMetadataSys.Delete(ctx, bucket, bucketPolicyConfig) if err != nil { return wrapSRErr(err) } @@ -1391,7 +1391,7 @@ func (c *SiteReplicationSys) PeerBucketTaggingHandler(ctx context.Context, bucke } // Delete the tags - _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, nil) + _, err := globalBucketMetadataSys.Delete(ctx, bucket, bucketTaggingConfig) if err != nil { return wrapSRErr(err) } @@ -1445,7 +1445,7 @@ func (c *SiteReplicationSys) PeerBucketSSEConfigHandler(ctx context.Context, buc } // Delete sse config - _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, nil) + _, err := globalBucketMetadataSys.Delete(ctx, bucket, bucketSSEConfig) if err != nil { return wrapSRErr(err) } @@ -1475,7 +1475,7 @@ func (c *SiteReplicationSys) PeerBucketQuotaConfigHandler(ctx context.Context, b } // Delete the bucket policy - _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketQuotaConfigFile, nil) + _, err := globalBucketMetadataSys.Delete(ctx, bucket, bucketQuotaConfigFile) if err != nil { return wrapSRErr(err) } @@ -2234,7 +2234,7 @@ func (c *SiteReplicationSys) RemoveRemoteTargetsForEndpoint(ctx context.Context, return err } } else { - if _, err := globalBucketMetadataSys.Update(ctx, b.Name, bucketReplicationConfig, nil); err != nil { + if _, err := globalBucketMetadataSys.Delete(ctx, b.Name, bucketReplicationConfig); err != nil { return err } }