diff --git a/neofs/api/errors.go b/api/errors.go similarity index 85% rename from neofs/api/errors.go rename to api/errors.go index 33a84cd11..c4d236b59 100644 --- a/neofs/api/errors.go +++ b/api/errors.go @@ -2,15 +2,9 @@ package api import ( "context" - "encoding/xml" "fmt" "net/http" - "net/url" - "strings" - - "github.com/minio/minio-go/v7/pkg/tags" - "github.com/minio/minio/auth" - "github.com/minio/minio/neofs/api/crypto" + "path" ) type ( @@ -24,7 +18,7 @@ const maxEConfigJSONSize = 262272 // Error codes, non exhaustive list - http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html const ( - ErrNone ErrorCode = iota + _ ErrorCode = iota ErrAccessDenied ErrBadDigest ErrEntityTooSmall @@ -1096,7 +1090,7 @@ var errorCodes = errorCodeMap{ }, ErrObjectTampered: { Code: "XMinioObjectTampered", - Description: errObjectTampered.Error(), + Description: "The requested object was modified and may be compromised", HTTPStatusCode: http.StatusPartialContent, }, ErrMaximumExpires: { @@ -1618,300 +1612,6 @@ func (e errorCodeMap) ToAPIErr(errCode ErrorCode) Error { 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. func GetAPIError(code ErrorCode) Error { if apiErr, ok := errorCodes[code]; ok { @@ -1930,8 +1630,366 @@ func getAPIErrorResponse(ctx context.Context, err Error, resource, requestID, ho BucketName: reqInfo.BucketName, Key: reqInfo.ObjectName, Resource: resource, - Region: "", RequestID: requestID, 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" +} diff --git a/neofs/api/handler/api.go b/api/handler/api.go similarity index 84% rename from neofs/api/handler/api.go rename to api/handler/api.go index d098b4f10..9499fca12 100644 --- a/neofs/api/handler/api.go +++ b/api/handler/api.go @@ -3,8 +3,8 @@ package handler import ( "errors" - "github.com/minio/minio/neofs/api" - "github.com/minio/minio/neofs/layer" + "github.com/nspcc-dev/neofs-s3-gate/api" + "github.com/nspcc-dev/neofs-s3-gate/api/layer" "go.uber.org/zap" ) diff --git a/neofs/api/handler/unimplemented.go b/api/handler/unimplemented.go similarity index 99% rename from neofs/api/handler/unimplemented.go rename to api/handler/unimplemented.go index 0caa2e432..d7155ab1d 100644 --- a/neofs/api/handler/unimplemented.go +++ b/api/handler/unimplemented.go @@ -3,7 +3,7 @@ package handler import ( "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) { diff --git a/neofs/layer/container.go b/api/layer/container.go similarity index 98% rename from neofs/layer/container.go rename to api/layer/container.go index 6e799386c..5d3308dbb 100644 --- a/neofs/layer/container.go +++ b/api/layer/container.go @@ -4,10 +4,10 @@ import ( "context" "time" - "github.com/minio/minio/auth" "github.com/nspcc-dev/neofs-api-go/container" "github.com/nspcc-dev/neofs-api-go/refs" "github.com/nspcc-dev/neofs-api-go/service" + "github.com/nspcc-dev/neofs-s3-gate/auth" "go.uber.org/zap" ) diff --git a/neofs/layer/layer.go b/api/layer/layer.go similarity index 99% rename from neofs/layer/layer.go rename to api/layer/layer.go index 80c9c4683..79994edde 100644 --- a/neofs/layer/layer.go +++ b/api/layer/layer.go @@ -7,10 +7,10 @@ import ( "strings" "time" - "github.com/minio/minio/neofs/pool" "github.com/nspcc-dev/neofs-api-go/object" "github.com/nspcc-dev/neofs-api-go/refs" "github.com/nspcc-dev/neofs-api-go/service" + "github.com/nspcc-dev/neofs-s3-gate/api/pool" "github.com/pkg/errors" "go.uber.org/zap" ) diff --git a/neofs/layer/object.go b/api/layer/object.go similarity index 99% rename from neofs/layer/object.go rename to api/layer/object.go index bbc9434a1..55b7be11c 100644 --- a/neofs/layer/object.go +++ b/api/layer/object.go @@ -5,12 +5,12 @@ import ( "io" "time" - "github.com/minio/minio/neofs/pool" "github.com/nspcc-dev/neofs-api-go/object" "github.com/nspcc-dev/neofs-api-go/query" "github.com/nspcc-dev/neofs-api-go/refs" "github.com/nspcc-dev/neofs-api-go/service" "github.com/nspcc-dev/neofs-api-go/storagegroup" + "github.com/nspcc-dev/neofs-s3-gate/api/pool" "github.com/pkg/errors" "go.uber.org/zap" ) diff --git a/neofs/layer/util.go b/api/layer/util.go similarity index 100% rename from neofs/layer/util.go rename to api/layer/util.go diff --git a/neofs/api/max-clients.go b/api/max-clients.go similarity index 100% rename from neofs/api/max-clients.go rename to api/max-clients.go diff --git a/neofs/metrics/api.go b/api/metrics/api.go similarity index 95% rename from neofs/metrics/api.go rename to api/metrics/api.go index 7e96771f3..8a29f37c0 100644 --- a/neofs/metrics/api.go +++ b/api/metrics/api.go @@ -49,10 +49,7 @@ type ( } ) -const ( - // TODO: should be imported from routing - systemPath = "/system" -) +const systemPath = "/system" var ( 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 { return func(w http.ResponseWriter, r *http.Request) { httpStatsMetric.currentS3Requests.Inc(api) diff --git a/neofs/metrics/collector.go b/api/metrics/collector.go similarity index 97% rename from neofs/metrics/collector.go rename to api/metrics/collector.go index ec45412d4..9064657c4 100644 --- a/neofs/metrics/collector.go +++ b/api/metrics/collector.go @@ -1,7 +1,7 @@ package metrics import ( - "github.com/minio/minio/misc" + "github.com/nspcc-dev/neofs-s3-gate/misc" "github.com/prometheus/client_golang/prometheus" ) diff --git a/neofs/pool/pool.go b/api/pool/pool.go similarity index 96% rename from neofs/pool/pool.go rename to api/pool/pool.go index 61f4000fd..b9374268f 100644 --- a/neofs/pool/pool.go +++ b/api/pool/pool.go @@ -3,15 +3,11 @@ package pool import ( "context" "crypto/ecdsa" - crand "crypto/rand" - "encoding/binary" "math/rand" "sort" "sync" "time" - "google.golang.org/grpc/grpclog" - "github.com/nspcc-dev/neofs-api-go/service" "github.com/nspcc-dev/neofs-api-go/state" "github.com/pkg/errors" @@ -19,6 +15,7 @@ import ( "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/grpclog" "google.golang.org/grpc/keepalive" ) @@ -121,14 +118,10 @@ func New(cfg *Config) (Pool, error) { grpclog.SetLoggerV2(cfg.GRPCLogger) } - buf := make([]byte, 8) - if _, err := crand.Read(buf); err != nil { - return nil, err - } + seed := time.Now().UnixNano() - seed := binary.BigEndian.Uint64(buf) - rand.Seed(int64(seed)) - cfg.Logger.Info("used random seed", zap.Uint64("seed", seed)) + rand.Seed(seed) + cfg.Logger.Info("used random seed", zap.Int64("seed", seed)) p.reqHealth = new(state.HealthRequest) p.reqHealth.SetTTL(service.NonForwardingTTL) diff --git a/neofs/pool/session.go b/api/pool/session.go similarity index 100% rename from neofs/pool/session.go rename to api/pool/session.go diff --git a/neofs/api/reqinfo.go b/api/reqinfo.go similarity index 100% rename from neofs/api/reqinfo.go rename to api/reqinfo.go diff --git a/neofs/api/response.go b/api/response.go similarity index 98% rename from neofs/api/response.go rename to api/response.go index 546a6aef6..2abc58235 100644 --- a/neofs/api/response.go +++ b/api/response.go @@ -10,7 +10,7 @@ import ( "strconv" "github.com/google/uuid" - "github.com/minio/minio/misc" + "github.com/nspcc-dev/neofs-s3-gate/misc" ) type ( @@ -152,7 +152,7 @@ func setCommonHeaders(w http.ResponseWriter) { // removeSensitiveHeaders removes confidential encryption // 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) { h.Del(hdrSSECustomerKey) h.Del(hdrSSECopyKey) diff --git a/neofs/api/router.go b/api/router.go similarity index 99% rename from neofs/api/router.go rename to api/router.go index 83a6db91a..9b8667d0e 100644 --- a/neofs/api/router.go +++ b/api/router.go @@ -4,8 +4,8 @@ import ( "net/http" "github.com/gorilla/mux" - "github.com/minio/minio/auth" - "github.com/minio/minio/neofs/metrics" + "github.com/nspcc-dev/neofs-s3-gate/api/metrics" + "github.com/nspcc-dev/neofs-s3-gate/auth" "go.uber.org/zap" ) @@ -79,7 +79,6 @@ type ( ) const ( - // SlashSeparator - slash separator. SlashSeparator = "/" diff --git a/neofs/api/user-auth.go b/api/user-auth.go similarity index 93% rename from neofs/api/user-auth.go rename to api/user-auth.go index 17d6eaea6..396d1cb32 100644 --- a/neofs/api/user-auth.go +++ b/api/user-auth.go @@ -4,7 +4,7 @@ import ( "net/http" "github.com/gorilla/mux" - "github.com/minio/minio/auth" + "github.com/nspcc-dev/neofs-s3-gate/auth" "go.uber.org/zap" ) diff --git a/cmd/gate/app-settings.go b/cmd/gate/app-settings.go index 231d3163a..40f3b6533 100644 --- a/cmd/gate/app-settings.go +++ b/cmd/gate/app-settings.go @@ -12,13 +12,11 @@ import ( "strings" "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" + "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/viper" "go.uber.org/zap" diff --git a/cmd/gate/app.go b/cmd/gate/app.go index 55d18ce95..da9bc5f21 100644 --- a/cmd/gate/app.go +++ b/cmd/gate/app.go @@ -7,11 +7,11 @@ import ( "net/http" "time" - "github.com/minio/minio/auth" - "github.com/minio/minio/neofs/api" - "github.com/minio/minio/neofs/api/handler" - "github.com/minio/minio/neofs/layer" - "github.com/minio/minio/neofs/pool" + "github.com/nspcc-dev/neofs-s3-gate/api" + "github.com/nspcc-dev/neofs-s3-gate/api/handler" + "github.com/nspcc-dev/neofs-s3-gate/api/layer" + "github.com/nspcc-dev/neofs-s3-gate/api/pool" + "github.com/nspcc-dev/neofs-s3-gate/auth" "github.com/spf13/viper" "go.uber.org/zap" "google.golang.org/grpc/keepalive" diff --git a/go.mod b/go.mod index 3bf4d3fa9..ec0123653 100644 --- a/go.mod +++ b/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 ( github.com/google/uuid v1.1.1 github.com/gorilla/mux v1.7.4 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-crypto v0.3.0 github.com/pkg/errors v0.9.1 @@ -15,5 +14,11 @@ require ( github.com/spf13/viper v1.7.0 go.uber.org/atomic v1.6.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 + gopkg.in/ini.v1 v1.57.0 // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect ) diff --git a/go.sum b/go.sum index ca99fbd9e..5bc10ab7a 100644 --- a/go.sum +++ b/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.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.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/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= @@ -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/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/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/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 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/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 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/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 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/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/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/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= @@ -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/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/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/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= diff --git a/neofs/api/crypto/errors.go b/neofs/api/crypto/errors.go deleted file mode 100644 index 14beb9c1a..000000000 --- a/neofs/api/crypto/errors.go +++ /dev/null @@ -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 " - } - 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") -) diff --git a/neofs/api/object-errors.go b/neofs/api/object-errors.go deleted file mode 100644 index be10d1eef..000000000 --- a/neofs/api/object-errors.go +++ /dev/null @@ -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 -} diff --git a/neofs/api/storage-errors.go b/neofs/api/storage-errors.go deleted file mode 100644 index c72b92382..000000000 --- a/neofs/api/storage-errors.go +++ /dev/null @@ -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 diff --git a/neofs/api/typed-errors.go b/neofs/api/typed-errors.go deleted file mode 100644 index 45791bd64..000000000 --- a/neofs/api/typed-errors.go +++ /dev/null @@ -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") diff --git a/neofs/api/xl-v1-errors.go b/neofs/api/xl-v1-errors.go deleted file mode 100644 index 52578040d..000000000 --- a/neofs/api/xl-v1-errors.go +++ /dev/null @@ -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")