diff --git a/cmd/bucket-replication.go b/cmd/bucket-replication.go index 06564bb3e..4f6a4b333 100644 --- a/cmd/bucket-replication.go +++ b/cmd/bucket-replication.go @@ -580,8 +580,8 @@ func replicateDeleteToTarget(ctx context.Context, dobj DeletedObjectReplicationI toi, err := tgt.StatObject(ctx, tgt.Bucket, dobj.ObjectName, miniogo.StatObjectOptions{ VersionID: versionID, Internal: miniogo.AdvancedGetOptions{ - ReplicationProxyRequest: "false", - ReplicationDeleteMarker: true, + ReplicationProxyRequest: "false", + IsReplicationReadyForDeleteMarker: true, }, }) if isErrMethodNotAllowed(ErrorRespToObjectError(err, dobj.Bucket, dobj.ObjectName)) { diff --git a/cmd/object-api-interface.go b/cmd/object-api-interface.go index 2c2673a70..700bad891 100644 --- a/cmd/object-api-interface.go +++ b/cmd/object-api-interface.go @@ -51,7 +51,9 @@ type ObjectOptions struct { MTime time.Time // Is only set in POST/PUT operations Expires time.Time // Is only used in POST/PUT operations - DeleteMarker bool // Is only set in DELETE operations for delete marker replication + DeleteMarker bool // Is only set in DELETE operations for delete marker replication + CheckDMReplicationReady bool // Is delete marker ready to be replicated - set only during HEAD + UserDefined map[string]string // only set in case of POST/PUT operations PartNumber int // only useful in case of GetObject/HeadObject CheckPrecondFn CheckPreconditionFn // only set during GetObject/HeadObject/CopyObjectPart preconditional valuation diff --git a/cmd/object-api-options.go b/cmd/object-api-options.go index 98229902b..43ac62cc7 100644 --- a/cmd/object-api-options.go +++ b/cmd/object-api-options.go @@ -159,6 +159,23 @@ func getOpts(ctx context.Context, r *http.Request, bucket, object string) (Objec } } } + replReadyCheck := strings.TrimSpace(r.Header.Get(xhttp.MinIOCheckDMReplicationReady)) + if replReadyCheck != "" { + switch replReadyCheck { + case "true": + opts.CheckDMReplicationReady = true + case "false": + default: + err = fmt.Errorf("Unable to parse %s, failed with %w", xhttp.MinIOCheckDMReplicationReady, fmt.Errorf("should be true or false")) + logger.LogIf(ctx, err) + return opts, InvalidArgument{ + Bucket: bucket, + Object: object, + Err: err, + } + } + } + opts.Versioned = globalBucketVersioningSys.PrefixEnabled(bucket, object) opts.VersionSuspended = globalBucketVersioningSys.PrefixSuspended(bucket, object) return opts, nil diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 5d454c67f..41f8f5080 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -739,14 +739,15 @@ func (api objectAPIHandlers) headObjectHandler(ctx context.Context, objectAPI Ob w.Header()[xhttp.AmzDeleteMarker] = []string{strconv.FormatBool(objInfo.DeleteMarker)} } QueueReplicationHeal(ctx, bucket, objInfo) - } - // do an additional verification whether object exists when opts.DeleteMarker is set by source - // cluster as part of delete marker replication - if opts.DeleteMarker && opts.ProxyHeaderSet { - opts.VersionID = "" - goi, gerr := getObjectInfo(ctx, bucket, object, opts) - if gerr == nil || goi.VersionID != "" { // object layer returned more info because object is deleted - w.Header().Set(xhttp.MinIOTargetReplicationReady, "true") + // do an additional verification whether object exists when object is deletemarker and request + // is from replication + if opts.CheckDMReplicationReady { + topts := opts + topts.VersionID = "" + goi, gerr := getObjectInfo(ctx, bucket, object, topts) + if gerr == nil || goi.VersionID != "" { // object layer returned more info because object is deleted + w.Header().Set(xhttp.MinIOTargetReplicationReady, "true") + } } } writeErrorResponseHeadersOnly(w, toAPIError(ctx, err)) diff --git a/go.mod b/go.mod index 73d87fb6b..044e86472 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/minio/highwayhash v1.0.2 github.com/minio/kes v0.21.0 github.com/minio/madmin-go v1.6.5 - github.com/minio/minio-go/v7 v7.0.41-0.20221013203648-8257e7003b5e + github.com/minio/minio-go/v7 v7.0.43-0.20221021202758-c6319beb6b27 github.com/minio/pkg v1.5.2 github.com/minio/selfupdate v0.5.0 github.com/minio/sha256-simd v1.0.0 diff --git a/go.sum b/go.sum index 6c3415953..87a3a3518 100644 --- a/go.sum +++ b/go.sum @@ -661,6 +661,8 @@ github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEp github.com/minio/minio-go/v7 v7.0.23/go.mod h1:ei5JjmxwHaMrgsMrn4U/+Nmg+d8MKS1U2DAn1ou4+Do= github.com/minio/minio-go/v7 v7.0.41-0.20221013203648-8257e7003b5e h1:Sq8FAHvwrz9x+Nwb1dt9f/BSmje07a6Q5LXdmprff/A= github.com/minio/minio-go/v7 v7.0.41-0.20221013203648-8257e7003b5e/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= +github.com/minio/minio-go/v7 v7.0.43-0.20221021202758-c6319beb6b27 h1:EqNpIeNzjGQjAe9Ih5gVW/4PccAse9+aa46hAoQSCQY= +github.com/minio/minio-go/v7 v7.0.43-0.20221021202758-c6319beb6b27/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASMg2/nvmbarw= github.com/minio/pkg v1.1.20/go.mod h1:Xo7LQshlxGa9shKwJ7NzQbgW4s8T/Wc1cOStR/eUiMY= github.com/minio/pkg v1.5.2 h1:vyEZ3TroiRGS/qb1XgP9RpK2zhjSWpBPjhNEbIo0pY8= github.com/minio/pkg v1.5.2/go.mod h1:koF2J2Ep/zpd//k+3UYdh6ySZKjqzy9C6RCZRX7uRY8= diff --git a/internal/http/headers.go b/internal/http/headers.go index 68b1f9a7a..962df8be5 100644 --- a/internal/http/headers.go +++ b/internal/http/headers.go @@ -197,6 +197,8 @@ const ( MinIOReplicationResetStatus = "X-Minio-Replication-Reset-Status" // Header indicating target cluster can receive delete marker replication requests because object has been replicated MinIOTargetReplicationReady = "X-Minio-Replication-Ready" + // Header asking if cluster can receive delete marker replication request now. + MinIOCheckDMReplicationReady = "X-Minio-Check-Replication-Ready" // Header indiicates last tag update time on source MinIOSourceTaggingTimestamp = "X-Minio-Source-Replication-Tagging-Timestamp" // Header indiicates last rtention update time on source