diff --git a/clientv3/auth.go b/clientv3/auth.go index 9370295f2d5..d72657edc1e 100644 --- a/clientv3/auth.go +++ b/clientv3/auth.go @@ -19,6 +19,7 @@ import ( "strings" "github.com/coreos/etcd/auth/authpb" + "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes" pb "github.com/coreos/etcd/etcdserver/etcdserverpb" "golang.org/x/net/context" "google.golang.org/grpc" @@ -87,37 +88,37 @@ func NewAuth(c *Client) Auth { func (auth *auth) AuthEnable(ctx context.Context) (*AuthEnableResponse, error) { resp, err := auth.remote.AuthEnable(ctx, &pb.AuthEnableRequest{}) - return (*AuthEnableResponse)(resp), err + return (*AuthEnableResponse)(resp), rpctypes.Error(err) } func (auth *auth) Authenticate(ctx context.Context, name string, password string) (*AuthenticateResponse, error) { resp, err := auth.remote.Authenticate(ctx, &pb.AuthenticateRequest{Name: name, Password: password}) - return (*AuthenticateResponse)(resp), err + return (*AuthenticateResponse)(resp), rpctypes.Error(err) } func (auth *auth) UserAdd(ctx context.Context, name string, password string) (*AuthUserAddResponse, error) { resp, err := auth.remote.UserAdd(ctx, &pb.AuthUserAddRequest{Name: name, Password: password}) - return (*AuthUserAddResponse)(resp), err + return (*AuthUserAddResponse)(resp), rpctypes.Error(err) } func (auth *auth) UserDelete(ctx context.Context, name string) (*AuthUserDeleteResponse, error) { resp, err := auth.remote.UserDelete(ctx, &pb.AuthUserDeleteRequest{Name: name}) - return (*AuthUserDeleteResponse)(resp), err + return (*AuthUserDeleteResponse)(resp), rpctypes.Error(err) } func (auth *auth) UserChangePassword(ctx context.Context, name string, password string) (*AuthUserChangePasswordResponse, error) { resp, err := auth.remote.UserChangePassword(ctx, &pb.AuthUserChangePasswordRequest{Name: name, Password: password}) - return (*AuthUserChangePasswordResponse)(resp), err + return (*AuthUserChangePasswordResponse)(resp), rpctypes.Error(err) } func (auth *auth) UserGrant(ctx context.Context, user string, role string) (*AuthUserGrantResponse, error) { resp, err := auth.remote.UserGrant(ctx, &pb.AuthUserGrantRequest{User: user, Role: role}) - return (*AuthUserGrantResponse)(resp), err + return (*AuthUserGrantResponse)(resp), rpctypes.Error(err) } func (auth *auth) RoleAdd(ctx context.Context, name string) (*AuthRoleAddResponse, error) { resp, err := auth.remote.RoleAdd(ctx, &pb.AuthRoleAddRequest{Name: name}) - return (*AuthRoleAddResponse)(resp), err + return (*AuthRoleAddResponse)(resp), rpctypes.Error(err) } func (auth *auth) RoleGrant(ctx context.Context, name string, key string, permType PermissionType) (*AuthRoleGrantResponse, error) { @@ -126,7 +127,7 @@ func (auth *auth) RoleGrant(ctx context.Context, name string, key string, permTy PermType: authpb.Permission_Type(permType), } resp, err := auth.remote.RoleGrant(ctx, &pb.AuthRoleGrantRequest{Name: name, Perm: perm}) - return (*AuthRoleGrantResponse)(resp), err + return (*AuthRoleGrantResponse)(resp), rpctypes.Error(err) } func StrToPermissionType(s string) (PermissionType, error) { diff --git a/clientv3/integration/kv_test.go b/clientv3/integration/kv_test.go index 99ccdff83a8..cfcb47aa37c 100644 --- a/clientv3/integration/kv_test.go +++ b/clientv3/integration/kv_test.go @@ -411,7 +411,7 @@ func TestKVCompact(t *testing.T) { } err = kv.Compact(ctx, 7) if err == nil || err != rpctypes.ErrCompacted { - t.Fatalf("error got %v, want %v", err, rpctypes.ErrFutureRev) + t.Fatalf("error got %v, want %v", err, rpctypes.ErrCompacted) } wcli := clus.RandClient() diff --git a/clientv3/integration/lease_test.go b/clientv3/integration/lease_test.go index 95addc65b0d..42337978fc0 100644 --- a/clientv3/integration/lease_test.go +++ b/clientv3/integration/lease_test.go @@ -23,11 +23,9 @@ import ( "github.com/coreos/etcd/integration" "github.com/coreos/etcd/pkg/testutil" "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" ) -func TestLeastNotFoundError(t *testing.T) { +func TestLeaseNotFoundError(t *testing.T) { defer testutil.AfterTest(t) clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) @@ -113,8 +111,8 @@ func TestLeaseKeepAliveOnce(t *testing.T) { } _, err = lapi.KeepAliveOnce(context.Background(), clientv3.LeaseID(0)) - if grpc.Code(err) != codes.NotFound { - t.Errorf("invalid error returned %v", err) + if err != rpctypes.ErrLeaseNotFound { + t.Errorf("expected %v, got %v", rpctypes.ErrLeaseNotFound, err) } } diff --git a/clientv3/integration/watch_test.go b/clientv3/integration/watch_test.go index f11a654c770..904a7839d5c 100644 --- a/clientv3/integration/watch_test.go +++ b/clientv3/integration/watch_test.go @@ -364,7 +364,7 @@ func TestWatchCompactRevision(t *testing.T) { t.Fatalf("expected wresp, but got closed channel") } if wresp.Err() != rpctypes.ErrCompacted { - t.Fatalf("wresp.Err() expected ErrCompacteed, but got %v", wresp.Err()) + t.Fatalf("wresp.Err() expected %v, but got %v", rpctypes.ErrCompacted, wresp.Err()) } // ensure the channel is closed diff --git a/etcdserver/api/v3rpc/key.go b/etcdserver/api/v3rpc/key.go index 6c3a3fda7b1..fb29d3ec094 100644 --- a/etcdserver/api/v3rpc/key.go +++ b/etcdserver/api/v3rpc/key.go @@ -125,33 +125,33 @@ func (s *kvServer) Compact(ctx context.Context, r *pb.CompactionRequest) (*pb.Co func checkRangeRequest(r *pb.RangeRequest) error { if len(r.Key) == 0 { - return rpctypes.ErrEmptyKey + return rpctypes.ErrGRPCEmptyKey } return nil } func checkPutRequest(r *pb.PutRequest) error { if len(r.Key) == 0 { - return rpctypes.ErrEmptyKey + return rpctypes.ErrGRPCEmptyKey } return nil } func checkDeleteRequest(r *pb.DeleteRangeRequest) error { if len(r.Key) == 0 { - return rpctypes.ErrEmptyKey + return rpctypes.ErrGRPCEmptyKey } return nil } func checkTxnRequest(r *pb.TxnRequest) error { if len(r.Compare) > MaxOpsPerTxn || len(r.Success) > MaxOpsPerTxn || len(r.Failure) > MaxOpsPerTxn { - return rpctypes.ErrTooManyOps + return rpctypes.ErrGRPCTooManyOps } for _, c := range r.Compare { if len(c.Key) == 0 { - return rpctypes.ErrEmptyKey + return rpctypes.ErrGRPCEmptyKey } } @@ -172,7 +172,7 @@ func checkTxnRequest(r *pb.TxnRequest) error { return checkRequestDupKeys(r.Failure) } -// checkRequestDupKeys gives rpctypes.ErrDuplicateKey if the same key is modified twice +// checkRequestDupKeys gives rpctypes.ErrGRPCDuplicateKey if the same key is modified twice func checkRequestDupKeys(reqs []*pb.RequestUnion) error { // check put overlap keys := make(map[string]struct{}) @@ -186,7 +186,7 @@ func checkRequestDupKeys(reqs []*pb.RequestUnion) error { continue } if _, ok := keys[string(preq.Key)]; ok { - return rpctypes.ErrDuplicateKey + return rpctypes.ErrGRPCDuplicateKey } keys[string(preq.Key)] = struct{}{} } @@ -215,14 +215,14 @@ func checkRequestDupKeys(reqs []*pb.RequestUnion) error { } if dreq.RangeEnd == nil { if _, found := keys[string(dreq.Key)]; found { - return rpctypes.ErrDuplicateKey + return rpctypes.ErrGRPCDuplicateKey } } else { lo := sort.SearchStrings(sortedKeys, string(dreq.Key)) hi := sort.SearchStrings(sortedKeys, string(dreq.RangeEnd)) if lo != hi { // element between lo and hi => overlap - return rpctypes.ErrDuplicateKey + return rpctypes.ErrGRPCDuplicateKey } } } diff --git a/etcdserver/api/v3rpc/lease.go b/etcdserver/api/v3rpc/lease.go index 8553cfffb47..917ef305ee1 100644 --- a/etcdserver/api/v3rpc/lease.go +++ b/etcdserver/api/v3rpc/lease.go @@ -36,7 +36,7 @@ func NewLeaseServer(s *etcdserver.EtcdServer) pb.LeaseServer { func (ls *LeaseServer) LeaseGrant(ctx context.Context, cr *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) { resp, err := ls.le.LeaseGrant(ctx, cr) if err == lease.ErrLeaseExists { - return nil, rpctypes.ErrLeaseExist + return nil, rpctypes.ErrGRPCLeaseExist } if err != nil { return nil, err @@ -48,7 +48,7 @@ func (ls *LeaseServer) LeaseGrant(ctx context.Context, cr *pb.LeaseGrantRequest) func (ls *LeaseServer) LeaseRevoke(ctx context.Context, rr *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) { resp, err := ls.le.LeaseRevoke(ctx, rr) if err != nil { - return nil, rpctypes.ErrLeaseNotFound + return nil, rpctypes.ErrGRPCLeaseNotFound } ls.hdr.fill(resp.Header) return resp, nil diff --git a/etcdserver/api/v3rpc/member.go b/etcdserver/api/v3rpc/member.go index aaf767e6b32..345089de95b 100644 --- a/etcdserver/api/v3rpc/member.go +++ b/etcdserver/api/v3rpc/member.go @@ -45,7 +45,7 @@ func NewClusterServer(s *etcdserver.EtcdServer) *ClusterServer { func (cs *ClusterServer) MemberAdd(ctx context.Context, r *pb.MemberAddRequest) (*pb.MemberAddResponse, error) { urls, err := types.NewURLs(r.PeerURLs) if err != nil { - return nil, rpctypes.ErrMemberBadURLs + return nil, rpctypes.ErrGRPCMemberBadURLs } now := time.Now() @@ -53,9 +53,9 @@ func (cs *ClusterServer) MemberAdd(ctx context.Context, r *pb.MemberAddRequest) err = cs.server.AddMember(ctx, *m) switch { case err == membership.ErrIDExists: - return nil, rpctypes.ErrMemberExist + return nil, rpctypes.ErrGRPCMemberExist case err == membership.ErrPeerURLexists: - return nil, rpctypes.ErrPeerURLExist + return nil, rpctypes.ErrGRPCPeerURLExist case err != nil: return nil, grpc.Errorf(codes.Internal, err.Error()) } @@ -72,7 +72,7 @@ func (cs *ClusterServer) MemberRemove(ctx context.Context, r *pb.MemberRemoveReq case err == membership.ErrIDRemoved: fallthrough case err == membership.ErrIDNotFound: - return nil, rpctypes.ErrMemberNotFound + return nil, rpctypes.ErrGRPCMemberNotFound case err != nil: return nil, grpc.Errorf(codes.Internal, err.Error()) } @@ -88,9 +88,9 @@ func (cs *ClusterServer) MemberUpdate(ctx context.Context, r *pb.MemberUpdateReq err := cs.server.UpdateMember(ctx, m) switch { case err == membership.ErrPeerURLexists: - return nil, rpctypes.ErrPeerURLExist + return nil, rpctypes.ErrGRPCPeerURLExist case err == membership.ErrIDNotFound: - return nil, rpctypes.ErrMemberNotFound + return nil, rpctypes.ErrGRPCMemberNotFound case err != nil: return nil, grpc.Errorf(codes.Internal, err.Error()) } diff --git a/etcdserver/api/v3rpc/quota.go b/etcdserver/api/v3rpc/quota.go index aa7794f967a..89116db3104 100644 --- a/etcdserver/api/v3rpc/quota.go +++ b/etcdserver/api/v3rpc/quota.go @@ -45,7 +45,7 @@ func (qa *quotaAlarmer) check(ctx context.Context, r interface{}) error { Alarm: pb.AlarmType_NOSPACE, } qa.a.Alarm(ctx, req) - return rpctypes.ErrNoSpace + return rpctypes.ErrGRPCNoSpace } func NewQuotaKVServer(s *etcdserver.EtcdServer) pb.KVServer { diff --git a/etcdserver/api/v3rpc/rpctypes/error.go b/etcdserver/api/v3rpc/rpctypes/error.go index 0de40773202..5b0d5630c70 100644 --- a/etcdserver/api/v3rpc/rpctypes/error.go +++ b/etcdserver/api/v3rpc/rpctypes/error.go @@ -20,62 +20,104 @@ import ( ) var ( - ErrEmptyKey = grpc.Errorf(codes.InvalidArgument, "etcdserver: key is not provided") - ErrTooManyOps = grpc.Errorf(codes.InvalidArgument, "etcdserver: too many operations in txn request") - ErrDuplicateKey = grpc.Errorf(codes.InvalidArgument, "etcdserver: duplicate key given in txn request") - ErrCompacted = grpc.Errorf(codes.OutOfRange, "etcdserver: mvcc: required revision has been compacted") - ErrFutureRev = grpc.Errorf(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision") - ErrNoSpace = grpc.Errorf(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded") + // server-side error + ErrGRPCEmptyKey = grpc.Errorf(codes.InvalidArgument, "etcdserver: key is not provided") + ErrGRPCTooManyOps = grpc.Errorf(codes.InvalidArgument, "etcdserver: too many operations in txn request") + ErrGRPCDuplicateKey = grpc.Errorf(codes.InvalidArgument, "etcdserver: duplicate key given in txn request") + ErrGRPCCompacted = grpc.Errorf(codes.OutOfRange, "etcdserver: mvcc: required revision has been compacted") + ErrGRPCFutureRev = grpc.Errorf(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision") + ErrGRPCNoSpace = grpc.Errorf(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded") - ErrLeaseNotFound = grpc.Errorf(codes.NotFound, "etcdserver: requested lease not found") - ErrLeaseExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: lease already exists") + ErrGRPCLeaseNotFound = grpc.Errorf(codes.NotFound, "etcdserver: requested lease not found") + ErrGRPCLeaseExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: lease already exists") - ErrMemberExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: member ID already exist") - ErrPeerURLExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: Peer URLs already exists") - ErrMemberBadURLs = grpc.Errorf(codes.InvalidArgument, "etcdserver: given member URLs are invalid") - ErrMemberNotFound = grpc.Errorf(codes.NotFound, "etcdserver: member not found") + ErrGRPCMemberExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: member ID already exist") + ErrGRPCPeerURLExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: Peer URLs already exists") + ErrGRPCMemberBadURLs = grpc.Errorf(codes.InvalidArgument, "etcdserver: given member URLs are invalid") + ErrGRPCMemberNotFound = grpc.Errorf(codes.NotFound, "etcdserver: member not found") - ErrRequestTooLarge = grpc.Errorf(codes.InvalidArgument, "etcdserver: request is too large") + ErrGRPCRequestTooLarge = grpc.Errorf(codes.InvalidArgument, "etcdserver: request is too large") - ErrUserAlreadyExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: user name already exists") - ErrUserNotFound = grpc.Errorf(codes.FailedPrecondition, "etcdserver: user name not found") - ErrRoleAlreadyExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: role name already exists") - ErrRoleNotFound = grpc.Errorf(codes.FailedPrecondition, "etcdserver: role name not found") - ErrAuthFailed = grpc.Errorf(codes.InvalidArgument, "etcdserver: authentication failed, invalid user ID or password") + ErrGRPCUserAlreadyExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: user name already exists") + ErrGRPCUserNotFound = grpc.Errorf(codes.FailedPrecondition, "etcdserver: user name not found") + ErrGRPCRoleAlreadyExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: role name already exists") + ErrGRPCRoleNotFound = grpc.Errorf(codes.FailedPrecondition, "etcdserver: role name not found") + ErrGRPCAuthFailed = grpc.Errorf(codes.InvalidArgument, "etcdserver: authentication failed, invalid user ID or password") errStringToError = map[string]error{ - grpc.ErrorDesc(ErrEmptyKey): ErrEmptyKey, - grpc.ErrorDesc(ErrTooManyOps): ErrTooManyOps, - grpc.ErrorDesc(ErrDuplicateKey): ErrDuplicateKey, - grpc.ErrorDesc(ErrCompacted): ErrCompacted, - grpc.ErrorDesc(ErrFutureRev): ErrFutureRev, - grpc.ErrorDesc(ErrNoSpace): ErrNoSpace, - - grpc.ErrorDesc(ErrLeaseNotFound): ErrLeaseNotFound, - grpc.ErrorDesc(ErrLeaseExist): ErrLeaseExist, - - grpc.ErrorDesc(ErrMemberExist): ErrMemberExist, - grpc.ErrorDesc(ErrPeerURLExist): ErrPeerURLExist, - grpc.ErrorDesc(ErrMemberBadURLs): ErrMemberBadURLs, - grpc.ErrorDesc(ErrMemberNotFound): ErrMemberNotFound, - - grpc.ErrorDesc(ErrRequestTooLarge): ErrRequestTooLarge, - - grpc.ErrorDesc(ErrUserAlreadyExist): ErrUserAlreadyExist, - grpc.ErrorDesc(ErrUserNotFound): ErrUserNotFound, - grpc.ErrorDesc(ErrRoleAlreadyExist): ErrRoleAlreadyExist, - grpc.ErrorDesc(ErrRoleNotFound): ErrRoleNotFound, - grpc.ErrorDesc(ErrAuthFailed): ErrAuthFailed, + grpc.ErrorDesc(ErrGRPCEmptyKey): ErrGRPCEmptyKey, + grpc.ErrorDesc(ErrGRPCTooManyOps): ErrGRPCTooManyOps, + grpc.ErrorDesc(ErrGRPCDuplicateKey): ErrGRPCDuplicateKey, + grpc.ErrorDesc(ErrGRPCCompacted): ErrGRPCCompacted, + grpc.ErrorDesc(ErrGRPCFutureRev): ErrGRPCFutureRev, + grpc.ErrorDesc(ErrGRPCNoSpace): ErrGRPCNoSpace, + + grpc.ErrorDesc(ErrGRPCLeaseNotFound): ErrGRPCLeaseNotFound, + grpc.ErrorDesc(ErrGRPCLeaseExist): ErrGRPCLeaseExist, + + grpc.ErrorDesc(ErrGRPCMemberExist): ErrGRPCMemberExist, + grpc.ErrorDesc(ErrGRPCPeerURLExist): ErrGRPCPeerURLExist, + grpc.ErrorDesc(ErrGRPCMemberBadURLs): ErrGRPCMemberBadURLs, + grpc.ErrorDesc(ErrGRPCMemberNotFound): ErrGRPCMemberNotFound, + + grpc.ErrorDesc(ErrGRPCRequestTooLarge): ErrGRPCRequestTooLarge, + + grpc.ErrorDesc(ErrGRPCUserAlreadyExist): ErrGRPCUserAlreadyExist, + grpc.ErrorDesc(ErrGRPCUserNotFound): ErrGRPCUserNotFound, + grpc.ErrorDesc(ErrGRPCRoleAlreadyExist): ErrGRPCRoleAlreadyExist, + grpc.ErrorDesc(ErrGRPCRoleNotFound): ErrGRPCRoleNotFound, + grpc.ErrorDesc(ErrGRPCAuthFailed): ErrGRPCAuthFailed, } + + // client-side error + ErrEmptyKey = Error(ErrGRPCEmptyKey) + ErrTooManyOps = Error(ErrGRPCTooManyOps) + ErrDuplicateKey = Error(ErrGRPCDuplicateKey) + ErrCompacted = Error(ErrGRPCCompacted) + ErrFutureRev = Error(ErrGRPCFutureRev) + ErrNoSpace = Error(ErrGRPCNoSpace) + + ErrLeaseNotFound = Error(ErrGRPCLeaseNotFound) + ErrLeaseExist = Error(ErrGRPCLeaseExist) + + ErrMemberExist = Error(ErrGRPCMemberExist) + ErrPeerURLExist = Error(ErrGRPCPeerURLExist) + ErrMemberBadURLs = Error(ErrGRPCMemberBadURLs) + ErrMemberNotFound = Error(ErrGRPCMemberNotFound) + + ErrRequestTooLarge = Error(ErrGRPCRequestTooLarge) + + ErrUserAlreadyExist = Error(ErrGRPCUserAlreadyExist) + ErrUserNotFound = Error(ErrGRPCUserNotFound) + ErrRoleAlreadyExist = Error(ErrGRPCRoleAlreadyExist) + ErrRoleNotFound = Error(ErrGRPCRoleNotFound) + ErrAuthFailed = Error(ErrGRPCAuthFailed) ) +// EtcdError defines gRPC server errors. +// (https://github.com/grpc/grpc-go/blob/master/rpc_util.go#L319-L323) +type EtcdError struct { + code codes.Code + desc string +} + +// Code returns grpc/codes.Code. +// TODO: define clientv3/codes.Code. +func (e EtcdError) Code() codes.Code { + return e.code +} + +func (e EtcdError) Error() string { + return e.desc +} + func Error(err error) error { if err == nil { return nil } - v, ok := errStringToError[err.Error()] - if !ok { + verr, ok := errStringToError[grpc.ErrorDesc(err)] + if !ok { // not gRPC error return err } - return v + return EtcdError{code: grpc.Code(verr), desc: grpc.ErrorDesc(verr)} } diff --git a/etcdserver/api/v3rpc/rpctypes/error_test.go b/etcdserver/api/v3rpc/rpctypes/error_test.go new file mode 100644 index 00000000000..991670f3307 --- /dev/null +++ b/etcdserver/api/v3rpc/rpctypes/error_test.go @@ -0,0 +1,42 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rpctypes + +import ( + "testing" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" +) + +func TestConvert(t *testing.T) { + e1 := grpc.Errorf(codes.InvalidArgument, "etcdserver: key is not provided") + e2 := ErrGRPCEmptyKey + e3 := ErrEmptyKey + + if e1 != e2 { + t.Fatalf("expected 'true', got %T != %T", e1, e2) + } + if grpc.Code(e1) != e3.(EtcdError).Code() { + t.Fatalf("expected them to be equal, got %v / %v", grpc.Code(e1), e3.(EtcdError).Code()) + } + + if e1 == e3 { + t.Fatalf("expected 'false', got %T == %T", e1, e3) + } + if grpc.Code(e2) != e3.(EtcdError).Code() { + t.Fatalf("expected them to be equal, got %v / %v", grpc.Code(e2), e3.(EtcdError).Code()) + } +} diff --git a/etcdserver/api/v3rpc/util.go b/etcdserver/api/v3rpc/util.go index 0f36057d918..d5f03261357 100644 --- a/etcdserver/api/v3rpc/util.go +++ b/etcdserver/api/v3rpc/util.go @@ -27,26 +27,26 @@ import ( func togRPCError(err error) error { switch err { case mvcc.ErrCompacted: - return rpctypes.ErrCompacted + return rpctypes.ErrGRPCCompacted case mvcc.ErrFutureRev: - return rpctypes.ErrFutureRev + return rpctypes.ErrGRPCFutureRev case lease.ErrLeaseNotFound: - return rpctypes.ErrLeaseNotFound + return rpctypes.ErrGRPCLeaseNotFound // TODO: handle error from raft and timeout case etcdserver.ErrRequestTooLarge: - return rpctypes.ErrRequestTooLarge + return rpctypes.ErrGRPCRequestTooLarge case etcdserver.ErrNoSpace: - return rpctypes.ErrNoSpace + return rpctypes.ErrGRPCNoSpace case auth.ErrUserAlreadyExist: - return rpctypes.ErrUserAlreadyExist + return rpctypes.ErrGRPCUserAlreadyExist case auth.ErrUserNotFound: - return rpctypes.ErrUserNotFound + return rpctypes.ErrGRPCUserNotFound case auth.ErrRoleAlreadyExist: - return rpctypes.ErrRoleAlreadyExist + return rpctypes.ErrGRPCRoleAlreadyExist case auth.ErrRoleNotFound: - return rpctypes.ErrRoleNotFound + return rpctypes.ErrGRPCRoleNotFound case auth.ErrAuthFailed: - return rpctypes.ErrAuthFailed + return rpctypes.ErrGRPCAuthFailed default: return grpc.Errorf(codes.Internal, err.Error()) } diff --git a/integration/cluster.go b/integration/cluster.go index 77d45dcc174..32b60c9071f 100644 --- a/integration/cluster.go +++ b/integration/cluster.go @@ -196,8 +196,13 @@ func (c *cluster) HTTPMembers() []client.Member { } func (c *cluster) mustNewMember(t *testing.T) *member { - name := c.name(rand.Int()) - m := mustNewMember(t, name, c.cfg.PeerTLS, c.cfg.ClientTLS, c.cfg.QuotaBackendBytes) + m := mustNewMember(t, + memberConfig{ + name: c.name(rand.Int()), + peerTLS: c.cfg.PeerTLS, + clientTLS: c.cfg.ClientTLS, + quotaBackendBytes: c.cfg.QuotaBackendBytes, + }) m.DiscoveryURL = c.cfg.DiscoveryURL if c.cfg.UseGRPC { if err := m.listenGRPC(); err != nil { @@ -416,17 +421,24 @@ type member struct { grpcAddr string } +type memberConfig struct { + name string + peerTLS *transport.TLSInfo + clientTLS *transport.TLSInfo + quotaBackendBytes int64 +} + // mustNewMember return an inited member with the given name. If peerTLS is // set, it will use https scheme to communicate between peers. -func mustNewMember(t *testing.T, name string, peerTLS *transport.TLSInfo, clientTLS *transport.TLSInfo, quotaBackendBytes int64) *member { +func mustNewMember(t *testing.T, mcfg memberConfig) *member { var err error m := &member{} peerScheme, clientScheme := "http", "http" - if peerTLS != nil { + if mcfg.peerTLS != nil { peerScheme = "https" } - if clientTLS != nil { + if mcfg.clientTLS != nil { clientScheme = "https" } @@ -436,7 +448,7 @@ func mustNewMember(t *testing.T, name string, peerTLS *transport.TLSInfo, client if err != nil { t.Fatal(err) } - m.PeerTLSInfo = peerTLS + m.PeerTLSInfo = mcfg.peerTLS cln := newLocalListener(t) m.ClientListeners = []net.Listener{cln} @@ -444,15 +456,15 @@ func mustNewMember(t *testing.T, name string, peerTLS *transport.TLSInfo, client if err != nil { t.Fatal(err) } - m.ClientTLSInfo = clientTLS + m.ClientTLSInfo = mcfg.clientTLS - m.Name = name + m.Name = mcfg.name m.DataDir, err = ioutil.TempDir(os.TempDir(), "etcd") if err != nil { t.Fatal(err) } - clusterStr := fmt.Sprintf("%s=%s://%s", name, peerScheme, pln.Addr().String()) + clusterStr := fmt.Sprintf("%s=%s://%s", mcfg.name, peerScheme, pln.Addr().String()) m.InitialPeerURLsMap, err = types.NewURLsMap(clusterStr) if err != nil { t.Fatal(err) @@ -465,7 +477,7 @@ func mustNewMember(t *testing.T, name string, peerTLS *transport.TLSInfo, client } m.ElectionTicks = electionTicks m.TickMs = uint(tickDuration / time.Millisecond) - m.QuotaBackendBytes = quotaBackendBytes + m.QuotaBackendBytes = mcfg.quotaBackendBytes return m } diff --git a/integration/member_test.go b/integration/member_test.go index e1a663ebc96..b38c147486a 100644 --- a/integration/member_test.go +++ b/integration/member_test.go @@ -84,7 +84,7 @@ func TestLaunchDuplicateMemberShouldFail(t *testing.T) { func TestSnapshotAndRestartMember(t *testing.T) { defer testutil.AfterTest(t) - m := mustNewMember(t, "snapAndRestartTest", nil, nil) + m := mustNewMember(t, memberConfig{name: "snapAndRestartTest"}) m.SnapCount = 100 m.Launch() defer m.Terminate(t) diff --git a/integration/migration_test.go b/integration/migration_test.go index cf3cf1a1ffe..e0ab1b3b285 100644 --- a/integration/migration_test.go +++ b/integration/migration_test.go @@ -23,7 +23,7 @@ import ( func TestUpgradeMember(t *testing.T) { defer testutil.AfterTest(t) - m := mustNewMember(t, "integration046", nil, nil) + m := mustNewMember(t, memberConfig{name: "integration046"}) cmd := exec.Command("cp", "-r", "testdata/integration046_data/conf", "testdata/integration046_data/log", "testdata/integration046_data/snapshot", m.DataDir) err := cmd.Run() if err != nil { diff --git a/integration/v3_grpc_test.go b/integration/v3_grpc_test.go index 95d93c17475..514de72d017 100644 --- a/integration/v3_grpc_test.go +++ b/integration/v3_grpc_test.go @@ -193,8 +193,8 @@ func TestV3TxnTooManyOps(t *testing.T) { } _, err := kvc.Txn(context.Background(), txn) - if err != rpctypes.ErrTooManyOps { - t.Errorf("#%d: err = %v, want %v", i, err, rpctypes.ErrTooManyOps) + if err != rpctypes.ErrGRPCTooManyOps { + t.Errorf("#%d: err = %v, want %v", i, err, rpctypes.ErrGRPCTooManyOps) } } } @@ -233,17 +233,17 @@ func TestV3TxnDuplicateKeys(t *testing.T) { { txnSuccess: []*pb.RequestUnion{putreq, putreq}, - werr: rpctypes.ErrDuplicateKey, + werr: rpctypes.ErrGRPCDuplicateKey, }, { txnSuccess: []*pb.RequestUnion{putreq, delKeyReq}, - werr: rpctypes.ErrDuplicateKey, + werr: rpctypes.ErrGRPCDuplicateKey, }, { txnSuccess: []*pb.RequestUnion{putreq, delInRangeReq}, - werr: rpctypes.ErrDuplicateKey, + werr: rpctypes.ErrGRPCDuplicateKey, }, { txnSuccess: []*pb.RequestUnion{delKeyReq, delInRangeReq, delKeyReq, delInRangeReq}, @@ -502,15 +502,15 @@ func TestV3TxnInvaildRange(t *testing.T) { Request: &pb.RequestUnion_RequestRange{ RequestRange: rreq}}) - if _, err := kvc.Txn(context.TODO(), txn); err != rpctypes.ErrFutureRev { - t.Errorf("err = %v, want %v", err, rpctypes.ErrFutureRev) + if _, err := kvc.Txn(context.TODO(), txn); err != rpctypes.ErrGRPCFutureRev { + t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCFutureRev) } // compacted rev tv, _ := txn.Success[1].Request.(*pb.RequestUnion_RequestRange) tv.RequestRange.Revision = 1 - if _, err := kvc.Txn(context.TODO(), txn); err != rpctypes.ErrCompacted { - t.Errorf("err = %v, want %v", err, rpctypes.ErrCompacted) + if _, err := kvc.Txn(context.TODO(), txn); err != rpctypes.ErrGRPCCompacted { + t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCCompacted) } } @@ -527,8 +527,8 @@ func TestV3TooLargeRequest(t *testing.T) { preq := &pb.PutRequest{Key: []byte("foo"), Value: largeV} _, err := kvc.Put(context.Background(), preq) - if err != rpctypes.ErrRequestTooLarge { - t.Errorf("err = %v, want %v", err, rpctypes.ErrRequestTooLarge) + if err != rpctypes.ErrGRPCRequestTooLarge { + t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCRequestTooLarge) } } @@ -581,8 +581,8 @@ func TestV3StorageQuotaAPI(t *testing.T) { // test big put bigbuf := make([]byte, 64*1024) _, err := kvc.Put(context.TODO(), &pb.PutRequest{Key: key, Value: bigbuf}) - if err == nil || err != rpctypes.ErrNoSpace { - t.Fatalf("big put got %v, expected %v", err, rpctypes.ErrNoSpace) + if err == nil || err != rpctypes.ErrGRPCNoSpace { + t.Fatalf("big put got %v, expected %v", err, rpctypes.ErrGRPCNoSpace) } // test big txn @@ -597,8 +597,8 @@ func TestV3StorageQuotaAPI(t *testing.T) { txnreq := &pb.TxnRequest{} txnreq.Success = append(txnreq.Success, puttxn) _, txnerr := kvc.Txn(context.TODO(), txnreq) - if txnerr == nil || err != rpctypes.ErrNoSpace { - t.Fatalf("big txn got %v, expected %v", err, rpctypes.ErrNoSpace) + if txnerr == nil || err != rpctypes.ErrGRPCNoSpace { + t.Fatalf("big txn got %v, expected %v", err, rpctypes.ErrGRPCNoSpace) } } @@ -696,8 +696,8 @@ func TestV3AlarmDeactivate(t *testing.T) { key := []byte("abc") smallbuf := make([]byte, 512) _, err := kvc.Put(context.TODO(), &pb.PutRequest{Key: key, Value: smallbuf}) - if err == nil && err != rpctypes.ErrNoSpace { - t.Fatalf("put got %v, expected %v", err, rpctypes.ErrNoSpace) + if err == nil && err != rpctypes.ErrGRPCNoSpace { + t.Fatalf("put got %v, expected %v", err, rpctypes.ErrGRPCNoSpace) } alarmReq.Action = pb.AlarmRequest_DEACTIVATE diff --git a/integration/v3_lease_test.go b/integration/v3_lease_test.go index 4a34bec2706..c050d52fac2 100644 --- a/integration/v3_lease_test.go +++ b/integration/v3_lease_test.go @@ -106,7 +106,7 @@ func TestV3LeaseGrantByID(t *testing.T) { lresp, err = toGRPC(clus.RandClient()).Lease.LeaseGrant( context.TODO(), &pb.LeaseGrantRequest{ID: 1, TTL: 1}) - if err != rpctypes.ErrLeaseExist { + if err != rpctypes.ErrGRPCLeaseExist { t.Error(err) } @@ -242,8 +242,8 @@ func TestV3PutOnNonExistLease(t *testing.T) { badLeaseID := int64(0x12345678) putr := &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: badLeaseID} _, err := toGRPC(clus.RandClient()).KV.Put(ctx, putr) - if err != rpctypes.ErrLeaseNotFound { - t.Errorf("err = %v, want %v", err, rpctypes.ErrCompacted) + if err != rpctypes.ErrGRPCLeaseNotFound { + t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCCompacted) } } @@ -424,7 +424,7 @@ func leaseExist(t *testing.T, clus *ClusterV3, leaseID int64) bool { return false } - if err == rpctypes.ErrLeaseExist { + if err == rpctypes.ErrGRPCLeaseExist { return true } t.Fatalf("unexpecter error %v", err) diff --git a/test b/test index d81c91bc5df..86d071907b3 100755 --- a/test +++ b/test @@ -28,7 +28,7 @@ ln -s ${PWD}/cmd/vendor $GOPATH/src # Hack: gofmt ./ will recursively check the .git directory. So use *.go for gofmt. PKGS=`ls pkg/*/*go | cut -f1,2 -d/ | sort | uniq` -TESTABLE_AND_FORMATTABLE="auth client clientv3 discovery error etcdctl/ctlv2 etcdctl/ctlv3 etcdmain etcdserver etcdserver/auth etcdserver/api/v2http etcdserver/api/v2http/httptypes $PKGS proxy/httpproxy proxy/tcpproxy raft snap mvcc mvcc/backend store version wal rafthttp" +TESTABLE_AND_FORMATTABLE="auth client clientv3 discovery error etcdctl/ctlv2 etcdctl/ctlv3 etcdmain etcdserver etcdserver/auth etcdserver/api/v2http etcdserver/api/v2http/httptypes etcdserver/api/v3rpc etcdserver/api/v3rpc/rpctypes $PKGS proxy/httpproxy proxy/tcpproxy raft snap mvcc mvcc/backend store version wal rafthttp" FORMATTABLE="$TESTABLE_AND_FORMATTABLE *.go etcdctl/ integration clientv3/integration e2e alarm" # user has not provided PKG override