1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package v3rpc
16
17 import (
18 "context"
19 "strings"
20
21 pb "go.etcd.io/etcd/api/v3/etcdserverpb"
22 "go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
23 "go.etcd.io/etcd/server/v3/auth"
24 "go.etcd.io/etcd/server/v3/etcdserver"
25 "go.etcd.io/etcd/server/v3/etcdserver/api/membership"
26 "go.etcd.io/etcd/server/v3/lease"
27 "go.etcd.io/etcd/server/v3/mvcc"
28
29 "google.golang.org/grpc/codes"
30 "google.golang.org/grpc/status"
31 )
32
33 var toGRPCErrorMap = map[error]error{
34 membership.ErrIDRemoved: rpctypes.ErrGRPCMemberNotFound,
35 membership.ErrIDNotFound: rpctypes.ErrGRPCMemberNotFound,
36 membership.ErrIDExists: rpctypes.ErrGRPCMemberExist,
37 membership.ErrPeerURLexists: rpctypes.ErrGRPCPeerURLExist,
38 membership.ErrMemberNotLearner: rpctypes.ErrGRPCMemberNotLearner,
39 membership.ErrTooManyLearners: rpctypes.ErrGRPCTooManyLearners,
40 etcdserver.ErrNotEnoughStartedMembers: rpctypes.ErrMemberNotEnoughStarted,
41 etcdserver.ErrLearnerNotReady: rpctypes.ErrGRPCLearnerNotReady,
42
43 mvcc.ErrCompacted: rpctypes.ErrGRPCCompacted,
44 mvcc.ErrFutureRev: rpctypes.ErrGRPCFutureRev,
45 etcdserver.ErrRequestTooLarge: rpctypes.ErrGRPCRequestTooLarge,
46 etcdserver.ErrNoSpace: rpctypes.ErrGRPCNoSpace,
47 etcdserver.ErrTooManyRequests: rpctypes.ErrTooManyRequests,
48
49 etcdserver.ErrNoLeader: rpctypes.ErrGRPCNoLeader,
50 etcdserver.ErrNotLeader: rpctypes.ErrGRPCNotLeader,
51 etcdserver.ErrLeaderChanged: rpctypes.ErrGRPCLeaderChanged,
52 etcdserver.ErrStopped: rpctypes.ErrGRPCStopped,
53 etcdserver.ErrTimeout: rpctypes.ErrGRPCTimeout,
54 etcdserver.ErrTimeoutDueToLeaderFail: rpctypes.ErrGRPCTimeoutDueToLeaderFail,
55 etcdserver.ErrTimeoutDueToConnectionLost: rpctypes.ErrGRPCTimeoutDueToConnectionLost,
56 etcdserver.ErrTimeoutWaitAppliedIndex: rpctypes.ErrGRPCTimeoutWaitAppliedIndex,
57 etcdserver.ErrUnhealthy: rpctypes.ErrGRPCUnhealthy,
58 etcdserver.ErrKeyNotFound: rpctypes.ErrGRPCKeyNotFound,
59 etcdserver.ErrCorrupt: rpctypes.ErrGRPCCorrupt,
60 etcdserver.ErrBadLeaderTransferee: rpctypes.ErrGRPCBadLeaderTransferee,
61
62 etcdserver.ErrClusterVersionUnavailable: rpctypes.ErrGRPCClusterVersionUnavailable,
63 etcdserver.ErrWrongDowngradeVersionFormat: rpctypes.ErrGRPCWrongDowngradeVersionFormat,
64 etcdserver.ErrInvalidDowngradeTargetVersion: rpctypes.ErrGRPCInvalidDowngradeTargetVersion,
65 etcdserver.ErrDowngradeInProcess: rpctypes.ErrGRPCDowngradeInProcess,
66 etcdserver.ErrNoInflightDowngrade: rpctypes.ErrGRPCNoInflightDowngrade,
67
68 lease.ErrLeaseNotFound: rpctypes.ErrGRPCLeaseNotFound,
69 lease.ErrLeaseExists: rpctypes.ErrGRPCLeaseExist,
70 lease.ErrLeaseTTLTooLarge: rpctypes.ErrGRPCLeaseTTLTooLarge,
71
72 auth.ErrRootUserNotExist: rpctypes.ErrGRPCRootUserNotExist,
73 auth.ErrRootRoleNotExist: rpctypes.ErrGRPCRootRoleNotExist,
74 auth.ErrUserAlreadyExist: rpctypes.ErrGRPCUserAlreadyExist,
75 auth.ErrUserEmpty: rpctypes.ErrGRPCUserEmpty,
76 auth.ErrUserNotFound: rpctypes.ErrGRPCUserNotFound,
77 auth.ErrRoleAlreadyExist: rpctypes.ErrGRPCRoleAlreadyExist,
78 auth.ErrRoleNotFound: rpctypes.ErrGRPCRoleNotFound,
79 auth.ErrRoleEmpty: rpctypes.ErrGRPCRoleEmpty,
80 auth.ErrAuthFailed: rpctypes.ErrGRPCAuthFailed,
81 auth.ErrPermissionNotGiven: rpctypes.ErrGRPCPermissionNotGiven,
82 auth.ErrPermissionDenied: rpctypes.ErrGRPCPermissionDenied,
83 auth.ErrRoleNotGranted: rpctypes.ErrGRPCRoleNotGranted,
84 auth.ErrPermissionNotGranted: rpctypes.ErrGRPCPermissionNotGranted,
85 auth.ErrAuthNotEnabled: rpctypes.ErrGRPCAuthNotEnabled,
86 auth.ErrInvalidAuthToken: rpctypes.ErrGRPCInvalidAuthToken,
87 auth.ErrInvalidAuthMgmt: rpctypes.ErrGRPCInvalidAuthMgmt,
88 auth.ErrAuthOldRevision: rpctypes.ErrGRPCAuthOldRevision,
89
90
91 context.Canceled: rpctypes.ErrGRPCCanceled,
92 context.DeadlineExceeded: rpctypes.ErrGRPCDeadlineExceeded,
93 }
94
95 func togRPCError(err error) error {
96
97 if err == context.Canceled || err == context.DeadlineExceeded {
98 return err
99 }
100 grpcErr, ok := toGRPCErrorMap[err]
101 if !ok {
102 return status.Error(codes.Unknown, err.Error())
103 }
104 return grpcErr
105 }
106
107 func isClientCtxErr(ctxErr error, err error) bool {
108 if ctxErr != nil {
109 return true
110 }
111
112 ev, ok := status.FromError(err)
113 if !ok {
114 return false
115 }
116
117 switch ev.Code() {
118 case codes.Canceled, codes.DeadlineExceeded:
119
120
121
122 return true
123 case codes.Unavailable:
124 msg := ev.Message()
125
126
127 if msg == "client disconnected" {
128 return true
129 }
130
131
132 if strings.HasPrefix(msg, "stream error: ") && strings.HasSuffix(msg, "; CANCEL") {
133 return true
134 }
135 }
136 return false
137 }
138
139
140 func isRPCSupportedForLearner(req interface{}) bool {
141 switch r := req.(type) {
142 case *pb.StatusRequest:
143 return true
144 case *pb.RangeRequest:
145 return r.Serializable
146 default:
147 return false
148 }
149 }
150
View as plain text