Browse Source

StatusFromError: handle return value of the function

status.FromError can return nil, false. We are handling the return values
most places in code but some places we aren't. Fixing it herewith.

Fixes #9117
Sahdev P. Zala 8 years ago
parent
commit
3b7e2ce0ca

+ 12 - 11
clientv3/client.go

@@ -537,18 +537,19 @@ func toErr(ctx context.Context, err error) error {
 	if _, ok := err.(rpctypes.EtcdError); ok {
 	if _, ok := err.(rpctypes.EtcdError); ok {
 		return err
 		return err
 	}
 	}
-	ev, _ := status.FromError(err)
-	code := ev.Code()
-	switch code {
-	case codes.DeadlineExceeded:
-		fallthrough
-	case codes.Canceled:
-		if ctx.Err() != nil {
-			err = ctx.Err()
+	if ev, ok := status.FromError(err); ok {
+		code := ev.Code()
+		switch code {
+		case codes.DeadlineExceeded:
+			fallthrough
+		case codes.Canceled:
+			if ctx.Err() != nil {
+				err = ctx.Err()
+			}
+		case codes.Unavailable:
+		case codes.FailedPrecondition:
+			err = grpc.ErrClientConnClosing
 		}
 		}
-	case codes.Unavailable:
-	case codes.FailedPrecondition:
-		err = grpc.ErrClientConnClosing
 	}
 	}
 	return err
 	return err
 }
 }

+ 4 - 1
clientv3/integration/server_shutdown_test.go

@@ -361,7 +361,10 @@ func isServerCtxTimeout(err error) bool {
 	if err == nil {
 	if err == nil {
 		return false
 		return false
 	}
 	}
-	ev, _ := status.FromError(err)
+	ev, ok := status.FromError(err)
+	if !ok {
+		return false
+	}
 	code := ev.Code()
 	code := ev.Code()
 	return code == codes.DeadlineExceeded && strings.Contains(err.Error(), "context deadline exceeded")
 	return code == codes.DeadlineExceeded && strings.Contains(err.Error(), "context deadline exceeded")
 }
 }

+ 1 - 1
clientv3/leasing/kv.go

@@ -285,7 +285,7 @@ func (lkv *leasingKV) acquire(ctx context.Context, key string, op v3.Op) (*v3.Tx
 		if _, ok := err.(rpctypes.EtcdError); ok {
 		if _, ok := err.(rpctypes.EtcdError); ok {
 			return nil, err
 			return nil, err
 		}
 		}
-		if ev, _ := status.FromError(err); ev.Code() != codes.Unavailable {
+		if ev, ok := status.FromError(err); ok && ev.Code() != codes.Unavailable {
 			return nil, err
 			return nil, err
 		}
 		}
 	}
 	}

+ 5 - 3
clientv3/retry.go

@@ -52,7 +52,10 @@ func isRepeatableStopError(err error) bool {
 		return true
 		return true
 	}
 	}
 	// only retry if unavailable
 	// only retry if unavailable
-	ev, _ := status.FromError(err)
+	ev, ok := status.FromError(err)
+	if !ok {
+		return false
+	}
 	return ev.Code() != codes.Unavailable
 	return ev.Code() != codes.Unavailable
 }
 }
 
 
@@ -68,8 +71,7 @@ func isRepeatableStopError(err error) bool {
 // Returning "true" means retry should stop, otherwise it violates
 // Returning "true" means retry should stop, otherwise it violates
 // write-at-most-once semantics.
 // write-at-most-once semantics.
 func isNonRepeatableStopError(err error) bool {
 func isNonRepeatableStopError(err error) bool {
-	ev, _ := status.FromError(err)
-	if ev.Code() != codes.Unavailable {
+	if ev, ok := status.FromError(err); ok && ev.Code() != codes.Unavailable {
 		return true
 		return true
 	}
 	}
 	desc := rpctypes.ErrorDesc(err)
 	desc := rpctypes.ErrorDesc(err)

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

@@ -29,16 +29,14 @@ func TestConvert(t *testing.T) {
 	if e1.Error() != e2.Error() {
 	if e1.Error() != e2.Error() {
 		t.Fatalf("expected %q == %q", e1.Error(), e2.Error())
 		t.Fatalf("expected %q == %q", e1.Error(), e2.Error())
 	}
 	}
-	ev1, _ := status.FromError(e1)
-	if ev1.Code() != e3.(EtcdError).Code() {
+	if ev1, ok := status.FromError(e1); ok && ev1.Code() != e3.(EtcdError).Code() {
 		t.Fatalf("expected them to be equal, got %v / %v", ev1.Code(), e3.(EtcdError).Code())
 		t.Fatalf("expected them to be equal, got %v / %v", ev1.Code(), e3.(EtcdError).Code())
 	}
 	}
 
 
 	if e1.Error() == e3.Error() {
 	if e1.Error() == e3.Error() {
 		t.Fatalf("expected %q != %q", e1.Error(), e3.Error())
 		t.Fatalf("expected %q != %q", e1.Error(), e3.Error())
 	}
 	}
-	ev2, _ := status.FromError(e2)
-	if ev2.Code() != e3.(EtcdError).Code() {
+	if ev2, ok := status.FromError(e2); ok && ev2.Code() != e3.(EtcdError).Code() {
 		t.Fatalf("expected them to be equal, got %v / %v", ev2.Code(), e3.(EtcdError).Code())
 		t.Fatalf("expected them to be equal, got %v / %v", ev2.Code(), e3.(EtcdError).Code())
 	}
 	}
 }
 }

+ 1 - 2
tools/functional-tester/etcd-runner/command/lease_renewer_command.go

@@ -68,8 +68,7 @@ func runLeaseRenewerFunc(cmd *cobra.Command, args []string) {
 
 
 		for {
 		for {
 			lk, err = c.Lease.KeepAliveOnce(ctx, l.ID)
 			lk, err = c.Lease.KeepAliveOnce(ctx, l.ID)
-			ev, _ := status.FromError(err)
-			if ev.Code() == codes.NotFound {
+			if ev, ok := status.FromError(err); ok && ev.Code() == codes.NotFound {
 				if time.Since(expire) < 0 {
 				if time.Since(expire) < 0 {
 					log.Fatalf("bad renew! exceeded: %v", time.Since(expire))
 					log.Fatalf("bad renew! exceeded: %v", time.Since(expire))
 					for {
 					for {