William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 1 | // Copyright 2015 The etcd Authors |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | package rpctypes |
| 16 | |
| 17 | import ( |
| 18 | "google.golang.org/grpc/codes" |
| 19 | "google.golang.org/grpc/status" |
| 20 | ) |
| 21 | |
| 22 | // server-side error |
| 23 | var ( |
| 24 | ErrGRPCEmptyKey = status.New(codes.InvalidArgument, "etcdserver: key is not provided").Err() |
| 25 | ErrGRPCKeyNotFound = status.New(codes.InvalidArgument, "etcdserver: key not found").Err() |
| 26 | ErrGRPCValueProvided = status.New(codes.InvalidArgument, "etcdserver: value is provided").Err() |
| 27 | ErrGRPCLeaseProvided = status.New(codes.InvalidArgument, "etcdserver: lease is provided").Err() |
| 28 | ErrGRPCTooManyOps = status.New(codes.InvalidArgument, "etcdserver: too many operations in txn request").Err() |
| 29 | ErrGRPCDuplicateKey = status.New(codes.InvalidArgument, "etcdserver: duplicate key given in txn request").Err() |
| 30 | ErrGRPCCompacted = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision has been compacted").Err() |
| 31 | ErrGRPCFutureRev = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision").Err() |
| 32 | ErrGRPCNoSpace = status.New(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded").Err() |
| 33 | |
| 34 | ErrGRPCLeaseNotFound = status.New(codes.NotFound, "etcdserver: requested lease not found").Err() |
| 35 | ErrGRPCLeaseExist = status.New(codes.FailedPrecondition, "etcdserver: lease already exists").Err() |
| 36 | ErrGRPCLeaseTTLTooLarge = status.New(codes.OutOfRange, "etcdserver: too large lease TTL").Err() |
| 37 | |
| 38 | ErrGRPCMemberExist = status.New(codes.FailedPrecondition, "etcdserver: member ID already exist").Err() |
| 39 | ErrGRPCPeerURLExist = status.New(codes.FailedPrecondition, "etcdserver: Peer URLs already exists").Err() |
| 40 | ErrGRPCMemberNotEnoughStarted = status.New(codes.FailedPrecondition, "etcdserver: re-configuration failed due to not enough started members").Err() |
| 41 | ErrGRPCMemberBadURLs = status.New(codes.InvalidArgument, "etcdserver: given member URLs are invalid").Err() |
| 42 | ErrGRPCMemberNotFound = status.New(codes.NotFound, "etcdserver: member not found").Err() |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 43 | ErrGRPCMemberNotLearner = status.New(codes.FailedPrecondition, "etcdserver: can only promote a learner member").Err() |
| 44 | ErrGRPCLearnerNotReady = status.New(codes.FailedPrecondition, "etcdserver: can only promote a learner member which is in sync with leader").Err() |
| 45 | ErrGRPCTooManyLearners = status.New(codes.FailedPrecondition, "etcdserver: too many learner members in cluster").Err() |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 46 | |
| 47 | ErrGRPCRequestTooLarge = status.New(codes.InvalidArgument, "etcdserver: request is too large").Err() |
| 48 | ErrGRPCRequestTooManyRequests = status.New(codes.ResourceExhausted, "etcdserver: too many requests").Err() |
| 49 | |
| 50 | ErrGRPCRootUserNotExist = status.New(codes.FailedPrecondition, "etcdserver: root user does not exist").Err() |
| 51 | ErrGRPCRootRoleNotExist = status.New(codes.FailedPrecondition, "etcdserver: root user does not have root role").Err() |
| 52 | ErrGRPCUserAlreadyExist = status.New(codes.FailedPrecondition, "etcdserver: user name already exists").Err() |
| 53 | ErrGRPCUserEmpty = status.New(codes.InvalidArgument, "etcdserver: user name is empty").Err() |
| 54 | ErrGRPCUserNotFound = status.New(codes.FailedPrecondition, "etcdserver: user name not found").Err() |
| 55 | ErrGRPCRoleAlreadyExist = status.New(codes.FailedPrecondition, "etcdserver: role name already exists").Err() |
| 56 | ErrGRPCRoleNotFound = status.New(codes.FailedPrecondition, "etcdserver: role name not found").Err() |
David Bainbridge | 788e520 | 2019-10-21 18:49:40 +0000 | [diff] [blame] | 57 | ErrGRPCRoleEmpty = status.New(codes.InvalidArgument, "etcdserver: role name is empty").Err() |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 58 | ErrGRPCAuthFailed = status.New(codes.InvalidArgument, "etcdserver: authentication failed, invalid user ID or password").Err() |
| 59 | ErrGRPCPermissionDenied = status.New(codes.PermissionDenied, "etcdserver: permission denied").Err() |
| 60 | ErrGRPCRoleNotGranted = status.New(codes.FailedPrecondition, "etcdserver: role is not granted to the user").Err() |
| 61 | ErrGRPCPermissionNotGranted = status.New(codes.FailedPrecondition, "etcdserver: permission is not granted to the role").Err() |
| 62 | ErrGRPCAuthNotEnabled = status.New(codes.FailedPrecondition, "etcdserver: authentication is not enabled").Err() |
| 63 | ErrGRPCInvalidAuthToken = status.New(codes.Unauthenticated, "etcdserver: invalid auth token").Err() |
| 64 | ErrGRPCInvalidAuthMgmt = status.New(codes.InvalidArgument, "etcdserver: invalid auth management").Err() |
| 65 | |
| 66 | ErrGRPCNoLeader = status.New(codes.Unavailable, "etcdserver: no leader").Err() |
| 67 | ErrGRPCNotLeader = status.New(codes.FailedPrecondition, "etcdserver: not leader").Err() |
| 68 | ErrGRPCLeaderChanged = status.New(codes.Unavailable, "etcdserver: leader changed").Err() |
| 69 | ErrGRPCNotCapable = status.New(codes.Unavailable, "etcdserver: not capable").Err() |
| 70 | ErrGRPCStopped = status.New(codes.Unavailable, "etcdserver: server stopped").Err() |
| 71 | ErrGRPCTimeout = status.New(codes.Unavailable, "etcdserver: request timed out").Err() |
| 72 | ErrGRPCTimeoutDueToLeaderFail = status.New(codes.Unavailable, "etcdserver: request timed out, possibly due to previous leader failure").Err() |
| 73 | ErrGRPCTimeoutDueToConnectionLost = status.New(codes.Unavailable, "etcdserver: request timed out, possibly due to connection lost").Err() |
| 74 | ErrGRPCUnhealthy = status.New(codes.Unavailable, "etcdserver: unhealthy cluster").Err() |
| 75 | ErrGRPCCorrupt = status.New(codes.DataLoss, "etcdserver: corrupt cluster").Err() |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 76 | ErrGPRCNotSupportedForLearner = status.New(codes.Unavailable, "etcdserver: rpc not supported for learner").Err() |
| 77 | ErrGRPCBadLeaderTransferee = status.New(codes.FailedPrecondition, "etcdserver: bad leader transferee").Err() |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 78 | |
| 79 | errStringToError = map[string]error{ |
| 80 | ErrorDesc(ErrGRPCEmptyKey): ErrGRPCEmptyKey, |
| 81 | ErrorDesc(ErrGRPCKeyNotFound): ErrGRPCKeyNotFound, |
| 82 | ErrorDesc(ErrGRPCValueProvided): ErrGRPCValueProvided, |
| 83 | ErrorDesc(ErrGRPCLeaseProvided): ErrGRPCLeaseProvided, |
| 84 | |
| 85 | ErrorDesc(ErrGRPCTooManyOps): ErrGRPCTooManyOps, |
| 86 | ErrorDesc(ErrGRPCDuplicateKey): ErrGRPCDuplicateKey, |
| 87 | ErrorDesc(ErrGRPCCompacted): ErrGRPCCompacted, |
| 88 | ErrorDesc(ErrGRPCFutureRev): ErrGRPCFutureRev, |
| 89 | ErrorDesc(ErrGRPCNoSpace): ErrGRPCNoSpace, |
| 90 | |
| 91 | ErrorDesc(ErrGRPCLeaseNotFound): ErrGRPCLeaseNotFound, |
| 92 | ErrorDesc(ErrGRPCLeaseExist): ErrGRPCLeaseExist, |
| 93 | ErrorDesc(ErrGRPCLeaseTTLTooLarge): ErrGRPCLeaseTTLTooLarge, |
| 94 | |
| 95 | ErrorDesc(ErrGRPCMemberExist): ErrGRPCMemberExist, |
| 96 | ErrorDesc(ErrGRPCPeerURLExist): ErrGRPCPeerURLExist, |
| 97 | ErrorDesc(ErrGRPCMemberNotEnoughStarted): ErrGRPCMemberNotEnoughStarted, |
| 98 | ErrorDesc(ErrGRPCMemberBadURLs): ErrGRPCMemberBadURLs, |
| 99 | ErrorDesc(ErrGRPCMemberNotFound): ErrGRPCMemberNotFound, |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 100 | ErrorDesc(ErrGRPCMemberNotLearner): ErrGRPCMemberNotLearner, |
| 101 | ErrorDesc(ErrGRPCLearnerNotReady): ErrGRPCLearnerNotReady, |
| 102 | ErrorDesc(ErrGRPCTooManyLearners): ErrGRPCTooManyLearners, |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 103 | |
| 104 | ErrorDesc(ErrGRPCRequestTooLarge): ErrGRPCRequestTooLarge, |
| 105 | ErrorDesc(ErrGRPCRequestTooManyRequests): ErrGRPCRequestTooManyRequests, |
| 106 | |
| 107 | ErrorDesc(ErrGRPCRootUserNotExist): ErrGRPCRootUserNotExist, |
| 108 | ErrorDesc(ErrGRPCRootRoleNotExist): ErrGRPCRootRoleNotExist, |
| 109 | ErrorDesc(ErrGRPCUserAlreadyExist): ErrGRPCUserAlreadyExist, |
| 110 | ErrorDesc(ErrGRPCUserEmpty): ErrGRPCUserEmpty, |
| 111 | ErrorDesc(ErrGRPCUserNotFound): ErrGRPCUserNotFound, |
| 112 | ErrorDesc(ErrGRPCRoleAlreadyExist): ErrGRPCRoleAlreadyExist, |
| 113 | ErrorDesc(ErrGRPCRoleNotFound): ErrGRPCRoleNotFound, |
David Bainbridge | 788e520 | 2019-10-21 18:49:40 +0000 | [diff] [blame] | 114 | ErrorDesc(ErrGRPCRoleEmpty): ErrGRPCRoleEmpty, |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 115 | ErrorDesc(ErrGRPCAuthFailed): ErrGRPCAuthFailed, |
| 116 | ErrorDesc(ErrGRPCPermissionDenied): ErrGRPCPermissionDenied, |
| 117 | ErrorDesc(ErrGRPCRoleNotGranted): ErrGRPCRoleNotGranted, |
| 118 | ErrorDesc(ErrGRPCPermissionNotGranted): ErrGRPCPermissionNotGranted, |
| 119 | ErrorDesc(ErrGRPCAuthNotEnabled): ErrGRPCAuthNotEnabled, |
| 120 | ErrorDesc(ErrGRPCInvalidAuthToken): ErrGRPCInvalidAuthToken, |
| 121 | ErrorDesc(ErrGRPCInvalidAuthMgmt): ErrGRPCInvalidAuthMgmt, |
| 122 | |
| 123 | ErrorDesc(ErrGRPCNoLeader): ErrGRPCNoLeader, |
| 124 | ErrorDesc(ErrGRPCNotLeader): ErrGRPCNotLeader, |
| 125 | ErrorDesc(ErrGRPCLeaderChanged): ErrGRPCLeaderChanged, |
| 126 | ErrorDesc(ErrGRPCNotCapable): ErrGRPCNotCapable, |
| 127 | ErrorDesc(ErrGRPCStopped): ErrGRPCStopped, |
| 128 | ErrorDesc(ErrGRPCTimeout): ErrGRPCTimeout, |
| 129 | ErrorDesc(ErrGRPCTimeoutDueToLeaderFail): ErrGRPCTimeoutDueToLeaderFail, |
| 130 | ErrorDesc(ErrGRPCTimeoutDueToConnectionLost): ErrGRPCTimeoutDueToConnectionLost, |
| 131 | ErrorDesc(ErrGRPCUnhealthy): ErrGRPCUnhealthy, |
| 132 | ErrorDesc(ErrGRPCCorrupt): ErrGRPCCorrupt, |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 133 | ErrorDesc(ErrGPRCNotSupportedForLearner): ErrGPRCNotSupportedForLearner, |
| 134 | ErrorDesc(ErrGRPCBadLeaderTransferee): ErrGRPCBadLeaderTransferee, |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 135 | } |
| 136 | ) |
| 137 | |
| 138 | // client-side error |
| 139 | var ( |
| 140 | ErrEmptyKey = Error(ErrGRPCEmptyKey) |
| 141 | ErrKeyNotFound = Error(ErrGRPCKeyNotFound) |
| 142 | ErrValueProvided = Error(ErrGRPCValueProvided) |
| 143 | ErrLeaseProvided = Error(ErrGRPCLeaseProvided) |
| 144 | ErrTooManyOps = Error(ErrGRPCTooManyOps) |
| 145 | ErrDuplicateKey = Error(ErrGRPCDuplicateKey) |
| 146 | ErrCompacted = Error(ErrGRPCCompacted) |
| 147 | ErrFutureRev = Error(ErrGRPCFutureRev) |
| 148 | ErrNoSpace = Error(ErrGRPCNoSpace) |
| 149 | |
| 150 | ErrLeaseNotFound = Error(ErrGRPCLeaseNotFound) |
| 151 | ErrLeaseExist = Error(ErrGRPCLeaseExist) |
| 152 | ErrLeaseTTLTooLarge = Error(ErrGRPCLeaseTTLTooLarge) |
| 153 | |
| 154 | ErrMemberExist = Error(ErrGRPCMemberExist) |
| 155 | ErrPeerURLExist = Error(ErrGRPCPeerURLExist) |
| 156 | ErrMemberNotEnoughStarted = Error(ErrGRPCMemberNotEnoughStarted) |
| 157 | ErrMemberBadURLs = Error(ErrGRPCMemberBadURLs) |
| 158 | ErrMemberNotFound = Error(ErrGRPCMemberNotFound) |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 159 | ErrMemberNotLearner = Error(ErrGRPCMemberNotLearner) |
| 160 | ErrMemberLearnerNotReady = Error(ErrGRPCLearnerNotReady) |
| 161 | ErrTooManyLearners = Error(ErrGRPCTooManyLearners) |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 162 | |
| 163 | ErrRequestTooLarge = Error(ErrGRPCRequestTooLarge) |
| 164 | ErrTooManyRequests = Error(ErrGRPCRequestTooManyRequests) |
| 165 | |
| 166 | ErrRootUserNotExist = Error(ErrGRPCRootUserNotExist) |
| 167 | ErrRootRoleNotExist = Error(ErrGRPCRootRoleNotExist) |
| 168 | ErrUserAlreadyExist = Error(ErrGRPCUserAlreadyExist) |
| 169 | ErrUserEmpty = Error(ErrGRPCUserEmpty) |
| 170 | ErrUserNotFound = Error(ErrGRPCUserNotFound) |
| 171 | ErrRoleAlreadyExist = Error(ErrGRPCRoleAlreadyExist) |
| 172 | ErrRoleNotFound = Error(ErrGRPCRoleNotFound) |
David Bainbridge | 788e520 | 2019-10-21 18:49:40 +0000 | [diff] [blame] | 173 | ErrRoleEmpty = Error(ErrGRPCRoleEmpty) |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 174 | ErrAuthFailed = Error(ErrGRPCAuthFailed) |
| 175 | ErrPermissionDenied = Error(ErrGRPCPermissionDenied) |
| 176 | ErrRoleNotGranted = Error(ErrGRPCRoleNotGranted) |
| 177 | ErrPermissionNotGranted = Error(ErrGRPCPermissionNotGranted) |
| 178 | ErrAuthNotEnabled = Error(ErrGRPCAuthNotEnabled) |
| 179 | ErrInvalidAuthToken = Error(ErrGRPCInvalidAuthToken) |
| 180 | ErrInvalidAuthMgmt = Error(ErrGRPCInvalidAuthMgmt) |
| 181 | |
| 182 | ErrNoLeader = Error(ErrGRPCNoLeader) |
| 183 | ErrNotLeader = Error(ErrGRPCNotLeader) |
| 184 | ErrLeaderChanged = Error(ErrGRPCLeaderChanged) |
| 185 | ErrNotCapable = Error(ErrGRPCNotCapable) |
| 186 | ErrStopped = Error(ErrGRPCStopped) |
| 187 | ErrTimeout = Error(ErrGRPCTimeout) |
| 188 | ErrTimeoutDueToLeaderFail = Error(ErrGRPCTimeoutDueToLeaderFail) |
| 189 | ErrTimeoutDueToConnectionLost = Error(ErrGRPCTimeoutDueToConnectionLost) |
| 190 | ErrUnhealthy = Error(ErrGRPCUnhealthy) |
| 191 | ErrCorrupt = Error(ErrGRPCCorrupt) |
Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [diff] [blame] | 192 | ErrBadLeaderTransferee = Error(ErrGRPCBadLeaderTransferee) |
William Kurkian | ea86948 | 2019-04-09 15:16:11 -0400 | [diff] [blame] | 193 | ) |
| 194 | |
| 195 | // EtcdError defines gRPC server errors. |
| 196 | // (https://github.com/grpc/grpc-go/blob/master/rpc_util.go#L319-L323) |
| 197 | type EtcdError struct { |
| 198 | code codes.Code |
| 199 | desc string |
| 200 | } |
| 201 | |
| 202 | // Code returns grpc/codes.Code. |
| 203 | // TODO: define clientv3/codes.Code. |
| 204 | func (e EtcdError) Code() codes.Code { |
| 205 | return e.code |
| 206 | } |
| 207 | |
| 208 | func (e EtcdError) Error() string { |
| 209 | return e.desc |
| 210 | } |
| 211 | |
| 212 | func Error(err error) error { |
| 213 | if err == nil { |
| 214 | return nil |
| 215 | } |
| 216 | verr, ok := errStringToError[ErrorDesc(err)] |
| 217 | if !ok { // not gRPC error |
| 218 | return err |
| 219 | } |
| 220 | ev, ok := status.FromError(verr) |
| 221 | var desc string |
| 222 | if ok { |
| 223 | desc = ev.Message() |
| 224 | } else { |
| 225 | desc = verr.Error() |
| 226 | } |
| 227 | return EtcdError{code: ev.Code(), desc: desc} |
| 228 | } |
| 229 | |
| 230 | func ErrorDesc(err error) string { |
| 231 | if s, ok := status.FromError(err); ok { |
| 232 | return s.Message() |
| 233 | } |
| 234 | return err.Error() |
| 235 | } |