mirror of
https://github.com/minio/minio.git
synced 2025-01-11 23:13:23 -05:00
site healing: Skip stale bucket metadata updates from peer (#15186)
Allow healing to apply bucket metadata change only when peer gave the most recent update.
This commit is contained in:
parent
2f25639ea0
commit
7cc9286e0f
@ -92,15 +92,17 @@ func (a adminAPIHandlers) PutBucketQuotaConfigHandler(w http.ResponseWriter, r *
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketQuotaConfigFile, data); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketQuotaConfigFile, data)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bucketMeta := madmin.SRBucketMeta{
|
bucketMeta := madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypeQuotaConfig,
|
Type: madmin.SRBucketMetaTypeQuotaConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Quota: data,
|
Quota: data,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}
|
}
|
||||||
if quotaConfig.Quota == 0 {
|
if quotaConfig.Quota == 0 {
|
||||||
bucketMeta.Quota = nil
|
bucketMeta.Quota = nil
|
||||||
@ -267,7 +269,7 @@ func (a adminAPIHandlers) SetRemoteTargetHandler(w http.ResponseWriter, r *http.
|
|||||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErrWithErr(ErrAdminConfigBadJSON, err), r.URL)
|
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErrWithErr(ErrAdminConfigBadJSON, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketTargetsFile, tgtBytes); err != nil {
|
if _, err = globalBucketMetadataSys.Update(ctx, bucket, bucketTargetsFile, tgtBytes); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -362,7 +364,7 @@ func (a adminAPIHandlers) RemoveRemoteTargetHandler(w http.ResponseWriter, r *ht
|
|||||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErrWithErr(ErrAdminConfigBadJSON, err), r.URL)
|
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErrWithErr(ErrAdminConfigBadJSON, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketTargetsFile, tgtBytes); err != nil {
|
if _, err = globalBucketMetadataSys.Update(ctx, bucket, bucketTargetsFile, tgtBytes); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -707,7 +709,8 @@ func (a adminAPIHandlers) ImportBucketMetadataHandler(w http.ResponseWriter, r *
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, objectLockConfig, configData); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, objectLockConfig, configData)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -721,6 +724,7 @@ func (a adminAPIHandlers) ImportBucketMetadataHandler(w http.ResponseWriter, r *
|
|||||||
Type: madmin.SRBucketMetaTypeObjectLockConfig,
|
Type: madmin.SRBucketMetaTypeObjectLockConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
ObjectLockConfig: &cfgStr,
|
ObjectLockConfig: &cfgStr,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
||||||
return
|
return
|
||||||
@ -794,7 +798,7 @@ func (a adminAPIHandlers) ImportBucketMetadataHandler(w http.ResponseWriter, r *
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketVersioningConfig, configData); err != nil {
|
if _, err = globalBucketMetadataSys.Update(ctx, bucket, bucketVersioningConfig, configData); err != nil {
|
||||||
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -846,7 +850,7 @@ func (a adminAPIHandlers) ImportBucketMetadataHandler(w http.ResponseWriter, r *
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketNotificationConfig, configData); err != nil {
|
if _, err = globalBucketMetadataSys.Update(ctx, bucket, bucketNotificationConfig, configData); err != nil {
|
||||||
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -883,15 +887,17 @@ func (a adminAPIHandlers) ImportBucketMetadataHandler(w http.ResponseWriter, r *
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, configData); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, configData)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Call site replication hook.
|
// Call site replication hook.
|
||||||
if err = globalSiteReplicationSys.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
if err = globalSiteReplicationSys.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypePolicy,
|
Type: madmin.SRBucketMetaTypePolicy,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Policy: bucketPolicyBytes,
|
Policy: bucketPolicyBytes,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
||||||
return
|
return
|
||||||
@ -922,7 +928,7 @@ func (a adminAPIHandlers) ImportBucketMetadataHandler(w http.ResponseWriter, r *
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketLifecycleConfig, configData); err != nil {
|
if _, err = globalBucketMetadataSys.Update(ctx, bucket, bucketLifecycleConfig, configData); err != nil {
|
||||||
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -965,7 +971,8 @@ func (a adminAPIHandlers) ImportBucketMetadataHandler(w http.ResponseWriter, r *
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store the bucket encryption configuration in the object layer
|
// Store the bucket encryption configuration in the object layer
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, configData); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, configData)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -979,6 +986,7 @@ func (a adminAPIHandlers) ImportBucketMetadataHandler(w http.ResponseWriter, r *
|
|||||||
Type: madmin.SRBucketMetaTypeSSEConfig,
|
Type: madmin.SRBucketMetaTypeSSEConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
SSEConfig: &cfgStr,
|
SSEConfig: &cfgStr,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
||||||
return
|
return
|
||||||
@ -998,7 +1006,8 @@ func (a adminAPIHandlers) ImportBucketMetadataHandler(w http.ResponseWriter, r *
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, configData); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, configData)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1008,9 +1017,10 @@ func (a adminAPIHandlers) ImportBucketMetadataHandler(w http.ResponseWriter, r *
|
|||||||
// errors.
|
// errors.
|
||||||
cfgStr := base64.StdEncoding.EncodeToString(configData)
|
cfgStr := base64.StdEncoding.EncodeToString(configData)
|
||||||
if err = globalSiteReplicationSys.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
if err = globalSiteReplicationSys.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypeTags,
|
Type: madmin.SRBucketMetaTypeTags,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Tags: &cfgStr,
|
Tags: &cfgStr,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
||||||
return
|
return
|
||||||
@ -1033,15 +1043,17 @@ func (a adminAPIHandlers) ImportBucketMetadataHandler(w http.ResponseWriter, r *
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketQuotaConfigFile, data); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketQuotaConfigFile, data)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
writeErrorResponse(ctx, w, importError(ctx, err, file.Name, bucket), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bucketMeta := madmin.SRBucketMeta{
|
bucketMeta := madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypeQuotaConfig,
|
Type: madmin.SRBucketMetaTypeQuotaConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Quota: data,
|
Quota: data,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}
|
}
|
||||||
if quotaConfig.Quota == 0 {
|
if quotaConfig.Quota == 0 {
|
||||||
bucketMeta.Quota = nil
|
bucketMeta.Quota = nil
|
||||||
|
@ -214,7 +214,7 @@ func (a adminAPIHandlers) SRPeerReplicateBucketItem(w http.ResponseWriter, r *ht
|
|||||||
err = errSRInvalidRequest(errInvalidArgument)
|
err = errSRInvalidRequest(errInvalidArgument)
|
||||||
case madmin.SRBucketMetaTypePolicy:
|
case madmin.SRBucketMetaTypePolicy:
|
||||||
if item.Policy == nil {
|
if item.Policy == nil {
|
||||||
err = globalSiteReplicationSys.PeerBucketPolicyHandler(ctx, item.Bucket, nil)
|
err = globalSiteReplicationSys.PeerBucketPolicyHandler(ctx, item.Bucket, nil, item.UpdatedAt)
|
||||||
} else {
|
} else {
|
||||||
bktPolicy, berr := policy.ParseConfig(bytes.NewReader(item.Policy), item.Bucket)
|
bktPolicy, berr := policy.ParseConfig(bytes.NewReader(item.Policy), item.Bucket)
|
||||||
if berr != nil {
|
if berr != nil {
|
||||||
@ -222,33 +222,33 @@ func (a adminAPIHandlers) SRPeerReplicateBucketItem(w http.ResponseWriter, r *ht
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if bktPolicy.IsEmpty() {
|
if bktPolicy.IsEmpty() {
|
||||||
err = globalSiteReplicationSys.PeerBucketPolicyHandler(ctx, item.Bucket, nil)
|
err = globalSiteReplicationSys.PeerBucketPolicyHandler(ctx, item.Bucket, nil, item.UpdatedAt)
|
||||||
} else {
|
} else {
|
||||||
err = globalSiteReplicationSys.PeerBucketPolicyHandler(ctx, item.Bucket, bktPolicy)
|
err = globalSiteReplicationSys.PeerBucketPolicyHandler(ctx, item.Bucket, bktPolicy, item.UpdatedAt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case madmin.SRBucketMetaTypeQuotaConfig:
|
case madmin.SRBucketMetaTypeQuotaConfig:
|
||||||
if item.Quota == nil {
|
if item.Quota == nil {
|
||||||
err = globalSiteReplicationSys.PeerBucketQuotaConfigHandler(ctx, item.Bucket, nil)
|
err = globalSiteReplicationSys.PeerBucketQuotaConfigHandler(ctx, item.Bucket, nil, item.UpdatedAt)
|
||||||
} else {
|
} else {
|
||||||
quotaConfig, err := parseBucketQuota(item.Bucket, item.Quota)
|
quotaConfig, err := parseBucketQuota(item.Bucket, item.Quota)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = globalSiteReplicationSys.PeerBucketQuotaConfigHandler(ctx, item.Bucket, quotaConfig); err != nil {
|
if err = globalSiteReplicationSys.PeerBucketQuotaConfigHandler(ctx, item.Bucket, quotaConfig, item.UpdatedAt); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case madmin.SRBucketMetaTypeVersionConfig:
|
case madmin.SRBucketMetaTypeVersionConfig:
|
||||||
err = globalSiteReplicationSys.PeerBucketVersioningHandler(ctx, item.Bucket, item.Versioning)
|
err = globalSiteReplicationSys.PeerBucketVersioningHandler(ctx, item.Bucket, item.Versioning, item.UpdatedAt)
|
||||||
case madmin.SRBucketMetaTypeTags:
|
case madmin.SRBucketMetaTypeTags:
|
||||||
err = globalSiteReplicationSys.PeerBucketTaggingHandler(ctx, item.Bucket, item.Tags)
|
err = globalSiteReplicationSys.PeerBucketTaggingHandler(ctx, item.Bucket, item.Tags, item.UpdatedAt)
|
||||||
case madmin.SRBucketMetaTypeObjectLockConfig:
|
case madmin.SRBucketMetaTypeObjectLockConfig:
|
||||||
err = globalSiteReplicationSys.PeerBucketObjectLockConfigHandler(ctx, item.Bucket, item.ObjectLockConfig)
|
err = globalSiteReplicationSys.PeerBucketObjectLockConfigHandler(ctx, item.Bucket, item.ObjectLockConfig, item.UpdatedAt)
|
||||||
case madmin.SRBucketMetaTypeSSEConfig:
|
case madmin.SRBucketMetaTypeSSEConfig:
|
||||||
err = globalSiteReplicationSys.PeerBucketSSEConfigHandler(ctx, item.Bucket, item.SSEConfig)
|
err = globalSiteReplicationSys.PeerBucketSSEConfigHandler(ctx, item.Bucket, item.SSEConfig, item.UpdatedAt)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.LogIf(ctx, err)
|
logger.LogIf(ctx, err)
|
||||||
|
@ -108,7 +108,8 @@ func (api objectAPIHandlers) PutBucketEncryptionHandler(w http.ResponseWriter, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store the bucket encryption configuration in the object layer
|
// Store the bucket encryption configuration in the object layer
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, configData); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, configData)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -122,6 +123,7 @@ func (api objectAPIHandlers) PutBucketEncryptionHandler(w http.ResponseWriter, r
|
|||||||
Type: madmin.SRBucketMetaTypeSSEConfig,
|
Type: madmin.SRBucketMetaTypeSSEConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
SSEConfig: &cfgStr,
|
SSEConfig: &cfgStr,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
@ -202,7 +204,8 @@ func (api objectAPIHandlers) DeleteBucketEncryptionHandler(w http.ResponseWriter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete bucket encryption config from object layer
|
// Delete bucket encryption config from object layer
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, nil); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, nil)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -212,6 +215,7 @@ func (api objectAPIHandlers) DeleteBucketEncryptionHandler(w http.ResponseWriter
|
|||||||
Type: madmin.SRBucketMetaTypeSSEConfig,
|
Type: madmin.SRBucketMetaTypeSSEConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
SSEConfig: nil,
|
SSEConfig: nil,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
|
@ -1385,7 +1385,8 @@ func (api objectAPIHandlers) PutBucketObjectLockConfigHandler(w http.ResponseWri
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, objectLockConfig, configData); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, objectLockConfig, configData)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1399,6 +1400,7 @@ func (api objectAPIHandlers) PutBucketObjectLockConfigHandler(w http.ResponseWri
|
|||||||
Type: madmin.SRBucketMetaTypeObjectLockConfig,
|
Type: madmin.SRBucketMetaTypeObjectLockConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
ObjectLockConfig: &cfgStr,
|
ObjectLockConfig: &cfgStr,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
@ -1490,7 +1492,8 @@ func (api objectAPIHandlers) PutBucketTaggingHandler(w http.ResponseWriter, r *h
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, configData); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, configData)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1501,9 +1504,10 @@ func (api objectAPIHandlers) PutBucketTaggingHandler(w http.ResponseWriter, r *h
|
|||||||
// errors.
|
// errors.
|
||||||
cfgStr := base64.StdEncoding.EncodeToString(configData)
|
cfgStr := base64.StdEncoding.EncodeToString(configData)
|
||||||
if err = globalSiteReplicationSys.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
if err = globalSiteReplicationSys.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypeTags,
|
Type: madmin.SRBucketMetaTypeTags,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Tags: &cfgStr,
|
Tags: &cfgStr,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
@ -1572,14 +1576,16 @@ func (api objectAPIHandlers) DeleteBucketTaggingHandler(w http.ResponseWriter, r
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, nil); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, nil)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := globalSiteReplicationSys.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
if err := globalSiteReplicationSys.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypeTags,
|
Type: madmin.SRBucketMetaTypeTags,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
|
@ -91,7 +91,7 @@ func (api objectAPIHandlers) PutBucketLifecycleHandler(w http.ResponseWriter, r
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketLifecycleConfig, configData); err != nil {
|
if _, err = globalBucketMetadataSys.Update(ctx, bucket, bucketLifecycleConfig, configData); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -168,7 +168,7 @@ func (api objectAPIHandlers) DeleteBucketLifecycleHandler(w http.ResponseWriter,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := globalBucketMetadataSys.Update(ctx, bucket, bucketLifecycleConfig, nil); err != nil {
|
if _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketLifecycleConfig, nil); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -75,28 +75,28 @@ func (sys *BucketMetadataSys) Set(bucket string, meta BucketMetadata) {
|
|||||||
|
|
||||||
// Update update bucket metadata for the specified config file.
|
// Update update bucket metadata for the specified config file.
|
||||||
// The configData data should not be modified after being sent here.
|
// The configData data should not be modified after being sent here.
|
||||||
func (sys *BucketMetadataSys) Update(ctx context.Context, bucket string, configFile string, configData []byte) error {
|
func (sys *BucketMetadataSys) Update(ctx context.Context, bucket string, configFile string, configData []byte) (updatedAt time.Time, err error) {
|
||||||
objAPI := newObjectLayerFn()
|
objAPI := newObjectLayerFn()
|
||||||
if objAPI == nil {
|
if objAPI == nil {
|
||||||
return errServerNotInitialized
|
return updatedAt, errServerNotInitialized
|
||||||
}
|
}
|
||||||
|
|
||||||
if globalIsGateway && globalGatewayName != NASBackendGateway {
|
if globalIsGateway && globalGatewayName != NASBackendGateway {
|
||||||
if configFile == bucketPolicyConfig {
|
if configFile == bucketPolicyConfig {
|
||||||
if configData == nil {
|
if configData == nil {
|
||||||
return objAPI.DeleteBucketPolicy(ctx, bucket)
|
return updatedAt, objAPI.DeleteBucketPolicy(ctx, bucket)
|
||||||
}
|
}
|
||||||
config, err := policy.ParseConfig(bytes.NewReader(configData), bucket)
|
config, err := policy.ParseConfig(bytes.NewReader(configData), bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return updatedAt, err
|
||||||
}
|
}
|
||||||
return objAPI.SetBucketPolicy(ctx, bucket, config)
|
return updatedAt, objAPI.SetBucketPolicy(ctx, bucket, config)
|
||||||
}
|
}
|
||||||
return NotImplemented{}
|
return updatedAt, NotImplemented{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if bucket == minioMetaBucket {
|
if bucket == minioMetaBucket {
|
||||||
return errInvalidArgument
|
return updatedAt, errInvalidArgument
|
||||||
}
|
}
|
||||||
|
|
||||||
meta, err := loadBucketMetadata(ctx, objAPI, bucket)
|
meta, err := loadBucketMetadata(ctx, objAPI, bucket)
|
||||||
@ -105,56 +105,56 @@ func (sys *BucketMetadataSys) Update(ctx context.Context, bucket string, configF
|
|||||||
// Only single drive mode needs this fallback.
|
// Only single drive mode needs this fallback.
|
||||||
meta = newBucketMetadata(bucket)
|
meta = newBucketMetadata(bucket)
|
||||||
} else {
|
} else {
|
||||||
return err
|
return updatedAt, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
updatedAt = UTCNow()
|
||||||
switch configFile {
|
switch configFile {
|
||||||
case bucketPolicyConfig:
|
case bucketPolicyConfig:
|
||||||
meta.PolicyConfigJSON = configData
|
meta.PolicyConfigJSON = configData
|
||||||
meta.PolicyConfigUpdatedAt = UTCNow()
|
meta.PolicyConfigUpdatedAt = updatedAt
|
||||||
case bucketNotificationConfig:
|
case bucketNotificationConfig:
|
||||||
meta.NotificationConfigXML = configData
|
meta.NotificationConfigXML = configData
|
||||||
case bucketLifecycleConfig:
|
case bucketLifecycleConfig:
|
||||||
meta.LifecycleConfigXML = configData
|
meta.LifecycleConfigXML = configData
|
||||||
case bucketSSEConfig:
|
case bucketSSEConfig:
|
||||||
meta.EncryptionConfigXML = configData
|
meta.EncryptionConfigXML = configData
|
||||||
meta.EncryptionConfigUpdatedAt = UTCNow()
|
meta.EncryptionConfigUpdatedAt = updatedAt
|
||||||
case bucketTaggingConfig:
|
case bucketTaggingConfig:
|
||||||
meta.TaggingConfigXML = configData
|
meta.TaggingConfigXML = configData
|
||||||
meta.TaggingConfigUpdatedAt = UTCNow()
|
meta.TaggingConfigUpdatedAt = updatedAt
|
||||||
case bucketQuotaConfigFile:
|
case bucketQuotaConfigFile:
|
||||||
meta.QuotaConfigJSON = configData
|
meta.QuotaConfigJSON = configData
|
||||||
meta.QuotaConfigUpdatedAt = UTCNow()
|
meta.QuotaConfigUpdatedAt = updatedAt
|
||||||
case objectLockConfig:
|
case objectLockConfig:
|
||||||
meta.ObjectLockConfigXML = configData
|
meta.ObjectLockConfigXML = configData
|
||||||
meta.ObjectLockConfigUpdatedAt = UTCNow()
|
meta.ObjectLockConfigUpdatedAt = updatedAt
|
||||||
case bucketVersioningConfig:
|
case bucketVersioningConfig:
|
||||||
meta.VersioningConfigXML = configData
|
meta.VersioningConfigXML = configData
|
||||||
meta.VersioningConfigUpdatedAt = UTCNow()
|
meta.VersioningConfigUpdatedAt = updatedAt
|
||||||
case bucketReplicationConfig:
|
case bucketReplicationConfig:
|
||||||
meta.ReplicationConfigXML = configData
|
meta.ReplicationConfigXML = configData
|
||||||
meta.ReplicationConfigUpdatedAt = UTCNow()
|
meta.ReplicationConfigUpdatedAt = updatedAt
|
||||||
case bucketTargetsFile:
|
case bucketTargetsFile:
|
||||||
meta.BucketTargetsConfigJSON, meta.BucketTargetsConfigMetaJSON, err = encryptBucketMetadata(meta.Name, configData, kms.Context{
|
meta.BucketTargetsConfigJSON, meta.BucketTargetsConfigMetaJSON, err = encryptBucketMetadata(meta.Name, configData, kms.Context{
|
||||||
bucket: meta.Name,
|
bucket: meta.Name,
|
||||||
bucketTargetsFile: bucketTargetsFile,
|
bucketTargetsFile: bucketTargetsFile,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error encrypting bucket target metadata %w", err)
|
return updatedAt, fmt.Errorf("Error encrypting bucket target metadata %w", err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknown bucket %s metadata update requested %s", bucket, configFile)
|
return updatedAt, fmt.Errorf("Unknown bucket %s metadata update requested %s", bucket, configFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := meta.Save(ctx, objAPI); err != nil {
|
if err := meta.Save(ctx, objAPI); err != nil {
|
||||||
return err
|
return updatedAt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sys.Set(bucket, meta)
|
sys.Set(bucket, meta)
|
||||||
globalNotificationSys.LoadBucketMetadata(bgContext(ctx), bucket) // Do not use caller context here
|
globalNotificationSys.LoadBucketMetadata(bgContext(ctx), bucket) // Do not use caller context here
|
||||||
|
|
||||||
return nil
|
return updatedAt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get metadata for a bucket.
|
// Get metadata for a bucket.
|
||||||
|
@ -160,7 +160,7 @@ func (api objectAPIHandlers) PutBucketNotificationHandler(w http.ResponseWriter,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucketName, bucketNotificationConfig, configData); err != nil {
|
if _, err = globalBucketMetadataSys.Update(ctx, bucketName, bucketNotificationConfig, configData); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -103,16 +103,18 @@ func (api objectAPIHandlers) PutBucketPolicyHandler(w http.ResponseWriter, r *ht
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, configData); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, configData)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call site replication hook.
|
// Call site replication hook.
|
||||||
if err = globalSiteReplicationSys.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
if err = globalSiteReplicationSys.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypePolicy,
|
Type: madmin.SRBucketMetaTypePolicy,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Policy: bucketPolicyBytes,
|
Policy: bucketPolicyBytes,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
@ -148,15 +150,17 @@ func (api objectAPIHandlers) DeleteBucketPolicyHandler(w http.ResponseWriter, r
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, nil); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, nil)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call site replication hook.
|
// Call site replication hook.
|
||||||
if err := globalSiteReplicationSys.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
if err := globalSiteReplicationSys.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypePolicy,
|
Type: madmin.SRBucketMetaTypePolicy,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
|
@ -86,7 +86,7 @@ func (api objectAPIHandlers) PutBucketReplicationConfigHandler(w http.ResponseWr
|
|||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketReplicationConfig, configData); err != nil {
|
if _, err = globalBucketMetadataSys.Update(ctx, bucket, bucketReplicationConfig, configData); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -165,7 +165,7 @@ func (api objectAPIHandlers) DeleteBucketReplicationConfigHandler(w http.Respons
|
|||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrReplicationDenyEditError), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrReplicationDenyEditError), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := globalBucketMetadataSys.Update(ctx, bucket, bucketReplicationConfig, nil); err != nil {
|
if _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketReplicationConfig, nil); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,8 @@ func (api objectAPIHandlers) PutBucketVersioningHandler(w http.ResponseWriter, r
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketVersioningConfig, configData); err != nil {
|
updatedAt, err := globalBucketMetadataSys.Update(ctx, bucket, bucketVersioningConfig, configData)
|
||||||
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -111,6 +112,7 @@ func (api objectAPIHandlers) PutBucketVersioningHandler(w http.ResponseWriter, r
|
|||||||
Type: madmin.SRBucketMetaTypeVersionConfig,
|
Type: madmin.SRBucketMetaTypeVersionConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Versioning: &cfgStr,
|
Versioning: &cfgStr,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
|
@ -817,7 +817,7 @@ func (c *SiteReplicationSys) PeerBucketConfigureReplHandler(ctx context.Context,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketTargetsFile, tgtBytes); err != nil {
|
if _, err = globalBucketMetadataSys.Update(ctx, bucket, bucketTargetsFile, tgtBytes); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
targetARN = bucketTarget.Arn
|
targetARN = bucketTarget.Arn
|
||||||
@ -930,7 +930,7 @@ func (c *SiteReplicationSys) PeerBucketConfigureReplHandler(ctx context.Context,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = globalBucketMetadataSys.Update(ctx, bucket, bucketReplicationConfig, replCfgData)
|
_, err = globalBucketMetadataSys.Update(ctx, bucket, bucketReplicationConfig, replCfgData)
|
||||||
return c.annotatePeerErr(peer.Name, "Error updating replication configuration", err)
|
return c.annotatePeerErr(peer.Name, "Error updating replication configuration", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1228,13 +1228,19 @@ func (c *SiteReplicationSys) BucketMetaHook(ctx context.Context, item madmin.SRB
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PeerBucketVersioningHandler - updates versioning config to local cluster.
|
// PeerBucketVersioningHandler - updates versioning config to local cluster.
|
||||||
func (c *SiteReplicationSys) PeerBucketVersioningHandler(ctx context.Context, bucket string, versioning *string) error {
|
func (c *SiteReplicationSys) PeerBucketVersioningHandler(ctx context.Context, bucket string, versioning *string, updatedAt time.Time) error {
|
||||||
if versioning != nil {
|
if versioning != nil {
|
||||||
|
// skip overwrite if local update is newer than peer update.
|
||||||
|
if !updatedAt.IsZero() {
|
||||||
|
if _, updateTm, err := globalBucketMetadataSys.GetVersioningConfig(bucket); err == nil && updateTm.After(updatedAt) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
configData, err := base64.StdEncoding.DecodeString(*versioning)
|
configData, err := base64.StdEncoding.DecodeString(*versioning)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
err = globalBucketMetadataSys.Update(ctx, bucket, bucketVersioningConfig, configData)
|
_, err = globalBucketMetadataSys.Update(ctx, bucket, bucketVersioningConfig, configData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
@ -1245,14 +1251,21 @@ func (c *SiteReplicationSys) PeerBucketVersioningHandler(ctx context.Context, bu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PeerBucketPolicyHandler - copies/deletes policy to local cluster.
|
// PeerBucketPolicyHandler - copies/deletes policy to local cluster.
|
||||||
func (c *SiteReplicationSys) PeerBucketPolicyHandler(ctx context.Context, bucket string, policy *policy.Policy) error {
|
func (c *SiteReplicationSys) PeerBucketPolicyHandler(ctx context.Context, bucket string, policy *policy.Policy, updatedAt time.Time) error {
|
||||||
|
// skip overwrite if local update is newer than peer update.
|
||||||
|
if !updatedAt.IsZero() {
|
||||||
|
if _, updateTm, err := globalBucketMetadataSys.GetPolicyConfig(bucket); err == nil && updateTm.After(updatedAt) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if policy != nil {
|
if policy != nil {
|
||||||
configData, err := json.Marshal(policy)
|
configData, err := json.Marshal(policy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, configData)
|
_, err = globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, configData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
@ -1260,7 +1273,7 @@ func (c *SiteReplicationSys) PeerBucketPolicyHandler(ctx context.Context, bucket
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete the bucket policy
|
// Delete the bucket policy
|
||||||
err := globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, nil)
|
_, err := globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
@ -1269,13 +1282,20 @@ func (c *SiteReplicationSys) PeerBucketPolicyHandler(ctx context.Context, bucket
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PeerBucketTaggingHandler - copies/deletes tags to local cluster.
|
// PeerBucketTaggingHandler - copies/deletes tags to local cluster.
|
||||||
func (c *SiteReplicationSys) PeerBucketTaggingHandler(ctx context.Context, bucket string, tags *string) error {
|
func (c *SiteReplicationSys) PeerBucketTaggingHandler(ctx context.Context, bucket string, tags *string, updatedAt time.Time) error {
|
||||||
|
// skip overwrite if local update is newer than peer update.
|
||||||
|
if !updatedAt.IsZero() {
|
||||||
|
if _, updateTm, err := globalBucketMetadataSys.GetTaggingConfig(bucket); err == nil && updateTm.After(updatedAt) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if tags != nil {
|
if tags != nil {
|
||||||
configData, err := base64.StdEncoding.DecodeString(*tags)
|
configData, err := base64.StdEncoding.DecodeString(*tags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
err = globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, configData)
|
_, err = globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, configData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
@ -1283,7 +1303,7 @@ func (c *SiteReplicationSys) PeerBucketTaggingHandler(ctx context.Context, bucke
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete the tags
|
// Delete the tags
|
||||||
err := globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, nil)
|
_, err := globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
@ -1292,13 +1312,20 @@ func (c *SiteReplicationSys) PeerBucketTaggingHandler(ctx context.Context, bucke
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PeerBucketObjectLockConfigHandler - sets object lock on local bucket.
|
// PeerBucketObjectLockConfigHandler - sets object lock on local bucket.
|
||||||
func (c *SiteReplicationSys) PeerBucketObjectLockConfigHandler(ctx context.Context, bucket string, objectLockData *string) error {
|
func (c *SiteReplicationSys) PeerBucketObjectLockConfigHandler(ctx context.Context, bucket string, objectLockData *string, updatedAt time.Time) error {
|
||||||
if objectLockData != nil {
|
if objectLockData != nil {
|
||||||
|
// skip overwrite if local update is newer than peer update.
|
||||||
|
if !updatedAt.IsZero() {
|
||||||
|
if _, updateTm, err := globalBucketMetadataSys.GetObjectLockConfig(bucket); err == nil && updateTm.After(updatedAt) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
configData, err := base64.StdEncoding.DecodeString(*objectLockData)
|
configData, err := base64.StdEncoding.DecodeString(*objectLockData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
err = globalBucketMetadataSys.Update(ctx, bucket, objectLockConfig, configData)
|
_, err = globalBucketMetadataSys.Update(ctx, bucket, objectLockConfig, configData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
@ -1309,13 +1336,20 @@ func (c *SiteReplicationSys) PeerBucketObjectLockConfigHandler(ctx context.Conte
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PeerBucketSSEConfigHandler - copies/deletes SSE config to local cluster.
|
// PeerBucketSSEConfigHandler - copies/deletes SSE config to local cluster.
|
||||||
func (c *SiteReplicationSys) PeerBucketSSEConfigHandler(ctx context.Context, bucket string, sseConfig *string) error {
|
func (c *SiteReplicationSys) PeerBucketSSEConfigHandler(ctx context.Context, bucket string, sseConfig *string, updatedAt time.Time) error {
|
||||||
|
// skip overwrite if local update is newer than peer update.
|
||||||
|
if !updatedAt.IsZero() {
|
||||||
|
if _, updateTm, err := globalBucketMetadataSys.GetSSEConfig(bucket); err == nil && updateTm.After(updatedAt) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if sseConfig != nil {
|
if sseConfig != nil {
|
||||||
configData, err := base64.StdEncoding.DecodeString(*sseConfig)
|
configData, err := base64.StdEncoding.DecodeString(*sseConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
err = globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, configData)
|
_, err = globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, configData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
@ -1323,7 +1357,7 @@ func (c *SiteReplicationSys) PeerBucketSSEConfigHandler(ctx context.Context, buc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete sse config
|
// Delete sse config
|
||||||
err := globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, nil)
|
_, err := globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
@ -1331,14 +1365,21 @@ func (c *SiteReplicationSys) PeerBucketSSEConfigHandler(ctx context.Context, buc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PeerBucketQuotaConfigHandler - copies/deletes policy to local cluster.
|
// PeerBucketQuotaConfigHandler - copies/deletes policy to local cluster.
|
||||||
func (c *SiteReplicationSys) PeerBucketQuotaConfigHandler(ctx context.Context, bucket string, quota *madmin.BucketQuota) error {
|
func (c *SiteReplicationSys) PeerBucketQuotaConfigHandler(ctx context.Context, bucket string, quota *madmin.BucketQuota, updatedAt time.Time) error {
|
||||||
|
// skip overwrite if local update is newer than peer update.
|
||||||
|
if !updatedAt.IsZero() {
|
||||||
|
if _, updateTm, err := globalBucketMetadataSys.GetQuotaConfig(ctx, bucket); err == nil && updateTm.After(updatedAt) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if quota != nil {
|
if quota != nil {
|
||||||
quotaData, err := json.Marshal(quota)
|
quotaData, err := json.Marshal(quota)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = globalBucketMetadataSys.Update(ctx, bucket, bucketQuotaConfigFile, quotaData); err != nil {
|
if _, err = globalBucketMetadataSys.Update(ctx, bucket, bucketQuotaConfigFile, quotaData); err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1346,7 +1387,7 @@ func (c *SiteReplicationSys) PeerBucketQuotaConfigHandler(ctx context.Context, b
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete the bucket policy
|
// Delete the bucket policy
|
||||||
err := globalBucketMetadataSys.Update(ctx, bucket, bucketQuotaConfigFile, nil)
|
_, err := globalBucketMetadataSys.Update(ctx, bucket, bucketQuotaConfigFile, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
@ -1437,7 +1478,7 @@ func (c *SiteReplicationSys) syncToAllPeers(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replicate bucket policy if present.
|
// Replicate bucket policy if present.
|
||||||
policy, err := globalPolicySys.Get(bucket)
|
policy, tm, err := globalBucketMetadataSys.GetPolicyConfig(bucket)
|
||||||
found := true
|
found := true
|
||||||
if _, ok := err.(BucketPolicyNotFound); ok {
|
if _, ok := err.(BucketPolicyNotFound); ok {
|
||||||
found = false
|
found = false
|
||||||
@ -1450,9 +1491,10 @@ func (c *SiteReplicationSys) syncToAllPeers(ctx context.Context) error {
|
|||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
err = c.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
err = c.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypePolicy,
|
Type: madmin.SRBucketMetaTypePolicy,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Policy: policyJSON,
|
Policy: policyJSON,
|
||||||
|
UpdatedAt: tm,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errSRBucketMetaError(err)
|
return errSRBucketMetaError(err)
|
||||||
@ -1460,7 +1502,7 @@ func (c *SiteReplicationSys) syncToAllPeers(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replicate bucket tags if present.
|
// Replicate bucket tags if present.
|
||||||
tags, _, err := globalBucketMetadataSys.GetTaggingConfig(bucket)
|
tags, tm, err := globalBucketMetadataSys.GetTaggingConfig(bucket)
|
||||||
found = true
|
found = true
|
||||||
if _, ok := err.(BucketTaggingNotFound); ok {
|
if _, ok := err.(BucketTaggingNotFound); ok {
|
||||||
found = false
|
found = false
|
||||||
@ -1474,9 +1516,10 @@ func (c *SiteReplicationSys) syncToAllPeers(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
tagCfgStr := base64.StdEncoding.EncodeToString(tagCfg)
|
tagCfgStr := base64.StdEncoding.EncodeToString(tagCfg)
|
||||||
err = c.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
err = c.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypeTags,
|
Type: madmin.SRBucketMetaTypeTags,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Tags: &tagCfgStr,
|
Tags: &tagCfgStr,
|
||||||
|
UpdatedAt: tm,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errSRBucketMetaError(err)
|
return errSRBucketMetaError(err)
|
||||||
@ -1484,7 +1527,7 @@ func (c *SiteReplicationSys) syncToAllPeers(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replicate object-lock config if present.
|
// Replicate object-lock config if present.
|
||||||
objLockCfg, _, err := globalBucketMetadataSys.GetObjectLockConfig(bucket)
|
objLockCfg, tm, err := globalBucketMetadataSys.GetObjectLockConfig(bucket)
|
||||||
found = true
|
found = true
|
||||||
if _, ok := err.(BucketObjectLockConfigNotFound); ok {
|
if _, ok := err.(BucketObjectLockConfigNotFound); ok {
|
||||||
found = false
|
found = false
|
||||||
@ -1498,9 +1541,10 @@ func (c *SiteReplicationSys) syncToAllPeers(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
objLockStr := base64.StdEncoding.EncodeToString(objLockCfgData)
|
objLockStr := base64.StdEncoding.EncodeToString(objLockCfgData)
|
||||||
err = c.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
err = c.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypeObjectLockConfig,
|
Type: madmin.SRBucketMetaTypeObjectLockConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Tags: &objLockStr,
|
Tags: &objLockStr,
|
||||||
|
UpdatedAt: tm,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errSRBucketMetaError(err)
|
return errSRBucketMetaError(err)
|
||||||
@ -1508,7 +1552,7 @@ func (c *SiteReplicationSys) syncToAllPeers(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replicate existing bucket bucket encryption settings
|
// Replicate existing bucket bucket encryption settings
|
||||||
sseConfig, _, err := globalBucketMetadataSys.GetSSEConfig(bucket)
|
sseConfig, tm, err := globalBucketMetadataSys.GetSSEConfig(bucket)
|
||||||
found = true
|
found = true
|
||||||
if _, ok := err.(BucketSSEConfigNotFound); ok {
|
if _, ok := err.(BucketSSEConfigNotFound); ok {
|
||||||
found = false
|
found = false
|
||||||
@ -1525,13 +1569,14 @@ func (c *SiteReplicationSys) syncToAllPeers(ctx context.Context) error {
|
|||||||
Type: madmin.SRBucketMetaTypeSSEConfig,
|
Type: madmin.SRBucketMetaTypeSSEConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
SSEConfig: &sseConfigStr,
|
SSEConfig: &sseConfigStr,
|
||||||
|
UpdatedAt: tm,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errSRBucketMetaError(err)
|
return errSRBucketMetaError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
quotaConfig, _, err := globalBucketMetadataSys.GetQuotaConfig(ctx, bucket)
|
quotaConfig, tm, err := globalBucketMetadataSys.GetQuotaConfig(ctx, bucket)
|
||||||
found = true
|
found = true
|
||||||
if _, ok := err.(BucketQuotaConfigNotFound); ok {
|
if _, ok := err.(BucketQuotaConfigNotFound); ok {
|
||||||
found = false
|
found = false
|
||||||
@ -1544,9 +1589,10 @@ func (c *SiteReplicationSys) syncToAllPeers(ctx context.Context) error {
|
|||||||
return wrapSRErr(err)
|
return wrapSRErr(err)
|
||||||
}
|
}
|
||||||
err = c.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
err = c.BucketMetaHook(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypeQuotaConfig,
|
Type: madmin.SRBucketMetaTypeQuotaConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Quota: quotaConfigJSON,
|
Quota: quotaConfigJSON,
|
||||||
|
UpdatedAt: tm,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errSRBucketMetaError(err)
|
return errSRBucketMetaError(err)
|
||||||
@ -2069,11 +2115,11 @@ func (c *SiteReplicationSys) RemoveRemoteTargetsForEndpoint(ctx context.Context,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = globalBucketMetadataSys.Update(ctx, b.Name, bucketReplicationConfig, configData); err != nil {
|
if _, err = globalBucketMetadataSys.Update(ctx, b.Name, bucketReplicationConfig, configData); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := globalBucketMetadataSys.Update(ctx, b.Name, bucketReplicationConfig, nil); err != nil {
|
if _, err := globalBucketMetadataSys.Update(ctx, b.Name, bucketReplicationConfig, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3440,14 +3486,20 @@ type srStatusInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *SiteReplicationSys) healBuckets(ctx context.Context, objAPI ObjectLayer) error {
|
func (c *SiteReplicationSys) healBuckets(ctx context.Context, objAPI ObjectLayer) error {
|
||||||
info, err := c.siteReplicationStatus(ctx, objAPI, madmin.SRStatusOptions{
|
buckets, err := c.listBuckets(ctx)
|
||||||
Buckets: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
for _, bi := range buckets {
|
||||||
for bucket := range info.BucketStats {
|
bucket := bi.Name
|
||||||
|
info, err := c.siteReplicationStatus(ctx, objAPI, madmin.SRStatusOptions{
|
||||||
|
Entity: madmin.SRBucketEntity,
|
||||||
|
EntityValue: bucket,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logger.LogIf(ctx, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
c.healCreateMissingBucket(ctx, objAPI, bucket, info)
|
c.healCreateMissingBucket(ctx, objAPI, bucket, info)
|
||||||
c.healVersioningMetadata(ctx, objAPI, bucket, info)
|
c.healVersioningMetadata(ctx, objAPI, bucket, info)
|
||||||
c.healOLockConfigMetadata(ctx, objAPI, bucket, info)
|
c.healOLockConfigMetadata(ctx, objAPI, bucket, info)
|
||||||
@ -3509,7 +3561,7 @@ func (c *SiteReplicationSys) healTagMetadata(ctx context.Context, objAPI ObjectL
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if dID == globalDeploymentID {
|
if dID == globalDeploymentID {
|
||||||
if err := globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, latestTaggingConfigBytes); err != nil {
|
if _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketTaggingConfig, latestTaggingConfigBytes); err != nil {
|
||||||
logger.LogIf(ctx, fmt.Errorf("Error healing tagging metadata from peer site %s : %w", latestPeerName, err))
|
logger.LogIf(ctx, fmt.Errorf("Error healing tagging metadata from peer site %s : %w", latestPeerName, err))
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@ -3573,7 +3625,7 @@ func (c *SiteReplicationSys) healBucketPolicies(ctx context.Context, objAPI Obje
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if dID == globalDeploymentID {
|
if dID == globalDeploymentID {
|
||||||
if err := globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, latestIAMPolicy); err != nil {
|
if _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketPolicyConfig, latestIAMPolicy); err != nil {
|
||||||
logger.LogIf(ctx, fmt.Errorf("Error healing bucket policy metadata from peer site %s : %w", latestPeerName, err))
|
logger.LogIf(ctx, fmt.Errorf("Error healing bucket policy metadata from peer site %s : %w", latestPeerName, err))
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@ -3585,9 +3637,10 @@ func (c *SiteReplicationSys) healBucketPolicies(ctx context.Context, objAPI Obje
|
|||||||
}
|
}
|
||||||
peerName := info.Sites[dID].Name
|
peerName := info.Sites[dID].Name
|
||||||
if err = admClient.SRPeerReplicateBucketMeta(ctx, madmin.SRBucketMeta{
|
if err = admClient.SRPeerReplicateBucketMeta(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypePolicy,
|
Type: madmin.SRBucketMetaTypePolicy,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Policy: latestIAMPolicy,
|
Policy: latestIAMPolicy,
|
||||||
|
UpdatedAt: lastUpdate,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
logger.LogIf(ctx, c.annotatePeerErr(peerName, replicateBucketMetadata,
|
logger.LogIf(ctx, c.annotatePeerErr(peerName, replicateBucketMetadata,
|
||||||
fmt.Errorf("Error healing bucket policy metadata for peer %s from peer %s : %w",
|
fmt.Errorf("Error healing bucket policy metadata for peer %s from peer %s : %w",
|
||||||
@ -3647,7 +3700,7 @@ func (c *SiteReplicationSys) healBucketQuotaConfig(ctx context.Context, objAPI O
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if dID == globalDeploymentID {
|
if dID == globalDeploymentID {
|
||||||
if err := globalBucketMetadataSys.Update(ctx, bucket, bucketQuotaConfigFile, latestQuotaConfigBytes); err != nil {
|
if _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketQuotaConfigFile, latestQuotaConfigBytes); err != nil {
|
||||||
logger.LogIf(ctx, fmt.Errorf("Error healing quota metadata from peer site %s : %w", latestPeerName, err))
|
logger.LogIf(ctx, fmt.Errorf("Error healing quota metadata from peer site %s : %w", latestPeerName, err))
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@ -3660,9 +3713,10 @@ func (c *SiteReplicationSys) healBucketQuotaConfig(ctx context.Context, objAPI O
|
|||||||
peerName := info.Sites[dID].Name
|
peerName := info.Sites[dID].Name
|
||||||
|
|
||||||
if err = admClient.SRPeerReplicateBucketMeta(ctx, madmin.SRBucketMeta{
|
if err = admClient.SRPeerReplicateBucketMeta(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypeQuotaConfig,
|
Type: madmin.SRBucketMetaTypeQuotaConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Quota: latestQuotaConfigBytes,
|
Quota: latestQuotaConfigBytes,
|
||||||
|
UpdatedAt: lastUpdate,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
logger.LogIf(ctx, c.annotatePeerErr(peerName, replicateBucketMetadata,
|
logger.LogIf(ctx, c.annotatePeerErr(peerName, replicateBucketMetadata,
|
||||||
fmt.Errorf("Error healing quota config metadata for peer %s from peer %s : %w",
|
fmt.Errorf("Error healing quota config metadata for peer %s from peer %s : %w",
|
||||||
@ -3721,7 +3775,7 @@ func (c *SiteReplicationSys) healVersioningMetadata(ctx context.Context, objAPI
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if dID == globalDeploymentID {
|
if dID == globalDeploymentID {
|
||||||
if err := globalBucketMetadataSys.Update(ctx, bucket, bucketVersioningConfig, latestVersioningConfigBytes); err != nil {
|
if _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketVersioningConfig, latestVersioningConfigBytes); err != nil {
|
||||||
logger.LogIf(ctx, fmt.Errorf("Error healing versioning metadata from peer site %s : %w", latestPeerName, err))
|
logger.LogIf(ctx, fmt.Errorf("Error healing versioning metadata from peer site %s : %w", latestPeerName, err))
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@ -3736,6 +3790,7 @@ func (c *SiteReplicationSys) healVersioningMetadata(ctx context.Context, objAPI
|
|||||||
Type: madmin.SRBucketMetaTypeVersionConfig,
|
Type: madmin.SRBucketMetaTypeVersionConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Versioning: latestVersioningConfig,
|
Versioning: latestVersioningConfig,
|
||||||
|
UpdatedAt: lastUpdate,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.LogIf(ctx, c.annotatePeerErr(peerName, replicateBucketMetadata,
|
logger.LogIf(ctx, c.annotatePeerErr(peerName, replicateBucketMetadata,
|
||||||
@ -3795,7 +3850,7 @@ func (c *SiteReplicationSys) healSSEMetadata(ctx context.Context, objAPI ObjectL
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if dID == globalDeploymentID {
|
if dID == globalDeploymentID {
|
||||||
if err := globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, latestSSEConfigBytes); err != nil {
|
if _, err := globalBucketMetadataSys.Update(ctx, bucket, bucketSSEConfig, latestSSEConfigBytes); err != nil {
|
||||||
logger.LogIf(ctx, fmt.Errorf("Error healing sse metadata from peer site %s : %w", latestPeerName, err))
|
logger.LogIf(ctx, fmt.Errorf("Error healing sse metadata from peer site %s : %w", latestPeerName, err))
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@ -3810,6 +3865,7 @@ func (c *SiteReplicationSys) healSSEMetadata(ctx context.Context, objAPI ObjectL
|
|||||||
Type: madmin.SRBucketMetaTypeSSEConfig,
|
Type: madmin.SRBucketMetaTypeSSEConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
SSEConfig: latestSSEConfig,
|
SSEConfig: latestSSEConfig,
|
||||||
|
UpdatedAt: lastUpdate,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.LogIf(ctx, c.annotatePeerErr(peerName, replicateBucketMetadata,
|
logger.LogIf(ctx, c.annotatePeerErr(peerName, replicateBucketMetadata,
|
||||||
@ -3869,7 +3925,7 @@ func (c *SiteReplicationSys) healOLockConfigMetadata(ctx context.Context, objAPI
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if dID == globalDeploymentID {
|
if dID == globalDeploymentID {
|
||||||
if err := globalBucketMetadataSys.Update(ctx, bucket, objectLockConfig, latestObjLockConfigBytes); err != nil {
|
if _, err := globalBucketMetadataSys.Update(ctx, bucket, objectLockConfig, latestObjLockConfigBytes); err != nil {
|
||||||
logger.LogIf(ctx, fmt.Errorf("Error healing objectlock config metadata from peer site %s : %w", latestPeerName, err))
|
logger.LogIf(ctx, fmt.Errorf("Error healing objectlock config metadata from peer site %s : %w", latestPeerName, err))
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@ -3881,9 +3937,10 @@ func (c *SiteReplicationSys) healOLockConfigMetadata(ctx context.Context, objAPI
|
|||||||
}
|
}
|
||||||
peerName := info.Sites[dID].Name
|
peerName := info.Sites[dID].Name
|
||||||
err = admClient.SRPeerReplicateBucketMeta(ctx, madmin.SRBucketMeta{
|
err = admClient.SRPeerReplicateBucketMeta(ctx, madmin.SRBucketMeta{
|
||||||
Type: madmin.SRBucketMetaTypeObjectLockConfig,
|
Type: madmin.SRBucketMetaTypeObjectLockConfig,
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Tags: latestObjLockConfig,
|
Tags: latestObjLockConfig,
|
||||||
|
UpdatedAt: lastUpdate,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.LogIf(ctx, c.annotatePeerErr(peerName, replicateBucketMetadata,
|
logger.LogIf(ctx, c.annotatePeerErr(peerName, replicateBucketMetadata,
|
||||||
|
@ -42,8 +42,11 @@ if [ ! -f ./mc ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
minio server --config-dir /tmp/minio-ldap --address ":9001" /tmp/minio-ldap-idp1/{1...4} >/tmp/minio1_1.log 2>&1 &
|
minio server --config-dir /tmp/minio-ldap --address ":9001" /tmp/minio-ldap-idp1/{1...4} >/tmp/minio1_1.log 2>&1 &
|
||||||
|
site1_pid=$!
|
||||||
minio server --config-dir /tmp/minio-ldap --address ":9002" /tmp/minio-ldap-idp2/{1...4} >/tmp/minio2_1.log 2>&1 &
|
minio server --config-dir /tmp/minio-ldap --address ":9002" /tmp/minio-ldap-idp2/{1...4} >/tmp/minio2_1.log 2>&1 &
|
||||||
|
site2_pid=$!
|
||||||
minio server --config-dir /tmp/minio-ldap --address ":9003" /tmp/minio-ldap-idp3/{1...4} >/tmp/minio3_1.log 2>&1 &
|
minio server --config-dir /tmp/minio-ldap --address ":9003" /tmp/minio-ldap-idp3/{1...4} >/tmp/minio3_1.log 2>&1 &
|
||||||
|
site3_pid=$!
|
||||||
|
|
||||||
sleep 10
|
sleep 10
|
||||||
|
|
||||||
@ -237,4 +240,31 @@ if [ "${enabled_minio1}" != "Enabled" ]; then
|
|||||||
exit_1;
|
exit_1;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# "Test if most recent tag update is replicated"
|
||||||
|
./mc tag set minio2/newbucket "key=val1"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "expecting tag set to be successful. exiting.."
|
||||||
|
exit_1;
|
||||||
|
fi
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
val=$(./mc tag list minio1/newbucket --json | jq -r .tagset | jq -r .key)
|
||||||
|
if [ "${val}" != "val1" ]; then
|
||||||
|
echo "expected bucket tag to have replicated, exiting..."
|
||||||
|
exit_1;
|
||||||
|
fi
|
||||||
|
# stop minio1
|
||||||
|
kill -9 ${site1_pid}
|
||||||
|
# Update tag on minio2/newbucket when minio1 is down
|
||||||
|
./mc tag set minio2/newbucket "key=val2"
|
||||||
|
# Restart minio1 instance
|
||||||
|
minio server --config-dir /tmp/minio-ldap --address ":9001" /tmp/minio-ldap-idp1/{1...4} >/tmp/minio1_1.log 2>&1 &
|
||||||
|
sleep 10
|
||||||
|
# Test whether most recent tag update on minio2 is replicated to minio1
|
||||||
|
val=$(./mc tag list minio1/newbucket --json | jq -r .tagset | jq -r .key )
|
||||||
|
if [ "${val}" != "val2" ]; then
|
||||||
|
echo "expected bucket tag to have replicated, exiting..."
|
||||||
|
exit_1;
|
||||||
|
fi
|
||||||
|
|
||||||
cleanup
|
cleanup
|
||||||
|
@ -34,8 +34,11 @@ if [ ! -f ./mc ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
minio server --config-dir /tmp/minio-internal --address ":9001" /tmp/minio-internal-idp1/{1...4} >/tmp/minio1_1.log 2>&1 &
|
minio server --config-dir /tmp/minio-internal --address ":9001" /tmp/minio-internal-idp1/{1...4} >/tmp/minio1_1.log 2>&1 &
|
||||||
|
site1_pid=$!
|
||||||
minio server --config-dir /tmp/minio-internal --address ":9002" /tmp/minio-internal-idp2/{1...4} >/tmp/minio2_1.log 2>&1 &
|
minio server --config-dir /tmp/minio-internal --address ":9002" /tmp/minio-internal-idp2/{1...4} >/tmp/minio2_1.log 2>&1 &
|
||||||
|
site2_pid=$!
|
||||||
minio server --config-dir /tmp/minio-internal --address ":9003" /tmp/minio-internal-idp3/{1...4} >/tmp/minio3_1.log 2>&1 &
|
minio server --config-dir /tmp/minio-internal --address ":9003" /tmp/minio-internal-idp3/{1...4} >/tmp/minio3_1.log 2>&1 &
|
||||||
|
site3_pid=$!
|
||||||
|
|
||||||
sleep 10
|
sleep 10
|
||||||
|
|
||||||
@ -268,3 +271,30 @@ if [ "${enabled_minio1}" != "Enabled" ]; then
|
|||||||
echo "expected bucket to be mirrored with object-lock enabled, exiting..."
|
echo "expected bucket to be mirrored with object-lock enabled, exiting..."
|
||||||
exit_1;
|
exit_1;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# "Test if most recent tag update is replicated"
|
||||||
|
./mc tag set minio2/newbucket "key=val1"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "expecting tag set to be successful. exiting.."
|
||||||
|
exit_1;
|
||||||
|
fi
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
val=$(./mc tag list minio1/newbucket --json | jq -r .tagset | jq -r .key)
|
||||||
|
if [ "${val}" != "val1" ]; then
|
||||||
|
echo "expected bucket tag to have replicated, exiting..."
|
||||||
|
exit_1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
kill -9 ${site1_pid}
|
||||||
|
# Update tag on minio2/newbucket when minio1 is down
|
||||||
|
./mc tag set minio2/newbucket "key=val2"
|
||||||
|
# Restart minio1 instance
|
||||||
|
minio server --config-dir /tmp/minio-internal --address ":9001" /tmp/minio-internal-idp1/{1...4} >/tmp/minio1_1.log 2>&1 &
|
||||||
|
sleep 10
|
||||||
|
# Test whether most recent tag update on minio2 is replicated to minio1
|
||||||
|
val=$(./mc tag list minio1/newbucket --json | jq -r .tagset | jq -r .key )
|
||||||
|
if [ "${val}" != "val2" ]; then
|
||||||
|
echo "expected bucket tag to have replicated, exiting..."
|
||||||
|
exit_1;
|
||||||
|
fi
|
||||||
|
@ -35,12 +35,14 @@ export MINIO_IDENTITY_OPENID_SCOPES="openid,groups"
|
|||||||
|
|
||||||
export MINIO_IDENTITY_OPENID_REDIRECT_URI="http://127.0.0.1:10000/oauth_callback"
|
export MINIO_IDENTITY_OPENID_REDIRECT_URI="http://127.0.0.1:10000/oauth_callback"
|
||||||
minio server --address ":9001" --console-address ":10000" /tmp/minio1/{1...4} >/tmp/minio1_1.log 2>&1 &
|
minio server --address ":9001" --console-address ":10000" /tmp/minio1/{1...4} >/tmp/minio1_1.log 2>&1 &
|
||||||
|
site1_pid=$!
|
||||||
export MINIO_IDENTITY_OPENID_REDIRECT_URI="http://127.0.0.1:11000/oauth_callback"
|
export MINIO_IDENTITY_OPENID_REDIRECT_URI="http://127.0.0.1:11000/oauth_callback"
|
||||||
minio server --address ":9002" --console-address ":11000" /tmp/minio2/{1...4} >/tmp/minio2_1.log 2>&1 &
|
minio server --address ":9002" --console-address ":11000" /tmp/minio2/{1...4} >/tmp/minio2_1.log 2>&1 &
|
||||||
|
site2_pid=$!
|
||||||
|
|
||||||
export MINIO_IDENTITY_OPENID_REDIRECT_URI="http://127.0.0.1:12000/oauth_callback"
|
export MINIO_IDENTITY_OPENID_REDIRECT_URI="http://127.0.0.1:12000/oauth_callback"
|
||||||
minio server --address ":9003" --console-address ":12000" /tmp/minio3/{1...4} >/tmp/minio3_1.log 2>&1 &
|
minio server --address ":9003" --console-address ":12000" /tmp/minio3/{1...4} >/tmp/minio3_1.log 2>&1 &
|
||||||
|
site3_pid=$!
|
||||||
|
|
||||||
if [ ! -f ./mc ]; then
|
if [ ! -f ./mc ]; then
|
||||||
wget -O mc https://dl.minio.io/client/mc/release/linux-amd64/mc \
|
wget -O mc https://dl.minio.io/client/mc/release/linux-amd64/mc \
|
||||||
@ -222,3 +224,30 @@ if [ "${enabled_minio1}" != "Enabled" ]; then
|
|||||||
echo "expected bucket to be mirrored with object-lock enabled, exiting..."
|
echo "expected bucket to be mirrored with object-lock enabled, exiting..."
|
||||||
exit_1;
|
exit_1;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# "Test if most recent tag update is replicated"
|
||||||
|
./mc tag set minio2/newbucket "key=val1"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "expecting tag set to be successful. exiting.."
|
||||||
|
exit_1;
|
||||||
|
fi
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
val=$(./mc tag list minio1/newbucket --json | jq -r .tagset | jq -r .key)
|
||||||
|
if [ "${val}" != "val1" ]; then
|
||||||
|
echo "expected bucket tag to have replicated, exiting..."
|
||||||
|
exit_1;
|
||||||
|
fi
|
||||||
|
# stop minio1 instance
|
||||||
|
kill -9 ${site1_pid}
|
||||||
|
# Update tag on minio2/newbucket when minio1 is down
|
||||||
|
./mc tag set minio2/newbucket "key=val2"
|
||||||
|
# Restart minio1 instance
|
||||||
|
minio server --address ":9001" --console-address ":10000" /tmp/minio1/{1...4} >/tmp/minio1_1.log 2>&1 &
|
||||||
|
sleep 10
|
||||||
|
# Test whether most recent tag update on minio2 is replicated to minio1
|
||||||
|
val=$(./mc tag list minio1/newbucket --json | jq -r .tagset | jq -r .key )
|
||||||
|
if [ "${val}" != "val2" ]; then
|
||||||
|
echo "expected bucket tag to have replicated, exiting..."
|
||||||
|
exit_1;
|
||||||
|
fi
|
||||||
|
2
go.mod
2
go.mod
@ -48,7 +48,7 @@ require (
|
|||||||
github.com/minio/dperf v0.4.2
|
github.com/minio/dperf v0.4.2
|
||||||
github.com/minio/highwayhash v1.0.2
|
github.com/minio/highwayhash v1.0.2
|
||||||
github.com/minio/kes v0.19.2
|
github.com/minio/kes v0.19.2
|
||||||
github.com/minio/madmin-go v1.3.14
|
github.com/minio/madmin-go v1.3.20
|
||||||
github.com/minio/minio-go/v7 v7.0.30
|
github.com/minio/minio-go/v7 v7.0.30
|
||||||
github.com/minio/pkg v1.1.26
|
github.com/minio/pkg v1.1.26
|
||||||
github.com/minio/selfupdate v0.4.0
|
github.com/minio/selfupdate v0.4.0
|
||||||
|
Loading…
Reference in New Issue
Block a user