go-ceph/rgw/admin/errors.go
Sébastien Han 6be8d370cb rgwadmin: add support for RadosGW Admin Ops API
Following this discussion #492

This commit introduces a new package "rgw/admin" which helps you interact
with the [RadosGW Admin Ops API](https://docs.ceph.com/en/latest/radosgw/adminops).
Not all the API capabilities are covered by this commit, but this is a
solid foundation for adding code on top. I'm expecting a few more
iterations to make 100% complete. Also, the RadosGW Admin API is going
to implement new functions soon (like bucket creation). So this library
will live on and keep catching up.

As many unit tests as possible have been added. A new integration test
suite also runs. The "micro-osd.sh" now deploys a RGW and the
integration suite tests on it. Thus the CI should cover it.

Shout out to @QuentinPerez and @IrekFasikhov for their existing
libraries. They were a very good inspiration to get started.

Co-authored-by: Irek Fasikhov <malmyzh@gmail.com>
Co-authored-by: Quentin Perez <qperez42@gmail.com>
Signed-off-by: Sébastien Han <seb@redhat.com>
2021-05-31 17:45:31 +02:00

117 lines
3.7 KiB
Go

package admin
import (
"encoding/json"
"errors"
"fmt"
)
const (
// ErrUserExists - Attempt to create existing user
ErrUserExists errorReason = "UserAlreadyExists"
// ErrNoSuchUser - Attempt to create existing user
ErrNoSuchUser errorReason = "NoSuchUser"
// ErrInvalidAccessKey - Invalid access key specified
ErrInvalidAccessKey errorReason = "InvalidAccessKey"
// ErrInvalidSecretKey - Invalid secret key specified
ErrInvalidSecretKey errorReason = "InvalidSecretKey"
// ErrInvalidKeyType - Invalid key type specified
ErrInvalidKeyType errorReason = "InvalidKeyType"
// ErrKeyExists - Provided access key exists and belongs to another user
ErrKeyExists errorReason = "KeyExists"
// ErrEmailExists - Provided email address exists
ErrEmailExists errorReason = "EmailExists"
// ErrInvalidCapability - Attempt to remove an invalid admin capability
ErrInvalidCapability errorReason = "InvalidCapability"
// ErrSubuserExists - Specified subuser exists
ErrSubuserExists errorReason = "SubuserExists"
// ErrInvalidAccess - Invalid subuser access specified
ErrInvalidAccess errorReason = "InvalidAccess"
// ErrIndexRepairFailed - Bucket index repair failed
ErrIndexRepairFailed errorReason = "IndexRepairFailed"
// ErrBucketNotEmpty - Attempted to delete non-empty bucket
ErrBucketNotEmpty errorReason = "BucketNotEmpty"
// ErrObjectRemovalFailed - Unable to remove objects
ErrObjectRemovalFailed errorReason = "ObjectRemovalFailed"
// ErrBucketUnlinkFailed - Unable to unlink bucket from specified user
ErrBucketUnlinkFailed errorReason = "BucketUnlinkFailed"
// ErrBucketLinkFailed - Unable to link bucket to specified user
ErrBucketLinkFailed errorReason = "BucketLinkFailed"
// ErrNoSuchObject - Specified object does not exist
ErrNoSuchObject errorReason = "NoSuchObject"
// ErrIncompleteBody - Either bucket was not specified for a bucket policy request or bucket and object were not specified for an object policy request.
ErrIncompleteBody errorReason = "IncompleteBody"
// ErrNoSuchCap - User does not possess specified capability
ErrNoSuchCap errorReason = "NoSuchCap"
// ErrInternalError - Internal server error.
ErrInternalError errorReason = "InternalError"
// ErrAccessDenied - Access denied.
ErrAccessDenied errorReason = "AccessDenied"
// ErrNoSuchBucket - Bucket does not exist.
ErrNoSuchBucket errorReason = "NoSuchBucket"
// ErrNoSuchKey - No such access key.
ErrNoSuchKey errorReason = "NoSuchKey"
// ErrInvalidArgument - Invalid argument.
ErrInvalidArgument errorReason = "InvalidArgument"
// ErrUnknown - reports an unknown error
ErrUnknown errorReason = "Unknown"
unmarshalError = "failed to unmarshal radosgw http response"
)
var (
errMissingUserID = errors.New("missing user ID")
errMissingUserDisplayName = errors.New("missing user display name")
)
// errorReason is the reason of the error
type errorReason string
// statusError is the API response when an error occurs
type statusError struct {
Code string `json:"Code,omitempty"`
RequestID string `json:"RequestId,omitempty"`
HostID string `json:"HostId,omitempty"`
}
func handleStatusError(decodedResponse []byte) error {
statusError := statusError{}
err := json.Unmarshal(decodedResponse, &statusError)
if err != nil {
return fmt.Errorf("%s. %s. %w", unmarshalError, string(decodedResponse), err)
}
return statusError
}
func (e errorReason) Error() string { return string(e) }
// Is determines whether the error is known to be reported
func (e statusError) Is(target error) bool { return target == errorReason(e.Code) }
// Error returns non-empty string if there was an error.
func (e statusError) Error() string { return fmt.Sprintf("%s %s %s", e.Code, e.RequestID, e.HostID) }