mirror of
https://github.com/versity/versitygw.git
synced 2026-01-04 11:03:57 +00:00
feat: add s3err QuotaExceeded for posix/scoutfs
When fileystem quota exceeded, the gateway will now return the error: S3 error: 403 (QuotaExceeded): Your request was denied due to quota exceeded. This will help clients to better detect upload errors due to quota exceeded. Fixes #483
This commit is contained in:
@@ -419,6 +419,9 @@ func (p *Posix) CompleteMultipartUpload(ctx context.Context, input *s3.CompleteM
|
||||
f, err := p.openTmpFile(filepath.Join(bucket, metaTmpDir), bucket, object,
|
||||
totalsize, acct)
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
return nil, fmt.Errorf("open temp file: %w", err)
|
||||
}
|
||||
defer f.cleanup()
|
||||
@@ -431,6 +434,9 @@ func (p *Posix) CompleteMultipartUpload(ctx context.Context, input *s3.CompleteM
|
||||
_, err = io.Copy(f, pf)
|
||||
pf.Close()
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
return nil, fmt.Errorf("copy part %v: %v", p.PartNumber, err)
|
||||
}
|
||||
}
|
||||
@@ -910,6 +916,9 @@ func (p *Posix) UploadPart(ctx context.Context, input *s3.UploadPartInput) (stri
|
||||
f, err := p.openTmpFile(filepath.Join(bucket, objdir),
|
||||
bucket, partPath, length, acct)
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return "", s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
return "", fmt.Errorf("open temp file: %w", err)
|
||||
}
|
||||
|
||||
@@ -917,6 +926,9 @@ func (p *Posix) UploadPart(ctx context.Context, input *s3.UploadPartInput) (stri
|
||||
tr := io.TeeReader(r, hash)
|
||||
_, err = io.Copy(f, tr)
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return "", s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
return "", fmt.Errorf("write part data: %w", err)
|
||||
}
|
||||
|
||||
@@ -1009,6 +1021,9 @@ func (p *Posix) UploadPartCopy(ctx context.Context, upi *s3.UploadPartCopyInput)
|
||||
f, err := p.openTmpFile(filepath.Join(*upi.Bucket, objdir),
|
||||
*upi.Bucket, partPath, length, acct)
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return s3response.CopyObjectResult{}, s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
return s3response.CopyObjectResult{}, fmt.Errorf("open temp file: %w", err)
|
||||
}
|
||||
defer f.cleanup()
|
||||
@@ -1028,6 +1043,9 @@ func (p *Posix) UploadPartCopy(ctx context.Context, upi *s3.UploadPartCopyInput)
|
||||
|
||||
_, err = io.Copy(f, tr)
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return s3response.CopyObjectResult{}, s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
return s3response.CopyObjectResult{}, fmt.Errorf("copy part data: %w", err)
|
||||
}
|
||||
|
||||
@@ -1107,6 +1125,9 @@ func (p *Posix) PutObject(ctx context.Context, po *s3.PutObjectInput) (string, e
|
||||
|
||||
err = backend.MkdirAll(name, uid, gid, doChown)
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return "", s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -1129,6 +1150,9 @@ func (p *Posix) PutObject(ctx context.Context, po *s3.PutObjectInput) (string, e
|
||||
f, err := p.openTmpFile(filepath.Join(*po.Bucket, metaTmpDir),
|
||||
*po.Bucket, *po.Key, contentLength, acct)
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return "", s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
return "", fmt.Errorf("open temp file: %w", err)
|
||||
}
|
||||
defer f.cleanup()
|
||||
@@ -1137,6 +1161,9 @@ func (p *Posix) PutObject(ctx context.Context, po *s3.PutObjectInput) (string, e
|
||||
rdr := io.TeeReader(po.Body, hash)
|
||||
_, err = io.Copy(f, rdr)
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return "", s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
return "", fmt.Errorf("write object data: %w", err)
|
||||
}
|
||||
dir := filepath.Dir(name)
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
@@ -222,6 +223,9 @@ func (s *ScoutFS) CompleteMultipartUpload(ctx context.Context, input *s3.Complet
|
||||
// extents around. so we dont want to fallocate this.
|
||||
f, err := s.openTmpFile(filepath.Join(bucket, metaTmpDir), bucket, object, 0, acct)
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
return nil, fmt.Errorf("open temp file: %w", err)
|
||||
}
|
||||
defer f.cleanup()
|
||||
|
||||
@@ -116,6 +116,7 @@ const (
|
||||
ErrExistingObjectIsDirectory
|
||||
ErrObjectParentIsFile
|
||||
ErrDirectoryObjectContainsData
|
||||
ErrQuotaExceeded
|
||||
)
|
||||
|
||||
var errorCodeResponse = map[ErrorCode]APIError{
|
||||
@@ -414,6 +415,11 @@ var errorCodeResponse = map[ErrorCode]APIError{
|
||||
Description: "Directory object contains data payload.",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrQuotaExceeded: {
|
||||
Code: "QuotaExceeded",
|
||||
Description: "Your request was denied due to quota exceeded.",
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
},
|
||||
}
|
||||
|
||||
// GetAPIError provides API Error for input API error code.
|
||||
|
||||
Reference in New Issue
Block a user