mirror of https://github.com/minio/minio.git
tagging: Add event notif for PUT object tagging (#11366)
An optimization to avoid double calling for during PutObject tagging
This commit is contained in:
parent
6ef678663e
commit
e96fdcd5ec
|
@ -1146,7 +1146,14 @@ func (er erasureObjects) addPartial(bucket, object, versionID string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutObjectTags - replace or add tags to an existing object
|
// PutObjectTags - replace or add tags to an existing object
|
||||||
func (er erasureObjects) PutObjectTags(ctx context.Context, bucket, object string, tags string, opts ObjectOptions) error {
|
func (er erasureObjects) PutObjectTags(ctx context.Context, bucket, object string, tags string, opts ObjectOptions) (ObjectInfo, error) {
|
||||||
|
// Lock the object before updating tags.
|
||||||
|
lk := er.NewNSLock(bucket, object)
|
||||||
|
if err := lk.GetLock(ctx, globalOperationTimeout); err != nil {
|
||||||
|
return ObjectInfo{}, err
|
||||||
|
}
|
||||||
|
defer lk.Unlock()
|
||||||
|
|
||||||
disks := er.getDisks()
|
disks := er.getDisks()
|
||||||
|
|
||||||
// Read metadata associated with the object from all disks.
|
// Read metadata associated with the object from all disks.
|
||||||
|
@ -1154,7 +1161,7 @@ func (er erasureObjects) PutObjectTags(ctx context.Context, bucket, object strin
|
||||||
|
|
||||||
readQuorum, writeQuorum, err := objectQuorumFromMeta(ctx, metaArr, errs, er.defaultParityCount)
|
readQuorum, writeQuorum, err := objectQuorumFromMeta(ctx, metaArr, errs, er.defaultParityCount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return toObjectErr(err, bucket, object)
|
return ObjectInfo{}, toObjectErr(err, bucket, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List all online disks.
|
// List all online disks.
|
||||||
|
@ -1163,13 +1170,13 @@ func (er erasureObjects) PutObjectTags(ctx context.Context, bucket, object strin
|
||||||
// Pick latest valid metadata.
|
// Pick latest valid metadata.
|
||||||
fi, err := pickValidFileInfo(ctx, metaArr, modTime, readQuorum)
|
fi, err := pickValidFileInfo(ctx, metaArr, modTime, readQuorum)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return toObjectErr(err, bucket, object)
|
return ObjectInfo{}, toObjectErr(err, bucket, object)
|
||||||
}
|
}
|
||||||
if fi.Deleted {
|
if fi.Deleted {
|
||||||
if opts.VersionID == "" {
|
if opts.VersionID == "" {
|
||||||
return toObjectErr(errFileNotFound, bucket, object)
|
return ObjectInfo{}, toObjectErr(errFileNotFound, bucket, object)
|
||||||
}
|
}
|
||||||
return toObjectErr(errMethodNotAllowed, bucket, object)
|
return ObjectInfo{}, toObjectErr(errMethodNotAllowed, bucket, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
onlineDisks, metaArr = shuffleDisksAndPartsMetadataByIndex(onlineDisks, metaArr, fi.Erasure.Distribution)
|
onlineDisks, metaArr = shuffleDisksAndPartsMetadataByIndex(onlineDisks, metaArr, fi.Erasure.Distribution)
|
||||||
|
@ -1192,15 +1199,18 @@ func (er erasureObjects) PutObjectTags(ctx context.Context, bucket, object strin
|
||||||
|
|
||||||
// Write unique `xl.meta` for each disk.
|
// Write unique `xl.meta` for each disk.
|
||||||
if onlineDisks, err = writeUniqueFileInfo(ctx, onlineDisks, minioMetaTmpBucket, tempObj, metaArr, writeQuorum); err != nil {
|
if onlineDisks, err = writeUniqueFileInfo(ctx, onlineDisks, minioMetaTmpBucket, tempObj, metaArr, writeQuorum); err != nil {
|
||||||
return toObjectErr(err, bucket, object)
|
return ObjectInfo{}, toObjectErr(err, bucket, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atomically rename metadata from tmp location to destination for each disk.
|
// Atomically rename metadata from tmp location to destination for each disk.
|
||||||
if _, err = renameFileInfo(ctx, onlineDisks, minioMetaTmpBucket, tempObj, bucket, object, writeQuorum); err != nil {
|
if _, err = renameFileInfo(ctx, onlineDisks, minioMetaTmpBucket, tempObj, bucket, object, writeQuorum); err != nil {
|
||||||
return toObjectErr(err, bucket, object)
|
return ObjectInfo{}, toObjectErr(err, bucket, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
objInfo := fi.ToObjectInfo(bucket, object)
|
||||||
|
objInfo.UserTags = tags
|
||||||
|
|
||||||
|
return objInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateObjectMeta will update the metadata of a file.
|
// updateObjectMeta will update the metadata of a file.
|
||||||
|
@ -1264,7 +1274,7 @@ func (er erasureObjects) updateObjectMeta(ctx context.Context, bucket, object st
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObjectTags - delete object tags from an existing object
|
// DeleteObjectTags - delete object tags from an existing object
|
||||||
func (er erasureObjects) DeleteObjectTags(ctx context.Context, bucket, object string, opts ObjectOptions) error {
|
func (er erasureObjects) DeleteObjectTags(ctx context.Context, bucket, object string, opts ObjectOptions) (ObjectInfo, error) {
|
||||||
return er.PutObjectTags(ctx, bucket, object, "", opts)
|
return er.PutObjectTags(ctx, bucket, object, "", opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1542,59 +1542,59 @@ func (z *erasureServerPools) Health(ctx context.Context, opts HealthOptions) Hea
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutObjectTags - replace or add tags to an existing object
|
// PutObjectTags - replace or add tags to an existing object
|
||||||
func (z *erasureServerPools) PutObjectTags(ctx context.Context, bucket, object string, tags string, opts ObjectOptions) error {
|
func (z *erasureServerPools) PutObjectTags(ctx context.Context, bucket, object string, tags string, opts ObjectOptions) (ObjectInfo, error) {
|
||||||
object = encodeDirObject(object)
|
object = encodeDirObject(object)
|
||||||
if z.SinglePool() {
|
if z.SinglePool() {
|
||||||
return z.serverPools[0].PutObjectTags(ctx, bucket, object, tags, opts)
|
return z.serverPools[0].PutObjectTags(ctx, bucket, object, tags, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pool := range z.serverPools {
|
for _, pool := range z.serverPools {
|
||||||
err := pool.PutObjectTags(ctx, bucket, object, tags, opts)
|
objInfo, err := pool.PutObjectTags(ctx, bucket, object, tags, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if isErrObjectNotFound(err) || isErrVersionNotFound(err) {
|
if isErrObjectNotFound(err) || isErrVersionNotFound(err) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return ObjectInfo{}, err
|
||||||
}
|
}
|
||||||
return nil
|
return objInfo, nil
|
||||||
}
|
}
|
||||||
if opts.VersionID != "" {
|
if opts.VersionID != "" {
|
||||||
return VersionNotFound{
|
return ObjectInfo{}, VersionNotFound{
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Object: object,
|
Object: object,
|
||||||
VersionID: opts.VersionID,
|
VersionID: opts.VersionID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ObjectNotFound{
|
return ObjectInfo{}, ObjectNotFound{
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Object: object,
|
Object: object,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObjectTags - delete object tags from an existing object
|
// DeleteObjectTags - delete object tags from an existing object
|
||||||
func (z *erasureServerPools) DeleteObjectTags(ctx context.Context, bucket, object string, opts ObjectOptions) error {
|
func (z *erasureServerPools) DeleteObjectTags(ctx context.Context, bucket, object string, opts ObjectOptions) (ObjectInfo, error) {
|
||||||
object = encodeDirObject(object)
|
object = encodeDirObject(object)
|
||||||
if z.SinglePool() {
|
if z.SinglePool() {
|
||||||
return z.serverPools[0].DeleteObjectTags(ctx, bucket, object, opts)
|
return z.serverPools[0].DeleteObjectTags(ctx, bucket, object, opts)
|
||||||
}
|
}
|
||||||
for _, pool := range z.serverPools {
|
for _, pool := range z.serverPools {
|
||||||
err := pool.DeleteObjectTags(ctx, bucket, object, opts)
|
objInfo, err := pool.DeleteObjectTags(ctx, bucket, object, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if isErrObjectNotFound(err) || isErrVersionNotFound(err) {
|
if isErrObjectNotFound(err) || isErrVersionNotFound(err) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return ObjectInfo{}, err
|
||||||
}
|
}
|
||||||
return nil
|
return objInfo, nil
|
||||||
}
|
}
|
||||||
if opts.VersionID != "" {
|
if opts.VersionID != "" {
|
||||||
return VersionNotFound{
|
return ObjectInfo{}, VersionNotFound{
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Object: object,
|
Object: object,
|
||||||
VersionID: opts.VersionID,
|
VersionID: opts.VersionID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ObjectNotFound{
|
return ObjectInfo{}, ObjectNotFound{
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Object: object,
|
Object: object,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1384,13 +1384,13 @@ func (s *erasureSets) HealObject(ctx context.Context, bucket, object, versionID
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutObjectTags - replace or add tags to an existing object
|
// PutObjectTags - replace or add tags to an existing object
|
||||||
func (s *erasureSets) PutObjectTags(ctx context.Context, bucket, object string, tags string, opts ObjectOptions) error {
|
func (s *erasureSets) PutObjectTags(ctx context.Context, bucket, object string, tags string, opts ObjectOptions) (ObjectInfo, error) {
|
||||||
er := s.getHashedSet(object)
|
er := s.getHashedSet(object)
|
||||||
return er.PutObjectTags(ctx, bucket, object, tags, opts)
|
return er.PutObjectTags(ctx, bucket, object, tags, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObjectTags - delete object tags from an existing object
|
// DeleteObjectTags - delete object tags from an existing object
|
||||||
func (s *erasureSets) DeleteObjectTags(ctx context.Context, bucket, object string, opts ObjectOptions) error {
|
func (s *erasureSets) DeleteObjectTags(ctx context.Context, bucket, object string, opts ObjectOptions) (ObjectInfo, error) {
|
||||||
er := s.getHashedSet(object)
|
er := s.getHashedSet(object)
|
||||||
return er.DeleteObjectTags(ctx, bucket, object, opts)
|
return er.DeleteObjectTags(ctx, bucket, object, opts)
|
||||||
}
|
}
|
||||||
|
|
19
cmd/fs-v1.go
19
cmd/fs-v1.go
|
@ -1475,9 +1475,9 @@ func (fs *FSObjects) GetObjectTags(ctx context.Context, bucket, object string, o
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutObjectTags - replace or add tags to an existing object
|
// PutObjectTags - replace or add tags to an existing object
|
||||||
func (fs *FSObjects) PutObjectTags(ctx context.Context, bucket, object string, tags string, opts ObjectOptions) error {
|
func (fs *FSObjects) PutObjectTags(ctx context.Context, bucket, object string, tags string, opts ObjectOptions) (ObjectInfo, error) {
|
||||||
if opts.VersionID != "" && opts.VersionID != nullVersionID {
|
if opts.VersionID != "" && opts.VersionID != nullVersionID {
|
||||||
return VersionNotFound{
|
return ObjectInfo{}, VersionNotFound{
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Object: object,
|
Object: object,
|
||||||
VersionID: opts.VersionID,
|
VersionID: opts.VersionID,
|
||||||
|
@ -1491,7 +1491,7 @@ func (fs *FSObjects) PutObjectTags(ctx context.Context, bucket, object string, t
|
||||||
wlk, err = fs.rwPool.Create(fsMetaPath)
|
wlk, err = fs.rwPool.Create(fsMetaPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.LogIf(ctx, err)
|
logger.LogIf(ctx, err)
|
||||||
return toObjectErr(err, bucket, object)
|
return ObjectInfo{}, toObjectErr(err, bucket, object)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// This close will allow for locks to be synchronized on `fs.json`.
|
// This close will allow for locks to be synchronized on `fs.json`.
|
||||||
|
@ -1512,13 +1512,20 @@ func (fs *FSObjects) PutObjectTags(ctx context.Context, bucket, object string, t
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = fsMeta.WriteTo(wlk); err != nil {
|
if _, err = fsMeta.WriteTo(wlk); err != nil {
|
||||||
return toObjectErr(err, bucket, object)
|
return ObjectInfo{}, toObjectErr(err, bucket, object)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
// Stat the file to get file size.
|
||||||
|
fi, err := fsStatFile(ctx, pathJoin(fs.fsPath, bucket, object))
|
||||||
|
if err != nil {
|
||||||
|
return ObjectInfo{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fsMeta.ToObjectInfo(bucket, object, fi), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObjectTags - delete object tags from an existing object
|
// DeleteObjectTags - delete object tags from an existing object
|
||||||
func (fs *FSObjects) DeleteObjectTags(ctx context.Context, bucket, object string, opts ObjectOptions) error {
|
func (fs *FSObjects) DeleteObjectTags(ctx context.Context, bucket, object string, opts ObjectOptions) (ObjectInfo, error) {
|
||||||
return fs.PutObjectTags(ctx, bucket, object, "", opts)
|
return fs.PutObjectTags(ctx, bucket, object, "", opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,9 +208,9 @@ func (a GatewayUnsupported) GetMetrics(ctx context.Context) (*BackendMetrics, er
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutObjectTags - not implemented.
|
// PutObjectTags - not implemented.
|
||||||
func (a GatewayUnsupported) PutObjectTags(ctx context.Context, bucket, object string, tags string, opts ObjectOptions) error {
|
func (a GatewayUnsupported) PutObjectTags(ctx context.Context, bucket, object string, tags string, opts ObjectOptions) (ObjectInfo, error) {
|
||||||
logger.LogIf(ctx, NotImplemented{})
|
logger.LogIf(ctx, NotImplemented{})
|
||||||
return NotImplemented{}
|
return ObjectInfo{}, NotImplemented{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObjectTags - not implemented.
|
// GetObjectTags - not implemented.
|
||||||
|
@ -220,9 +220,9 @@ func (a GatewayUnsupported) GetObjectTags(ctx context.Context, bucket, object st
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObjectTags - not implemented.
|
// DeleteObjectTags - not implemented.
|
||||||
func (a GatewayUnsupported) DeleteObjectTags(ctx context.Context, bucket, object string, opts ObjectOptions) error {
|
func (a GatewayUnsupported) DeleteObjectTags(ctx context.Context, bucket, object string, opts ObjectOptions) (ObjectInfo, error) {
|
||||||
logger.LogIf(ctx, NotImplemented{})
|
logger.LogIf(ctx, NotImplemented{})
|
||||||
return NotImplemented{}
|
return ObjectInfo{}, NotImplemented{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNotificationSupported returns whether bucket notification is applicable for this layer.
|
// IsNotificationSupported returns whether bucket notification is applicable for this layer.
|
||||||
|
|
|
@ -728,23 +728,34 @@ func (l *s3Objects) GetObjectTags(ctx context.Context, bucket string, object str
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutObjectTags attaches the tags to the object
|
// PutObjectTags attaches the tags to the object
|
||||||
func (l *s3Objects) PutObjectTags(ctx context.Context, bucket, object string, tagStr string, opts minio.ObjectOptions) error {
|
func (l *s3Objects) PutObjectTags(ctx context.Context, bucket, object string, tagStr string, opts minio.ObjectOptions) (minio.ObjectInfo, error) {
|
||||||
tagObj, err := tags.Parse(tagStr, true)
|
tagObj, err := tags.Parse(tagStr, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return minio.ErrorRespToObjectError(err, bucket, object)
|
return minio.ObjectInfo{}, minio.ErrorRespToObjectError(err, bucket, object)
|
||||||
}
|
}
|
||||||
if err = l.Client.PutObjectTagging(ctx, bucket, object, tagObj, miniogo.PutObjectTaggingOptions{}); err != nil {
|
if err = l.Client.PutObjectTagging(ctx, bucket, object, tagObj, miniogo.PutObjectTaggingOptions{VersionID: opts.VersionID}); err != nil {
|
||||||
return minio.ErrorRespToObjectError(err, bucket, object)
|
return minio.ObjectInfo{}, minio.ErrorRespToObjectError(err, bucket, object)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
objInfo, err := l.GetObjectInfo(ctx, bucket, object, opts)
|
||||||
|
if err != nil {
|
||||||
|
return minio.ObjectInfo{}, minio.ErrorRespToObjectError(err, bucket, object)
|
||||||
|
}
|
||||||
|
|
||||||
|
return objInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObjectTags removes the tags attached to the object
|
// DeleteObjectTags removes the tags attached to the object
|
||||||
func (l *s3Objects) DeleteObjectTags(ctx context.Context, bucket, object string, opts minio.ObjectOptions) error {
|
func (l *s3Objects) DeleteObjectTags(ctx context.Context, bucket, object string, opts minio.ObjectOptions) (minio.ObjectInfo, error) {
|
||||||
if err := l.Client.RemoveObjectTagging(ctx, bucket, object, miniogo.RemoveObjectTaggingOptions{}); err != nil {
|
if err := l.Client.RemoveObjectTagging(ctx, bucket, object, miniogo.RemoveObjectTaggingOptions{}); err != nil {
|
||||||
return minio.ErrorRespToObjectError(err, bucket, object)
|
return minio.ObjectInfo{}, minio.ErrorRespToObjectError(err, bucket, object)
|
||||||
}
|
}
|
||||||
return nil
|
objInfo, err := l.GetObjectInfo(ctx, bucket, object, opts)
|
||||||
|
if err != nil {
|
||||||
|
return minio.ObjectInfo{}, minio.ErrorRespToObjectError(err, bucket, object)
|
||||||
|
}
|
||||||
|
|
||||||
|
return objInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsCompressionSupported returns whether compression is applicable for this layer.
|
// IsCompressionSupported returns whether compression is applicable for this layer.
|
||||||
|
|
|
@ -157,7 +157,7 @@ type ObjectLayer interface {
|
||||||
Health(ctx context.Context, opts HealthOptions) HealthResult
|
Health(ctx context.Context, opts HealthOptions) HealthResult
|
||||||
|
|
||||||
// ObjectTagging operations
|
// ObjectTagging operations
|
||||||
PutObjectTags(context.Context, string, string, string, ObjectOptions) error
|
PutObjectTags(context.Context, string, string, string, ObjectOptions) (ObjectInfo, error)
|
||||||
GetObjectTags(context.Context, string, string, ObjectOptions) (*tags.Tags, error)
|
GetObjectTags(context.Context, string, string, ObjectOptions) (*tags.Tags, error)
|
||||||
DeleteObjectTags(context.Context, string, string, ObjectOptions) error
|
DeleteObjectTags(context.Context, string, string, ObjectOptions) (ObjectInfo, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3281,24 +3281,35 @@ func (api objectAPIHandlers) PutObjectTaggingHandler(w http.ResponseWriter, r *h
|
||||||
opts.UserDefined[xhttp.AmzBucketReplicationStatus] = replication.Pending.String()
|
opts.UserDefined[xhttp.AmzBucketReplicationStatus] = replication.Pending.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tagsStr := tags.String()
|
||||||
|
|
||||||
// Put object tags
|
// Put object tags
|
||||||
err = objAPI.PutObjectTags(ctx, bucket, object, tags.String(), opts)
|
objInfo, err := objAPI.PutObjectTags(ctx, bucket, object, tagsStr, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if replicate {
|
if replicate {
|
||||||
if objInfo, err := objAPI.GetObjectInfo(ctx, bucket, object, opts); err == nil {
|
|
||||||
scheduleReplication(ctx, objInfo, objAPI, sync)
|
scheduleReplication(ctx, objInfo, objAPI, sync)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if opts.VersionID != "" {
|
if objInfo.VersionID != "" {
|
||||||
w.Header()[xhttp.AmzVersionID] = []string{opts.VersionID}
|
w.Header()[xhttp.AmzVersionID] = []string{objInfo.VersionID}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeSuccessResponseHeadersOnly(w)
|
writeSuccessResponseHeadersOnly(w)
|
||||||
|
|
||||||
|
sendEvent(eventArgs{
|
||||||
|
EventName: event.ObjectCreatedPutTagging,
|
||||||
|
BucketName: bucket,
|
||||||
|
Object: objInfo,
|
||||||
|
ReqParams: extractReqParams(r),
|
||||||
|
RespElements: extractRespElements(w),
|
||||||
|
UserAgent: r.UserAgent(),
|
||||||
|
Host: handlers.GetSourceIP(r),
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObjectTaggingHandler - DELETE object tagging
|
// DeleteObjectTaggingHandler - DELETE object tagging
|
||||||
|
@ -3345,21 +3356,31 @@ func (api objectAPIHandlers) DeleteObjectTaggingHandler(w http.ResponseWriter, r
|
||||||
opts.UserDefined = make(map[string]string)
|
opts.UserDefined = make(map[string]string)
|
||||||
opts.UserDefined[xhttp.AmzBucketReplicationStatus] = replication.Pending.String()
|
opts.UserDefined[xhttp.AmzBucketReplicationStatus] = replication.Pending.String()
|
||||||
}
|
}
|
||||||
// Delete object tags
|
|
||||||
if err = objAPI.DeleteObjectTags(ctx, bucket, object, opts); err != nil {
|
if _, err = objAPI.DeleteObjectTags(ctx, bucket, object, opts); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
oi.UserTags = ""
|
||||||
if opts.VersionID != "" {
|
|
||||||
w.Header()[xhttp.AmzVersionID] = []string{opts.VersionID}
|
|
||||||
}
|
|
||||||
|
|
||||||
if replicate {
|
if replicate {
|
||||||
scheduleReplication(ctx, oi, objAPI, sync)
|
scheduleReplication(ctx, oi, objAPI, sync)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if oi.VersionID != "" {
|
||||||
|
w.Header()[xhttp.AmzVersionID] = []string{oi.VersionID}
|
||||||
|
}
|
||||||
writeSuccessNoContent(w)
|
writeSuccessNoContent(w)
|
||||||
|
|
||||||
|
sendEvent(eventArgs{
|
||||||
|
EventName: event.ObjectCreatedDeleteTagging,
|
||||||
|
BucketName: bucket,
|
||||||
|
Object: oi,
|
||||||
|
ReqParams: extractReqParams(r),
|
||||||
|
RespElements: extractRespElements(w),
|
||||||
|
UserAgent: r.UserAgent(),
|
||||||
|
Host: handlers.GetSourceIP(r),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// RestoreObjectHandler - POST restore object handler.
|
// RestoreObjectHandler - POST restore object handler.
|
||||||
|
|
|
@ -41,6 +41,8 @@ const (
|
||||||
ObjectCreatedPut
|
ObjectCreatedPut
|
||||||
ObjectCreatedPutRetention
|
ObjectCreatedPutRetention
|
||||||
ObjectCreatedPutLegalHold
|
ObjectCreatedPutLegalHold
|
||||||
|
ObjectCreatedPutTagging
|
||||||
|
ObjectCreatedDeleteTagging
|
||||||
ObjectRemovedAll
|
ObjectRemovedAll
|
||||||
ObjectRemovedDelete
|
ObjectRemovedDelete
|
||||||
ObjectRemovedDeleteMarkerCreated
|
ObjectRemovedDeleteMarkerCreated
|
||||||
|
@ -77,6 +79,7 @@ func (name Name) Expand() []Name {
|
||||||
ObjectCreatedCompleteMultipartUpload, ObjectCreatedCopy,
|
ObjectCreatedCompleteMultipartUpload, ObjectCreatedCopy,
|
||||||
ObjectCreatedPost, ObjectCreatedPut,
|
ObjectCreatedPost, ObjectCreatedPut,
|
||||||
ObjectCreatedPutRetention, ObjectCreatedPutLegalHold,
|
ObjectCreatedPutRetention, ObjectCreatedPutLegalHold,
|
||||||
|
ObjectCreatedPutTagging, ObjectCreatedDeleteTagging,
|
||||||
ObjectReplicationComplete, ObjectReplicationFailed,
|
ObjectReplicationComplete, ObjectReplicationFailed,
|
||||||
}
|
}
|
||||||
case ObjectRemovedAll:
|
case ObjectRemovedAll:
|
||||||
|
@ -134,6 +137,10 @@ func (name Name) String() string {
|
||||||
return "s3:ObjectCreated:Post"
|
return "s3:ObjectCreated:Post"
|
||||||
case ObjectCreatedPut:
|
case ObjectCreatedPut:
|
||||||
return "s3:ObjectCreated:Put"
|
return "s3:ObjectCreated:Put"
|
||||||
|
case ObjectCreatedPutTagging:
|
||||||
|
return "s3:ObjectCreated:PutTagging"
|
||||||
|
case ObjectCreatedDeleteTagging:
|
||||||
|
return "s3:ObjectCreated:DeleteTagging"
|
||||||
case ObjectCreatedPutRetention:
|
case ObjectCreatedPutRetention:
|
||||||
return "s3:ObjectCreated:PutRetention"
|
return "s3:ObjectCreated:PutRetention"
|
||||||
case ObjectCreatedPutLegalHold:
|
case ObjectCreatedPutLegalHold:
|
||||||
|
@ -244,6 +251,10 @@ func ParseName(s string) (Name, error) {
|
||||||
return ObjectCreatedPutRetention, nil
|
return ObjectCreatedPutRetention, nil
|
||||||
case "s3:ObjectCreated:PutLegalHold":
|
case "s3:ObjectCreated:PutLegalHold":
|
||||||
return ObjectCreatedPutLegalHold, nil
|
return ObjectCreatedPutLegalHold, nil
|
||||||
|
case "s3:ObjectCreated:PutTagging":
|
||||||
|
return ObjectCreatedPutTagging, nil
|
||||||
|
case "s3:ObjectCreated:DeleteTagging":
|
||||||
|
return ObjectCreatedDeleteTagging, nil
|
||||||
case "s3:ObjectRemoved:*":
|
case "s3:ObjectRemoved:*":
|
||||||
return ObjectRemovedAll, nil
|
return ObjectRemovedAll, nil
|
||||||
case "s3:ObjectRemoved:Delete":
|
case "s3:ObjectRemoved:Delete":
|
||||||
|
|
|
@ -31,8 +31,9 @@ func TestNameExpand(t *testing.T) {
|
||||||
{BucketCreated, []Name{BucketCreated}},
|
{BucketCreated, []Name{BucketCreated}},
|
||||||
{BucketRemoved, []Name{BucketRemoved}},
|
{BucketRemoved, []Name{BucketRemoved}},
|
||||||
{ObjectAccessedAll, []Name{ObjectAccessedGet, ObjectAccessedHead, ObjectAccessedGetRetention, ObjectAccessedGetLegalHold}},
|
{ObjectAccessedAll, []Name{ObjectAccessedGet, ObjectAccessedHead, ObjectAccessedGetRetention, ObjectAccessedGetLegalHold}},
|
||||||
{ObjectCreatedAll, []Name{ObjectCreatedCompleteMultipartUpload, ObjectCreatedCopy,
|
{ObjectCreatedAll, []Name{ObjectCreatedCompleteMultipartUpload, ObjectCreatedCopy, ObjectCreatedPost, ObjectCreatedPut,
|
||||||
ObjectCreatedPost, ObjectCreatedPut, ObjectCreatedPutRetention, ObjectCreatedPutLegalHold, ObjectReplicationComplete, ObjectReplicationFailed}},
|
ObjectCreatedPutRetention, ObjectCreatedPutLegalHold, ObjectCreatedPutTagging, ObjectCreatedDeleteTagging,
|
||||||
|
ObjectReplicationComplete, ObjectReplicationFailed}},
|
||||||
{ObjectRemovedAll, []Name{ObjectRemovedDelete, ObjectRemovedDeleteMarkerCreated}},
|
{ObjectRemovedAll, []Name{ObjectRemovedDelete, ObjectRemovedDeleteMarkerCreated}},
|
||||||
{ObjectAccessedHead, []Name{ObjectAccessedHead}},
|
{ObjectAccessedHead, []Name{ObjectAccessedHead}},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue