mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
add gateway object tagging support (#9124)
This commit is contained in:
parent
c138272d63
commit
3f6d624c7b
19
cmd/fs-v1.go
19
cmd/fs-v1.go
@ -1218,8 +1218,8 @@ func (fs *FSObjects) ListObjects(ctx context.Context, bucket, prefix, marker, de
|
||||
fs.listDirFactory(), fs.getObjectInfo, fs.getObjectInfo)
|
||||
}
|
||||
|
||||
// GetObjectTag - get object tags from an existing object
|
||||
func (fs *FSObjects) GetObjectTag(ctx context.Context, bucket, object string) (*tags.Tags, error) {
|
||||
// GetObjectTags - get object tags from an existing object
|
||||
func (fs *FSObjects) GetObjectTags(ctx context.Context, bucket, object string) (*tags.Tags, error) {
|
||||
oi, err := fs.GetObjectInfo(ctx, bucket, object, ObjectOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -1228,8 +1228,8 @@ func (fs *FSObjects) GetObjectTag(ctx context.Context, bucket, object string) (*
|
||||
return tags.ParseObjectTags(oi.UserTags)
|
||||
}
|
||||
|
||||
// PutObjectTag - replace or add tags to an existing object
|
||||
func (fs *FSObjects) PutObjectTag(ctx context.Context, bucket, object string, tags string) error {
|
||||
// PutObjectTags - replace or add tags to an existing object
|
||||
func (fs *FSObjects) PutObjectTags(ctx context.Context, bucket, object string, tags string) error {
|
||||
fsMetaPath := pathJoin(fs.fsPath, minioMetaBucket, bucketMetaPrefix, bucket, object, fs.metaJSONFile)
|
||||
fsMeta := fsMetaV1{}
|
||||
wlk, err := fs.rwPool.Write(fsMetaPath)
|
||||
@ -1260,9 +1260,9 @@ func (fs *FSObjects) PutObjectTag(ctx context.Context, bucket, object string, ta
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteObjectTag - delete object tags from an existing object
|
||||
func (fs *FSObjects) DeleteObjectTag(ctx context.Context, bucket, object string) error {
|
||||
return fs.PutObjectTag(ctx, bucket, object, "")
|
||||
// DeleteObjectTags - delete object tags from an existing object
|
||||
func (fs *FSObjects) DeleteObjectTags(ctx context.Context, bucket, object string) error {
|
||||
return fs.PutObjectTags(ctx, bucket, object, "")
|
||||
}
|
||||
|
||||
// ReloadFormat - no-op for fs, Valid only for XL.
|
||||
@ -1360,6 +1360,11 @@ func (fs *FSObjects) IsCompressionSupported() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsTaggingSupported returns true, object tagging is supported in fs object layer.
|
||||
func (fs *FSObjects) IsTaggingSupported() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsReady - Check if the backend disk is ready to accept traffic.
|
||||
func (fs *FSObjects) IsReady(_ context.Context) bool {
|
||||
if _, err := os.Stat(fs.fsPath); err != nil {
|
||||
|
@ -228,20 +228,20 @@ func (a GatewayUnsupported) DeleteBucketTagging(ctx context.Context, bucket stri
|
||||
return NotImplemented{}
|
||||
}
|
||||
|
||||
// PutObjectTag - not implemented.
|
||||
func (a GatewayUnsupported) PutObjectTag(ctx context.Context, bucket, object string, tags string) error {
|
||||
// PutObjectTags - not implemented.
|
||||
func (a GatewayUnsupported) PutObjectTags(ctx context.Context, bucket, object string, tags string) error {
|
||||
logger.LogIf(ctx, NotImplemented{})
|
||||
return NotImplemented{}
|
||||
}
|
||||
|
||||
// GetObjectTag - not implemented.
|
||||
func (a GatewayUnsupported) GetObjectTag(ctx context.Context, bucket, object string) (*tags.Tags, error) {
|
||||
// GetObjectTags - not implemented.
|
||||
func (a GatewayUnsupported) GetObjectTags(ctx context.Context, bucket, object string) (*tags.Tags, error) {
|
||||
logger.LogIf(ctx, NotImplemented{})
|
||||
return nil, NotImplemented{}
|
||||
}
|
||||
|
||||
// DeleteObjectTag - not implemented.
|
||||
func (a GatewayUnsupported) DeleteObjectTag(ctx context.Context, bucket, object string) error {
|
||||
// DeleteObjectTags - not implemented.
|
||||
func (a GatewayUnsupported) DeleteObjectTags(ctx context.Context, bucket, object string) error {
|
||||
logger.LogIf(ctx, NotImplemented{})
|
||||
return NotImplemented{}
|
||||
}
|
||||
@ -261,6 +261,11 @@ func (a GatewayUnsupported) IsEncryptionSupported() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsTaggingSupported returns whether object tagging is supported or not for this layer.
|
||||
func (a GatewayUnsupported) IsTaggingSupported() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCompressionSupported returns whether compression is applicable for this layer.
|
||||
func (a GatewayUnsupported) IsCompressionSupported() bool {
|
||||
return false
|
||||
|
@ -137,3 +137,7 @@ func (n *nasObjects) IsReady(ctx context.Context) bool {
|
||||
sinfo := n.ObjectLayer.StorageInfo(ctx, false)
|
||||
return sinfo.Backend.Type == minio.BackendFS
|
||||
}
|
||||
|
||||
func (n *nasObjects) IsTaggingSupported() bool {
|
||||
return true
|
||||
}
|
||||
|
@ -16,7 +16,9 @@
|
||||
|
||||
package s3
|
||||
|
||||
import minio "github.com/minio/minio/cmd"
|
||||
import (
|
||||
minio "github.com/minio/minio/cmd"
|
||||
)
|
||||
|
||||
// List of header keys to be filtered, usually
|
||||
// from all S3 API http responses.
|
||||
|
@ -29,10 +29,12 @@ import (
|
||||
"github.com/minio/cli"
|
||||
miniogo "github.com/minio/minio-go/v6"
|
||||
"github.com/minio/minio-go/v6/pkg/credentials"
|
||||
"github.com/minio/minio-go/v6/pkg/tags"
|
||||
minio "github.com/minio/minio/cmd"
|
||||
|
||||
"github.com/minio/minio-go/v6/pkg/encrypt"
|
||||
"github.com/minio/minio-go/v6/pkg/s3utils"
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/auth"
|
||||
"github.com/minio/minio/pkg/bucket/policy"
|
||||
@ -459,11 +461,25 @@ func (l *s3Objects) GetObjectInfo(ctx context.Context, bucket string, object str
|
||||
// PutObject creates a new object with the incoming data,
|
||||
func (l *s3Objects) PutObject(ctx context.Context, bucket string, object string, r *minio.PutObjReader, opts minio.ObjectOptions) (objInfo minio.ObjectInfo, err error) {
|
||||
data := r.Reader
|
||||
|
||||
oi, err := l.Client.PutObject(bucket, object, data, data.Size(), data.MD5Base64String(), data.SHA256HexString(), minio.ToMinioClientMetadata(opts.UserDefined), opts.ServerSideEncryption)
|
||||
var tagMap map[string]string
|
||||
if tagstr, ok := opts.UserDefined[xhttp.AmzObjectTagging]; ok && tagstr != "" {
|
||||
tagObj, err := tags.ParseObjectTags(tagstr)
|
||||
if err != nil {
|
||||
return objInfo, minio.ErrorRespToObjectError(err, bucket, object)
|
||||
}
|
||||
tagMap = tagObj.ToMap()
|
||||
delete(opts.UserDefined, xhttp.AmzObjectTagging)
|
||||
}
|
||||
putOpts := miniogo.PutObjectOptions{
|
||||
UserMetadata: opts.UserDefined,
|
||||
ServerSideEncryption: opts.ServerSideEncryption,
|
||||
UserTags: tagMap,
|
||||
}
|
||||
oi, err := l.Client.PutObject(bucket, object, data, data.Size(), data.MD5Base64String(), data.SHA256HexString(), putOpts)
|
||||
if err != nil {
|
||||
return objInfo, minio.ErrorRespToObjectError(err, bucket, object)
|
||||
}
|
||||
|
||||
// On success, populate the key & metadata so they are present in the notification
|
||||
oi.Key = object
|
||||
oi.Metadata = minio.ToMinioClientObjectInfoMetadata(opts.UserDefined)
|
||||
@ -490,6 +506,7 @@ func (l *s3Objects) CopyObject(ctx context.Context, srcBucket string, srcObject
|
||||
if dstOpts.ServerSideEncryption != nil {
|
||||
dstOpts.ServerSideEncryption.Marshal(header)
|
||||
}
|
||||
|
||||
for k, v := range header {
|
||||
srcInfo.UserDefined[k] = v[0]
|
||||
}
|
||||
@ -530,8 +547,21 @@ func (l *s3Objects) ListMultipartUploads(ctx context.Context, bucket string, pre
|
||||
|
||||
// NewMultipartUpload upload object in multiple parts
|
||||
func (l *s3Objects) NewMultipartUpload(ctx context.Context, bucket string, object string, o minio.ObjectOptions) (uploadID string, err error) {
|
||||
var tagMap map[string]string
|
||||
if tagStr, ok := o.UserDefined[xhttp.AmzObjectTagging]; ok {
|
||||
tagObj, err := tags.Parse(tagStr, true)
|
||||
if err != nil {
|
||||
return uploadID, minio.ErrorRespToObjectError(err, bucket, object)
|
||||
}
|
||||
tagMap = tagObj.ToMap()
|
||||
delete(o.UserDefined, xhttp.AmzObjectTagging)
|
||||
}
|
||||
// Create PutObject options
|
||||
opts := miniogo.PutObjectOptions{UserMetadata: o.UserDefined, ServerSideEncryption: o.ServerSideEncryption}
|
||||
opts := miniogo.PutObjectOptions{
|
||||
UserMetadata: o.UserDefined,
|
||||
ServerSideEncryption: o.ServerSideEncryption,
|
||||
UserTags: tagMap,
|
||||
}
|
||||
uploadID, err = l.Client.NewMultipartUpload(bucket, object, opts)
|
||||
if err != nil {
|
||||
return uploadID, minio.ErrorRespToObjectError(err, bucket, object)
|
||||
@ -643,6 +673,47 @@ func (l *s3Objects) DeleteBucketPolicy(ctx context.Context, bucket string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetObjectTags gets the tags set on the object
|
||||
func (l *s3Objects) GetObjectTags(ctx context.Context, bucket string, object string) (*tags.Tags, error) {
|
||||
var err error
|
||||
var tagObj *tags.Tags
|
||||
var tagStr string
|
||||
var opts minio.ObjectOptions
|
||||
|
||||
if _, err = l.GetObjectInfo(ctx, bucket, object, opts); err != nil {
|
||||
return nil, minio.ErrorRespToObjectError(err, bucket, object)
|
||||
}
|
||||
|
||||
if tagStr, err = l.Client.GetObjectTagging(bucket, object); err != nil {
|
||||
return nil, minio.ErrorRespToObjectError(err, bucket, object)
|
||||
}
|
||||
|
||||
if tagObj, err = tags.ParseObjectXML(strings.NewReader(tagStr)); err != nil {
|
||||
return nil, minio.ErrorRespToObjectError(err, bucket, object)
|
||||
}
|
||||
return tagObj, err
|
||||
}
|
||||
|
||||
// PutObjectTags attaches the tags to the object
|
||||
func (l *s3Objects) PutObjectTags(ctx context.Context, bucket, object string, tagStr string) error {
|
||||
tagObj, err := tags.Parse(tagStr, true)
|
||||
if err != nil {
|
||||
return minio.ErrorRespToObjectError(err, bucket, object)
|
||||
}
|
||||
if err = l.Client.PutObjectTagging(bucket, object, tagObj.ToMap()); err != nil {
|
||||
return minio.ErrorRespToObjectError(err, bucket, object)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteObjectTags removes the tags attached to the object
|
||||
func (l *s3Objects) DeleteObjectTags(ctx context.Context, bucket, object string) error {
|
||||
if err := l.Client.RemoveObjectTagging(bucket, object); err != nil {
|
||||
return minio.ErrorRespToObjectError(err, bucket, object)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsCompressionSupported returns whether compression is applicable for this layer.
|
||||
func (l *s3Objects) IsCompressionSupported() bool {
|
||||
return false
|
||||
@ -657,3 +728,7 @@ func (l *s3Objects) IsEncryptionSupported() bool {
|
||||
func (l *s3Objects) IsReady(ctx context.Context) bool {
|
||||
return minio.IsBackendOnline(ctx, l.HTTPClient, l.Client.EndpointURL().String())
|
||||
}
|
||||
|
||||
func (l *s3Objects) IsTaggingSupported() bool {
|
||||
return true
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ const (
|
||||
|
||||
// S3 object tagging
|
||||
AmzObjectTagging = "X-Amz-Tagging"
|
||||
AmzTagCount = "X-Amz-Tag-Count"
|
||||
AmzTagCount = "X-Amz-Tagging-Count"
|
||||
AmzTagDirective = "X-Amz-Tagging-Directive"
|
||||
|
||||
// S3 extensions
|
||||
|
@ -123,8 +123,11 @@ type ObjectLayer interface {
|
||||
// Check Readiness
|
||||
IsReady(ctx context.Context) bool
|
||||
|
||||
// Object Tagging Support check.
|
||||
IsTaggingSupported() bool
|
||||
|
||||
// ObjectTagging operations
|
||||
PutObjectTag(context.Context, string, string, string) error
|
||||
GetObjectTag(context.Context, string, string) (*tags.Tags, error)
|
||||
DeleteObjectTag(context.Context, string, string) error
|
||||
PutObjectTags(context.Context, string, string, string) error
|
||||
GetObjectTags(context.Context, string, string) (*tags.Tags, error)
|
||||
DeleteObjectTags(context.Context, string, string) error
|
||||
}
|
||||
|
@ -1072,6 +1072,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
|
||||
// If x-amz-tagging-directive header is REPLACE, get passed tags.
|
||||
if isDirectiveReplace(r.Header.Get(xhttp.AmzTagDirective)) {
|
||||
objTags = r.Header.Get(xhttp.AmzObjectTagging)
|
||||
srcInfo.UserDefined[xhttp.AmzTagDirective] = replaceDirective
|
||||
if _, err := tags.ParseObjectTags(objTags); err != nil {
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
@ -1147,8 +1148,18 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, rerr), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
}
|
||||
tag, err := tags.ParseObjectTags(objTags)
|
||||
if err != nil {
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
}
|
||||
opts := miniogo.PutObjectOptions{
|
||||
UserMetadata: srcInfo.UserDefined,
|
||||
ServerSideEncryption: dstOpts.ServerSideEncryption,
|
||||
UserTags: tag.ToMap(),
|
||||
}
|
||||
remoteObjInfo, rerr := client.PutObject(dstBucket, dstObject, srcInfo.Reader,
|
||||
srcInfo.Size, "", "", srcInfo.UserDefined, dstOpts.ServerSideEncryption)
|
||||
srcInfo.Size, "", "", opts)
|
||||
if rerr != nil {
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, rerr), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
@ -1284,6 +1295,11 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req
|
||||
}
|
||||
|
||||
if objTags := r.Header.Get(xhttp.AmzObjectTagging); objTags != "" {
|
||||
if !objectAPI.IsTaggingSupported() {
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := tags.ParseObjectTags(objTags); err != nil {
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
@ -2946,6 +2962,10 @@ func (api objectAPIHandlers) GetObjectTaggingHandler(w http.ResponseWriter, r *h
|
||||
return
|
||||
}
|
||||
|
||||
if !objAPI.IsTaggingSupported() {
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
}
|
||||
// Allow getObjectTagging if policy action is set.
|
||||
if s3Error := checkRequestAuthType(ctx, r, policy.GetObjectTaggingAction, bucket, object); s3Error != ErrNone {
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r))
|
||||
@ -2953,7 +2973,7 @@ func (api objectAPIHandlers) GetObjectTaggingHandler(w http.ResponseWriter, r *h
|
||||
}
|
||||
|
||||
// Get object tags
|
||||
tags, err := objAPI.GetObjectTag(ctx, bucket, object)
|
||||
tags, err := objAPI.GetObjectTags(ctx, bucket, object)
|
||||
if err != nil {
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
@ -2980,6 +3000,10 @@ func (api objectAPIHandlers) PutObjectTaggingHandler(w http.ResponseWriter, r *h
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
}
|
||||
if !objAPI.IsTaggingSupported() {
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
}
|
||||
|
||||
// Allow putObjectTagging if policy action is set
|
||||
if s3Error := checkRequestAuthType(ctx, r, policy.PutObjectTaggingAction, bucket, object); s3Error != ErrNone {
|
||||
@ -2994,7 +3018,7 @@ func (api objectAPIHandlers) PutObjectTaggingHandler(w http.ResponseWriter, r *h
|
||||
}
|
||||
|
||||
// Put object tags
|
||||
err = objAPI.PutObjectTag(ctx, bucket, object, tags.String())
|
||||
err = objAPI.PutObjectTags(ctx, bucket, object, tags.String())
|
||||
if err != nil {
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
@ -3013,6 +3037,10 @@ func (api objectAPIHandlers) DeleteObjectTaggingHandler(w http.ResponseWriter, r
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
}
|
||||
if !objAPI.IsTaggingSupported() {
|
||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
bucket := vars["bucket"]
|
||||
@ -3029,7 +3057,7 @@ func (api objectAPIHandlers) DeleteObjectTaggingHandler(w http.ResponseWriter, r
|
||||
}
|
||||
|
||||
// Delete object tags
|
||||
if err = objAPI.DeleteObjectTag(ctx, bucket, object); err != nil && err != errConfigNotFound {
|
||||
if err = objAPI.DeleteObjectTags(ctx, bucket, object); err != nil && err != errConfigNotFound {
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||
return
|
||||
}
|
||||
|
@ -588,6 +588,10 @@ func (s *xlSets) IsCompressionSupported() bool {
|
||||
return s.getHashedSet("").IsCompressionSupported()
|
||||
}
|
||||
|
||||
func (s *xlSets) IsTaggingSupported() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// DeleteBucket - deletes a bucket on all sets simultaneously,
|
||||
// even if one of the sets fail to delete buckets, we proceed to
|
||||
// undo a successful operation.
|
||||
@ -1684,19 +1688,19 @@ func (s *xlSets) HealObjects(ctx context.Context, bucket, prefix string, opts ma
|
||||
return nil
|
||||
}
|
||||
|
||||
// PutObjectTag - replace or add tags to an existing object
|
||||
func (s *xlSets) PutObjectTag(ctx context.Context, bucket, object string, tags string) error {
|
||||
return s.getHashedSet(object).PutObjectTag(ctx, bucket, object, tags)
|
||||
// PutObjectTags - replace or add tags to an existing object
|
||||
func (s *xlSets) PutObjectTags(ctx context.Context, bucket, object string, tags string) error {
|
||||
return s.getHashedSet(object).PutObjectTags(ctx, bucket, object, tags)
|
||||
}
|
||||
|
||||
// DeleteObjectTag - delete object tags from an existing object
|
||||
func (s *xlSets) DeleteObjectTag(ctx context.Context, bucket, object string) error {
|
||||
return s.getHashedSet(object).DeleteObjectTag(ctx, bucket, object)
|
||||
// DeleteObjectTags - delete object tags from an existing object
|
||||
func (s *xlSets) DeleteObjectTags(ctx context.Context, bucket, object string) error {
|
||||
return s.getHashedSet(object).DeleteObjectTags(ctx, bucket, object)
|
||||
}
|
||||
|
||||
// GetObjectTag - get object tags from an existing object
|
||||
func (s *xlSets) GetObjectTag(ctx context.Context, bucket, object string) (*tags.Tags, error) {
|
||||
return s.getHashedSet(object).GetObjectTag(ctx, bucket, object)
|
||||
// GetObjectTags - get object tags from an existing object
|
||||
func (s *xlSets) GetObjectTags(ctx context.Context, bucket, object string) (*tags.Tags, error) {
|
||||
return s.getHashedSet(object).GetObjectTags(ctx, bucket, object)
|
||||
}
|
||||
|
||||
// GetMetrics - no op
|
||||
|
@ -269,3 +269,7 @@ func (xl xlObjects) IsEncryptionSupported() bool {
|
||||
func (xl xlObjects) IsCompressionSupported() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (xl xlObjects) IsTaggingSupported() bool {
|
||||
return true
|
||||
}
|
||||
|
@ -1009,8 +1009,8 @@ func (xl xlObjects) addPartialUpload(bucket, key string) {
|
||||
}
|
||||
}
|
||||
|
||||
// PutObjectTag - replace or add tags to an existing object
|
||||
func (xl xlObjects) PutObjectTag(ctx context.Context, bucket, object string, tags string) error {
|
||||
// PutObjectTags - replace or add tags to an existing object
|
||||
func (xl xlObjects) PutObjectTags(ctx context.Context, bucket, object string, tags string) error {
|
||||
disks := xl.getDisks()
|
||||
|
||||
// Read metadata associated with the object from all disks.
|
||||
@ -1046,13 +1046,13 @@ func (xl xlObjects) PutObjectTag(ctx context.Context, bucket, object string, tag
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteObjectTag - delete object tags from an existing object
|
||||
func (xl xlObjects) DeleteObjectTag(ctx context.Context, bucket, object string) error {
|
||||
return xl.PutObjectTag(ctx, bucket, object, "")
|
||||
// DeleteObjectTags - delete object tags from an existing object
|
||||
func (xl xlObjects) DeleteObjectTags(ctx context.Context, bucket, object string) error {
|
||||
return xl.PutObjectTags(ctx, bucket, object, "")
|
||||
}
|
||||
|
||||
// GetObjectTag - get object tags from an existing object
|
||||
func (xl xlObjects) GetObjectTag(ctx context.Context, bucket, object string) (*tags.Tags, error) {
|
||||
// GetObjectTags - get object tags from an existing object
|
||||
func (xl xlObjects) GetObjectTags(ctx context.Context, bucket, object string) (*tags.Tags, error) {
|
||||
// GetObjectInfo will return tag value as well
|
||||
oi, err := xl.GetObjectInfo(ctx, bucket, object, ObjectOptions{})
|
||||
if err != nil {
|
||||
|
@ -1223,6 +1223,10 @@ func (z *xlZones) IsCompressionSupported() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (z *xlZones) IsTaggingSupported() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// DeleteBucket - deletes a bucket on all zones simultaneously,
|
||||
// even if one of the zones fail to delete buckets, we proceed to
|
||||
// undo a successful operation.
|
||||
@ -1538,13 +1542,13 @@ func (z *xlZones) IsReady(ctx context.Context) bool {
|
||||
return z.zones[0].IsReady(ctx)
|
||||
}
|
||||
|
||||
// PutObjectTag - replace or add tags to an existing object
|
||||
func (z *xlZones) PutObjectTag(ctx context.Context, bucket, object string, tags string) error {
|
||||
// PutObjectTags - replace or add tags to an existing object
|
||||
func (z *xlZones) PutObjectTags(ctx context.Context, bucket, object string, tags string) error {
|
||||
if z.SingleZone() {
|
||||
return z.zones[0].PutObjectTag(ctx, bucket, object, tags)
|
||||
return z.zones[0].PutObjectTags(ctx, bucket, object, tags)
|
||||
}
|
||||
for _, zone := range z.zones {
|
||||
err := zone.PutObjectTag(ctx, bucket, object, tags)
|
||||
err := zone.PutObjectTags(ctx, bucket, object, tags)
|
||||
if err != nil {
|
||||
if isErrBucketNotFound(err) {
|
||||
continue
|
||||
@ -1558,13 +1562,13 @@ func (z *xlZones) PutObjectTag(ctx context.Context, bucket, object string, tags
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteObjectTag - delete object tags from an existing object
|
||||
func (z *xlZones) DeleteObjectTag(ctx context.Context, bucket, object string) error {
|
||||
// DeleteObjectTags - delete object tags from an existing object
|
||||
func (z *xlZones) DeleteObjectTags(ctx context.Context, bucket, object string) error {
|
||||
if z.SingleZone() {
|
||||
return z.zones[0].DeleteObjectTag(ctx, bucket, object)
|
||||
return z.zones[0].DeleteObjectTags(ctx, bucket, object)
|
||||
}
|
||||
for _, zone := range z.zones {
|
||||
err := zone.DeleteObjectTag(ctx, bucket, object)
|
||||
err := zone.DeleteObjectTags(ctx, bucket, object)
|
||||
if err != nil {
|
||||
if isErrBucketNotFound(err) {
|
||||
continue
|
||||
@ -1578,13 +1582,13 @@ func (z *xlZones) DeleteObjectTag(ctx context.Context, bucket, object string) er
|
||||
}
|
||||
}
|
||||
|
||||
// GetObjectTag - get object tags from an existing object
|
||||
func (z *xlZones) GetObjectTag(ctx context.Context, bucket, object string) (*tags.Tags, error) {
|
||||
// GetObjectTags - get object tags from an existing object
|
||||
func (z *xlZones) GetObjectTags(ctx context.Context, bucket, object string) (*tags.Tags, error) {
|
||||
if z.SingleZone() {
|
||||
return z.zones[0].GetObjectTag(ctx, bucket, object)
|
||||
return z.zones[0].GetObjectTags(ctx, bucket, object)
|
||||
}
|
||||
for _, zone := range z.zones {
|
||||
tags, err := zone.GetObjectTag(ctx, bucket, object)
|
||||
tags, err := zone.GetObjectTags(ctx, bucket, object)
|
||||
if err != nil {
|
||||
if isErrBucketNotFound(err) {
|
||||
continue
|
||||
|
2
go.mod
2
go.mod
@ -66,7 +66,7 @@ require (
|
||||
github.com/minio/hdfs/v3 v3.0.1
|
||||
github.com/minio/highwayhash v1.0.0
|
||||
github.com/minio/lsync v1.0.1
|
||||
github.com/minio/minio-go/v6 v6.0.55-0.20200425081427-89eebdef2af0
|
||||
github.com/minio/minio-go/v6 v6.0.56-0.20200522164946-44a5f2e3b76b
|
||||
github.com/minio/parquet-go v0.0.0-20200414234858-838cfa8aae61
|
||||
github.com/minio/sha256-simd v0.1.1
|
||||
github.com/minio/simdjson-go v0.1.5-0.20200303142138-b17fe061ea37
|
||||
|
4
go.sum
4
go.sum
@ -267,6 +267,10 @@ github.com/minio/lsync v1.0.1/go.mod h1:tCFzfo0dlvdGl70IT4IAK/5Wtgb0/BrTmo/jE8pA
|
||||
github.com/minio/minio-go/v6 v6.0.53/go.mod h1:DIvC/IApeHX8q1BAMVCXSXwpmrmM+I+iBvhvztQorfI=
|
||||
github.com/minio/minio-go/v6 v6.0.55-0.20200425081427-89eebdef2af0 h1:PdHKpM9h2vqCDr1AjJdK8e/6tRdOSjUNzIqeNmxu7ak=
|
||||
github.com/minio/minio-go/v6 v6.0.55-0.20200425081427-89eebdef2af0/go.mod h1:KQMM+/44DSlSGSQWSfRrAZ12FVMmpWNuX37i2AX0jfI=
|
||||
github.com/minio/minio-go/v6 v6.0.56-0.20200522005053-e9bc14bbccf9 h1:GpjSzFSjmNL9+SOzdJaQ6vxdvpFjhJR+xjtoK00Rle4=
|
||||
github.com/minio/minio-go/v6 v6.0.56-0.20200522005053-e9bc14bbccf9/go.mod h1:KQMM+/44DSlSGSQWSfRrAZ12FVMmpWNuX37i2AX0jfI=
|
||||
github.com/minio/minio-go/v6 v6.0.56-0.20200522164946-44a5f2e3b76b h1:hY8tAl7MwUuUB9ZqVDXEnrIqCuEy3dfU1RH0cZ7gu+o=
|
||||
github.com/minio/minio-go/v6 v6.0.56-0.20200522164946-44a5f2e3b76b/go.mod h1:KQMM+/44DSlSGSQWSfRrAZ12FVMmpWNuX37i2AX0jfI=
|
||||
github.com/minio/parquet-go v0.0.0-20200414234858-838cfa8aae61 h1:pUSI/WKPdd77gcuoJkSzhJ4wdS8OMDOsOu99MtpXEQA=
|
||||
github.com/minio/parquet-go v0.0.0-20200414234858-838cfa8aae61/go.mod h1:4trzEJ7N1nBTd5Tt7OCZT5SEin+WiAXpdJ/WgPkESA8=
|
||||
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
|
||||
|
@ -626,7 +626,7 @@ func testObjectTagging(s3Client *s3.S3) {
|
||||
|
||||
func testObjectTaggingErrors(s3Client *s3.S3) {
|
||||
startTime := time.Now()
|
||||
function := "testObjectTagging"
|
||||
function := "testObjectTaggingErrors"
|
||||
bucket := randString(60, rand.NewSource(time.Now().UnixNano()), "aws-sdk-go-test-")
|
||||
object := randString(60, rand.NewSource(time.Now().UnixNano()), "")
|
||||
args := map[string]interface{}{
|
||||
|
Loading…
Reference in New Issue
Block a user