2021-11-16 18:15:56 +00:00
|
|
|
package apistatus
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2024-05-06 13:33:20 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
|
2023-03-07 11:20:03 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status"
|
2021-11-16 18:15:56 +00:00
|
|
|
)
|
|
|
|
|
2022-12-29 10:46:18 +00:00
|
|
|
// StatusV2 defines a variety of Status instances compatible with FrostFS API V2 protocol.
|
2021-11-16 18:15:56 +00:00
|
|
|
//
|
|
|
|
// Note: it is not recommended to use this type directly, it is intended for documentation of the library functionality.
|
|
|
|
type StatusV2 interface {
|
|
|
|
Status
|
|
|
|
|
2023-03-07 11:20:03 +00:00
|
|
|
// ToStatusV2 returns the status as git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status.Status message structure.
|
2021-11-16 18:15:56 +00:00
|
|
|
ToStatusV2() *status.Status
|
|
|
|
}
|
|
|
|
|
|
|
|
// FromStatusV2 converts status.Status message structure to Status instance. Inverse to ToStatusV2 operation.
|
|
|
|
//
|
|
|
|
// If result is not nil, it implements StatusV2. This fact should be taken into account only when passing
|
|
|
|
// the result to the inverse function ToStatusV2, casts are not compatibility-safe.
|
|
|
|
//
|
|
|
|
// Below is the mapping of return codes to Status instance types (with a description of parsing details).
|
|
|
|
// Note: notice if the return type is a pointer.
|
|
|
|
//
|
|
|
|
// Successes:
|
2022-08-24 14:17:40 +00:00
|
|
|
// - status.OK: *SuccessDefaultV2 (this also includes nil argument).
|
2021-11-16 18:15:56 +00:00
|
|
|
//
|
|
|
|
// Common failures:
|
2022-08-24 14:17:40 +00:00
|
|
|
// - status.Internal: *ServerInternal;
|
2024-10-02 08:12:49 +00:00
|
|
|
// - status.WrongMagicNumber: *WrongMagicNumber;
|
|
|
|
// - status.SignatureVerificationFail: *SignatureVerification;
|
|
|
|
// - status.NodeUnderMaintenance: *NodeUnderMaintenance;
|
|
|
|
// - status.InvalidArgument: *InvalidArgument.
|
2022-02-15 05:41:03 +00:00
|
|
|
//
|
|
|
|
// Object failures:
|
2022-08-24 14:17:40 +00:00
|
|
|
// - object.StatusLocked: *ObjectLocked;
|
2024-10-02 08:12:49 +00:00
|
|
|
// - object.StatusLockNonRegularObject: *LockNonRegularObject;
|
|
|
|
// - object.StatusAccessDenied: *ObjectAccessDenied;
|
|
|
|
// - object.StatusNotFound: *ObjectNotFound;
|
|
|
|
// - object.StatusAlreadyRemoved: *ObjectAlreadyRemoved;
|
|
|
|
// - object.StatusOutOfRange: *ObjectOutOfRange.
|
|
|
|
//
|
|
|
|
// Container failures:
|
|
|
|
// - container.StatusNotFound: *ContainerNotFound;
|
|
|
|
// - container.StatusEACLNotFound: *EACLNotFound.
|
|
|
|
//
|
|
|
|
// Session failures:
|
|
|
|
// - session.StatusTokenNotFound: *SessionTokenNotFound;
|
|
|
|
// - session.StatusTokenExpired: *SessionTokenExpired.
|
|
|
|
//
|
|
|
|
// APE Manager failures
|
|
|
|
// - apemanager.StatusAPEManagerAccessDenied: *APEManagerAccessDenied.
|
2021-11-16 18:15:56 +00:00
|
|
|
func FromStatusV2(st *status.Status) Status {
|
|
|
|
var decoder interface {
|
|
|
|
fromStatusV2(*status.Status)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch code := st.Code(); {
|
|
|
|
case status.IsSuccess(code):
|
2022-02-24 12:04:12 +00:00
|
|
|
//nolint:exhaustive
|
2021-11-16 18:15:56 +00:00
|
|
|
switch status.LocalizeSuccess(&code); code {
|
|
|
|
case status.OK:
|
|
|
|
decoder = new(SuccessDefaultV2)
|
|
|
|
}
|
|
|
|
case status.IsCommonFail(code):
|
|
|
|
switch status.LocalizeCommonFail(&code); code {
|
|
|
|
case status.Internal:
|
|
|
|
decoder = new(ServerInternal)
|
2022-01-25 12:37:30 +00:00
|
|
|
case status.WrongMagicNumber:
|
|
|
|
decoder = new(WrongMagicNumber)
|
2022-06-16 21:04:23 +00:00
|
|
|
case status.SignatureVerificationFail:
|
|
|
|
decoder = new(SignatureVerification)
|
2022-09-19 17:34:14 +00:00
|
|
|
case status.NodeUnderMaintenance:
|
|
|
|
decoder = new(NodeUnderMaintenance)
|
2024-10-02 08:12:49 +00:00
|
|
|
case status.InvalidArgument:
|
|
|
|
decoder = new(InvalidArgument)
|
2021-11-16 18:15:56 +00:00
|
|
|
}
|
2022-02-15 05:41:03 +00:00
|
|
|
case object.LocalizeFailStatus(&code):
|
|
|
|
switch code {
|
|
|
|
case object.StatusLocked:
|
|
|
|
decoder = new(ObjectLocked)
|
|
|
|
case object.StatusLockNonRegularObject:
|
|
|
|
decoder = new(LockNonRegularObject)
|
2022-02-28 08:39:22 +00:00
|
|
|
case object.StatusAccessDenied:
|
|
|
|
decoder = new(ObjectAccessDenied)
|
2022-02-28 08:45:33 +00:00
|
|
|
case object.StatusNotFound:
|
|
|
|
decoder = new(ObjectNotFound)
|
2022-02-28 08:49:34 +00:00
|
|
|
case object.StatusAlreadyRemoved:
|
|
|
|
decoder = new(ObjectAlreadyRemoved)
|
2022-06-29 17:24:56 +00:00
|
|
|
case object.StatusOutOfRange:
|
|
|
|
decoder = new(ObjectOutOfRange)
|
2022-02-15 05:41:03 +00:00
|
|
|
}
|
2022-02-28 08:55:25 +00:00
|
|
|
case container.LocalizeFailStatus(&code):
|
|
|
|
//nolint:exhaustive
|
|
|
|
switch code {
|
|
|
|
case container.StatusNotFound:
|
|
|
|
decoder = new(ContainerNotFound)
|
2022-08-01 14:17:48 +00:00
|
|
|
case container.StatusEACLNotFound:
|
|
|
|
decoder = new(EACLNotFound)
|
2022-02-28 08:55:25 +00:00
|
|
|
}
|
2022-02-28 10:19:54 +00:00
|
|
|
case session.LocalizeFailStatus(&code):
|
|
|
|
//nolint:exhaustive
|
|
|
|
switch code {
|
|
|
|
case session.StatusTokenNotFound:
|
|
|
|
decoder = new(SessionTokenNotFound)
|
|
|
|
case session.StatusTokenExpired:
|
|
|
|
decoder = new(SessionTokenExpired)
|
|
|
|
}
|
2024-05-06 13:33:20 +00:00
|
|
|
case apemanager.LocalizeFailStatus(&code):
|
|
|
|
//nolint:exhaustive
|
|
|
|
switch code {
|
|
|
|
case apemanager.StatusAPEManagerAccessDenied:
|
|
|
|
decoder = new(APEManagerAccessDenied)
|
|
|
|
}
|
2021-11-16 18:15:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if decoder == nil {
|
|
|
|
decoder = new(unrecognizedStatusV2)
|
|
|
|
}
|
|
|
|
|
|
|
|
decoder.fromStatusV2(st)
|
|
|
|
|
|
|
|
return decoder
|
|
|
|
}
|
|
|
|
|
|
|
|
// ToStatusV2 converts Status instance to status.Status message structure. Inverse to FromStatusV2 operation.
|
|
|
|
//
|
|
|
|
// If argument is the StatusV2 instance, it is converted directly.
|
2022-03-16 13:54:20 +00:00
|
|
|
// Otherwise, successes are converted with status.OK code w/o details and message,
|
|
|
|
// failures - with status.Internal and error text message w/o details.
|
2021-11-16 18:15:56 +00:00
|
|
|
func ToStatusV2(st Status) *status.Status {
|
|
|
|
if v, ok := st.(StatusV2); ok {
|
|
|
|
return v.ToStatusV2()
|
|
|
|
}
|
|
|
|
|
|
|
|
if IsSuccessful(st) {
|
|
|
|
return newStatusV2WithLocalCode(status.OK, status.GlobalizeSuccess)
|
|
|
|
}
|
|
|
|
|
2022-03-16 13:54:20 +00:00
|
|
|
internalErrorStatus := newStatusV2WithLocalCode(status.Internal, status.GlobalizeCommonFail)
|
|
|
|
internalErrorStatus.SetMessage(st.(error).Error()) // type cast never panics because IsSuccessful() checks cast
|
|
|
|
|
|
|
|
return internalErrorStatus
|
2021-11-16 18:15:56 +00:00
|
|
|
}
|
|
|
|
|
2023-05-15 14:21:49 +00:00
|
|
|
func errMessageStatusV2(code any, msg string) string {
|
2021-11-16 18:15:56 +00:00
|
|
|
const (
|
|
|
|
noMsgFmt = "status: code = %v"
|
|
|
|
msgFmt = noMsgFmt + " message = %s"
|
|
|
|
)
|
|
|
|
|
|
|
|
if msg != "" {
|
|
|
|
return fmt.Sprintf(msgFmt, code, msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Sprintf(noMsgFmt, code)
|
|
|
|
}
|
|
|
|
|
|
|
|
func newStatusV2WithLocalCode(code status.Code, globalizer func(*status.Code)) *status.Status {
|
|
|
|
var st status.Status
|
|
|
|
|
|
|
|
st.SetCode(globalizeCodeV2(code, globalizer))
|
|
|
|
|
|
|
|
return &st
|
|
|
|
}
|
|
|
|
|
|
|
|
func globalizeCodeV2(code status.Code, globalizer func(*status.Code)) status.Code {
|
|
|
|
globalizer(&code)
|
|
|
|
return code
|
|
|
|
}
|