mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
web-handlers: Support removal of multiple objects at once. (#3810)
This commit is contained in:
parent
2b0ed21f08
commit
91cf54f895
@ -36,7 +36,7 @@ test_script:
|
|||||||
# Unit tests
|
# Unit tests
|
||||||
- ps: Add-AppveyorTest "Unit Tests" -Outcome Running
|
- ps: Add-AppveyorTest "Unit Tests" -Outcome Running
|
||||||
- mkdir build\coverage
|
- mkdir build\coverage
|
||||||
- go test -timeout 15m -race github.com/minio/minio/cmd...
|
- go test -timeout 17m -race github.com/minio/minio/cmd...
|
||||||
- go test -race github.com/minio/minio/pkg...
|
- go test -race github.com/minio/minio/pkg...
|
||||||
- go test -coverprofile=build\coverage\coverage.txt -covermode=atomic github.com/minio/minio/cmd
|
- go test -coverprofile=build\coverage\coverage.txt -covermode=atomic github.com/minio/minio/cmd
|
||||||
- ps: Update-AppveyorTest "Unit Tests" -Outcome Passed
|
- ps: Update-AppveyorTest "Unit Tests" -Outcome Passed
|
||||||
|
@ -249,10 +249,12 @@ func (web *webAPIHandlers) ListObjects(r *http.Request, args *ListObjectsArgs, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RemoveObjectArgs - args to remove an object
|
// RemoveObjectArgs - args to remove an object
|
||||||
|
// JSON will look like:
|
||||||
|
// '{"bucketname":"testbucket","prefix":"john/pics/","objects":["hawaii/","maldives/","sanjose.jpg"]}'
|
||||||
type RemoveObjectArgs struct {
|
type RemoveObjectArgs struct {
|
||||||
TargetHost string `json:"targetHost"`
|
Objects []string `json:"objects"` // can be files or sub-directories
|
||||||
BucketName string `json:"bucketName"`
|
Prefix string `json:"prefix"` // current directory in the browser-ui
|
||||||
ObjectName string `json:"objectName"`
|
BucketName string `json:"bucketname"` // bucket name.
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveObject - removes an object.
|
// RemoveObject - removes an object.
|
||||||
@ -264,31 +266,65 @@ func (web *webAPIHandlers) RemoveObject(r *http.Request, args *RemoveObjectArgs,
|
|||||||
if !isHTTPRequestValid(r) {
|
if !isHTTPRequestValid(r) {
|
||||||
return toJSONError(errAuthentication)
|
return toJSONError(errAuthentication)
|
||||||
}
|
}
|
||||||
|
if args.BucketName == "" || len(args.Objects) == 0 {
|
||||||
objectLock := globalNSMutex.NewNSLock(args.BucketName, args.ObjectName)
|
return toJSONError(errUnexpected)
|
||||||
objectLock.Lock()
|
}
|
||||||
defer objectLock.Unlock()
|
var err error
|
||||||
|
objectLoop:
|
||||||
if err := objectAPI.DeleteObject(args.BucketName, args.ObjectName); err != nil {
|
for _, object := range args.Objects {
|
||||||
if isErrObjectNotFound(err) {
|
remove := func(objectName string) error {
|
||||||
// Ignore object not found error.
|
objectLock := globalNSMutex.NewNSLock(args.BucketName, objectName)
|
||||||
reply.UIVersion = browser.UIVersion
|
objectLock.Lock()
|
||||||
return nil
|
defer objectLock.Unlock()
|
||||||
|
err = objectAPI.DeleteObject(args.BucketName, objectName)
|
||||||
|
if err == nil {
|
||||||
|
// Notify object deleted event.
|
||||||
|
eventNotify(eventData{
|
||||||
|
Type: ObjectRemovedDelete,
|
||||||
|
Bucket: args.BucketName,
|
||||||
|
ObjInfo: ObjectInfo{
|
||||||
|
Name: objectName,
|
||||||
|
},
|
||||||
|
ReqParams: map[string]string{
|
||||||
|
"sourceIPAddress": r.RemoteAddr,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !hasSuffix(object, slashSeparator) {
|
||||||
|
// If not a directory, compress the file and write it to response.
|
||||||
|
err = remove(pathJoin(args.Prefix, object))
|
||||||
|
if err != nil {
|
||||||
|
break objectLoop
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// For directories, list the contents recursively and remove.
|
||||||
|
marker := ""
|
||||||
|
for {
|
||||||
|
var lo ListObjectsInfo
|
||||||
|
lo, err = objectAPI.ListObjects(args.BucketName, pathJoin(args.Prefix, object), marker, "", 1000)
|
||||||
|
if err != nil {
|
||||||
|
break objectLoop
|
||||||
|
}
|
||||||
|
marker = lo.NextMarker
|
||||||
|
for _, obj := range lo.Objects {
|
||||||
|
err = remove(obj.Name)
|
||||||
|
if err != nil {
|
||||||
|
break objectLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !lo.IsTruncated {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return toJSONError(err, args.BucketName, args.ObjectName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify object deleted event.
|
if err != nil && !isErrObjectNotFound(err) {
|
||||||
eventNotify(eventData{
|
// Ignore object not found error.
|
||||||
Type: ObjectRemovedDelete,
|
return toJSONError(err, args.BucketName, "")
|
||||||
Bucket: args.BucketName,
|
}
|
||||||
ObjInfo: ObjectInfo{
|
|
||||||
Name: args.ObjectName,
|
|
||||||
},
|
|
||||||
ReqParams: map[string]string{
|
|
||||||
"sourceIPAddress": r.RemoteAddr,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
reply.UIVersion = browser.UIVersion
|
reply.UIVersion = browser.UIVersion
|
||||||
return nil
|
return nil
|
||||||
|
@ -468,7 +468,14 @@ func testRemoveObjectWebHandler(obj ObjectLayer, instanceType string, t TestErrH
|
|||||||
t.Fatalf("Was not able to upload an object, %v", err)
|
t.Fatalf("Was not able to upload an object, %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
removeObjectRequest := RemoveObjectArgs{BucketName: bucketName, ObjectName: objectName}
|
objectName = "a/object"
|
||||||
|
_, err = obj.PutObject(bucketName, objectName, int64(len(data)), bytes.NewReader(data),
|
||||||
|
map[string]string{"md5Sum": "c9a34cfc85d982698c6ac89f76071abd"}, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Was not able to upload an object, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
removeObjectRequest := RemoveObjectArgs{BucketName: bucketName, Prefix: "", Objects: []string{"a/", "object"}}
|
||||||
removeObjectReply := &WebGenericRep{}
|
removeObjectReply := &WebGenericRep{}
|
||||||
req, err := newTestWebRPCRequest("Web.RemoveObject", authorization, removeObjectRequest)
|
req, err := newTestWebRPCRequest("Web.RemoveObject", authorization, removeObjectRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -483,7 +490,7 @@ func testRemoveObjectWebHandler(obj ObjectLayer, instanceType string, t TestErrH
|
|||||||
t.Fatalf("Failed, %v", err)
|
t.Fatalf("Failed, %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
removeObjectRequest = RemoveObjectArgs{BucketName: bucketName, ObjectName: objectName}
|
removeObjectRequest = RemoveObjectArgs{BucketName: bucketName, Prefix: "", Objects: []string{"a/", "object"}}
|
||||||
removeObjectReply = &WebGenericRep{}
|
removeObjectReply = &WebGenericRep{}
|
||||||
req, err = newTestWebRPCRequest("Web.RemoveObject", authorization, removeObjectRequest)
|
req, err = newTestWebRPCRequest("Web.RemoveObject", authorization, removeObjectRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user