git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/client/status/v2.go (about) 1 package apistatus 2 3 import ( 4 "fmt" 5 6 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" 7 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" 8 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" 9 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" 10 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" 11 ) 12 13 // StatusV2 defines a variety of Status instances compatible with FrostFS API V2 protocol. 14 // 15 // Note: it is not recommended to use this type directly, it is intended for documentation of the library functionality. 16 type StatusV2 interface { 17 Status 18 19 // ToStatusV2 returns the status as git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status.Status message structure. 20 ToStatusV2() *status.Status 21 } 22 23 // FromStatusV2 converts status.Status message structure to Status instance. Inverse to ToStatusV2 operation. 24 // 25 // If result is not nil, it implements StatusV2. This fact should be taken into account only when passing 26 // the result to the inverse function ToStatusV2, casts are not compatibility-safe. 27 // 28 // Below is the mapping of return codes to Status instance types (with a description of parsing details). 29 // Note: notice if the return type is a pointer. 30 // 31 // Successes: 32 // - status.OK: *SuccessDefaultV2 (this also includes nil argument). 33 // 34 // Common failures: 35 // - status.Internal: *ServerInternal; 36 // - status.WrongMagicNumber: *WrongMagicNumber; 37 // - status.SignatureVerificationFail: *SignatureVerification; 38 // - status.NodeUnderMaintenance: *NodeUnderMaintenance; 39 // - status.InvalidArgument: *InvalidArgument. 40 // 41 // Object failures: 42 // - object.StatusLocked: *ObjectLocked; 43 // - object.StatusLockNonRegularObject: *LockNonRegularObject; 44 // - object.StatusAccessDenied: *ObjectAccessDenied; 45 // - object.StatusNotFound: *ObjectNotFound; 46 // - object.StatusAlreadyRemoved: *ObjectAlreadyRemoved; 47 // - object.StatusOutOfRange: *ObjectOutOfRange. 48 // 49 // Container failures: 50 // - container.StatusNotFound: *ContainerNotFound; 51 // - container.StatusEACLNotFound: *EACLNotFound. 52 // 53 // Session failures: 54 // - session.StatusTokenNotFound: *SessionTokenNotFound; 55 // - session.StatusTokenExpired: *SessionTokenExpired. 56 // 57 // APE Manager failures 58 // - apemanager.StatusAPEManagerAccessDenied: *APEManagerAccessDenied. 59 func FromStatusV2(st *status.Status) Status { 60 var decoder interface { 61 fromStatusV2(*status.Status) 62 } 63 64 switch code := st.Code(); { 65 case status.IsSuccess(code): 66 //nolint:exhaustive 67 switch status.LocalizeSuccess(&code); code { 68 case status.OK: 69 decoder = new(SuccessDefaultV2) 70 } 71 case status.IsCommonFail(code): 72 switch status.LocalizeCommonFail(&code); code { 73 case status.Internal: 74 decoder = new(ServerInternal) 75 case status.WrongMagicNumber: 76 decoder = new(WrongMagicNumber) 77 case status.SignatureVerificationFail: 78 decoder = new(SignatureVerification) 79 case status.NodeUnderMaintenance: 80 decoder = new(NodeUnderMaintenance) 81 case status.InvalidArgument: 82 decoder = new(InvalidArgument) 83 } 84 case object.LocalizeFailStatus(&code): 85 switch code { 86 case object.StatusLocked: 87 decoder = new(ObjectLocked) 88 case object.StatusLockNonRegularObject: 89 decoder = new(LockNonRegularObject) 90 case object.StatusAccessDenied: 91 decoder = new(ObjectAccessDenied) 92 case object.StatusNotFound: 93 decoder = new(ObjectNotFound) 94 case object.StatusAlreadyRemoved: 95 decoder = new(ObjectAlreadyRemoved) 96 case object.StatusOutOfRange: 97 decoder = new(ObjectOutOfRange) 98 } 99 case container.LocalizeFailStatus(&code): 100 //nolint:exhaustive 101 switch code { 102 case container.StatusNotFound: 103 decoder = new(ContainerNotFound) 104 case container.StatusEACLNotFound: 105 decoder = new(EACLNotFound) 106 } 107 case session.LocalizeFailStatus(&code): 108 //nolint:exhaustive 109 switch code { 110 case session.StatusTokenNotFound: 111 decoder = new(SessionTokenNotFound) 112 case session.StatusTokenExpired: 113 decoder = new(SessionTokenExpired) 114 } 115 case apemanager.LocalizeFailStatus(&code): 116 //nolint:exhaustive 117 switch code { 118 case apemanager.StatusAPEManagerAccessDenied: 119 decoder = new(APEManagerAccessDenied) 120 } 121 } 122 123 if decoder == nil { 124 decoder = new(unrecognizedStatusV2) 125 } 126 127 decoder.fromStatusV2(st) 128 129 return decoder 130 } 131 132 // ToStatusV2 converts Status instance to status.Status message structure. Inverse to FromStatusV2 operation. 133 // 134 // If argument is the StatusV2 instance, it is converted directly. 135 // Otherwise, successes are converted with status.OK code w/o details and message, 136 // failures - with status.Internal and error text message w/o details. 137 func ToStatusV2(st Status) *status.Status { 138 if v, ok := st.(StatusV2); ok { 139 return v.ToStatusV2() 140 } 141 142 if IsSuccessful(st) { 143 return newStatusV2WithLocalCode(status.OK, status.GlobalizeSuccess) 144 } 145 146 internalErrorStatus := newStatusV2WithLocalCode(status.Internal, status.GlobalizeCommonFail) 147 internalErrorStatus.SetMessage(st.(error).Error()) // type cast never panics because IsSuccessful() checks cast 148 149 return internalErrorStatus 150 } 151 152 func errMessageStatusV2(code any, msg string) string { 153 const ( 154 noMsgFmt = "status: code = %v" 155 msgFmt = noMsgFmt + " message = %s" 156 ) 157 158 if msg != "" { 159 return fmt.Sprintf(msgFmt, code, msg) 160 } 161 162 return fmt.Sprintf(noMsgFmt, code) 163 } 164 165 func newStatusV2WithLocalCode(code status.Code, globalizer func(*status.Code)) *status.Status { 166 var st status.Status 167 168 st.SetCode(globalizeCodeV2(code, globalizer)) 169 170 return &st 171 } 172 173 func globalizeCodeV2(code status.Code, globalizer func(*status.Code)) status.Code { 174 globalizer(&code) 175 return code 176 }