forked from TrueCloudLab/frostfs-s3-gw
[#13] Rename go module name according to NSPCC standards
- refactoring s3 gate structure - cleanup unused code - rename go module to `github.com/nspcc-dev/neofs-s3-gate` closes #13 Signed-off-by: Evgeniy Kulikov <kim@nspcc.ru>
This commit is contained in:
parent
e7f72fc670
commit
0161d2fbd3
25 changed files with 396 additions and 1112 deletions
|
@ -2,15 +2,9 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"path"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/minio/minio-go/v7/pkg/tags"
|
|
||||||
"github.com/minio/minio/auth"
|
|
||||||
"github.com/minio/minio/neofs/api/crypto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -24,7 +18,7 @@ const maxEConfigJSONSize = 262272
|
||||||
|
|
||||||
// Error codes, non exhaustive list - http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
|
// Error codes, non exhaustive list - http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
|
||||||
const (
|
const (
|
||||||
ErrNone ErrorCode = iota
|
_ ErrorCode = iota
|
||||||
ErrAccessDenied
|
ErrAccessDenied
|
||||||
ErrBadDigest
|
ErrBadDigest
|
||||||
ErrEntityTooSmall
|
ErrEntityTooSmall
|
||||||
|
@ -1096,7 +1090,7 @@ var errorCodes = errorCodeMap{
|
||||||
},
|
},
|
||||||
ErrObjectTampered: {
|
ErrObjectTampered: {
|
||||||
Code: "XMinioObjectTampered",
|
Code: "XMinioObjectTampered",
|
||||||
Description: errObjectTampered.Error(),
|
Description: "The requested object was modified and may be compromised",
|
||||||
HTTPStatusCode: http.StatusPartialContent,
|
HTTPStatusCode: http.StatusPartialContent,
|
||||||
},
|
},
|
||||||
ErrMaximumExpires: {
|
ErrMaximumExpires: {
|
||||||
|
@ -1618,300 +1612,6 @@ func (e errorCodeMap) ToAPIErr(errCode ErrorCode) Error {
|
||||||
return e.ToAPIErrWithErr(errCode, nil)
|
return e.ToAPIErrWithErr(errCode, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// toAPIErrorCode - Converts embedded errors. Convenience
|
|
||||||
// function written to handle all cases where we have known types of
|
|
||||||
// errors returned by underlying layers.
|
|
||||||
func toAPIErrorCode(_ context.Context, err error) (apiErr ErrorCode) {
|
|
||||||
if err == nil {
|
|
||||||
return ErrNone
|
|
||||||
}
|
|
||||||
|
|
||||||
switch err {
|
|
||||||
case errInvalidArgument:
|
|
||||||
apiErr = ErrAdminInvalidArgument
|
|
||||||
case errNoSuchUser:
|
|
||||||
apiErr = ErrAdminNoSuchUser
|
|
||||||
case errNoSuchGroup:
|
|
||||||
apiErr = ErrAdminNoSuchGroup
|
|
||||||
case errGroupNotEmpty:
|
|
||||||
apiErr = ErrAdminGroupNotEmpty
|
|
||||||
case errNoSuchPolicy:
|
|
||||||
apiErr = ErrAdminNoSuchPolicy
|
|
||||||
case errSignatureMismatch:
|
|
||||||
apiErr = ErrSignatureDoesNotMatch
|
|
||||||
case errInvalidRange:
|
|
||||||
apiErr = ErrInvalidRange
|
|
||||||
case errDataTooLarge:
|
|
||||||
apiErr = ErrEntityTooLarge
|
|
||||||
case errDataTooSmall:
|
|
||||||
apiErr = ErrEntityTooSmall
|
|
||||||
case errAuthentication:
|
|
||||||
apiErr = ErrAccessDenied
|
|
||||||
case auth.ErrInvalidAccessKeyLength:
|
|
||||||
apiErr = ErrAdminInvalidAccessKey
|
|
||||||
case auth.ErrInvalidSecretKeyLength:
|
|
||||||
apiErr = ErrAdminInvalidSecretKey
|
|
||||||
// SSE errors
|
|
||||||
case errInvalidEncryptionParameters:
|
|
||||||
apiErr = ErrInvalidEncryptionParameters
|
|
||||||
case crypto.ErrInvalidEncryptionMethod:
|
|
||||||
apiErr = ErrInvalidEncryptionMethod
|
|
||||||
case crypto.ErrInvalidCustomerAlgorithm:
|
|
||||||
apiErr = ErrInvalidSSECustomerAlgorithm
|
|
||||||
case crypto.ErrMissingCustomerKey:
|
|
||||||
apiErr = ErrMissingSSECustomerKey
|
|
||||||
case crypto.ErrMissingCustomerKeyMD5:
|
|
||||||
apiErr = ErrMissingSSECustomerKeyMD5
|
|
||||||
case crypto.ErrCustomerKeyMD5Mismatch:
|
|
||||||
apiErr = ErrSSECustomerKeyMD5Mismatch
|
|
||||||
case errObjectTampered:
|
|
||||||
apiErr = ErrObjectTampered
|
|
||||||
case errEncryptedObject:
|
|
||||||
apiErr = ErrSSEEncryptedObject
|
|
||||||
case errInvalidSSEParameters:
|
|
||||||
apiErr = ErrInvalidSSECustomerParameters
|
|
||||||
case crypto.ErrInvalidCustomerKey, crypto.ErrSecretKeyMismatch:
|
|
||||||
apiErr = ErrAccessDenied // no access without correct key
|
|
||||||
case crypto.ErrIncompatibleEncryptionMethod:
|
|
||||||
apiErr = ErrIncompatibleEncryptionMethod
|
|
||||||
case errKMSNotConfigured:
|
|
||||||
apiErr = ErrKMSNotConfigured
|
|
||||||
case crypto.ErrKMSAuthLogin:
|
|
||||||
apiErr = ErrKMSAuthFailure
|
|
||||||
case context.Canceled, context.DeadlineExceeded:
|
|
||||||
apiErr = ErrOperationTimedOut
|
|
||||||
case errDiskNotFound:
|
|
||||||
apiErr = ErrSlowDown
|
|
||||||
// case objectlock.ErrInvalidRetentionDate:
|
|
||||||
// apiErr = ErrInvalidRetentionDate
|
|
||||||
// case objectlock.ErrPastObjectLockRetainDate:
|
|
||||||
// apiErr = ErrPastObjectLockRetainDate
|
|
||||||
// case objectlock.ErrUnknownWORMModeDirective:
|
|
||||||
// apiErr = ErrUnknownWORMModeDirective
|
|
||||||
// case objectlock.ErrObjectLockInvalidHeaders:
|
|
||||||
// apiErr = ErrObjectLockInvalidHeaders
|
|
||||||
// case objectlock.ErrMalformedXML:
|
|
||||||
// apiErr = ErrMalformedXML
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compression errors
|
|
||||||
switch err {
|
|
||||||
case errInvalidDecompressedSize:
|
|
||||||
apiErr = ErrInvalidDecompressedSize
|
|
||||||
}
|
|
||||||
|
|
||||||
if apiErr != ErrNone {
|
|
||||||
// If there was a match in the above switch case.
|
|
||||||
return apiErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// etcd specific errors, a key is always a bucket for us return
|
|
||||||
// ErrNoSuchBucket in such a case.
|
|
||||||
if err == ErrNoEntriesFound {
|
|
||||||
return ErrNoSuchBucket
|
|
||||||
}
|
|
||||||
|
|
||||||
switch err.(type) {
|
|
||||||
case StorageFull:
|
|
||||||
apiErr = ErrStorageFull
|
|
||||||
// case hash.BadDigest:
|
|
||||||
// apiErr = ErrBadDigest
|
|
||||||
case AllAccessDisabled:
|
|
||||||
apiErr = ErrAllAccessDisabled
|
|
||||||
case IncompleteBody:
|
|
||||||
apiErr = ErrIncompleteBody
|
|
||||||
case ObjectExistsAsDirectory:
|
|
||||||
apiErr = ErrObjectExistsAsDirectory
|
|
||||||
case PrefixAccessDenied:
|
|
||||||
apiErr = ErrAccessDenied
|
|
||||||
case ParentIsObject:
|
|
||||||
apiErr = ErrParentIsObject
|
|
||||||
case BucketNameInvalid:
|
|
||||||
apiErr = ErrInvalidBucketName
|
|
||||||
case BucketNotFound:
|
|
||||||
apiErr = ErrNoSuchBucket
|
|
||||||
case BucketAlreadyOwnedByYou:
|
|
||||||
apiErr = ErrBucketAlreadyOwnedByYou
|
|
||||||
case BucketNotEmpty:
|
|
||||||
apiErr = ErrBucketNotEmpty
|
|
||||||
case BucketAlreadyExists:
|
|
||||||
apiErr = ErrBucketAlreadyExists
|
|
||||||
case BucketExists:
|
|
||||||
apiErr = ErrBucketAlreadyOwnedByYou
|
|
||||||
case ObjectNotFound:
|
|
||||||
apiErr = ErrNoSuchKey
|
|
||||||
case ObjectAlreadyExists:
|
|
||||||
apiErr = ErrMethodNotAllowed
|
|
||||||
case ObjectNameInvalid:
|
|
||||||
apiErr = ErrInvalidObjectName
|
|
||||||
case ObjectNamePrefixAsSlash:
|
|
||||||
apiErr = ErrInvalidObjectNamePrefixSlash
|
|
||||||
case InvalidUploadID:
|
|
||||||
apiErr = ErrNoSuchUpload
|
|
||||||
case InvalidPart:
|
|
||||||
apiErr = ErrInvalidPart
|
|
||||||
case InsufficientWriteQuorum:
|
|
||||||
apiErr = ErrSlowDown
|
|
||||||
case InsufficientReadQuorum:
|
|
||||||
apiErr = ErrSlowDown
|
|
||||||
case UnsupportedDelimiter:
|
|
||||||
apiErr = ErrNotImplemented
|
|
||||||
case InvalidMarkerPrefixCombination:
|
|
||||||
apiErr = ErrNotImplemented
|
|
||||||
case InvalidUploadIDKeyCombination:
|
|
||||||
apiErr = ErrNotImplemented
|
|
||||||
case MalformedUploadID:
|
|
||||||
apiErr = ErrNoSuchUpload
|
|
||||||
case PartTooSmall:
|
|
||||||
apiErr = ErrEntityTooSmall
|
|
||||||
case SignatureDoesNotMatch:
|
|
||||||
apiErr = ErrSignatureDoesNotMatch
|
|
||||||
// case hash.SHA256Mismatch:
|
|
||||||
// apiErr = ErrContentSHA256Mismatch
|
|
||||||
case ObjectTooLarge:
|
|
||||||
apiErr = ErrEntityTooLarge
|
|
||||||
case ObjectTooSmall:
|
|
||||||
apiErr = ErrEntityTooSmall
|
|
||||||
case NotImplemented:
|
|
||||||
apiErr = ErrNotImplemented
|
|
||||||
case PartTooBig:
|
|
||||||
apiErr = ErrEntityTooLarge
|
|
||||||
case UnsupportedMetadata:
|
|
||||||
apiErr = ErrUnsupportedMetadata
|
|
||||||
case BucketPolicyNotFound:
|
|
||||||
apiErr = ErrNoSuchBucketPolicy
|
|
||||||
case BucketLifecycleNotFound:
|
|
||||||
apiErr = ErrNoSuchLifecycleConfiguration
|
|
||||||
case BucketSSEConfigNotFound:
|
|
||||||
apiErr = ErrNoSuchBucketSSEConfig
|
|
||||||
case BucketTaggingNotFound:
|
|
||||||
apiErr = ErrBucketTaggingNotFound
|
|
||||||
case BucketObjectLockConfigNotFound:
|
|
||||||
apiErr = ErrObjectLockConfigurationNotFound
|
|
||||||
case BucketQuotaConfigNotFound:
|
|
||||||
apiErr = ErrAdminNoSuchQuotaConfiguration
|
|
||||||
case BucketQuotaExceeded:
|
|
||||||
apiErr = ErrAdminBucketQuotaExceeded
|
|
||||||
// case *event.ErrInvalidEventName:
|
|
||||||
// apiErr = ErrEventNotification
|
|
||||||
// case *event.ErrInvalidARN:
|
|
||||||
// apiErr = ErrARNNotification
|
|
||||||
// case *event.ErrARNNotFound:
|
|
||||||
// apiErr = ErrARNNotification
|
|
||||||
// case *event.ErrUnknownRegion:
|
|
||||||
// apiErr = ErrRegionNotification
|
|
||||||
// case *event.ErrInvalidFilterName:
|
|
||||||
// apiErr = ErrFilterNameInvalid
|
|
||||||
// case *event.ErrFilterNamePrefix:
|
|
||||||
// apiErr = ErrFilterNamePrefix
|
|
||||||
// case *event.ErrFilterNameSuffix:
|
|
||||||
// apiErr = ErrFilterNameSuffix
|
|
||||||
// case *event.ErrInvalidFilterValue:
|
|
||||||
// apiErr = ErrFilterValueInvalid
|
|
||||||
// case *event.ErrDuplicateEventName:
|
|
||||||
// apiErr = ErrOverlappingConfigs
|
|
||||||
// case *event.ErrDuplicateQueueConfiguration:
|
|
||||||
// apiErr = ErrOverlappingFilterNotification
|
|
||||||
// case *event.ErrUnsupportedConfiguration:
|
|
||||||
// apiErr = ErrUnsupportedNotification
|
|
||||||
case OperationTimedOut:
|
|
||||||
apiErr = ErrOperationTimedOut
|
|
||||||
case BackendDown:
|
|
||||||
apiErr = ErrBackendDown
|
|
||||||
case ObjectNameTooLong:
|
|
||||||
apiErr = ErrKeyTooLongError
|
|
||||||
default:
|
|
||||||
var ie, iw int
|
|
||||||
// This work-around is to handle the issue golang/go#30648
|
|
||||||
if _, ferr := fmt.Fscanf(strings.NewReader(err.Error()),
|
|
||||||
"request declared a Content-Length of %d but only wrote %d bytes",
|
|
||||||
&ie, &iw); ferr != nil {
|
|
||||||
apiErr = ErrInternalError
|
|
||||||
// Make sure to log the errors which we cannot translate
|
|
||||||
// to a meaningful S3 API errors. This is added to aid in
|
|
||||||
// debugging unexpected/unhandled errors.
|
|
||||||
// logger.LogIf(ctx, err)
|
|
||||||
} else if ie > iw {
|
|
||||||
apiErr = ErrIncompleteBody
|
|
||||||
} else {
|
|
||||||
apiErr = ErrInternalError
|
|
||||||
// Make sure to log the errors which we cannot translate
|
|
||||||
// to a meaningful S3 API errors. This is added to aid in
|
|
||||||
// debugging unexpected/unhandled errors.
|
|
||||||
// logger.LogIf(ctx, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return apiErr
|
|
||||||
}
|
|
||||||
|
|
||||||
var noError = Error{}
|
|
||||||
|
|
||||||
// toAPIError - Converts embedded errors. Convenience
|
|
||||||
// function written to handle all cases where we have known types of
|
|
||||||
// errors returned by underlying layers.
|
|
||||||
func toAPIError(ctx context.Context, err error) Error {
|
|
||||||
if err == nil {
|
|
||||||
return noError
|
|
||||||
}
|
|
||||||
|
|
||||||
var apiErr = errorCodes.ToAPIErr(toAPIErrorCode(ctx, err))
|
|
||||||
if apiErr.Code == "InternalError" {
|
|
||||||
// If we see an internal error try to interpret
|
|
||||||
// any underlying errors if possible depending on
|
|
||||||
// their internal error types. This code is only
|
|
||||||
// useful with gateway implementations.
|
|
||||||
switch e := err.(type) {
|
|
||||||
case *xml.SyntaxError:
|
|
||||||
apiErr = Error{
|
|
||||||
Code: "MalformedXML",
|
|
||||||
Description: fmt.Sprintf("%s (%s)", errorCodes[ErrMalformedXML].Description,
|
|
||||||
e.Error()),
|
|
||||||
HTTPStatusCode: errorCodes[ErrMalformedXML].HTTPStatusCode,
|
|
||||||
}
|
|
||||||
case url.EscapeError:
|
|
||||||
apiErr = Error{
|
|
||||||
Code: "XMinioInvalidObjectName",
|
|
||||||
Description: fmt.Sprintf("%s (%s)", errorCodes[ErrInvalidObjectName].Description,
|
|
||||||
e.Error()),
|
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
|
||||||
}
|
|
||||||
// case lifecycle.Error:
|
|
||||||
// apiErr = Error{
|
|
||||||
// Code: "InvalidRequest",
|
|
||||||
// Description: e.Error(),
|
|
||||||
// HTTPStatusCode: http.StatusBadRequest,
|
|
||||||
// }
|
|
||||||
case tags.Error:
|
|
||||||
apiErr = Error{
|
|
||||||
Code: e.Code(),
|
|
||||||
Description: e.Error(),
|
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
|
||||||
}
|
|
||||||
// case policy.Error:
|
|
||||||
// apiErr = Error{
|
|
||||||
// Code: "MalformedPolicy",
|
|
||||||
// Description: e.Error(),
|
|
||||||
// HTTPStatusCode: http.StatusBadRequest,
|
|
||||||
// }
|
|
||||||
case crypto.Error:
|
|
||||||
apiErr = Error{
|
|
||||||
Code: "XMinIOEncryptionError",
|
|
||||||
Description: e.Error(),
|
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
|
||||||
}
|
|
||||||
case ErrorResponse:
|
|
||||||
apiErr = Error{
|
|
||||||
Code: e.Code,
|
|
||||||
Description: e.Message,
|
|
||||||
HTTPStatusCode: e.StatusCode,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return apiErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAPIError provides API Error for input API error code.
|
// GetAPIError provides API Error for input API error code.
|
||||||
func GetAPIError(code ErrorCode) Error {
|
func GetAPIError(code ErrorCode) Error {
|
||||||
if apiErr, ok := errorCodes[code]; ok {
|
if apiErr, ok := errorCodes[code]; ok {
|
||||||
|
@ -1930,8 +1630,366 @@ func getAPIErrorResponse(ctx context.Context, err Error, resource, requestID, ho
|
||||||
BucketName: reqInfo.BucketName,
|
BucketName: reqInfo.BucketName,
|
||||||
Key: reqInfo.ObjectName,
|
Key: reqInfo.ObjectName,
|
||||||
Resource: resource,
|
Resource: resource,
|
||||||
Region: "",
|
|
||||||
RequestID: requestID,
|
RequestID: requestID,
|
||||||
HostID: hostID,
|
HostID: hostID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SignatureDoesNotMatch - when content md5 does not match with what was sent from client.
|
||||||
|
type SignatureDoesNotMatch struct{}
|
||||||
|
|
||||||
|
func (e SignatureDoesNotMatch) Error() string {
|
||||||
|
return "The request signature we calculated does not match the signature you provided. Check your key and signing method."
|
||||||
|
}
|
||||||
|
|
||||||
|
// StorageFull storage ran out of space.
|
||||||
|
type StorageFull struct{}
|
||||||
|
|
||||||
|
func (e StorageFull) Error() string {
|
||||||
|
return "Storage reached its minimum free disk threshold."
|
||||||
|
}
|
||||||
|
|
||||||
|
// SlowDown too many file descriptors open or backend busy .
|
||||||
|
type SlowDown struct{}
|
||||||
|
|
||||||
|
func (e SlowDown) Error() string {
|
||||||
|
return "Please reduce your request rate"
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsufficientReadQuorum storage cannot satisfy quorum for read operation.
|
||||||
|
type InsufficientReadQuorum struct{}
|
||||||
|
|
||||||
|
func (e InsufficientReadQuorum) Error() string {
|
||||||
|
return "Storage resources are insufficient for the read operation."
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsufficientWriteQuorum storage cannot satisfy quorum for write operation.
|
||||||
|
type InsufficientWriteQuorum struct{}
|
||||||
|
|
||||||
|
func (e InsufficientWriteQuorum) Error() string {
|
||||||
|
return "Storage resources are insufficient for the write operation."
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenericError - generic object layer error.
|
||||||
|
type GenericError struct {
|
||||||
|
Bucket string
|
||||||
|
Object string
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketNotFound bucket does not exist.
|
||||||
|
type BucketNotFound GenericError
|
||||||
|
|
||||||
|
func (e BucketNotFound) Error() string {
|
||||||
|
return "Bucket not found: " + e.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketAlreadyExists the requested bucket name is not available.
|
||||||
|
type BucketAlreadyExists GenericError
|
||||||
|
|
||||||
|
func (e BucketAlreadyExists) Error() string {
|
||||||
|
return "The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again."
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketAlreadyOwnedByYou already owned by you.
|
||||||
|
type BucketAlreadyOwnedByYou GenericError
|
||||||
|
|
||||||
|
func (e BucketAlreadyOwnedByYou) Error() string {
|
||||||
|
return "Bucket already owned by you: " + e.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketNotEmpty bucket is not empty.
|
||||||
|
type BucketNotEmpty GenericError
|
||||||
|
|
||||||
|
func (e BucketNotEmpty) Error() string {
|
||||||
|
return "Bucket not empty: " + e.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectNotFound object does not exist.
|
||||||
|
type ObjectNotFound GenericError
|
||||||
|
|
||||||
|
func (e ObjectNotFound) Error() string {
|
||||||
|
return "Object not found: " + e.Bucket + "#" + e.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectAlreadyExists object already exists.
|
||||||
|
type ObjectAlreadyExists GenericError
|
||||||
|
|
||||||
|
func (e ObjectAlreadyExists) Error() string {
|
||||||
|
return "Object: " + e.Bucket + "#" + e.Object + " already exists"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectExistsAsDirectory object already exists as a directory.
|
||||||
|
type ObjectExistsAsDirectory GenericError
|
||||||
|
|
||||||
|
func (e ObjectExistsAsDirectory) Error() string {
|
||||||
|
return "Object exists on : " + e.Bucket + " as directory " + e.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrefixAccessDenied object access is denied.
|
||||||
|
type PrefixAccessDenied GenericError
|
||||||
|
|
||||||
|
func (e PrefixAccessDenied) Error() string {
|
||||||
|
return "Prefix access is denied: " + e.Bucket + SlashSeparator + e.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentIsObject object access is denied.
|
||||||
|
type ParentIsObject GenericError
|
||||||
|
|
||||||
|
func (e ParentIsObject) Error() string {
|
||||||
|
return "Parent is object " + e.Bucket + SlashSeparator + path.Dir(e.Object)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketExists bucket exists.
|
||||||
|
type BucketExists GenericError
|
||||||
|
|
||||||
|
func (e BucketExists) Error() string {
|
||||||
|
return "Bucket exists: " + e.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsupportedDelimiter - unsupported delimiter.
|
||||||
|
type UnsupportedDelimiter struct {
|
||||||
|
Delimiter string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e UnsupportedDelimiter) Error() string {
|
||||||
|
return fmt.Sprintf("delimiter '%s' is not supported. Only '/' is supported", e.Delimiter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InvalidUploadIDKeyCombination - invalid upload id and key marker combination.
|
||||||
|
type InvalidUploadIDKeyCombination struct {
|
||||||
|
UploadIDMarker, KeyMarker string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e InvalidUploadIDKeyCombination) Error() string {
|
||||||
|
return fmt.Sprintf("Invalid combination of uploadID marker '%s' and marker '%s'", e.UploadIDMarker, e.KeyMarker)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InvalidMarkerPrefixCombination - invalid marker and prefix combination.
|
||||||
|
type InvalidMarkerPrefixCombination struct {
|
||||||
|
Marker, Prefix string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e InvalidMarkerPrefixCombination) Error() string {
|
||||||
|
return fmt.Sprintf("Invalid combination of marker '%s' and prefix '%s'", e.Marker, e.Prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketPolicyNotFound - no bucket policy found.
|
||||||
|
type BucketPolicyNotFound GenericError
|
||||||
|
|
||||||
|
func (e BucketPolicyNotFound) Error() string {
|
||||||
|
return "No bucket policy configuration found for bucket: " + e.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketLifecycleNotFound - no bucket lifecycle found.
|
||||||
|
type BucketLifecycleNotFound GenericError
|
||||||
|
|
||||||
|
func (e BucketLifecycleNotFound) Error() string {
|
||||||
|
return "No bucket lifecycle configuration found for bucket : " + e.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketSSEConfigNotFound - no bucket encryption found
|
||||||
|
type BucketSSEConfigNotFound GenericError
|
||||||
|
|
||||||
|
func (e BucketSSEConfigNotFound) Error() string {
|
||||||
|
return "No bucket encryption configuration found for bucket: " + e.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketTaggingNotFound - no bucket tags found
|
||||||
|
type BucketTaggingNotFound GenericError
|
||||||
|
|
||||||
|
func (e BucketTaggingNotFound) Error() string {
|
||||||
|
return "No bucket tags found for bucket: " + e.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketObjectLockConfigNotFound - no bucket object lock config found
|
||||||
|
type BucketObjectLockConfigNotFound GenericError
|
||||||
|
|
||||||
|
func (e BucketObjectLockConfigNotFound) Error() string {
|
||||||
|
return "No bucket object lock configuration found for bucket: " + e.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketQuotaConfigNotFound - no bucket quota config found.
|
||||||
|
type BucketQuotaConfigNotFound GenericError
|
||||||
|
|
||||||
|
func (e BucketQuotaConfigNotFound) Error() string {
|
||||||
|
return "No quota config found for bucket : " + e.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// BucketQuotaExceeded - bucket quota exceeded.
|
||||||
|
type BucketQuotaExceeded GenericError
|
||||||
|
|
||||||
|
func (e BucketQuotaExceeded) Error() string {
|
||||||
|
return "Bucket quota exceeded for bucket: " + e.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bucket related errors.
|
||||||
|
|
||||||
|
// BucketNameInvalid - bucketname provided is invalid.
|
||||||
|
type BucketNameInvalid GenericError
|
||||||
|
|
||||||
|
// Error returns string an error formatted as the given text.
|
||||||
|
func (e BucketNameInvalid) Error() string {
|
||||||
|
return "Bucket name invalid: " + e.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object related errors.
|
||||||
|
|
||||||
|
// ObjectNameInvalid - object name provided is invalid.
|
||||||
|
type ObjectNameInvalid GenericError
|
||||||
|
|
||||||
|
// ObjectNameTooLong - object name too long.
|
||||||
|
type ObjectNameTooLong GenericError
|
||||||
|
|
||||||
|
// ObjectNamePrefixAsSlash - object name has a slash as prefix.
|
||||||
|
type ObjectNamePrefixAsSlash GenericError
|
||||||
|
|
||||||
|
// Error returns string an error formatted as the given text.
|
||||||
|
func (e ObjectNameInvalid) Error() string {
|
||||||
|
return "Object name invalid: " + e.Bucket + "#" + e.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns string an error formatted as the given text.
|
||||||
|
func (e ObjectNameTooLong) Error() string {
|
||||||
|
return "Object name too long: " + e.Bucket + "#" + e.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns string an error formatted as the given text.
|
||||||
|
func (e ObjectNamePrefixAsSlash) Error() string {
|
||||||
|
return "Object name contains forward slash as pefix: " + e.Bucket + "#" + e.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllAccessDisabled All access to this object has been disabled
|
||||||
|
type AllAccessDisabled GenericError
|
||||||
|
|
||||||
|
// Error returns string an error formatted as the given text.
|
||||||
|
func (e AllAccessDisabled) Error() string {
|
||||||
|
return "All access to this object has been disabled"
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncompleteBody You did not provide the number of bytes specified by the Content-Length HTTP header.
|
||||||
|
type IncompleteBody GenericError
|
||||||
|
|
||||||
|
// Error returns string an error formatted as the given text.
|
||||||
|
func (e IncompleteBody) Error() string {
|
||||||
|
return e.Bucket + "#" + e.Object + "has incomplete body"
|
||||||
|
}
|
||||||
|
|
||||||
|
// InvalidRange - invalid range typed error.
|
||||||
|
type InvalidRange struct {
|
||||||
|
OffsetBegin int64
|
||||||
|
OffsetEnd int64
|
||||||
|
ResourceSize int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e InvalidRange) Error() string {
|
||||||
|
return fmt.Sprintf("The requested range \"bytes %d-%d/%d\" is not satisfiable.", e.OffsetBegin, e.OffsetEnd, e.ResourceSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectTooLarge error returned when the size of the object > max object size allowed (5G) per request.
|
||||||
|
type ObjectTooLarge GenericError
|
||||||
|
|
||||||
|
func (e ObjectTooLarge) Error() string {
|
||||||
|
return "size of the object greater than what is allowed(5G)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectTooSmall error returned when the size of the object < what is expected.
|
||||||
|
type ObjectTooSmall GenericError
|
||||||
|
|
||||||
|
func (e ObjectTooSmall) Error() string {
|
||||||
|
return "size of the object less than what is expected"
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperationTimedOut - a timeout occurred.
|
||||||
|
type OperationTimedOut struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e OperationTimedOut) Error() string {
|
||||||
|
return "Operation timed out"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multipart related errors.
|
||||||
|
|
||||||
|
// MalformedUploadID malformed upload id.
|
||||||
|
type MalformedUploadID struct {
|
||||||
|
UploadID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e MalformedUploadID) Error() string {
|
||||||
|
return "Malformed upload id " + e.UploadID
|
||||||
|
}
|
||||||
|
|
||||||
|
// InvalidUploadID invalid upload id.
|
||||||
|
type InvalidUploadID struct {
|
||||||
|
Bucket string
|
||||||
|
Object string
|
||||||
|
UploadID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e InvalidUploadID) Error() string {
|
||||||
|
return "Invalid upload id " + e.UploadID
|
||||||
|
}
|
||||||
|
|
||||||
|
// InvalidPart One or more of the specified parts could not be found
|
||||||
|
type InvalidPart struct {
|
||||||
|
PartNumber int
|
||||||
|
ExpETag string
|
||||||
|
GotETag string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e InvalidPart) Error() string {
|
||||||
|
return fmt.Sprintf("Specified part could not be found. PartNumber %d, Expected %s, got %s",
|
||||||
|
e.PartNumber, e.ExpETag, e.GotETag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartTooSmall - error if part size is less than 5MB.
|
||||||
|
type PartTooSmall struct {
|
||||||
|
PartSize int64
|
||||||
|
PartNumber int
|
||||||
|
PartETag string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e PartTooSmall) Error() string {
|
||||||
|
return fmt.Sprintf("Part size for %d should be at least 5MB", e.PartNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartTooBig returned if size of part is bigger than the allowed limit.
|
||||||
|
type PartTooBig struct{}
|
||||||
|
|
||||||
|
func (e PartTooBig) Error() string {
|
||||||
|
return "Part size bigger than the allowed limit"
|
||||||
|
}
|
||||||
|
|
||||||
|
// InvalidETag error returned when the etag has changed on disk
|
||||||
|
type InvalidETag struct{}
|
||||||
|
|
||||||
|
func (e InvalidETag) Error() string {
|
||||||
|
return "etag of the object has changed"
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotImplemented If a feature is not implemented
|
||||||
|
type NotImplemented struct{}
|
||||||
|
|
||||||
|
func (e NotImplemented) Error() string {
|
||||||
|
return "Not Implemented"
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsupportedMetadata - unsupported metadata
|
||||||
|
type UnsupportedMetadata struct{}
|
||||||
|
|
||||||
|
func (e UnsupportedMetadata) Error() string {
|
||||||
|
return "Unsupported headers in Metadata"
|
||||||
|
}
|
||||||
|
|
||||||
|
// BackendDown is returned for network errors or if the gateway's backend is down.
|
||||||
|
type BackendDown struct{}
|
||||||
|
|
||||||
|
func (e BackendDown) Error() string {
|
||||||
|
return "Backend down"
|
||||||
|
}
|
||||||
|
|
||||||
|
// PreConditionFailed - Check if copy precondition failed
|
||||||
|
type PreConditionFailed struct{}
|
||||||
|
|
||||||
|
func (e PreConditionFailed) Error() string {
|
||||||
|
return "At least one of the pre-conditions you specified did not hold"
|
||||||
|
}
|
|
@ -3,8 +3,8 @@ package handler
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/minio/minio/neofs/api"
|
"github.com/nspcc-dev/neofs-s3-gate/api"
|
||||||
"github.com/minio/minio/neofs/layer"
|
"github.com/nspcc-dev/neofs-s3-gate/api/layer"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,7 +3,7 @@ package handler
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/minio/minio/neofs/api"
|
"github.com/nspcc-dev/neofs-s3-gate/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *handler) ListBucketsHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) ListBucketsHandler(w http.ResponseWriter, r *http.Request) {
|
|
@ -4,10 +4,10 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/minio/minio/auth"
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/container"
|
"github.com/nspcc-dev/neofs-api-go/container"
|
||||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||||
"github.com/nspcc-dev/neofs-api-go/service"
|
"github.com/nspcc-dev/neofs-api-go/service"
|
||||||
|
"github.com/nspcc-dev/neofs-s3-gate/auth"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,10 +7,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/minio/minio/neofs/pool"
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/object"
|
"github.com/nspcc-dev/neofs-api-go/object"
|
||||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||||
"github.com/nspcc-dev/neofs-api-go/service"
|
"github.com/nspcc-dev/neofs-api-go/service"
|
||||||
|
"github.com/nspcc-dev/neofs-s3-gate/api/pool"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
|
@ -5,12 +5,12 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/minio/minio/neofs/pool"
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/object"
|
"github.com/nspcc-dev/neofs-api-go/object"
|
||||||
"github.com/nspcc-dev/neofs-api-go/query"
|
"github.com/nspcc-dev/neofs-api-go/query"
|
||||||
"github.com/nspcc-dev/neofs-api-go/refs"
|
"github.com/nspcc-dev/neofs-api-go/refs"
|
||||||
"github.com/nspcc-dev/neofs-api-go/service"
|
"github.com/nspcc-dev/neofs-api-go/service"
|
||||||
"github.com/nspcc-dev/neofs-api-go/storagegroup"
|
"github.com/nspcc-dev/neofs-api-go/storagegroup"
|
||||||
|
"github.com/nspcc-dev/neofs-s3-gate/api/pool"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
|
@ -49,10 +49,7 @@ type (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const systemPath = "/system"
|
||||||
// TODO: should be imported from routing
|
|
||||||
systemPath = "/system"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
httpStatsMetric = new(HTTPStats)
|
httpStatsMetric = new(HTTPStats)
|
||||||
|
@ -106,12 +103,6 @@ func collectHTTPMetrics(ch chan<- prometheus.Metric) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Middleware(h http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
APIStats(r.RequestURI, h.ServeHTTP).ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func APIStats(api string, f http.HandlerFunc) http.HandlerFunc {
|
func APIStats(api string, f http.HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
httpStatsMetric.currentS3Requests.Inc(api)
|
httpStatsMetric.currentS3Requests.Inc(api)
|
|
@ -1,7 +1,7 @@
|
||||||
package metrics
|
package metrics
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/minio/minio/misc"
|
"github.com/nspcc-dev/neofs-s3-gate/misc"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,15 +3,11 @@ package pool
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
crand "crypto/rand"
|
|
||||||
"encoding/binary"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"google.golang.org/grpc/grpclog"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/service"
|
"github.com/nspcc-dev/neofs-api-go/service"
|
||||||
"github.com/nspcc-dev/neofs-api-go/state"
|
"github.com/nspcc-dev/neofs-api-go/state"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -19,6 +15,7 @@ import (
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/connectivity"
|
"google.golang.org/grpc/connectivity"
|
||||||
|
"google.golang.org/grpc/grpclog"
|
||||||
"google.golang.org/grpc/keepalive"
|
"google.golang.org/grpc/keepalive"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -121,14 +118,10 @@ func New(cfg *Config) (Pool, error) {
|
||||||
grpclog.SetLoggerV2(cfg.GRPCLogger)
|
grpclog.SetLoggerV2(cfg.GRPCLogger)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, 8)
|
seed := time.Now().UnixNano()
|
||||||
if _, err := crand.Read(buf); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
seed := binary.BigEndian.Uint64(buf)
|
rand.Seed(seed)
|
||||||
rand.Seed(int64(seed))
|
cfg.Logger.Info("used random seed", zap.Int64("seed", seed))
|
||||||
cfg.Logger.Info("used random seed", zap.Uint64("seed", seed))
|
|
||||||
|
|
||||||
p.reqHealth = new(state.HealthRequest)
|
p.reqHealth = new(state.HealthRequest)
|
||||||
p.reqHealth.SetTTL(service.NonForwardingTTL)
|
p.reqHealth.SetTTL(service.NonForwardingTTL)
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/minio/minio/misc"
|
"github.com/nspcc-dev/neofs-s3-gate/misc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -152,7 +152,7 @@ func setCommonHeaders(w http.ResponseWriter) {
|
||||||
|
|
||||||
// removeSensitiveHeaders removes confidential encryption
|
// removeSensitiveHeaders removes confidential encryption
|
||||||
// information - e.g. the SSE-C key - from the HTTP headers.
|
// information - e.g. the SSE-C key - from the HTTP headers.
|
||||||
// It has the same semantics as RemoveSensitiveEntires.
|
// It has the same semantics as RemoveSensitiveEntries.
|
||||||
func removeSensitiveHeaders(h http.Header) {
|
func removeSensitiveHeaders(h http.Header) {
|
||||||
h.Del(hdrSSECustomerKey)
|
h.Del(hdrSSECustomerKey)
|
||||||
h.Del(hdrSSECopyKey)
|
h.Del(hdrSSECopyKey)
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/minio/minio/auth"
|
"github.com/nspcc-dev/neofs-s3-gate/api/metrics"
|
||||||
"github.com/minio/minio/neofs/metrics"
|
"github.com/nspcc-dev/neofs-s3-gate/auth"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -79,7 +79,6 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
||||||
// SlashSeparator - slash separator.
|
// SlashSeparator - slash separator.
|
||||||
SlashSeparator = "/"
|
SlashSeparator = "/"
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/minio/minio/auth"
|
"github.com/nspcc-dev/neofs-s3-gate/auth"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,13 +12,11 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/minio/minio/auth"
|
|
||||||
"github.com/minio/minio/neofs/pool"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/minio/minio/misc"
|
|
||||||
|
|
||||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||||
|
"github.com/nspcc-dev/neofs-s3-gate/api/pool"
|
||||||
|
"github.com/nspcc-dev/neofs-s3-gate/auth"
|
||||||
|
"github.com/nspcc-dev/neofs-s3-gate/misc"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
|
@ -7,11 +7,11 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/minio/minio/auth"
|
"github.com/nspcc-dev/neofs-s3-gate/api"
|
||||||
"github.com/minio/minio/neofs/api"
|
"github.com/nspcc-dev/neofs-s3-gate/api/handler"
|
||||||
"github.com/minio/minio/neofs/api/handler"
|
"github.com/nspcc-dev/neofs-s3-gate/api/layer"
|
||||||
"github.com/minio/minio/neofs/layer"
|
"github.com/nspcc-dev/neofs-s3-gate/api/pool"
|
||||||
"github.com/minio/minio/neofs/pool"
|
"github.com/nspcc-dev/neofs-s3-gate/auth"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"google.golang.org/grpc/keepalive"
|
"google.golang.org/grpc/keepalive"
|
||||||
|
|
11
go.mod
11
go.mod
|
@ -1,12 +1,11 @@
|
||||||
module github.com/minio/minio
|
module github.com/nspcc-dev/neofs-s3-gate
|
||||||
|
|
||||||
go 1.13
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/google/uuid v1.1.1
|
github.com/google/uuid v1.1.1
|
||||||
github.com/gorilla/mux v1.7.4
|
github.com/gorilla/mux v1.7.4
|
||||||
github.com/klauspost/compress v1.10.10
|
github.com/klauspost/compress v1.10.10
|
||||||
github.com/minio/minio-go/v7 v7.0.3
|
|
||||||
github.com/nspcc-dev/neofs-api-go v1.3.0
|
github.com/nspcc-dev/neofs-api-go v1.3.0
|
||||||
github.com/nspcc-dev/neofs-crypto v0.3.0
|
github.com/nspcc-dev/neofs-crypto v0.3.0
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
|
@ -15,5 +14,11 @@ require (
|
||||||
github.com/spf13/viper v1.7.0
|
github.com/spf13/viper v1.7.0
|
||||||
go.uber.org/atomic v1.6.0
|
go.uber.org/atomic v1.6.0
|
||||||
go.uber.org/zap v1.15.0
|
go.uber.org/zap v1.15.0
|
||||||
|
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 // indirect
|
||||||
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
|
||||||
|
golang.org/x/text v0.3.3 // indirect
|
||||||
google.golang.org/grpc v1.29.1
|
google.golang.org/grpc v1.29.1
|
||||||
|
gopkg.in/ini.v1 v1.57.0 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||||
)
|
)
|
||||||
|
|
11
go.sum
11
go.sum
|
@ -182,7 +182,6 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
@ -192,8 +191,6 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I=
|
github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I=
|
||||||
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
|
||||||
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
@ -218,12 +215,6 @@ github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcME
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
|
|
||||||
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
|
|
||||||
github.com/minio/minio-go/v7 v7.0.3 h1:a2VHaXDlKBcB3J5XJhKVfWBRi1+ZmMWFXABQ8TLlWbA=
|
|
||||||
github.com/minio/minio-go/v7 v7.0.3/go.mod h1:TA0CQCjJZHM5SJj9IjqR0NmpmQJ6bCbXifAJ3mUU6Hw=
|
|
||||||
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
|
|
||||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
|
||||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
|
@ -309,7 +300,6 @@ github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
|
@ -317,7 +307,6 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
|
||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
package crypto
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// Error is the generic type for any error happening during decrypting
|
|
||||||
// an object. It indicates that the object itself or its metadata was
|
|
||||||
// modified accidentally or maliciously.
|
|
||||||
type Error struct {
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorf - formats according to a format specifier and returns
|
|
||||||
// the string as a value that satisfies error of type crypto.Error
|
|
||||||
func Errorf(format string, a ...interface{}) error {
|
|
||||||
return Error{err: fmt.Errorf(format, a...)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap the internal error.
|
|
||||||
func (e Error) Unwrap() error { return e.err }
|
|
||||||
|
|
||||||
// Error 'error' compatible method.
|
|
||||||
func (e Error) Error() string {
|
|
||||||
if e.err == nil {
|
|
||||||
return "crypto: cause <nil>"
|
|
||||||
}
|
|
||||||
return e.err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrInvalidEncryptionMethod indicates that the specified SSE encryption method
|
|
||||||
// is not supported.
|
|
||||||
ErrInvalidEncryptionMethod = Errorf("The encryption method is not supported")
|
|
||||||
|
|
||||||
// ErrInvalidCustomerAlgorithm indicates that the specified SSE-C algorithm
|
|
||||||
// is not supported.
|
|
||||||
ErrInvalidCustomerAlgorithm = Errorf("The SSE-C algorithm is not supported")
|
|
||||||
|
|
||||||
// ErrMissingCustomerKey indicates that the HTTP headers contains no SSE-C client key.
|
|
||||||
ErrMissingCustomerKey = Errorf("The SSE-C request is missing the customer key")
|
|
||||||
|
|
||||||
// ErrMissingCustomerKeyMD5 indicates that the HTTP headers contains no SSE-C client key
|
|
||||||
// MD5 checksum.
|
|
||||||
ErrMissingCustomerKeyMD5 = Errorf("The SSE-C request is missing the customer key MD5")
|
|
||||||
|
|
||||||
// ErrInvalidCustomerKey indicates that the SSE-C client key is not valid - e.g. not a
|
|
||||||
// base64-encoded string or not 256 bits long.
|
|
||||||
ErrInvalidCustomerKey = Errorf("The SSE-C client key is invalid")
|
|
||||||
|
|
||||||
// ErrSecretKeyMismatch indicates that the provided secret key (SSE-C client key / SSE-S3 KMS key)
|
|
||||||
// does not match the secret key used during encrypting the object.
|
|
||||||
ErrSecretKeyMismatch = Errorf("The secret key does not match the secret key used during upload")
|
|
||||||
|
|
||||||
// ErrCustomerKeyMD5Mismatch indicates that the SSE-C key MD5 does not match the
|
|
||||||
// computed MD5 sum. This means that the client provided either the wrong key for
|
|
||||||
// a certain MD5 checksum or the wrong MD5 for a certain key.
|
|
||||||
ErrCustomerKeyMD5Mismatch = Errorf("The provided SSE-C key MD5 does not match the computed MD5 of the SSE-C key")
|
|
||||||
// ErrIncompatibleEncryptionMethod indicates that both SSE-C headers and SSE-S3 headers were specified, and are incompatible
|
|
||||||
// The client needs to remove the SSE-S3 header or the SSE-C headers
|
|
||||||
ErrIncompatibleEncryptionMethod = Errorf("Server side encryption specified with both SSE-C and SSE-S3 headers")
|
|
||||||
|
|
||||||
// ErrKMSAuthLogin is raised when there is a failure authenticating to KMS
|
|
||||||
ErrKMSAuthLogin = Errorf("Vault service did not return auth info")
|
|
||||||
)
|
|
|
@ -1,474 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Converts underlying storage error. Convenience function written to
|
|
||||||
// handle all cases where we have known types of errors returned by
|
|
||||||
// underlying storage layer.
|
|
||||||
func toObjectErr(err error, params ...string) error {
|
|
||||||
switch err {
|
|
||||||
case errVolumeNotFound:
|
|
||||||
if len(params) >= 1 {
|
|
||||||
err = BucketNotFound{Bucket: params[0]}
|
|
||||||
}
|
|
||||||
case errVolumeNotEmpty:
|
|
||||||
if len(params) >= 1 {
|
|
||||||
err = BucketNotEmpty{Bucket: params[0]}
|
|
||||||
}
|
|
||||||
case errVolumeExists:
|
|
||||||
if len(params) >= 1 {
|
|
||||||
err = BucketExists{Bucket: params[0]}
|
|
||||||
}
|
|
||||||
case errDiskFull:
|
|
||||||
err = StorageFull{}
|
|
||||||
case errTooManyOpenFiles:
|
|
||||||
err = SlowDown{}
|
|
||||||
case errFileAccessDenied:
|
|
||||||
if len(params) >= 2 {
|
|
||||||
err = PrefixAccessDenied{
|
|
||||||
Bucket: params[0],
|
|
||||||
Object: params[1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case errFileParentIsFile:
|
|
||||||
if len(params) >= 2 {
|
|
||||||
err = ParentIsObject{
|
|
||||||
Bucket: params[0],
|
|
||||||
Object: params[1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case errIsNotRegular:
|
|
||||||
if len(params) >= 2 {
|
|
||||||
err = ObjectExistsAsDirectory{
|
|
||||||
Bucket: params[0],
|
|
||||||
Object: params[1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case errFileNotFound:
|
|
||||||
switch len(params) {
|
|
||||||
case 2:
|
|
||||||
err = ObjectNotFound{
|
|
||||||
Bucket: params[0],
|
|
||||||
Object: params[1],
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
err = InvalidUploadID{
|
|
||||||
Bucket: params[0],
|
|
||||||
Object: params[1],
|
|
||||||
UploadID: params[2],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case errFileNameTooLong:
|
|
||||||
if len(params) >= 2 {
|
|
||||||
err = ObjectNameInvalid{
|
|
||||||
Bucket: params[0],
|
|
||||||
Object: params[1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case errDataTooLarge:
|
|
||||||
if len(params) >= 2 {
|
|
||||||
err = ObjectTooLarge{
|
|
||||||
Bucket: params[0],
|
|
||||||
Object: params[1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case errDataTooSmall:
|
|
||||||
if len(params) >= 2 {
|
|
||||||
err = ObjectTooSmall{
|
|
||||||
Bucket: params[0],
|
|
||||||
Object: params[1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case errXLReadQuorum:
|
|
||||||
err = InsufficientReadQuorum{}
|
|
||||||
case errXLWriteQuorum:
|
|
||||||
err = InsufficientWriteQuorum{}
|
|
||||||
case io.ErrUnexpectedEOF, io.ErrShortWrite:
|
|
||||||
err = IncompleteBody{}
|
|
||||||
case context.Canceled, context.DeadlineExceeded:
|
|
||||||
err = IncompleteBody{}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignatureDoesNotMatch - when content md5 does not match with what was sent from client.
|
|
||||||
type SignatureDoesNotMatch struct{}
|
|
||||||
|
|
||||||
func (e SignatureDoesNotMatch) Error() string {
|
|
||||||
return "The request signature we calculated does not match the signature you provided. Check your key and signing method."
|
|
||||||
}
|
|
||||||
|
|
||||||
// StorageFull storage ran out of space.
|
|
||||||
type StorageFull struct{}
|
|
||||||
|
|
||||||
func (e StorageFull) Error() string {
|
|
||||||
return "Storage reached its minimum free disk threshold."
|
|
||||||
}
|
|
||||||
|
|
||||||
// SlowDown too many file descriptors open or backend busy .
|
|
||||||
type SlowDown struct{}
|
|
||||||
|
|
||||||
func (e SlowDown) Error() string {
|
|
||||||
return "Please reduce your request rate"
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsufficientReadQuorum storage cannot satisfy quorum for read operation.
|
|
||||||
type InsufficientReadQuorum struct{}
|
|
||||||
|
|
||||||
func (e InsufficientReadQuorum) Error() string {
|
|
||||||
return "Storage resources are insufficient for the read operation."
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsufficientWriteQuorum storage cannot satisfy quorum for write operation.
|
|
||||||
type InsufficientWriteQuorum struct{}
|
|
||||||
|
|
||||||
func (e InsufficientWriteQuorum) Error() string {
|
|
||||||
return "Storage resources are insufficient for the write operation."
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenericError - generic object layer error.
|
|
||||||
type GenericError struct {
|
|
||||||
Bucket string
|
|
||||||
Object string
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketNotFound bucket does not exist.
|
|
||||||
type BucketNotFound GenericError
|
|
||||||
|
|
||||||
func (e BucketNotFound) Error() string {
|
|
||||||
return "Bucket not found: " + e.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketAlreadyExists the requested bucket name is not available.
|
|
||||||
type BucketAlreadyExists GenericError
|
|
||||||
|
|
||||||
func (e BucketAlreadyExists) Error() string {
|
|
||||||
return "The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again."
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketAlreadyOwnedByYou already owned by you.
|
|
||||||
type BucketAlreadyOwnedByYou GenericError
|
|
||||||
|
|
||||||
func (e BucketAlreadyOwnedByYou) Error() string {
|
|
||||||
return "Bucket already owned by you: " + e.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketNotEmpty bucket is not empty.
|
|
||||||
type BucketNotEmpty GenericError
|
|
||||||
|
|
||||||
func (e BucketNotEmpty) Error() string {
|
|
||||||
return "Bucket not empty: " + e.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectNotFound object does not exist.
|
|
||||||
type ObjectNotFound GenericError
|
|
||||||
|
|
||||||
func (e ObjectNotFound) Error() string {
|
|
||||||
return "Object not found: " + e.Bucket + "#" + e.Object
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectAlreadyExists object already exists.
|
|
||||||
type ObjectAlreadyExists GenericError
|
|
||||||
|
|
||||||
func (e ObjectAlreadyExists) Error() string {
|
|
||||||
return "Object: " + e.Bucket + "#" + e.Object + " already exists"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectExistsAsDirectory object already exists as a directory.
|
|
||||||
type ObjectExistsAsDirectory GenericError
|
|
||||||
|
|
||||||
func (e ObjectExistsAsDirectory) Error() string {
|
|
||||||
return "Object exists on : " + e.Bucket + " as directory " + e.Object
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrefixAccessDenied object access is denied.
|
|
||||||
type PrefixAccessDenied GenericError
|
|
||||||
|
|
||||||
func (e PrefixAccessDenied) Error() string {
|
|
||||||
return "Prefix access is denied: " + e.Bucket + SlashSeparator + e.Object
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParentIsObject object access is denied.
|
|
||||||
type ParentIsObject GenericError
|
|
||||||
|
|
||||||
func (e ParentIsObject) Error() string {
|
|
||||||
return "Parent is object " + e.Bucket + SlashSeparator + path.Dir(e.Object)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketExists bucket exists.
|
|
||||||
type BucketExists GenericError
|
|
||||||
|
|
||||||
func (e BucketExists) Error() string {
|
|
||||||
return "Bucket exists: " + e.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnsupportedDelimiter - unsupported delimiter.
|
|
||||||
type UnsupportedDelimiter struct {
|
|
||||||
Delimiter string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e UnsupportedDelimiter) Error() string {
|
|
||||||
return fmt.Sprintf("delimiter '%s' is not supported. Only '/' is supported", e.Delimiter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidUploadIDKeyCombination - invalid upload id and key marker combination.
|
|
||||||
type InvalidUploadIDKeyCombination struct {
|
|
||||||
UploadIDMarker, KeyMarker string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e InvalidUploadIDKeyCombination) Error() string {
|
|
||||||
return fmt.Sprintf("Invalid combination of uploadID marker '%s' and marker '%s'", e.UploadIDMarker, e.KeyMarker)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidMarkerPrefixCombination - invalid marker and prefix combination.
|
|
||||||
type InvalidMarkerPrefixCombination struct {
|
|
||||||
Marker, Prefix string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e InvalidMarkerPrefixCombination) Error() string {
|
|
||||||
return fmt.Sprintf("Invalid combination of marker '%s' and prefix '%s'", e.Marker, e.Prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketPolicyNotFound - no bucket policy found.
|
|
||||||
type BucketPolicyNotFound GenericError
|
|
||||||
|
|
||||||
func (e BucketPolicyNotFound) Error() string {
|
|
||||||
return "No bucket policy configuration found for bucket: " + e.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketLifecycleNotFound - no bucket lifecycle found.
|
|
||||||
type BucketLifecycleNotFound GenericError
|
|
||||||
|
|
||||||
func (e BucketLifecycleNotFound) Error() string {
|
|
||||||
return "No bucket lifecycle configuration found for bucket : " + e.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketSSEConfigNotFound - no bucket encryption found
|
|
||||||
type BucketSSEConfigNotFound GenericError
|
|
||||||
|
|
||||||
func (e BucketSSEConfigNotFound) Error() string {
|
|
||||||
return "No bucket encryption configuration found for bucket: " + e.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketTaggingNotFound - no bucket tags found
|
|
||||||
type BucketTaggingNotFound GenericError
|
|
||||||
|
|
||||||
func (e BucketTaggingNotFound) Error() string {
|
|
||||||
return "No bucket tags found for bucket: " + e.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketObjectLockConfigNotFound - no bucket object lock config found
|
|
||||||
type BucketObjectLockConfigNotFound GenericError
|
|
||||||
|
|
||||||
func (e BucketObjectLockConfigNotFound) Error() string {
|
|
||||||
return "No bucket object lock configuration found for bucket: " + e.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketQuotaConfigNotFound - no bucket quota config found.
|
|
||||||
type BucketQuotaConfigNotFound GenericError
|
|
||||||
|
|
||||||
func (e BucketQuotaConfigNotFound) Error() string {
|
|
||||||
return "No quota config found for bucket : " + e.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// BucketQuotaExceeded - bucket quota exceeded.
|
|
||||||
type BucketQuotaExceeded GenericError
|
|
||||||
|
|
||||||
func (e BucketQuotaExceeded) Error() string {
|
|
||||||
return "Bucket quota exceeded for bucket: " + e.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bucket related errors.
|
|
||||||
|
|
||||||
// BucketNameInvalid - bucketname provided is invalid.
|
|
||||||
type BucketNameInvalid GenericError
|
|
||||||
|
|
||||||
// Error returns string an error formatted as the given text.
|
|
||||||
func (e BucketNameInvalid) Error() string {
|
|
||||||
return "Bucket name invalid: " + e.Bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
// Object related errors.
|
|
||||||
|
|
||||||
// ObjectNameInvalid - object name provided is invalid.
|
|
||||||
type ObjectNameInvalid GenericError
|
|
||||||
|
|
||||||
// ObjectNameTooLong - object name too long.
|
|
||||||
type ObjectNameTooLong GenericError
|
|
||||||
|
|
||||||
// ObjectNamePrefixAsSlash - object name has a slash as prefix.
|
|
||||||
type ObjectNamePrefixAsSlash GenericError
|
|
||||||
|
|
||||||
// Error returns string an error formatted as the given text.
|
|
||||||
func (e ObjectNameInvalid) Error() string {
|
|
||||||
return "Object name invalid: " + e.Bucket + "#" + e.Object
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns string an error formatted as the given text.
|
|
||||||
func (e ObjectNameTooLong) Error() string {
|
|
||||||
return "Object name too long: " + e.Bucket + "#" + e.Object
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns string an error formatted as the given text.
|
|
||||||
func (e ObjectNamePrefixAsSlash) Error() string {
|
|
||||||
return "Object name contains forward slash as pefix: " + e.Bucket + "#" + e.Object
|
|
||||||
}
|
|
||||||
|
|
||||||
// AllAccessDisabled All access to this object has been disabled
|
|
||||||
type AllAccessDisabled GenericError
|
|
||||||
|
|
||||||
// Error returns string an error formatted as the given text.
|
|
||||||
func (e AllAccessDisabled) Error() string {
|
|
||||||
return "All access to this object has been disabled"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IncompleteBody You did not provide the number of bytes specified by the Content-Length HTTP header.
|
|
||||||
type IncompleteBody GenericError
|
|
||||||
|
|
||||||
// Error returns string an error formatted as the given text.
|
|
||||||
func (e IncompleteBody) Error() string {
|
|
||||||
return e.Bucket + "#" + e.Object + "has incomplete body"
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidRange - invalid range typed error.
|
|
||||||
type InvalidRange struct {
|
|
||||||
OffsetBegin int64
|
|
||||||
OffsetEnd int64
|
|
||||||
ResourceSize int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e InvalidRange) Error() string {
|
|
||||||
return fmt.Sprintf("The requested range \"bytes %d-%d/%d\" is not satisfiable.", e.OffsetBegin, e.OffsetEnd, e.ResourceSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectTooLarge error returned when the size of the object > max object size allowed (5G) per request.
|
|
||||||
type ObjectTooLarge GenericError
|
|
||||||
|
|
||||||
func (e ObjectTooLarge) Error() string {
|
|
||||||
return "size of the object greater than what is allowed(5G)"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectTooSmall error returned when the size of the object < what is expected.
|
|
||||||
type ObjectTooSmall GenericError
|
|
||||||
|
|
||||||
func (e ObjectTooSmall) Error() string {
|
|
||||||
return "size of the object less than what is expected"
|
|
||||||
}
|
|
||||||
|
|
||||||
// OperationTimedOut - a timeout occurred.
|
|
||||||
type OperationTimedOut struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e OperationTimedOut) Error() string {
|
|
||||||
return "Operation timed out"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multipart related errors.
|
|
||||||
|
|
||||||
// MalformedUploadID malformed upload id.
|
|
||||||
type MalformedUploadID struct {
|
|
||||||
UploadID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e MalformedUploadID) Error() string {
|
|
||||||
return "Malformed upload id " + e.UploadID
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidUploadID invalid upload id.
|
|
||||||
type InvalidUploadID struct {
|
|
||||||
Bucket string
|
|
||||||
Object string
|
|
||||||
UploadID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e InvalidUploadID) Error() string {
|
|
||||||
return "Invalid upload id " + e.UploadID
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidPart One or more of the specified parts could not be found
|
|
||||||
type InvalidPart struct {
|
|
||||||
PartNumber int
|
|
||||||
ExpETag string
|
|
||||||
GotETag string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e InvalidPart) Error() string {
|
|
||||||
return fmt.Sprintf("Specified part could not be found. PartNumber %d, Expected %s, got %s",
|
|
||||||
e.PartNumber, e.ExpETag, e.GotETag)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PartTooSmall - error if part size is less than 5MB.
|
|
||||||
type PartTooSmall struct {
|
|
||||||
PartSize int64
|
|
||||||
PartNumber int
|
|
||||||
PartETag string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e PartTooSmall) Error() string {
|
|
||||||
return fmt.Sprintf("Part size for %d should be at least 5MB", e.PartNumber)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PartTooBig returned if size of part is bigger than the allowed limit.
|
|
||||||
type PartTooBig struct{}
|
|
||||||
|
|
||||||
func (e PartTooBig) Error() string {
|
|
||||||
return "Part size bigger than the allowed limit"
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidETag error returned when the etag has changed on disk
|
|
||||||
type InvalidETag struct{}
|
|
||||||
|
|
||||||
func (e InvalidETag) Error() string {
|
|
||||||
return "etag of the object has changed"
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotImplemented If a feature is not implemented
|
|
||||||
type NotImplemented struct{}
|
|
||||||
|
|
||||||
func (e NotImplemented) Error() string {
|
|
||||||
return "Not Implemented"
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnsupportedMetadata - unsupported metadata
|
|
||||||
type UnsupportedMetadata struct{}
|
|
||||||
|
|
||||||
func (e UnsupportedMetadata) Error() string {
|
|
||||||
return "Unsupported headers in Metadata"
|
|
||||||
}
|
|
||||||
|
|
||||||
// BackendDown is returned for network errors or if the gateway's backend is down.
|
|
||||||
type BackendDown struct{}
|
|
||||||
|
|
||||||
func (e BackendDown) Error() string {
|
|
||||||
return "Backend down"
|
|
||||||
}
|
|
||||||
|
|
||||||
// isErrBucketNotFound - Check if error type is BucketNotFound.
|
|
||||||
func isErrBucketNotFound(err error) bool {
|
|
||||||
var bkNotFound BucketNotFound
|
|
||||||
return errors.As(err, &bkNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
// isErrObjectNotFound - Check if error type is ObjectNotFound.
|
|
||||||
func isErrObjectNotFound(err error) bool {
|
|
||||||
var objNotFound ObjectNotFound
|
|
||||||
return errors.As(err, &objNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PreConditionFailed - Check if copy precondition failed
|
|
||||||
type PreConditionFailed struct{}
|
|
||||||
|
|
||||||
func (e PreConditionFailed) Error() string {
|
|
||||||
return "At least one of the pre-conditions you specified did not hold"
|
|
||||||
}
|
|
||||||
|
|
||||||
func isErrPreconditionFailed(err error) bool {
|
|
||||||
_, ok := err.(PreConditionFailed)
|
|
||||||
return ok
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
// errUnexpected - unexpected error, requires manual intervention.
|
|
||||||
var errUnexpected = StorageErr("Unexpected error, please report this issue at https://github.com/minio/minio/issues")
|
|
||||||
|
|
||||||
// errCorruptedFormat - corrupted backend format.
|
|
||||||
var errCorruptedFormat = StorageErr("corrupted backend format, please join https://slack.min.io for assistance")
|
|
||||||
|
|
||||||
// errUnformattedDisk - unformatted disk found.
|
|
||||||
var errUnformattedDisk = StorageErr("unformatted disk found")
|
|
||||||
|
|
||||||
// errUnsupporteDisk - when disk does not support O_DIRECT flag.
|
|
||||||
var errUnsupportedDisk = StorageErr("disk does not support O_DIRECT")
|
|
||||||
|
|
||||||
// errDiskFull - cannot create volume or files when disk is full.
|
|
||||||
var errDiskFull = StorageErr("disk path full")
|
|
||||||
|
|
||||||
// errDiskNotFound - cannot find the underlying configured disk anymore.
|
|
||||||
var errDiskNotFound = StorageErr("disk not found")
|
|
||||||
|
|
||||||
// errFaultyRemoteDisk - remote disk is faulty.
|
|
||||||
var errFaultyRemoteDisk = StorageErr("remote disk is faulty")
|
|
||||||
|
|
||||||
// errFaultyDisk - disk is faulty.
|
|
||||||
var errFaultyDisk = StorageErr("disk is faulty")
|
|
||||||
|
|
||||||
// errDiskAccessDenied - we don't have write permissions on disk.
|
|
||||||
var errDiskAccessDenied = StorageErr("disk access denied")
|
|
||||||
|
|
||||||
// errFileNotFound - cannot find the file.
|
|
||||||
var errFileNotFound = StorageErr("file not found")
|
|
||||||
|
|
||||||
// errTooManyOpenFiles - too many open files.
|
|
||||||
var errTooManyOpenFiles = StorageErr("too many open files")
|
|
||||||
|
|
||||||
// errFileNameTooLong - given file name is too long than supported length.
|
|
||||||
var errFileNameTooLong = StorageErr("file name too long")
|
|
||||||
|
|
||||||
// errVolumeExists - cannot create same volume again.
|
|
||||||
var errVolumeExists = StorageErr("volume already exists")
|
|
||||||
|
|
||||||
// errIsNotRegular - not of regular file type.
|
|
||||||
var errIsNotRegular = StorageErr("not of regular file type")
|
|
||||||
|
|
||||||
// errVolumeNotFound - cannot find the volume.
|
|
||||||
var errVolumeNotFound = StorageErr("volume not found")
|
|
||||||
|
|
||||||
// errVolumeNotEmpty - volume not empty.
|
|
||||||
var errVolumeNotEmpty = StorageErr("volume is not empty")
|
|
||||||
|
|
||||||
// errVolumeAccessDenied - cannot access volume, insufficient permissions.
|
|
||||||
var errVolumeAccessDenied = StorageErr("volume access denied")
|
|
||||||
|
|
||||||
// errFileAccessDenied - cannot access file, insufficient permissions.
|
|
||||||
var errFileAccessDenied = StorageErr("file access denied")
|
|
||||||
|
|
||||||
// errFileCorrupt - file has an unexpected size, or is not readable
|
|
||||||
var errFileCorrupt = StorageErr("file is corrupted")
|
|
||||||
|
|
||||||
// errFileParentIsFile - cannot have overlapping objects, parent is already a file.
|
|
||||||
var errFileParentIsFile = StorageErr("parent is a file")
|
|
||||||
|
|
||||||
// errBitrotHashAlgoInvalid - the algo for bit-rot hash
|
|
||||||
// verification is empty or invalid.
|
|
||||||
var errBitrotHashAlgoInvalid = StorageErr("bit-rot hash algorithm is invalid")
|
|
||||||
|
|
||||||
// errCrossDeviceLink - rename across devices not allowed.
|
|
||||||
var errCrossDeviceLink = StorageErr("Rename across devices not allowed, please fix your backend configuration")
|
|
||||||
|
|
||||||
// errMinDiskSize - cannot create volume or files when disk size is less than threshold.
|
|
||||||
var errMinDiskSize = StorageErr("The disk size is less than 900MiB threshold")
|
|
||||||
|
|
||||||
// errLessData - returned when less data available than what was requested.
|
|
||||||
var errLessData = StorageErr("less data available than what was requested")
|
|
||||||
|
|
||||||
// errMoreData = returned when more data was sent by the caller than what it was supposed to.
|
|
||||||
var errMoreData = StorageErr("more data was sent than what was advertised")
|
|
||||||
|
|
||||||
// StorageErr represents error generated by posix call.
|
|
||||||
type StorageErr string
|
|
||||||
|
|
||||||
func (h StorageErr) Error() string {
|
|
||||||
return string(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collection of basic errors.
|
|
||||||
var baseErrs = []error{
|
|
||||||
errDiskNotFound,
|
|
||||||
errFaultyDisk,
|
|
||||||
errFaultyRemoteDisk,
|
|
||||||
}
|
|
||||||
|
|
||||||
var baseIgnoredErrs = baseErrs
|
|
|
@ -1,107 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// errInvalidArgument means that input argument is invalid.
|
|
||||||
var errInvalidArgument = errors.New("Invalid arguments specified")
|
|
||||||
|
|
||||||
// errMethodNotAllowed means that method is not allowed.
|
|
||||||
var errMethodNotAllowed = errors.New("Method not allowed")
|
|
||||||
|
|
||||||
// errSignatureMismatch means signature did not match.
|
|
||||||
var errSignatureMismatch = errors.New("Signature does not match")
|
|
||||||
|
|
||||||
// used when we deal with data larger than expected
|
|
||||||
var errSizeUnexpected = errors.New("Data size larger than expected")
|
|
||||||
|
|
||||||
// used when we deal with data with unknown size
|
|
||||||
var errSizeUnspecified = errors.New("Data size is unspecified")
|
|
||||||
|
|
||||||
// When upload object size is greater than 5G in a single PUT/POST operation.
|
|
||||||
var errDataTooLarge = errors.New("Object size larger than allowed limit")
|
|
||||||
|
|
||||||
// When upload object size is less than what was expected.
|
|
||||||
var errDataTooSmall = errors.New("Object size smaller than expected")
|
|
||||||
|
|
||||||
// errServerNotInitialized - server not initialized.
|
|
||||||
var errServerNotInitialized = errors.New("Server not initialized, please try again")
|
|
||||||
|
|
||||||
// errRPCAPIVersionUnsupported - unsupported rpc API version.
|
|
||||||
var errRPCAPIVersionUnsupported = errors.New("Unsupported rpc API version")
|
|
||||||
|
|
||||||
// errServerTimeMismatch - server times are too far apart.
|
|
||||||
var errServerTimeMismatch = errors.New("Server times are too far apart")
|
|
||||||
|
|
||||||
// errInvalidBucketName - bucket name is reserved for MinIO, usually
|
|
||||||
// returned for 'minio', '.minio.sys', buckets with capital letters.
|
|
||||||
var errInvalidBucketName = errors.New("The specified bucket is not valid")
|
|
||||||
|
|
||||||
// errInvalidRange - returned when given range value is not valid.
|
|
||||||
var errInvalidRange = errors.New("Invalid range")
|
|
||||||
|
|
||||||
// errInvalidRangeSource - returned when given range value exceeds
|
|
||||||
// the source object size.
|
|
||||||
var errInvalidRangeSource = errors.New("Range specified exceeds source object size")
|
|
||||||
|
|
||||||
// error returned by disks which are to be initialized are waiting for the
|
|
||||||
// first server to initialize them in distributed set to initialize them.
|
|
||||||
var errNotFirstDisk = errors.New("Not first disk")
|
|
||||||
|
|
||||||
// error returned by first disk waiting to initialize other servers.
|
|
||||||
var errFirstDiskWait = errors.New("Waiting on other disks")
|
|
||||||
|
|
||||||
// error returned when a bucket already exists
|
|
||||||
var errBucketAlreadyExists = errors.New("Your previous request to create the named bucket succeeded and you already own it")
|
|
||||||
|
|
||||||
// error returned for a negative actual size.
|
|
||||||
var errInvalidDecompressedSize = errors.New("Invalid Decompressed Size")
|
|
||||||
|
|
||||||
// error returned in IAM subsystem when user doesn't exist.
|
|
||||||
var errNoSuchUser = errors.New("Specified user does not exist")
|
|
||||||
|
|
||||||
// error returned in IAM subsystem when groups doesn't exist.
|
|
||||||
var errNoSuchGroup = errors.New("Specified group does not exist")
|
|
||||||
|
|
||||||
// error returned in IAM subsystem when a non-empty group needs to be
|
|
||||||
// deleted.
|
|
||||||
var errGroupNotEmpty = errors.New("Specified group is not empty - cannot remove it")
|
|
||||||
|
|
||||||
// error returned in IAM subsystem when policy doesn't exist.
|
|
||||||
var errNoSuchPolicy = errors.New("Specified canned policy does not exist")
|
|
||||||
|
|
||||||
// error returned in IAM subsystem when an external users systems is configured.
|
|
||||||
var errIAMActionNotAllowed = errors.New("Specified IAM action is not allowed with LDAP configuration")
|
|
||||||
|
|
||||||
// error returned in IAM subsystem when IAM sub-system is still being initialized.
|
|
||||||
var errIAMNotInitialized = errors.New("IAM sub-system is being initialized, please try again")
|
|
||||||
|
|
||||||
// error returned when access is denied.
|
|
||||||
var errAccessDenied = errors.New("Do not have enough permissions to access this resource")
|
|
||||||
|
|
||||||
// error returned when object is locked.
|
|
||||||
var errLockedObject = errors.New("Object is WORM protected and cannot be overwritten or deleted")
|
|
||||||
|
|
||||||
var (
|
|
||||||
errInvalidAccessKeyID = errors.New("The access key ID you provided does not exist in our records")
|
|
||||||
errChangeCredNotAllowed = errors.New("Changing access key and secret key not allowed")
|
|
||||||
errAuthentication = errors.New("Authentication failed, check your access credentials")
|
|
||||||
errNoAuthToken = errors.New("JWT token missing")
|
|
||||||
errIncorrectCreds = errors.New("Current access key or secret key is incorrect")
|
|
||||||
errPresignedNotAllowed = errors.New("Unable to generate shareable URL due to lack of read permissions")
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// AWS errors for invalid SSE-C requests.
|
|
||||||
errEncryptedObject = errors.New("The object was stored using a form of SSE")
|
|
||||||
errInvalidSSEParameters = errors.New("The SSE-C key for key-rotation is not correct") // special access denied
|
|
||||||
errKMSNotConfigured = errors.New("KMS not configured for a server side encrypted object")
|
|
||||||
// Additional MinIO errors for SSE-C requests.
|
|
||||||
errObjectTampered = errors.New("The requested object was modified and may be compromised")
|
|
||||||
// error returned when invalid encryption parameters are specified
|
|
||||||
errInvalidEncryptionParameters = errors.New("The encryption parameters are not applicable to this object")
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrNoEntriesFound - Indicates no entries were found for the given key (directory)
|
|
||||||
var ErrNoEntriesFound = errors.New("No entries found for this key")
|
|
|
@ -1,12 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
// errXLReadQuorum - did not meet read quorum.
|
|
||||||
var errXLReadQuorum = errors.New("Read failed. Insufficient number of disks online")
|
|
||||||
|
|
||||||
// errXLWriteQuorum - did not meet write quorum.
|
|
||||||
var errXLWriteQuorum = errors.New("Write failed. Insufficient number of disks online")
|
|
||||||
|
|
||||||
// errNoHealRequired - returned when healing is attempted on a previously healed disks.
|
|
||||||
var errNoHealRequired = errors.New("No healing is required")
|
|
Loading…
Reference in a new issue