Skip to content

Commit

Permalink
Merge pull request etcd-io#11 from jingyih/filter_rpc_request_to_learner
Browse files Browse the repository at this point in the history
etcdserver: filter rpc request to learner
  • Loading branch information
jingyih authored Mar 30, 2019
2 parents 58a03d1 + 066ae1d commit fbaba02
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 0 deletions.
9 changes: 9 additions & 0 deletions etcdserver/api/v3rpc/interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor {
return nil, rpctypes.ErrGRPCNotCapable
}

// TODO: add test in clientv3/integration to verify behavior
if s.IsLearner() && !isRPCEnabledForLearner(req) {
return nil, rpctypes.ErrGPRCNotSupportedForLearner
}

md, ok := metadata.FromIncomingContext(ctx)
if ok {
if ks := md[rpctypes.MetadataRequireLeaderKey]; len(ks) > 0 && ks[0] == rpctypes.MetadataHasLeader {
Expand Down Expand Up @@ -190,6 +195,10 @@ func newStreamInterceptor(s *etcdserver.EtcdServer) grpc.StreamServerInterceptor
return rpctypes.ErrGRPCNotCapable
}

if s.IsLearner() { // learner does not support Watch and LeaseKeepAlive RPC
return rpctypes.ErrGPRCNotSupportedForLearner
}

md, ok := metadata.FromIncomingContext(ss.Context())
if ok {
if ks := md[rpctypes.MetadataRequireLeaderKey]; len(ks) > 0 && ks[0] == rpctypes.MetadataHasLeader {
Expand Down
1 change: 1 addition & 0 deletions etcdserver/api/v3rpc/rpctypes/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ var (
ErrGRPCTimeoutDueToConnectionLost = status.New(codes.Unavailable, "etcdserver: request timed out, possibly due to connection lost").Err()
ErrGRPCUnhealthy = status.New(codes.Unavailable, "etcdserver: unhealthy cluster").Err()
ErrGRPCCorrupt = status.New(codes.DataLoss, "etcdserver: corrupt cluster").Err()
ErrGPRCNotSupportedForLearner = status.New(codes.FailedPrecondition, "etcdserver: rpc not supported for learner").Err()

errStringToError = map[string]error{
ErrorDesc(ErrGRPCEmptyKey): ErrGRPCEmptyKey,
Expand Down
13 changes: 13 additions & 0 deletions etcdserver/api/v3rpc/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"go.etcd.io/etcd/etcdserver"
"go.etcd.io/etcd/etcdserver/api/membership"
"go.etcd.io/etcd/etcdserver/api/v3rpc/rpctypes"
pb "go.etcd.io/etcd/etcdserver/etcdserverpb"
"go.etcd.io/etcd/lease"
"go.etcd.io/etcd/mvcc"

Expand Down Expand Up @@ -116,3 +117,15 @@ func isClientCtxErr(ctxErr error, err error) bool {
}
return false
}

// in v3.4, learner is allowed to serve serializable read and endpoint status
func isRPCEnabledForLearner(req interface{}) bool {
switch r := req.(type) {
case *pb.StatusRequest:
return true
case *pb.RangeRequest:
return r.Serializable
default:
return false
}
}

0 comments on commit fbaba02

Please sign in to comment.