Browse Source

Merge pull request #5948 from heyitsanthony/upgrade-grpc-cred-clobber

vendor: update grpc
Anthony Romano 9 years ago
parent
commit
bf0be0fe5e

+ 16 - 16
clientv3/auth.go

@@ -115,52 +115,52 @@ func NewAuth(c *Client) Auth {
 }
 }
 
 
 func (auth *auth) AuthEnable(ctx context.Context) (*AuthEnableResponse, error) {
 func (auth *auth) AuthEnable(ctx context.Context) (*AuthEnableResponse, error) {
-	resp, err := auth.remote.AuthEnable(ctx, &pb.AuthEnableRequest{})
+	resp, err := auth.remote.AuthEnable(ctx, &pb.AuthEnableRequest{}, grpc.FailFast(false))
 	return (*AuthEnableResponse)(resp), toErr(ctx, err)
 	return (*AuthEnableResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) AuthDisable(ctx context.Context) (*AuthDisableResponse, error) {
 func (auth *auth) AuthDisable(ctx context.Context) (*AuthDisableResponse, error) {
-	resp, err := auth.remote.AuthDisable(ctx, &pb.AuthDisableRequest{})
+	resp, err := auth.remote.AuthDisable(ctx, &pb.AuthDisableRequest{}, grpc.FailFast(false))
 	return (*AuthDisableResponse)(resp), toErr(ctx, err)
 	return (*AuthDisableResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) UserAdd(ctx context.Context, name string, password string) (*AuthUserAddResponse, error) {
 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})
+	resp, err := auth.remote.UserAdd(ctx, &pb.AuthUserAddRequest{Name: name, Password: password}, grpc.FailFast(false))
 	return (*AuthUserAddResponse)(resp), toErr(ctx, err)
 	return (*AuthUserAddResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) UserDelete(ctx context.Context, name string) (*AuthUserDeleteResponse, error) {
 func (auth *auth) UserDelete(ctx context.Context, name string) (*AuthUserDeleteResponse, error) {
-	resp, err := auth.remote.UserDelete(ctx, &pb.AuthUserDeleteRequest{Name: name})
+	resp, err := auth.remote.UserDelete(ctx, &pb.AuthUserDeleteRequest{Name: name}, grpc.FailFast(false))
 	return (*AuthUserDeleteResponse)(resp), toErr(ctx, err)
 	return (*AuthUserDeleteResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) UserChangePassword(ctx context.Context, name string, password string) (*AuthUserChangePasswordResponse, error) {
 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})
+	resp, err := auth.remote.UserChangePassword(ctx, &pb.AuthUserChangePasswordRequest{Name: name, Password: password}, grpc.FailFast(false))
 	return (*AuthUserChangePasswordResponse)(resp), toErr(ctx, err)
 	return (*AuthUserChangePasswordResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) UserGrantRole(ctx context.Context, user string, role string) (*AuthUserGrantRoleResponse, error) {
 func (auth *auth) UserGrantRole(ctx context.Context, user string, role string) (*AuthUserGrantRoleResponse, error) {
-	resp, err := auth.remote.UserGrantRole(ctx, &pb.AuthUserGrantRoleRequest{User: user, Role: role})
+	resp, err := auth.remote.UserGrantRole(ctx, &pb.AuthUserGrantRoleRequest{User: user, Role: role}, grpc.FailFast(false))
 	return (*AuthUserGrantRoleResponse)(resp), toErr(ctx, err)
 	return (*AuthUserGrantRoleResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) UserGet(ctx context.Context, name string) (*AuthUserGetResponse, error) {
 func (auth *auth) UserGet(ctx context.Context, name string) (*AuthUserGetResponse, error) {
-	resp, err := auth.remote.UserGet(ctx, &pb.AuthUserGetRequest{Name: name})
+	resp, err := auth.remote.UserGet(ctx, &pb.AuthUserGetRequest{Name: name}, grpc.FailFast(false))
 	return (*AuthUserGetResponse)(resp), toErr(ctx, err)
 	return (*AuthUserGetResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) UserList(ctx context.Context) (*AuthUserListResponse, error) {
 func (auth *auth) UserList(ctx context.Context) (*AuthUserListResponse, error) {
-	resp, err := auth.remote.UserList(ctx, &pb.AuthUserListRequest{})
+	resp, err := auth.remote.UserList(ctx, &pb.AuthUserListRequest{}, grpc.FailFast(false))
 	return (*AuthUserListResponse)(resp), toErr(ctx, err)
 	return (*AuthUserListResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) UserRevokeRole(ctx context.Context, name string, role string) (*AuthUserRevokeRoleResponse, error) {
 func (auth *auth) UserRevokeRole(ctx context.Context, name string, role string) (*AuthUserRevokeRoleResponse, error) {
-	resp, err := auth.remote.UserRevokeRole(ctx, &pb.AuthUserRevokeRoleRequest{Name: name, Role: role})
+	resp, err := auth.remote.UserRevokeRole(ctx, &pb.AuthUserRevokeRoleRequest{Name: name, Role: role}, grpc.FailFast(false))
 	return (*AuthUserRevokeRoleResponse)(resp), toErr(ctx, err)
 	return (*AuthUserRevokeRoleResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) RoleAdd(ctx context.Context, name string) (*AuthRoleAddResponse, error) {
 func (auth *auth) RoleAdd(ctx context.Context, name string) (*AuthRoleAddResponse, error) {
-	resp, err := auth.remote.RoleAdd(ctx, &pb.AuthRoleAddRequest{Name: name})
+	resp, err := auth.remote.RoleAdd(ctx, &pb.AuthRoleAddRequest{Name: name}, grpc.FailFast(false))
 	return (*AuthRoleAddResponse)(resp), toErr(ctx, err)
 	return (*AuthRoleAddResponse)(resp), toErr(ctx, err)
 }
 }
 
 
@@ -170,27 +170,27 @@ func (auth *auth) RoleGrantPermission(ctx context.Context, name string, key, ran
 		RangeEnd: []byte(rangeEnd),
 		RangeEnd: []byte(rangeEnd),
 		PermType: authpb.Permission_Type(permType),
 		PermType: authpb.Permission_Type(permType),
 	}
 	}
-	resp, err := auth.remote.RoleGrantPermission(ctx, &pb.AuthRoleGrantPermissionRequest{Name: name, Perm: perm})
+	resp, err := auth.remote.RoleGrantPermission(ctx, &pb.AuthRoleGrantPermissionRequest{Name: name, Perm: perm}, grpc.FailFast(false))
 	return (*AuthRoleGrantPermissionResponse)(resp), toErr(ctx, err)
 	return (*AuthRoleGrantPermissionResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) RoleGet(ctx context.Context, role string) (*AuthRoleGetResponse, error) {
 func (auth *auth) RoleGet(ctx context.Context, role string) (*AuthRoleGetResponse, error) {
-	resp, err := auth.remote.RoleGet(ctx, &pb.AuthRoleGetRequest{Role: role})
+	resp, err := auth.remote.RoleGet(ctx, &pb.AuthRoleGetRequest{Role: role}, grpc.FailFast(false))
 	return (*AuthRoleGetResponse)(resp), toErr(ctx, err)
 	return (*AuthRoleGetResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) RoleList(ctx context.Context) (*AuthRoleListResponse, error) {
 func (auth *auth) RoleList(ctx context.Context) (*AuthRoleListResponse, error) {
-	resp, err := auth.remote.RoleList(ctx, &pb.AuthRoleListRequest{})
+	resp, err := auth.remote.RoleList(ctx, &pb.AuthRoleListRequest{}, grpc.FailFast(false))
 	return (*AuthRoleListResponse)(resp), toErr(ctx, err)
 	return (*AuthRoleListResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) RoleRevokePermission(ctx context.Context, role string, key, rangeEnd string) (*AuthRoleRevokePermissionResponse, error) {
 func (auth *auth) RoleRevokePermission(ctx context.Context, role string, key, rangeEnd string) (*AuthRoleRevokePermissionResponse, error) {
-	resp, err := auth.remote.RoleRevokePermission(ctx, &pb.AuthRoleRevokePermissionRequest{Role: role, Key: key, RangeEnd: rangeEnd})
+	resp, err := auth.remote.RoleRevokePermission(ctx, &pb.AuthRoleRevokePermissionRequest{Role: role, Key: key, RangeEnd: rangeEnd}, grpc.FailFast(false))
 	return (*AuthRoleRevokePermissionResponse)(resp), toErr(ctx, err)
 	return (*AuthRoleRevokePermissionResponse)(resp), toErr(ctx, err)
 }
 }
 
 
 func (auth *auth) RoleDelete(ctx context.Context, role string) (*AuthRoleDeleteResponse, error) {
 func (auth *auth) RoleDelete(ctx context.Context, role string) (*AuthRoleDeleteResponse, error) {
-	resp, err := auth.remote.RoleDelete(ctx, &pb.AuthRoleDeleteRequest{Role: role})
+	resp, err := auth.remote.RoleDelete(ctx, &pb.AuthRoleDeleteRequest{Role: role}, grpc.FailFast(false))
 	return (*AuthRoleDeleteResponse)(resp), toErr(ctx, err)
 	return (*AuthRoleDeleteResponse)(resp), toErr(ctx, err)
 }
 }
 
 
@@ -208,7 +208,7 @@ type authenticator struct {
 }
 }
 
 
 func (auth *authenticator) authenticate(ctx context.Context, name string, password string) (*AuthenticateResponse, error) {
 func (auth *authenticator) authenticate(ctx context.Context, name string, password string) (*AuthenticateResponse, error) {
-	resp, err := auth.remote.Authenticate(ctx, &pb.AuthenticateRequest{Name: name, Password: password})
+	resp, err := auth.remote.Authenticate(ctx, &pb.AuthenticateRequest{Name: name, Password: password}, grpc.FailFast(false))
 	return (*AuthenticateResponse)(resp), toErr(ctx, err)
 	return (*AuthenticateResponse)(resp), toErr(ctx, err)
 }
 }
 
 

+ 5 - 4
clientv3/cluster.go

@@ -17,6 +17,7 @@ package clientv3
 import (
 import (
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
+	"google.golang.org/grpc"
 )
 )
 
 
 type (
 type (
@@ -51,7 +52,7 @@ func NewCluster(c *Client) Cluster {
 
 
 func (c *cluster) MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) {
 func (c *cluster) MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) {
 	r := &pb.MemberAddRequest{PeerURLs: peerAddrs}
 	r := &pb.MemberAddRequest{PeerURLs: peerAddrs}
-	resp, err := c.remote.MemberAdd(ctx, r)
+	resp, err := c.remote.MemberAdd(ctx, r, grpc.FailFast(false))
 	if err == nil {
 	if err == nil {
 		return (*MemberAddResponse)(resp), nil
 		return (*MemberAddResponse)(resp), nil
 	}
 	}
@@ -63,7 +64,7 @@ func (c *cluster) MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAdd
 
 
 func (c *cluster) MemberRemove(ctx context.Context, id uint64) (*MemberRemoveResponse, error) {
 func (c *cluster) MemberRemove(ctx context.Context, id uint64) (*MemberRemoveResponse, error) {
 	r := &pb.MemberRemoveRequest{ID: id}
 	r := &pb.MemberRemoveRequest{ID: id}
-	resp, err := c.remote.MemberRemove(ctx, r)
+	resp, err := c.remote.MemberRemove(ctx, r, grpc.FailFast(false))
 	if err == nil {
 	if err == nil {
 		return (*MemberRemoveResponse)(resp), nil
 		return (*MemberRemoveResponse)(resp), nil
 	}
 	}
@@ -77,7 +78,7 @@ func (c *cluster) MemberUpdate(ctx context.Context, id uint64, peerAddrs []strin
 	// it is safe to retry on update.
 	// it is safe to retry on update.
 	for {
 	for {
 		r := &pb.MemberUpdateRequest{ID: id, PeerURLs: peerAddrs}
 		r := &pb.MemberUpdateRequest{ID: id, PeerURLs: peerAddrs}
-		resp, err := c.remote.MemberUpdate(ctx, r)
+		resp, err := c.remote.MemberUpdate(ctx, r, grpc.FailFast(false))
 		if err == nil {
 		if err == nil {
 			return (*MemberUpdateResponse)(resp), nil
 			return (*MemberUpdateResponse)(resp), nil
 		}
 		}
@@ -90,7 +91,7 @@ func (c *cluster) MemberUpdate(ctx context.Context, id uint64, peerAddrs []strin
 func (c *cluster) MemberList(ctx context.Context) (*MemberListResponse, error) {
 func (c *cluster) MemberList(ctx context.Context) (*MemberListResponse, error) {
 	// it is safe to retry on list.
 	// it is safe to retry on list.
 	for {
 	for {
-		resp, err := c.remote.MemberList(ctx, &pb.MemberListRequest{})
+		resp, err := c.remote.MemberList(ctx, &pb.MemberListRequest{}, grpc.FailFast(false))
 		if err == nil {
 		if err == nil {
 			return (*MemberListResponse)(resp), nil
 			return (*MemberListResponse)(resp), nil
 		}
 		}

+ 5 - 4
clientv3/kv.go

@@ -17,6 +17,7 @@ package clientv3
 import (
 import (
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
+	"google.golang.org/grpc"
 )
 )
 
 
 type (
 type (
@@ -100,7 +101,7 @@ func (kv *kv) Delete(ctx context.Context, key string, opts ...OpOption) (*Delete
 }
 }
 
 
 func (kv *kv) Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error) {
 func (kv *kv) Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error) {
-	resp, err := kv.remote.Compact(ctx, OpCompact(rev, opts...).toRequest())
+	resp, err := kv.remote.Compact(ctx, OpCompact(rev, opts...).toRequest(), grpc.FailFast(false))
 	if err != nil {
 	if err != nil {
 		return nil, toErr(ctx, err)
 		return nil, toErr(ctx, err)
 	}
 	}
@@ -150,21 +151,21 @@ func (kv *kv) do(ctx context.Context, op Op) (OpResponse, error) {
 			r.SortTarget = pb.RangeRequest_SortTarget(op.sort.Target)
 			r.SortTarget = pb.RangeRequest_SortTarget(op.sort.Target)
 		}
 		}
 
 
-		resp, err = kv.remote.Range(ctx, r)
+		resp, err = kv.remote.Range(ctx, r, grpc.FailFast(false))
 		if err == nil {
 		if err == nil {
 			return OpResponse{get: (*GetResponse)(resp)}, nil
 			return OpResponse{get: (*GetResponse)(resp)}, nil
 		}
 		}
 	case tPut:
 	case tPut:
 		var resp *pb.PutResponse
 		var resp *pb.PutResponse
 		r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV}
 		r := &pb.PutRequest{Key: op.key, Value: op.val, Lease: int64(op.leaseID), PrevKv: op.prevKV}
-		resp, err = kv.remote.Put(ctx, r)
+		resp, err = kv.remote.Put(ctx, r, grpc.FailFast(false))
 		if err == nil {
 		if err == nil {
 			return OpResponse{put: (*PutResponse)(resp)}, nil
 			return OpResponse{put: (*PutResponse)(resp)}, nil
 		}
 		}
 	case tDeleteRange:
 	case tDeleteRange:
 		var resp *pb.DeleteRangeResponse
 		var resp *pb.DeleteRangeResponse
 		r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV}
 		r := &pb.DeleteRangeRequest{Key: op.key, RangeEnd: op.end, PrevKv: op.prevKV}
-		resp, err = kv.remote.DeleteRange(ctx, r)
+		resp, err = kv.remote.DeleteRange(ctx, r, grpc.FailFast(false))
 		if err == nil {
 		if err == nil {
 			return OpResponse{del: (*DeleteResponse)(resp)}, nil
 			return OpResponse{del: (*DeleteResponse)(resp)}, nil
 		}
 		}

+ 5 - 4
clientv3/lease.go

@@ -21,6 +21,7 @@ import (
 	"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
 	"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
+	"google.golang.org/grpc"
 )
 )
 
 
 type (
 type (
@@ -129,7 +130,7 @@ func (l *lessor) Grant(ctx context.Context, ttl int64) (*LeaseGrantResponse, err
 
 
 	for {
 	for {
 		r := &pb.LeaseGrantRequest{TTL: ttl}
 		r := &pb.LeaseGrantRequest{TTL: ttl}
-		resp, err := l.remote.LeaseGrant(cctx, r)
+		resp, err := l.remote.LeaseGrant(cctx, r, grpc.FailFast(false))
 		if err == nil {
 		if err == nil {
 			gresp := &LeaseGrantResponse{
 			gresp := &LeaseGrantResponse{
 				ResponseHeader: resp.GetHeader(),
 				ResponseHeader: resp.GetHeader(),
@@ -155,7 +156,7 @@ func (l *lessor) Revoke(ctx context.Context, id LeaseID) (*LeaseRevokeResponse,
 
 
 	for {
 	for {
 		r := &pb.LeaseRevokeRequest{ID: int64(id)}
 		r := &pb.LeaseRevokeRequest{ID: int64(id)}
-		resp, err := l.remote.LeaseRevoke(cctx, r)
+		resp, err := l.remote.LeaseRevoke(cctx, r, grpc.FailFast(false))
 
 
 		if err == nil {
 		if err == nil {
 			return (*LeaseRevokeResponse)(resp), nil
 			return (*LeaseRevokeResponse)(resp), nil
@@ -261,7 +262,7 @@ func (l *lessor) keepAliveOnce(ctx context.Context, id LeaseID) (*LeaseKeepAlive
 	cctx, cancel := context.WithCancel(ctx)
 	cctx, cancel := context.WithCancel(ctx)
 	defer cancel()
 	defer cancel()
 
 
-	stream, err := l.remote.LeaseKeepAlive(cctx)
+	stream, err := l.remote.LeaseKeepAlive(cctx, grpc.FailFast(false))
 	if err != nil {
 	if err != nil {
 		return nil, toErr(ctx, err)
 		return nil, toErr(ctx, err)
 	}
 	}
@@ -418,7 +419,7 @@ func (l *lessor) getKeepAliveStream() pb.Lease_LeaseKeepAliveClient {
 
 
 func (l *lessor) newStream() error {
 func (l *lessor) newStream() error {
 	sctx, cancel := context.WithCancel(l.stopCtx)
 	sctx, cancel := context.WithCancel(l.stopCtx)
-	stream, err := l.remote.LeaseKeepAlive(sctx)
+	stream, err := l.remote.LeaseKeepAlive(sctx, grpc.FailFast(false))
 	if err != nil {
 	if err != nil {
 		cancel()
 		cancel()
 		return toErr(sctx, err)
 		return toErr(sctx, err)

+ 6 - 5
clientv3/maintenance.go

@@ -19,6 +19,7 @@ import (
 
 
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
+	"google.golang.org/grpc"
 )
 )
 
 
 type (
 type (
@@ -67,7 +68,7 @@ func (m *maintenance) AlarmList(ctx context.Context) (*AlarmResponse, error) {
 		Alarm:    pb.AlarmType_NONE, // all
 		Alarm:    pb.AlarmType_NONE, // all
 	}
 	}
 	for {
 	for {
-		resp, err := m.remote.Alarm(ctx, req)
+		resp, err := m.remote.Alarm(ctx, req, grpc.FailFast(false))
 		if err == nil {
 		if err == nil {
 			return (*AlarmResponse)(resp), nil
 			return (*AlarmResponse)(resp), nil
 		}
 		}
@@ -100,7 +101,7 @@ func (m *maintenance) AlarmDisarm(ctx context.Context, am *AlarmMember) (*AlarmR
 		return &ret, nil
 		return &ret, nil
 	}
 	}
 
 
-	resp, err := m.remote.Alarm(ctx, req)
+	resp, err := m.remote.Alarm(ctx, req, grpc.FailFast(false))
 	if err == nil {
 	if err == nil {
 		return (*AlarmResponse)(resp), nil
 		return (*AlarmResponse)(resp), nil
 	}
 	}
@@ -114,7 +115,7 @@ func (m *maintenance) Defragment(ctx context.Context, endpoint string) (*Defragm
 	}
 	}
 	defer conn.Close()
 	defer conn.Close()
 	remote := pb.NewMaintenanceClient(conn)
 	remote := pb.NewMaintenanceClient(conn)
-	resp, err := remote.Defragment(ctx, &pb.DefragmentRequest{})
+	resp, err := remote.Defragment(ctx, &pb.DefragmentRequest{}, grpc.FailFast(false))
 	if err != nil {
 	if err != nil {
 		return nil, toErr(ctx, err)
 		return nil, toErr(ctx, err)
 	}
 	}
@@ -128,7 +129,7 @@ func (m *maintenance) Status(ctx context.Context, endpoint string) (*StatusRespo
 	}
 	}
 	defer conn.Close()
 	defer conn.Close()
 	remote := pb.NewMaintenanceClient(conn)
 	remote := pb.NewMaintenanceClient(conn)
-	resp, err := remote.Status(ctx, &pb.StatusRequest{})
+	resp, err := remote.Status(ctx, &pb.StatusRequest{}, grpc.FailFast(false))
 	if err != nil {
 	if err != nil {
 		return nil, toErr(ctx, err)
 		return nil, toErr(ctx, err)
 	}
 	}
@@ -136,7 +137,7 @@ func (m *maintenance) Status(ctx context.Context, endpoint string) (*StatusRespo
 }
 }
 
 
 func (m *maintenance) Snapshot(ctx context.Context) (io.ReadCloser, error) {
 func (m *maintenance) Snapshot(ctx context.Context) (io.ReadCloser, error) {
-	ss, err := m.remote.Snapshot(ctx, &pb.SnapshotRequest{})
+	ss, err := m.remote.Snapshot(ctx, &pb.SnapshotRequest{}, grpc.FailFast(false))
 	if err != nil {
 	if err != nil {
 		return nil, toErr(ctx, err)
 		return nil, toErr(ctx, err)
 	}
 	}

+ 2 - 1
clientv3/txn.go

@@ -19,6 +19,7 @@ import (
 
 
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
+	"google.golang.org/grpc"
 )
 )
 
 
 // Txn is the interface that wraps mini-transactions.
 // Txn is the interface that wraps mini-transactions.
@@ -152,7 +153,7 @@ func (txn *txn) Commit() (*TxnResponse, error) {
 
 
 func (txn *txn) commit() (*TxnResponse, error) {
 func (txn *txn) commit() (*TxnResponse, error) {
 	r := &pb.TxnRequest{Compare: txn.cmps, Success: txn.sus, Failure: txn.fas}
 	r := &pb.TxnRequest{Compare: txn.cmps, Success: txn.sus, Failure: txn.fas}
-	resp, err := txn.kv.remote.Txn(txn.ctx, r)
+	resp, err := txn.kv.remote.Txn(txn.ctx, r, grpc.FailFast(false))
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 2 - 1
clientv3/watch.go

@@ -23,6 +23,7 @@ import (
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
 	mvccpb "github.com/coreos/etcd/mvcc/mvccpb"
 	mvccpb "github.com/coreos/etcd/mvcc/mvccpb"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
+	"google.golang.org/grpc"
 )
 )
 
 
 const (
 const (
@@ -626,7 +627,7 @@ func (w *watchGrpcStream) openWatchClient() (ws pb.Watch_WatchClient, err error)
 			return nil, err
 			return nil, err
 		default:
 		default:
 		}
 		}
-		if ws, err = w.remote.Watch(w.ctx); ws != nil && err == nil {
+		if ws, err = w.remote.Watch(w.ctx, grpc.FailFast(false)); ws != nil && err == nil {
 			break
 			break
 		}
 		}
 		if isHaltErr(w.ctx, err) {
 		if isHaltErr(w.ctx, err) {

+ 18 - 9
cmd/Godeps/Godeps.json

@@ -234,39 +234,48 @@
 		},
 		},
 		{
 		{
 			"ImportPath": "google.golang.org/grpc",
 			"ImportPath": "google.golang.org/grpc",
-			"Rev": "e78224b060cf3215247b7be455f80ea22e469b66"
+			"Comment": "v1.0.0-6-g02fca89",
+			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03"
 		},
 		},
 		{
 		{
 			"ImportPath": "google.golang.org/grpc/codes",
 			"ImportPath": "google.golang.org/grpc/codes",
-			"Rev": "e78224b060cf3215247b7be455f80ea22e469b66"
+			"Comment": "v1.0.0-6-g02fca89",
+			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03"
 		},
 		},
 		{
 		{
 			"ImportPath": "google.golang.org/grpc/credentials",
 			"ImportPath": "google.golang.org/grpc/credentials",
-			"Rev": "e78224b060cf3215247b7be455f80ea22e469b66"
+			"Comment": "v1.0.0-6-g02fca89",
+			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03"
 		},
 		},
 		{
 		{
 			"ImportPath": "google.golang.org/grpc/grpclog",
 			"ImportPath": "google.golang.org/grpc/grpclog",
-			"Rev": "e78224b060cf3215247b7be455f80ea22e469b66"
+			"Comment": "v1.0.0-6-g02fca89",
+			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03"
 		},
 		},
 		{
 		{
 			"ImportPath": "google.golang.org/grpc/internal",
 			"ImportPath": "google.golang.org/grpc/internal",
-			"Rev": "e78224b060cf3215247b7be455f80ea22e469b66"
+			"Comment": "v1.0.0-6-g02fca89",
+			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03"
 		},
 		},
 		{
 		{
 			"ImportPath": "google.golang.org/grpc/metadata",
 			"ImportPath": "google.golang.org/grpc/metadata",
-			"Rev": "e78224b060cf3215247b7be455f80ea22e469b66"
+			"Comment": "v1.0.0-6-g02fca89",
+			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03"
 		},
 		},
 		{
 		{
 			"ImportPath": "google.golang.org/grpc/naming",
 			"ImportPath": "google.golang.org/grpc/naming",
-			"Rev": "e78224b060cf3215247b7be455f80ea22e469b66"
+			"Comment": "v1.0.0-6-g02fca89",
+			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03"
 		},
 		},
 		{
 		{
 			"ImportPath": "google.golang.org/grpc/peer",
 			"ImportPath": "google.golang.org/grpc/peer",
-			"Rev": "e78224b060cf3215247b7be455f80ea22e469b66"
+			"Comment": "v1.0.0-6-g02fca89",
+			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03"
 		},
 		},
 		{
 		{
 			"ImportPath": "google.golang.org/grpc/transport",
 			"ImportPath": "google.golang.org/grpc/transport",
-			"Rev": "e78224b060cf3215247b7be455f80ea22e469b66"
+			"Comment": "v1.0.0-6-g02fca89",
+			"Rev": "02fca896ff5f50c6bbbee0860345a49344b37a03"
 		},
 		},
 		{
 		{
 			"ImportPath": "gopkg.in/cheggaaa/pb.v1",
 			"ImportPath": "gopkg.in/cheggaaa/pb.v1",

+ 110 - 65
cmd/vendor/google.golang.org/grpc/balancer.go

@@ -40,7 +40,6 @@ import (
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc/grpclog"
 	"google.golang.org/grpc/grpclog"
 	"google.golang.org/grpc/naming"
 	"google.golang.org/grpc/naming"
-	"google.golang.org/grpc/transport"
 )
 )
 
 
 // Address represents a server the client connects to.
 // Address represents a server the client connects to.
@@ -94,10 +93,10 @@ type Balancer interface {
 	// instead of blocking.
 	// instead of blocking.
 	//
 	//
 	// The function returns put which is called once the rpc has completed or failed.
 	// The function returns put which is called once the rpc has completed or failed.
-	// put can collect and report RPC stats to a remote load balancer. gRPC internals
-	// will try to call this again if err is non-nil (unless err is ErrClientConnClosing).
+	// put can collect and report RPC stats to a remote load balancer.
 	//
 	//
-	// TODO: Add other non-recoverable errors?
+	// This function should only return the errors Balancer cannot recover by itself.
+	// gRPC internals will fail the RPC if an error is returned.
 	Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error)
 	Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error)
 	// Notify returns a channel that is used by gRPC internals to watch the addresses
 	// Notify returns a channel that is used by gRPC internals to watch the addresses
 	// gRPC needs to connect. The addresses might be from a name resolver or remote
 	// gRPC needs to connect. The addresses might be from a name resolver or remote
@@ -139,35 +138,40 @@ func RoundRobin(r naming.Resolver) Balancer {
 	return &roundRobin{r: r}
 	return &roundRobin{r: r}
 }
 }
 
 
+type addrInfo struct {
+	addr      Address
+	connected bool
+}
+
 type roundRobin struct {
 type roundRobin struct {
-	r         naming.Resolver
-	w         naming.Watcher
-	open      []Address // all the addresses the client should potentially connect
-	mu        sync.Mutex
-	addrCh    chan []Address // the channel to notify gRPC internals the list of addresses the client should connect to.
-	connected []Address      // all the connected addresses
-	next      int            // index of the next address to return for Get()
-	waitCh    chan struct{}  // the channel to block when there is no connected address available
-	done      bool           // The Balancer is closed.
+	r      naming.Resolver
+	w      naming.Watcher
+	addrs  []*addrInfo // all the addresses the client should potentially connect
+	mu     sync.Mutex
+	addrCh chan []Address // the channel to notify gRPC internals the list of addresses the client should connect to.
+	next   int            // index of the next address to return for Get()
+	waitCh chan struct{}  // the channel to block when there is no connected address available
+	done   bool           // The Balancer is closed.
 }
 }
 
 
 func (rr *roundRobin) watchAddrUpdates() error {
 func (rr *roundRobin) watchAddrUpdates() error {
 	updates, err := rr.w.Next()
 	updates, err := rr.w.Next()
 	if err != nil {
 	if err != nil {
-		grpclog.Println("grpc: the naming watcher stops working due to %v.", err)
+		grpclog.Printf("grpc: the naming watcher stops working due to %v.\n", err)
 		return err
 		return err
 	}
 	}
 	rr.mu.Lock()
 	rr.mu.Lock()
 	defer rr.mu.Unlock()
 	defer rr.mu.Unlock()
 	for _, update := range updates {
 	for _, update := range updates {
 		addr := Address{
 		addr := Address{
-			Addr: update.Addr,
+			Addr:     update.Addr,
+			Metadata: update.Metadata,
 		}
 		}
 		switch update.Op {
 		switch update.Op {
 		case naming.Add:
 		case naming.Add:
 			var exist bool
 			var exist bool
-			for _, v := range rr.open {
-				if addr == v {
+			for _, v := range rr.addrs {
+				if addr == v.addr {
 					exist = true
 					exist = true
 					grpclog.Println("grpc: The name resolver wanted to add an existing address: ", addr)
 					grpclog.Println("grpc: The name resolver wanted to add an existing address: ", addr)
 					break
 					break
@@ -176,12 +180,12 @@ func (rr *roundRobin) watchAddrUpdates() error {
 			if exist {
 			if exist {
 				continue
 				continue
 			}
 			}
-			rr.open = append(rr.open, addr)
+			rr.addrs = append(rr.addrs, &addrInfo{addr: addr})
 		case naming.Delete:
 		case naming.Delete:
-			for i, v := range rr.open {
-				if v == addr {
-					copy(rr.open[i:], rr.open[i+1:])
-					rr.open = rr.open[:len(rr.open)-1]
+			for i, v := range rr.addrs {
+				if addr == v.addr {
+					copy(rr.addrs[i:], rr.addrs[i+1:])
+					rr.addrs = rr.addrs[:len(rr.addrs)-1]
 					break
 					break
 				}
 				}
 			}
 			}
@@ -189,9 +193,11 @@ func (rr *roundRobin) watchAddrUpdates() error {
 			grpclog.Println("Unknown update.Op ", update.Op)
 			grpclog.Println("Unknown update.Op ", update.Op)
 		}
 		}
 	}
 	}
-	// Make a copy of rr.open and write it onto rr.addrCh so that gRPC internals gets notified.
-	open := make([]Address, len(rr.open), len(rr.open))
-	copy(open, rr.open)
+	// Make a copy of rr.addrs and write it onto rr.addrCh so that gRPC internals gets notified.
+	open := make([]Address, len(rr.addrs))
+	for i, v := range rr.addrs {
+		open[i] = v.addr
+	}
 	if rr.done {
 	if rr.done {
 		return ErrClientConnClosing
 		return ErrClientConnClosing
 	}
 	}
@@ -202,7 +208,9 @@ func (rr *roundRobin) watchAddrUpdates() error {
 func (rr *roundRobin) Start(target string) error {
 func (rr *roundRobin) Start(target string) error {
 	if rr.r == nil {
 	if rr.r == nil {
 		// If there is no name resolver installed, it is not needed to
 		// If there is no name resolver installed, it is not needed to
-		// do name resolution. In this case, rr.addrCh stays nil.
+		// do name resolution. In this case, target is added into rr.addrs
+		// as the only address available and rr.addrCh stays nil.
+		rr.addrs = append(rr.addrs, &addrInfo{addr: Address{Addr: target}})
 		return nil
 		return nil
 	}
 	}
 	w, err := rr.r.Resolve(target)
 	w, err := rr.r.Resolve(target)
@@ -221,38 +229,41 @@ func (rr *roundRobin) Start(target string) error {
 	return nil
 	return nil
 }
 }
 
 
-// Up appends addr to the end of rr.connected and sends notification if there
-// are pending Get() calls.
+// Up sets the connected state of addr and sends notification if there are pending
+// Get() calls.
 func (rr *roundRobin) Up(addr Address) func(error) {
 func (rr *roundRobin) Up(addr Address) func(error) {
 	rr.mu.Lock()
 	rr.mu.Lock()
 	defer rr.mu.Unlock()
 	defer rr.mu.Unlock()
-	for _, a := range rr.connected {
-		if a == addr {
-			return nil
+	var cnt int
+	for _, a := range rr.addrs {
+		if a.addr == addr {
+			if a.connected {
+				return nil
+			}
+			a.connected = true
 		}
 		}
-	}
-	rr.connected = append(rr.connected, addr)
-	if len(rr.connected) == 1 {
-		// addr is only one available. Notify the Get() callers who are blocking.
-		if rr.waitCh != nil {
-			close(rr.waitCh)
-			rr.waitCh = nil
+		if a.connected {
+			cnt++
 		}
 		}
 	}
 	}
+	// addr is only one which is connected. Notify the Get() callers who are blocking.
+	if cnt == 1 && rr.waitCh != nil {
+		close(rr.waitCh)
+		rr.waitCh = nil
+	}
 	return func(err error) {
 	return func(err error) {
 		rr.down(addr, err)
 		rr.down(addr, err)
 	}
 	}
 }
 }
 
 
-// down removes addr from rr.connected and moves the remaining addrs forward.
+// down unsets the connected state of addr.
 func (rr *roundRobin) down(addr Address, err error) {
 func (rr *roundRobin) down(addr Address, err error) {
 	rr.mu.Lock()
 	rr.mu.Lock()
 	defer rr.mu.Unlock()
 	defer rr.mu.Unlock()
-	for i, a := range rr.connected {
-		if a == addr {
-			copy(rr.connected[i:], rr.connected[i+1:])
-			rr.connected = rr.connected[:len(rr.connected)-1]
-			return
+	for _, a := range rr.addrs {
+		if addr == a.addr {
+			a.connected = false
+			break
 		}
 		}
 	}
 	}
 }
 }
@@ -266,17 +277,40 @@ func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Ad
 		err = ErrClientConnClosing
 		err = ErrClientConnClosing
 		return
 		return
 	}
 	}
-	if rr.next >= len(rr.connected) {
-		rr.next = 0
+
+	if len(rr.addrs) > 0 {
+		if rr.next >= len(rr.addrs) {
+			rr.next = 0
+		}
+		next := rr.next
+		for {
+			a := rr.addrs[next]
+			next = (next + 1) % len(rr.addrs)
+			if a.connected {
+				addr = a.addr
+				rr.next = next
+				rr.mu.Unlock()
+				return
+			}
+			if next == rr.next {
+				// Has iterated all the possible address but none is connected.
+				break
+			}
+		}
 	}
 	}
-	if len(rr.connected) > 0 {
-		addr = rr.connected[rr.next]
+	if !opts.BlockingWait {
+		if len(rr.addrs) == 0 {
+			rr.mu.Unlock()
+			err = fmt.Errorf("there is no address available")
+			return
+		}
+		// Returns the next addr on rr.addrs for failfast RPCs.
+		addr = rr.addrs[rr.next].addr
 		rr.next++
 		rr.next++
 		rr.mu.Unlock()
 		rr.mu.Unlock()
 		return
 		return
 	}
 	}
-	// There is no address available. Wait on rr.waitCh.
-	// TODO(zhaoq): Handle the case when opts.BlockingWait is false.
+	// Wait on rr.waitCh for non-failfast RPCs.
 	if rr.waitCh == nil {
 	if rr.waitCh == nil {
 		ch = make(chan struct{})
 		ch = make(chan struct{})
 		rr.waitCh = ch
 		rr.waitCh = ch
@@ -287,7 +321,7 @@ func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Ad
 	for {
 	for {
 		select {
 		select {
 		case <-ctx.Done():
 		case <-ctx.Done():
-			err = transport.ContextErr(ctx.Err())
+			err = ctx.Err()
 			return
 			return
 		case <-ch:
 		case <-ch:
 			rr.mu.Lock()
 			rr.mu.Lock()
@@ -296,24 +330,35 @@ func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Ad
 				err = ErrClientConnClosing
 				err = ErrClientConnClosing
 				return
 				return
 			}
 			}
-			if len(rr.connected) == 0 {
-				// The newly added addr got removed by Down() again.
-				if rr.waitCh == nil {
-					ch = make(chan struct{})
-					rr.waitCh = ch
-				} else {
-					ch = rr.waitCh
+
+			if len(rr.addrs) > 0 {
+				if rr.next >= len(rr.addrs) {
+					rr.next = 0
+				}
+				next := rr.next
+				for {
+					a := rr.addrs[next]
+					next = (next + 1) % len(rr.addrs)
+					if a.connected {
+						addr = a.addr
+						rr.next = next
+						rr.mu.Unlock()
+						return
+					}
+					if next == rr.next {
+						// Has iterated all the possible address but none is connected.
+						break
+					}
 				}
 				}
-				rr.mu.Unlock()
-				continue
 			}
 			}
-			if rr.next >= len(rr.connected) {
-				rr.next = 0
+			// The newly added addr got removed by Down() again.
+			if rr.waitCh == nil {
+				ch = make(chan struct{})
+				rr.waitCh = ch
+			} else {
+				ch = rr.waitCh
 			}
 			}
-			addr = rr.connected[rr.next]
-			rr.next++
 			rr.mu.Unlock()
 			rr.mu.Unlock()
-			return
 		}
 		}
 	}
 	}
 }
 }

+ 8 - 10
cmd/vendor/google.golang.org/grpc/call.go

@@ -101,7 +101,7 @@ func sendRequest(ctx context.Context, codec Codec, compressor Compressor, callHd
 // Invoke is called by generated code. Also users can call Invoke directly when it
 // Invoke is called by generated code. Also users can call Invoke directly when it
 // is really needed in their use cases.
 // is really needed in their use cases.
 func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) (err error) {
 func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) (err error) {
-	var c callInfo
+	c := defaultCallInfo
 	for _, o := range opts {
 	for _, o := range opts {
 		if err := o.before(&c); err != nil {
 		if err := o.before(&c); err != nil {
 			return toRPCErr(err)
 			return toRPCErr(err)
@@ -155,19 +155,17 @@ func Invoke(ctx context.Context, method string, args, reply interface{}, cc *Cli
 		t, put, err = cc.getTransport(ctx, gopts)
 		t, put, err = cc.getTransport(ctx, gopts)
 		if err != nil {
 		if err != nil {
 			// TODO(zhaoq): Probably revisit the error handling.
 			// TODO(zhaoq): Probably revisit the error handling.
-			if err == ErrClientConnClosing {
-				return Errorf(codes.FailedPrecondition, "%v", err)
+			if _, ok := err.(*rpcError); ok {
+				return err
 			}
 			}
-			if _, ok := err.(transport.StreamError); ok {
-				return toRPCErr(err)
-			}
-			if _, ok := err.(transport.ConnectionError); ok {
+			if err == errConnClosing {
 				if c.failFast {
 				if c.failFast {
-					return toRPCErr(err)
+					return Errorf(codes.Unavailable, "%v", errConnClosing)
 				}
 				}
+				continue
 			}
 			}
-			// All the remaining cases are treated as retryable.
-			continue
+			// All the other errors are treated as Internal errors.
+			return Errorf(codes.Internal, "%v", err)
 		}
 		}
 		if c.traceInfo.tr != nil {
 		if c.traceInfo.tr != nil {
 			c.traceInfo.tr.LazyLog(&payload{sent: true, msg: args}, true)
 			c.traceInfo.tr.LazyLog(&payload{sent: true, msg: args}, true)

+ 22 - 21
cmd/vendor/google.golang.org/grpc/clientconn.go

@@ -218,27 +218,26 @@ func Dial(target string, opts ...DialOption) (*ClientConn, error) {
 	for _, opt := range opts {
 	for _, opt := range opts {
 		opt(&cc.dopts)
 		opt(&cc.dopts)
 	}
 	}
+
+	// Set defaults.
 	if cc.dopts.codec == nil {
 	if cc.dopts.codec == nil {
-		// Set the default codec.
 		cc.dopts.codec = protoCodec{}
 		cc.dopts.codec = protoCodec{}
 	}
 	}
-
 	if cc.dopts.bs == nil {
 	if cc.dopts.bs == nil {
 		cc.dopts.bs = DefaultBackoffConfig
 		cc.dopts.bs = DefaultBackoffConfig
 	}
 	}
-
-	cc.balancer = cc.dopts.balancer
-	if cc.balancer == nil {
-		cc.balancer = RoundRobin(nil)
+	if cc.dopts.balancer == nil {
+		cc.dopts.balancer = RoundRobin(nil)
 	}
 	}
-	if err := cc.balancer.Start(target); err != nil {
+
+	if err := cc.dopts.balancer.Start(target); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 	var (
 	var (
 		ok    bool
 		ok    bool
 		addrs []Address
 		addrs []Address
 	)
 	)
-	ch := cc.balancer.Notify()
+	ch := cc.dopts.balancer.Notify()
 	if ch == nil {
 	if ch == nil {
 		// There is no name resolver installed.
 		// There is no name resolver installed.
 		addrs = append(addrs, Address{Addr: target})
 		addrs = append(addrs, Address{Addr: target})
@@ -319,7 +318,6 @@ func (s ConnectivityState) String() string {
 // ClientConn represents a client connection to an RPC server.
 // ClientConn represents a client connection to an RPC server.
 type ClientConn struct {
 type ClientConn struct {
 	target    string
 	target    string
-	balancer  Balancer
 	authority string
 	authority string
 	dopts     dialOptions
 	dopts     dialOptions
 
 
@@ -328,7 +326,7 @@ type ClientConn struct {
 }
 }
 
 
 func (cc *ClientConn) lbWatcher() {
 func (cc *ClientConn) lbWatcher() {
-	for addrs := range cc.balancer.Notify() {
+	for addrs := range cc.dopts.balancer.Notify() {
 		var (
 		var (
 			add []Address   // Addresses need to setup connections.
 			add []Address   // Addresses need to setup connections.
 			del []*addrConn // Connections need to tear down.
 			del []*addrConn // Connections need to tear down.
@@ -424,15 +422,14 @@ func (cc *ClientConn) newAddrConn(addr Address, skipWait bool) error {
 }
 }
 
 
 func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) (transport.ClientTransport, func(), error) {
 func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions) (transport.ClientTransport, func(), error) {
-	// TODO(zhaoq): Implement fail-fast logic.
-	addr, put, err := cc.balancer.Get(ctx, opts)
+	addr, put, err := cc.dopts.balancer.Get(ctx, opts)
 	if err != nil {
 	if err != nil {
-		return nil, nil, err
+		return nil, nil, toRPCErr(err)
 	}
 	}
 	cc.mu.RLock()
 	cc.mu.RLock()
 	if cc.conns == nil {
 	if cc.conns == nil {
 		cc.mu.RUnlock()
 		cc.mu.RUnlock()
-		return nil, nil, ErrClientConnClosing
+		return nil, nil, toRPCErr(ErrClientConnClosing)
 	}
 	}
 	ac, ok := cc.conns[addr]
 	ac, ok := cc.conns[addr]
 	cc.mu.RUnlock()
 	cc.mu.RUnlock()
@@ -440,9 +437,9 @@ func (cc *ClientConn) getTransport(ctx context.Context, opts BalancerGetOptions)
 		if put != nil {
 		if put != nil {
 			put()
 			put()
 		}
 		}
-		return nil, nil, transport.StreamErrorf(codes.Internal, "grpc: failed to find the transport to send the rpc")
+		return nil, nil, Errorf(codes.Internal, "grpc: failed to find the transport to send the rpc")
 	}
 	}
-	t, err := ac.wait(ctx)
+	t, err := ac.wait(ctx, !opts.BlockingWait)
 	if err != nil {
 	if err != nil {
 		if put != nil {
 		if put != nil {
 			put()
 			put()
@@ -462,7 +459,7 @@ func (cc *ClientConn) Close() error {
 	conns := cc.conns
 	conns := cc.conns
 	cc.conns = nil
 	cc.conns = nil
 	cc.mu.Unlock()
 	cc.mu.Unlock()
-	cc.balancer.Close()
+	cc.dopts.balancer.Close()
 	for _, ac := range conns {
 	for _, ac := range conns {
 		ac.tearDown(ErrClientConnClosing)
 		ac.tearDown(ErrClientConnClosing)
 	}
 	}
@@ -610,7 +607,7 @@ func (ac *addrConn) resetTransport(closeTransport bool) error {
 			close(ac.ready)
 			close(ac.ready)
 			ac.ready = nil
 			ac.ready = nil
 		}
 		}
-		ac.down = ac.cc.balancer.Up(ac.addr)
+		ac.down = ac.cc.dopts.balancer.Up(ac.addr)
 		ac.mu.Unlock()
 		ac.mu.Unlock()
 		return nil
 		return nil
 	}
 	}
@@ -649,8 +646,9 @@ func (ac *addrConn) transportMonitor() {
 	}
 	}
 }
 }
 
 
-// wait blocks until i) the new transport is up or ii) ctx is done or iii) ac is closed.
-func (ac *addrConn) wait(ctx context.Context) (transport.ClientTransport, error) {
+// wait blocks until i) the new transport is up or ii) ctx is done or iii) ac is closed or
+// iv) transport is in TransientFailure and the RPC is fail-fast.
+func (ac *addrConn) wait(ctx context.Context, failFast bool) (transport.ClientTransport, error) {
 	for {
 	for {
 		ac.mu.Lock()
 		ac.mu.Lock()
 		switch {
 		switch {
@@ -661,6 +659,9 @@ func (ac *addrConn) wait(ctx context.Context) (transport.ClientTransport, error)
 			ct := ac.transport
 			ct := ac.transport
 			ac.mu.Unlock()
 			ac.mu.Unlock()
 			return ct, nil
 			return ct, nil
+		case ac.state == TransientFailure && failFast:
+			ac.mu.Unlock()
+			return nil, Errorf(codes.Unavailable, "grpc: RPC failed fast due to transport failure")
 		default:
 		default:
 			ready := ac.ready
 			ready := ac.ready
 			if ready == nil {
 			if ready == nil {
@@ -670,7 +671,7 @@ func (ac *addrConn) wait(ctx context.Context) (transport.ClientTransport, error)
 			ac.mu.Unlock()
 			ac.mu.Unlock()
 			select {
 			select {
 			case <-ctx.Done():
 			case <-ctx.Done():
-				return nil, transport.ContextErr(ctx.Err())
+				return nil, toRPCErr(ctx.Err())
 			// Wait until the new transport is ready or failed.
 			// Wait until the new transport is ready or failed.
 			case <-ready:
 			case <-ready:
 			}
 			}

+ 8 - 6
cmd/vendor/google.golang.org/grpc/credentials/credentials.go

@@ -66,7 +66,7 @@ type PerRPCCredentials interface {
 	// TODO(zhaoq): Define the set of the qualified keys instead of leaving
 	// TODO(zhaoq): Define the set of the qualified keys instead of leaving
 	// it as an arbitrary string.
 	// it as an arbitrary string.
 	GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
 	GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
-	// RequireTransportSecurity indicates whether the credentails requires
+	// RequireTransportSecurity indicates whether the credentials requires
 	// transport security.
 	// transport security.
 	RequireTransportSecurity() bool
 	RequireTransportSecurity() bool
 }
 }
@@ -116,7 +116,7 @@ func (t TLSInfo) AuthType() string {
 // tlsCreds is the credentials required for authenticating a connection using TLS.
 // tlsCreds is the credentials required for authenticating a connection using TLS.
 type tlsCreds struct {
 type tlsCreds struct {
 	// TLS configuration
 	// TLS configuration
-	config tls.Config
+	config *tls.Config
 }
 }
 
 
 func (c tlsCreds) Info() ProtocolInfo {
 func (c tlsCreds) Info() ProtocolInfo {
@@ -151,14 +151,16 @@ func (c *tlsCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.D
 			errChannel <- timeoutError{}
 			errChannel <- timeoutError{}
 		})
 		})
 	}
 	}
+	// use local cfg to avoid clobbering ServerName if using multiple endpoints
+	cfg := *c.config
 	if c.config.ServerName == "" {
 	if c.config.ServerName == "" {
 		colonPos := strings.LastIndex(addr, ":")
 		colonPos := strings.LastIndex(addr, ":")
 		if colonPos == -1 {
 		if colonPos == -1 {
 			colonPos = len(addr)
 			colonPos = len(addr)
 		}
 		}
-		c.config.ServerName = addr[:colonPos]
+		cfg.ServerName = addr[:colonPos]
 	}
 	}
-	conn := tls.Client(rawConn, &c.config)
+	conn := tls.Client(rawConn, &cfg)
 	if timeout == 0 {
 	if timeout == 0 {
 		err = conn.Handshake()
 		err = conn.Handshake()
 	} else {
 	} else {
@@ -177,7 +179,7 @@ func (c *tlsCreds) ClientHandshake(addr string, rawConn net.Conn, timeout time.D
 }
 }
 
 
 func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) {
 func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) {
-	conn := tls.Server(rawConn, &c.config)
+	conn := tls.Server(rawConn, c.config)
 	if err := conn.Handshake(); err != nil {
 	if err := conn.Handshake(); err != nil {
 		rawConn.Close()
 		rawConn.Close()
 		return nil, nil, err
 		return nil, nil, err
@@ -187,7 +189,7 @@ func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error)
 
 
 // NewTLS uses c to construct a TransportCredentials based on TLS.
 // NewTLS uses c to construct a TransportCredentials based on TLS.
 func NewTLS(c *tls.Config) TransportCredentials {
 func NewTLS(c *tls.Config) TransportCredentials {
-	tc := &tlsCreds{*c}
+	tc := &tlsCreds{c}
 	tc.config.NextProtos = alpnProtoStr
 	tc.config.NextProtos = alpnProtoStr
 	return tc
 	return tc
 }
 }

+ 41 - 7
cmd/vendor/google.golang.org/grpc/rpc_util.go

@@ -141,6 +141,8 @@ type callInfo struct {
 	traceInfo traceInfo // in trace.go
 	traceInfo traceInfo // in trace.go
 }
 }
 
 
+var defaultCallInfo = callInfo{failFast: true}
+
 // CallOption configures a Call before it starts or extracts information from
 // CallOption configures a Call before it starts or extracts information from
 // a Call after it completes.
 // a Call after it completes.
 type CallOption interface {
 type CallOption interface {
@@ -179,6 +181,19 @@ func Trailer(md *metadata.MD) CallOption {
 	})
 	})
 }
 }
 
 
+// FailFast configures the action to take when an RPC is attempted on broken
+// connections or unreachable servers. If failfast is true, the RPC will fail
+// immediately. Otherwise, the RPC client will block the call until a
+// connection is available (or the call is canceled or times out) and will retry
+// the call if it fails due to a transient error. Please refer to
+// https://github.com/grpc/grpc/blob/master/doc/fail_fast.md
+func FailFast(failFast bool) CallOption {
+	return beforeCall(func(c *callInfo) error {
+		c.failFast = failFast
+		return nil
+	})
+}
+
 // The format of the payload: compressed or not?
 // The format of the payload: compressed or not?
 type payloadFormat uint8
 type payloadFormat uint8
 
 
@@ -319,7 +334,7 @@ type rpcError struct {
 	desc string
 	desc string
 }
 }
 
 
-func (e rpcError) Error() string {
+func (e *rpcError) Error() string {
 	return fmt.Sprintf("rpc error: code = %d desc = %s", e.code, e.desc)
 	return fmt.Sprintf("rpc error: code = %d desc = %s", e.code, e.desc)
 }
 }
 
 
@@ -329,7 +344,7 @@ func Code(err error) codes.Code {
 	if err == nil {
 	if err == nil {
 		return codes.OK
 		return codes.OK
 	}
 	}
-	if e, ok := err.(rpcError); ok {
+	if e, ok := err.(*rpcError); ok {
 		return e.code
 		return e.code
 	}
 	}
 	return codes.Unknown
 	return codes.Unknown
@@ -341,7 +356,7 @@ func ErrorDesc(err error) string {
 	if err == nil {
 	if err == nil {
 		return ""
 		return ""
 	}
 	}
-	if e, ok := err.(rpcError); ok {
+	if e, ok := err.(*rpcError); ok {
 		return e.desc
 		return e.desc
 	}
 	}
 	return err.Error()
 	return err.Error()
@@ -353,7 +368,7 @@ func Errorf(c codes.Code, format string, a ...interface{}) error {
 	if c == codes.OK {
 	if c == codes.OK {
 		return nil
 		return nil
 	}
 	}
-	return rpcError{
+	return &rpcError{
 		code: c,
 		code: c,
 		desc: fmt.Sprintf(format, a...),
 		desc: fmt.Sprintf(format, a...),
 	}
 	}
@@ -362,18 +377,37 @@ func Errorf(c codes.Code, format string, a ...interface{}) error {
 // toRPCErr converts an error into a rpcError.
 // toRPCErr converts an error into a rpcError.
 func toRPCErr(err error) error {
 func toRPCErr(err error) error {
 	switch e := err.(type) {
 	switch e := err.(type) {
-	case rpcError:
+	case *rpcError:
 		return err
 		return err
 	case transport.StreamError:
 	case transport.StreamError:
-		return rpcError{
+		return &rpcError{
 			code: e.Code,
 			code: e.Code,
 			desc: e.Desc,
 			desc: e.Desc,
 		}
 		}
 	case transport.ConnectionError:
 	case transport.ConnectionError:
-		return rpcError{
+		return &rpcError{
 			code: codes.Internal,
 			code: codes.Internal,
 			desc: e.Desc,
 			desc: e.Desc,
 		}
 		}
+	default:
+		switch err {
+		case context.DeadlineExceeded:
+			return &rpcError{
+				code: codes.DeadlineExceeded,
+				desc: err.Error(),
+			}
+		case context.Canceled:
+			return &rpcError{
+				code: codes.Canceled,
+				desc: err.Error(),
+			}
+		case ErrClientConnClosing:
+			return &rpcError{
+				code: codes.FailedPrecondition,
+				desc: err.Error(),
+			}
+		}
+
 	}
 	}
 	return Errorf(codes.Unknown, "%v", err)
 	return Errorf(codes.Unknown, "%v", err)
 }
 }

+ 54 - 4
cmd/vendor/google.golang.org/grpc/server.go

@@ -82,6 +82,7 @@ type service struct {
 	server interface{} // the server for service methods
 	server interface{} // the server for service methods
 	md     map[string]*MethodDesc
 	md     map[string]*MethodDesc
 	sd     map[string]*StreamDesc
 	sd     map[string]*StreamDesc
+	mdata  interface{}
 }
 }
 
 
 // Server is a gRPC server to serve RPC requests.
 // Server is a gRPC server to serve RPC requests.
@@ -231,6 +232,7 @@ func (s *Server) register(sd *ServiceDesc, ss interface{}) {
 		server: ss,
 		server: ss,
 		md:     make(map[string]*MethodDesc),
 		md:     make(map[string]*MethodDesc),
 		sd:     make(map[string]*StreamDesc),
 		sd:     make(map[string]*StreamDesc),
+		mdata:  sd.Metadata,
 	}
 	}
 	for i := range sd.Methods {
 	for i := range sd.Methods {
 		d := &sd.Methods[i]
 		d := &sd.Methods[i]
@@ -243,6 +245,52 @@ func (s *Server) register(sd *ServiceDesc, ss interface{}) {
 	s.m[sd.ServiceName] = srv
 	s.m[sd.ServiceName] = srv
 }
 }
 
 
+// MethodInfo contains the information of an RPC including its method name and type.
+type MethodInfo struct {
+	// Name is the method name only, without the service name or package name.
+	Name string
+	// IsClientStream indicates whether the RPC is a client streaming RPC.
+	IsClientStream bool
+	// IsServerStream indicates whether the RPC is a server streaming RPC.
+	IsServerStream bool
+}
+
+// ServiceInfo contains unary RPC method info, streaming RPC methid info and metadata for a service.
+type ServiceInfo struct {
+	Methods []MethodInfo
+	// Metadata is the metadata specified in ServiceDesc when registering service.
+	Metadata interface{}
+}
+
+// GetServiceInfo returns a map from service names to ServiceInfo.
+// Service names include the package names, in the form of <package>.<service>.
+func (s *Server) GetServiceInfo() map[string]*ServiceInfo {
+	ret := make(map[string]*ServiceInfo)
+	for n, srv := range s.m {
+		methods := make([]MethodInfo, 0, len(srv.md)+len(srv.sd))
+		for m := range srv.md {
+			methods = append(methods, MethodInfo{
+				Name:           m,
+				IsClientStream: false,
+				IsServerStream: false,
+			})
+		}
+		for m, d := range srv.sd {
+			methods = append(methods, MethodInfo{
+				Name:           m,
+				IsClientStream: d.ClientStreams,
+				IsServerStream: d.ServerStreams,
+			})
+		}
+
+		ret[n] = &ServiceInfo{
+			Methods:  methods,
+			Metadata: srv.mdata,
+		}
+	}
+	return ret
+}
+
 var (
 var (
 	// ErrServerStopped indicates that the operation is now illegal because of
 	// ErrServerStopped indicates that the operation is now illegal because of
 	// the server being stopped.
 	// the server being stopped.
@@ -272,9 +320,11 @@ func (s *Server) Serve(lis net.Listener) error {
 	s.lis[lis] = true
 	s.lis[lis] = true
 	s.mu.Unlock()
 	s.mu.Unlock()
 	defer func() {
 	defer func() {
-		lis.Close()
 		s.mu.Lock()
 		s.mu.Lock()
-		delete(s.lis, lis)
+		if s.lis != nil && s.lis[lis] {
+			lis.Close()
+			delete(s.lis, lis)
+		}
 		s.mu.Unlock()
 		s.mu.Unlock()
 	}()
 	}()
 	for {
 	for {
@@ -529,7 +579,7 @@ func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.
 		}
 		}
 		reply, appErr := md.Handler(srv.server, stream.Context(), df, s.opts.unaryInt)
 		reply, appErr := md.Handler(srv.server, stream.Context(), df, s.opts.unaryInt)
 		if appErr != nil {
 		if appErr != nil {
-			if err, ok := appErr.(rpcError); ok {
+			if err, ok := appErr.(*rpcError); ok {
 				statusCode = err.code
 				statusCode = err.code
 				statusDesc = err.desc
 				statusDesc = err.desc
 			} else {
 			} else {
@@ -614,7 +664,7 @@ func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transp
 		appErr = s.opts.streamInt(srv.server, ss, info, sd.Handler)
 		appErr = s.opts.streamInt(srv.server, ss, info, sd.Handler)
 	}
 	}
 	if appErr != nil {
 	if appErr != nil {
-		if err, ok := appErr.(rpcError); ok {
+		if err, ok := appErr.(*rpcError); ok {
 			ss.statusCode = err.code
 			ss.statusCode = err.code
 			ss.statusDesc = err.desc
 			ss.statusDesc = err.desc
 		} else if err, ok := appErr.(transport.StreamError); ok {
 		} else if err, ok := appErr.(transport.StreamError); ok {

+ 53 - 15
cmd/vendor/google.golang.org/grpc/stream.go

@@ -102,16 +102,15 @@ type ClientStream interface {
 func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error) {
 func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error) {
 	var (
 	var (
 		t   transport.ClientTransport
 		t   transport.ClientTransport
+		s   *transport.Stream
 		err error
 		err error
 		put func()
 		put func()
 	)
 	)
-	// TODO(zhaoq): CallOption is omitted. Add support when it is needed.
-	gopts := BalancerGetOptions{
-		BlockingWait: false,
-	}
-	t, put, err = cc.getTransport(ctx, gopts)
-	if err != nil {
-		return nil, toRPCErr(err)
+	c := defaultCallInfo
+	for _, o := range opts {
+		if err := o.before(&c); err != nil {
+			return nil, toRPCErr(err)
+		}
 	}
 	}
 	callHdr := &transport.CallHdr{
 	callHdr := &transport.CallHdr{
 		Host:   cc.authority,
 		Host:   cc.authority,
@@ -122,8 +121,9 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
 		callHdr.SendCompress = cc.dopts.cp.Type()
 		callHdr.SendCompress = cc.dopts.cp.Type()
 	}
 	}
 	cs := &clientStream{
 	cs := &clientStream{
+		opts:    opts,
+		c:       c,
 		desc:    desc,
 		desc:    desc,
-		put:     put,
 		codec:   cc.dopts.codec,
 		codec:   cc.dopts.codec,
 		cp:      cc.dopts.cp,
 		cp:      cc.dopts.cp,
 		dc:      cc.dopts.dc,
 		dc:      cc.dopts.dc,
@@ -142,11 +142,44 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
 		cs.trInfo.tr.LazyLog(&cs.trInfo.firstLine, false)
 		cs.trInfo.tr.LazyLog(&cs.trInfo.firstLine, false)
 		ctx = trace.NewContext(ctx, cs.trInfo.tr)
 		ctx = trace.NewContext(ctx, cs.trInfo.tr)
 	}
 	}
-	s, err := t.NewStream(ctx, callHdr)
-	if err != nil {
-		cs.finish(err)
-		return nil, toRPCErr(err)
+	gopts := BalancerGetOptions{
+		BlockingWait: !c.failFast,
 	}
 	}
+	for {
+		t, put, err = cc.getTransport(ctx, gopts)
+		if err != nil {
+			// TODO(zhaoq): Probably revisit the error handling.
+			if _, ok := err.(*rpcError); ok {
+				return nil, err
+			}
+			if err == errConnClosing {
+				if c.failFast {
+					return nil, Errorf(codes.Unavailable, "%v", errConnClosing)
+				}
+				continue
+			}
+			// All the other errors are treated as Internal errors.
+			return nil, Errorf(codes.Internal, "%v", err)
+		}
+
+		s, err = t.NewStream(ctx, callHdr)
+		if err != nil {
+			if put != nil {
+				put()
+				put = nil
+			}
+			if _, ok := err.(transport.ConnectionError); ok {
+				if c.failFast {
+					cs.finish(err)
+					return nil, toRPCErr(err)
+				}
+				continue
+			}
+			return nil, toRPCErr(err)
+		}
+		break
+	}
+	cs.put = put
 	cs.t = t
 	cs.t = t
 	cs.s = s
 	cs.s = s
 	cs.p = &parser{r: s}
 	cs.p = &parser{r: s}
@@ -167,6 +200,8 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth
 
 
 // clientStream implements a client side Stream.
 // clientStream implements a client side Stream.
 type clientStream struct {
 type clientStream struct {
+	opts  []CallOption
+	c     callInfo
 	t     transport.ClientTransport
 	t     transport.ClientTransport
 	s     *transport.Stream
 	s     *transport.Stream
 	p     *parser
 	p     *parser
@@ -312,15 +347,18 @@ func (cs *clientStream) closeTransportStream(err error) {
 }
 }
 
 
 func (cs *clientStream) finish(err error) {
 func (cs *clientStream) finish(err error) {
-	if !cs.tracing {
-		return
-	}
 	cs.mu.Lock()
 	cs.mu.Lock()
 	defer cs.mu.Unlock()
 	defer cs.mu.Unlock()
+	for _, o := range cs.opts {
+		o.after(&cs.c)
+	}
 	if cs.put != nil {
 	if cs.put != nil {
 		cs.put()
 		cs.put()
 		cs.put = nil
 		cs.put = nil
 	}
 	}
+	if !cs.tracing {
+		return
+	}
 	if cs.trInfo.tr != nil {
 	if cs.trInfo.tr != nil {
 		if err == nil || err == io.EOF {
 		if err == nil || err == io.EOF {
 			cs.trInfo.tr.LazyPrintf("RPC: [OK]")
 			cs.trInfo.tr.LazyPrintf("RPC: [OK]")

+ 1 - 1
cmd/vendor/google.golang.org/grpc/transport/handler_server.go

@@ -312,7 +312,7 @@ func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream)) {
 		Addr: ht.RemoteAddr(),
 		Addr: ht.RemoteAddr(),
 	}
 	}
 	if req.TLS != nil {
 	if req.TLS != nil {
-		pr.AuthInfo = credentials.TLSInfo{*req.TLS}
+		pr.AuthInfo = credentials.TLSInfo{State: *req.TLS}
 	}
 	}
 	ctx = metadata.NewContext(ctx, ht.headerMD)
 	ctx = metadata.NewContext(ctx, ht.headerMD)
 	ctx = peer.NewContext(ctx, pr)
 	ctx = peer.NewContext(ctx, pr)

+ 4 - 1
cmd/vendor/google.golang.org/grpc/transport/http2_client.go

@@ -175,7 +175,10 @@ func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err e
 		return nil, ConnectionErrorf("transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface))
 		return nil, ConnectionErrorf("transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface))
 	}
 	}
 	if initialWindowSize != defaultWindowSize {
 	if initialWindowSize != defaultWindowSize {
-		err = t.framer.writeSettings(true, http2.Setting{http2.SettingInitialWindowSize, uint32(initialWindowSize)})
+		err = t.framer.writeSettings(true, http2.Setting{
+			ID:  http2.SettingInitialWindowSize,
+			Val: uint32(initialWindowSize),
+		})
 	} else {
 	} else {
 		err = t.framer.writeSettings(true)
 		err = t.framer.writeSettings(true)
 	}
 	}

+ 7 - 2
cmd/vendor/google.golang.org/grpc/transport/http2_server.go

@@ -100,10 +100,15 @@ func newHTTP2Server(conn net.Conn, maxStreams uint32, authInfo credentials.AuthI
 	if maxStreams == 0 {
 	if maxStreams == 0 {
 		maxStreams = math.MaxUint32
 		maxStreams = math.MaxUint32
 	} else {
 	} else {
-		settings = append(settings, http2.Setting{http2.SettingMaxConcurrentStreams, maxStreams})
+		settings = append(settings, http2.Setting{
+			ID:  http2.SettingMaxConcurrentStreams,
+			Val: maxStreams,
+		})
 	}
 	}
 	if initialWindowSize != defaultWindowSize {
 	if initialWindowSize != defaultWindowSize {
-		settings = append(settings, http2.Setting{http2.SettingInitialWindowSize, uint32(initialWindowSize)})
+		settings = append(settings, http2.Setting{
+			ID:  http2.SettingInitialWindowSize,
+			Val: uint32(initialWindowSize)})
 	}
 	}
 	if err := framer.writeSettings(true, settings...); err != nil {
 	if err := framer.writeSettings(true, settings...); err != nil {
 		return nil, ConnectionErrorf("transport: %v", err)
 		return nil, ConnectionErrorf("transport: %v", err)

+ 4 - 4
etcdserver/api/v3rpc/rpctypes/error_test.go

@@ -26,15 +26,15 @@ func TestConvert(t *testing.T) {
 	e2 := ErrGRPCEmptyKey
 	e2 := ErrGRPCEmptyKey
 	e3 := ErrEmptyKey
 	e3 := ErrEmptyKey
 
 
-	if e1 != e2 {
-		t.Fatalf("expected 'true', got %T != %T", e1, e2)
+	if e1.Error() != e2.Error() {
+		t.Fatalf("expected %q == %q", e1.Error(), e2.Error())
 	}
 	}
 	if grpc.Code(e1) != e3.(EtcdError).Code() {
 	if grpc.Code(e1) != e3.(EtcdError).Code() {
 		t.Fatalf("expected them to be equal, got %v / %v", 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 e1.Error() == e3.Error() {
+		t.Fatalf("expected %q != %q", e1.Error(), e3.Error())
 	}
 	}
 	if grpc.Code(e2) != e3.(EtcdError).Code() {
 	if grpc.Code(e2) != e3.(EtcdError).Code() {
 		t.Fatalf("expected them to be equal, got %v / %v", grpc.Code(e2), e3.(EtcdError).Code())
 		t.Fatalf("expected them to be equal, got %v / %v", grpc.Code(e2), e3.(EtcdError).Code())

+ 16 - 12
integration/v3_grpc_test.go

@@ -191,7 +191,7 @@ func TestV3TxnTooManyOps(t *testing.T) {
 		}
 		}
 
 
 		_, err := kvc.Txn(context.Background(), txn)
 		_, err := kvc.Txn(context.Background(), txn)
-		if err != rpctypes.ErrGRPCTooManyOps {
+		if !eqErrGRPC(err, rpctypes.ErrGRPCTooManyOps) {
 			t.Errorf("#%d: err = %v, want %v", i, err, rpctypes.ErrGRPCTooManyOps)
 			t.Errorf("#%d: err = %v, want %v", i, err, rpctypes.ErrGRPCTooManyOps)
 		}
 		}
 	}
 	}
@@ -257,7 +257,7 @@ func TestV3TxnDuplicateKeys(t *testing.T) {
 	for i, tt := range tests {
 	for i, tt := range tests {
 		txn := &pb.TxnRequest{Success: tt.txnSuccess}
 		txn := &pb.TxnRequest{Success: tt.txnSuccess}
 		_, err := kvc.Txn(context.Background(), txn)
 		_, err := kvc.Txn(context.Background(), txn)
-		if err != tt.werr {
+		if !eqErrGRPC(err, tt.werr) {
 			t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
 			t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
 		}
 		}
 	}
 	}
@@ -481,8 +481,8 @@ func TestV3DeleteRange(t *testing.T) {
 	}
 	}
 }
 }
 
 
-// TestV3TxnInvaildRange tests txn
-func TestV3TxnInvaildRange(t *testing.T) {
+// TestV3TxnInvalidRange tests that invalid ranges are rejected in txns.
+func TestV3TxnInvalidRange(t *testing.T) {
 	defer testutil.AfterTest(t)
 	defer testutil.AfterTest(t)
 	clus := NewClusterV3(t, &ClusterConfig{Size: 3})
 	clus := NewClusterV3(t, &ClusterConfig{Size: 3})
 	defer clus.Terminate(t)
 	defer clus.Terminate(t)
@@ -513,14 +513,14 @@ func TestV3TxnInvaildRange(t *testing.T) {
 		Request: &pb.RequestOp_RequestRange{
 		Request: &pb.RequestOp_RequestRange{
 			RequestRange: rreq}})
 			RequestRange: rreq}})
 
 
-	if _, err := kvc.Txn(context.TODO(), txn); err != rpctypes.ErrGRPCFutureRev {
+	if _, err := kvc.Txn(context.TODO(), txn); !eqErrGRPC(err, rpctypes.ErrGRPCFutureRev) {
 		t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCFutureRev)
 		t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCFutureRev)
 	}
 	}
 
 
 	// compacted rev
 	// compacted rev
 	tv, _ := txn.Success[1].Request.(*pb.RequestOp_RequestRange)
 	tv, _ := txn.Success[1].Request.(*pb.RequestOp_RequestRange)
 	tv.RequestRange.Revision = 1
 	tv.RequestRange.Revision = 1
-	if _, err := kvc.Txn(context.TODO(), txn); err != rpctypes.ErrGRPCCompacted {
+	if _, err := kvc.Txn(context.TODO(), txn); !eqErrGRPC(err, rpctypes.ErrGRPCCompacted) {
 		t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCCompacted)
 		t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCCompacted)
 	}
 	}
 }
 }
@@ -538,7 +538,7 @@ func TestV3TooLargeRequest(t *testing.T) {
 	preq := &pb.PutRequest{Key: []byte("foo"), Value: largeV}
 	preq := &pb.PutRequest{Key: []byte("foo"), Value: largeV}
 
 
 	_, err := kvc.Put(context.Background(), preq)
 	_, err := kvc.Put(context.Background(), preq)
-	if err != rpctypes.ErrGRPCRequestTooLarge {
+	if !eqErrGRPC(err, rpctypes.ErrGRPCRequestTooLarge) {
 		t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCRequestTooLarge)
 		t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCRequestTooLarge)
 	}
 	}
 }
 }
@@ -585,14 +585,14 @@ func TestV3StorageQuotaAPI(t *testing.T) {
 
 
 	// test small put that fits in quota
 	// test small put that fits in quota
 	smallbuf := make([]byte, 512)
 	smallbuf := make([]byte, 512)
-	if _, err := kvc.Put(context.TODO(), &pb.PutRequest{Key: key, Value: smallbuf}); err != nil {
+	if _, err := kvc.Put(context.TODO(), &pb.PutRequest{Key: key, Value: smallbuf}, grpc.FailFast(false)); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
 
 
 	// test big put
 	// test big put
 	bigbuf := make([]byte, 64*1024)
 	bigbuf := make([]byte, 64*1024)
 	_, err := kvc.Put(context.TODO(), &pb.PutRequest{Key: key, Value: bigbuf})
 	_, err := kvc.Put(context.TODO(), &pb.PutRequest{Key: key, Value: bigbuf})
-	if err == nil || err != rpctypes.ErrGRPCNoSpace {
+	if !eqErrGRPC(err, rpctypes.ErrGRPCNoSpace) {
 		t.Fatalf("big put got %v, expected %v", err, rpctypes.ErrGRPCNoSpace)
 		t.Fatalf("big put got %v, expected %v", err, rpctypes.ErrGRPCNoSpace)
 	}
 	}
 
 
@@ -608,7 +608,7 @@ func TestV3StorageQuotaAPI(t *testing.T) {
 	txnreq := &pb.TxnRequest{}
 	txnreq := &pb.TxnRequest{}
 	txnreq.Success = append(txnreq.Success, puttxn)
 	txnreq.Success = append(txnreq.Success, puttxn)
 	_, txnerr := kvc.Txn(context.TODO(), txnreq)
 	_, txnerr := kvc.Txn(context.TODO(), txnreq)
-	if txnerr == nil || err != rpctypes.ErrGRPCNoSpace {
+	if !eqErrGRPC(txnerr, rpctypes.ErrGRPCNoSpace) {
 		t.Fatalf("big txn got %v, expected %v", err, rpctypes.ErrGRPCNoSpace)
 		t.Fatalf("big txn got %v, expected %v", err, rpctypes.ErrGRPCNoSpace)
 	}
 	}
 }
 }
@@ -632,7 +632,7 @@ func TestV3StorageQuotaApply(t *testing.T) {
 
 
 	// test small put still works
 	// test small put still works
 	smallbuf := make([]byte, 1024)
 	smallbuf := make([]byte, 1024)
-	_, serr := kvc0.Put(context.TODO(), &pb.PutRequest{Key: key, Value: smallbuf})
+	_, serr := kvc0.Put(context.TODO(), &pb.PutRequest{Key: key, Value: smallbuf}, grpc.FailFast(false))
 	if serr != nil {
 	if serr != nil {
 		t.Fatal(serr)
 		t.Fatal(serr)
 	}
 	}
@@ -707,7 +707,7 @@ func TestV3AlarmDeactivate(t *testing.T) {
 	key := []byte("abc")
 	key := []byte("abc")
 	smallbuf := make([]byte, 512)
 	smallbuf := make([]byte, 512)
 	_, err := kvc.Put(context.TODO(), &pb.PutRequest{Key: key, Value: smallbuf})
 	_, err := kvc.Put(context.TODO(), &pb.PutRequest{Key: key, Value: smallbuf})
-	if err == nil && err != rpctypes.ErrGRPCNoSpace {
+	if err == nil && !eqErrGRPC(err, rpctypes.ErrGRPCNoSpace) {
 		t.Fatalf("put got %v, expected %v", err, rpctypes.ErrGRPCNoSpace)
 		t.Fatalf("put got %v, expected %v", err, rpctypes.ErrGRPCNoSpace)
 	}
 	}
 
 
@@ -1061,3 +1061,7 @@ func TestGRPCStreamRequireLeader(t *testing.T) {
 		t.Errorf("err = %v, want nil", err)
 		t.Errorf("err = %v, want nil", err)
 	}
 	}
 }
 }
+
+func eqErrGRPC(err1 error, err2 error) bool {
+	return !(err1 == nil && err2 != nil) || err1.Error() == err2.Error()
+}

+ 3 - 3
integration/v3_lease_test.go

@@ -106,7 +106,7 @@ func TestV3LeaseGrantByID(t *testing.T) {
 	lresp, err = toGRPC(clus.RandClient()).Lease.LeaseGrant(
 	lresp, err = toGRPC(clus.RandClient()).Lease.LeaseGrant(
 		context.TODO(),
 		context.TODO(),
 		&pb.LeaseGrantRequest{ID: 1, TTL: 1})
 		&pb.LeaseGrantRequest{ID: 1, TTL: 1})
-	if err != rpctypes.ErrGRPCLeaseExist {
+	if !eqErrGRPC(err, rpctypes.ErrGRPCLeaseExist) {
 		t.Error(err)
 		t.Error(err)
 	}
 	}
 
 
@@ -242,7 +242,7 @@ func TestV3PutOnNonExistLease(t *testing.T) {
 	badLeaseID := int64(0x12345678)
 	badLeaseID := int64(0x12345678)
 	putr := &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: badLeaseID}
 	putr := &pb.PutRequest{Key: []byte("foo"), Value: []byte("bar"), Lease: badLeaseID}
 	_, err := toGRPC(clus.RandClient()).KV.Put(ctx, putr)
 	_, err := toGRPC(clus.RandClient()).KV.Put(ctx, putr)
-	if err != rpctypes.ErrGRPCLeaseNotFound {
+	if !eqErrGRPC(err, rpctypes.ErrGRPCLeaseNotFound) {
 		t.Errorf("err = %v, want %v", err, rpctypes.ErrGRPCCompacted)
 		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
 		return false
 	}
 	}
 
 
-	if err == rpctypes.ErrGRPCLeaseExist {
+	if eqErrGRPC(err, rpctypes.ErrGRPCLeaseExist) {
 		return true
 		return true
 	}
 	}
 	t.Fatalf("unexpecter error %v", err)
 	t.Fatalf("unexpecter error %v", err)