Moto: S3 DeleteObjects Operation issue in Moto results failure in LocalStack

Created on 30 Apr 2020  路  2Comments  路  Source: spulec/moto

Sending a DeleteObjects request from AWS Go SDK to localStack ( set to latest, so fetched moto-ext>=1.3.15.12) results is 500 error.

DeleteObject operation works successfully, it's the DeleteObjects that fails. Looking into the difference between the request payload (AWS Go SDK github.com/aws/aws-sdk-go v1.28.6):

DeleteObject:
op := &request.Operation{ Name: opDeleteObject, HTTPMethod: "DELETE", HTTPPath: "/{Bucket}/{Key+}", }

Where const opDeleteObject = "DeleteObject"

DeleteObjects
op := &request.Operation{ Name: opDeleteObjects, HTTPMethod: "POST", HTTPPath: "/{Bucket}?delete", }

Where const opDeleteObjects = "DeleteObjects"

In _bucket_response_delete_keys method of class ResponseObject *_line 843_ the check is:
objects = body_dict["Delete"].get("Object", [])
*

In case of DeleteObjects the key is "Objects", so objects variable will be []

Note the difference between how each of these operations is called:

DeleteObject

_, err := s.Client.DeleteObject(&s3.DeleteObjectInput{Bucket: aws.String(bucket), Key: aws.String(key)})
DeleteObjects
_, err := s.Client.DeleteObjects(&s3.DeleteObjectsInput{Bucket: aws.String(bucket), Delete: &s3.Delete{ Objects: keys, Quiet: aws.Bool(false), }})

the Delete struct has a field Objects instead of Object
Objects []*ObjectIdentifierlocationName:"Object" type:"list" flattened:"true" required:"true"

#

How to replicate:

Place some files in 'examplebucket'
call the DeleteObjects (code from AWS Docs) which the keys:

`svc := s3.New(session.New())
input := &s3.DeleteObjectsInput{
Bucket: aws.String("examplebucket"),
Delete: &s3.Delete{
Objects: []*s3.ObjectIdentifier{
{
Key: aws.String("objectkey1"),
},
{
Key: aws.String("objectkey2"),
},
},
Quiet: aws.Bool(false),
},
}

result, err := svc.DeleteObjects(input)
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
switch aerr.Code() {
default:
fmt.Println(aerr.Error())
}
} else {
// Print the error, cast err to awserr.Error to get the Code and
// Message from an error.
fmt.Println(err.Error())
}
return
}

fmt.Println(result)
}`

bug

All 2 comments

Hi @Nasrin-Shiraly, thanks for raising this.
We have a unit test where we use the correct request: client.delete_objects( Bucket="blah", Delete={"Objects": [{"Key": "test1", "VersionId": id_to_delete}]} ), which works as it should.
So I'm a little confused 1) why our unit test works, and 2) why yours doesn't.

Will mark it as debugging for now - I'll try to have a look today

It's officially a bug, due to a slight difference in how the HTTP requests are formatted by the Python and GoLang lib. See the attached PR for more info

Was this page helpful?
0 / 5 - 0 ratings

Related issues

VictorHiroshi picture VictorHiroshi  路  3Comments

dazza-codes picture dazza-codes  路  3Comments

sturmer picture sturmer  路  3Comments

muhammad-ammar picture muhammad-ammar  路  3Comments

sunilkumarmohanty picture sunilkumarmohanty  路  5Comments