[#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:
Evgeniy Kulikov 2020-08-06 15:02:13 +03:00
parent e7f72fc670
commit 0161d2fbd3
25 changed files with 396 additions and 1112 deletions

View file

@ -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"
}

View file

@ -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"
)

View file

@ -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) {

View file

@ -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"
)

View file

@ -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"
)

View file

@ -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"
)

View file

@ -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)

View file

@ -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"
)

View file

@ -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)

View file

@ -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)

View file

@ -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 = "/"

View file

@ -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"
)

View file

@ -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"

View file

@ -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"

11
go.mod
View file

@ -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
)

11
go.sum
View file

@ -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=

View file

@ -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")
)

View file

@ -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
}

View file

@ -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

View file

@ -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")

View file

@ -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")