fix: return better error when trying to delete non empty directory object

The posix backend will return ENOTEMPTY when trying to delete a
directory that is not empty. This normally would run successfully
on object systems. So we need to create another non-standard error
for this case. We mainly just don't want to return InternalError
for this case.

Fixes #946
This commit is contained in:
Ben McClelland
2024-11-14 22:33:08 -08:00
parent a26f069c53
commit db305142f1
4 changed files with 42 additions and 0 deletions
+3
View File
@@ -2646,6 +2646,9 @@ func (p *Posix) DeleteObject(ctx context.Context, input *s3.DeleteObjectInput) (
if errors.Is(err, fs.ErrNotExist) {
return nil, s3err.GetAPIError(s3err.ErrNoSuchKey)
}
if errors.Is(err, syscall.ENOTEMPTY) {
return nil, s3err.GetAPIError(s3err.ErrDirectoryNotEmpty)
}
if err != nil {
return nil, fmt.Errorf("delete object: %w", err)
}
+6
View File
@@ -144,6 +144,7 @@ const (
ErrExistingObjectIsDirectory
ErrObjectParentIsFile
ErrDirectoryObjectContainsData
ErrDirectoryNotEmpty
ErrQuotaExceeded
ErrVersioningNotConfigured
@@ -593,6 +594,11 @@ var errorCodeResponse = map[ErrorCode]APIError{
Description: "Directory object contains data payload.",
HTTPStatusCode: http.StatusBadRequest,
},
ErrDirectoryNotEmpty: {
Code: "ErrDirectoryNotEmpty",
Description: "Directory object not empty.",
HTTPStatusCode: http.StatusBadRequest,
},
ErrQuotaExceeded: {
Code: "QuotaExceeded",
Description: "Your request was denied due to quota exceeded.",
+2
View File
@@ -519,6 +519,7 @@ func TestPosix(s *S3Conf) {
PutObject_name_too_long(s)
HeadObject_name_too_long(s)
DeleteObject_name_too_long(s)
DeleteObject_directory_not_empty(s)
// posix specific versioning tests
if !s.versioningEnabled {
TestVersioningDisabled(s)
@@ -770,6 +771,7 @@ func GetIntTests() IntTests {
"ListObjectVersions_VD_success": ListObjectVersions_VD_success,
"DeleteObject_non_existing_object": DeleteObject_non_existing_object,
"DeleteObject_directory_object_noslash": DeleteObject_directory_object_noslash,
"DeleteObject_directory_not_empty": DeleteObject_directory_not_empty,
"DeleteObject_name_too_long": DeleteObject_name_too_long,
"DeleteObject_non_existing_dir_object": DeleteObject_non_existing_dir_object,
"DeleteObject_success": DeleteObject_success,
+31
View File
@@ -4749,6 +4749,37 @@ func DeleteObject_directory_object_noslash(s *S3Conf) error {
})
}
func DeleteObject_directory_not_empty(s *S3Conf) error {
testName := "DeleteObject_directory_not_empty"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {
obj := "dir/my-obj"
ctx, cancel := context.WithTimeout(context.Background(), shortTimeout)
_, err := s3client.PutObject(ctx, &s3.PutObjectInput{
Bucket: &bucket,
Key: &obj,
})
cancel()
if err != nil {
return err
}
obj = "dir/"
ctx, cancel = context.WithTimeout(context.Background(), shortTimeout)
_, err = s3client.DeleteObject(ctx, &s3.DeleteObjectInput{
Bucket: &bucket,
Key: &obj,
})
cancel()
// object servers will return no error, but the posix backend returns
// a non-standard directory not empty. This test is a posix only test
// to validate the specific error response.
if err := checkApiErr(err, s3err.GetAPIError(s3err.ErrDirectoryNotEmpty)); err != nil {
return err
}
return nil
})
}
func DeleteObject_non_existing_dir_object(s *S3Conf) error {
testName := "DeleteObject_non_existing_dir_object"
return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {