From 8f11d5f037ab7efe36b6fd743b9a0a400126cb7c Mon Sep 17 00:00:00 2001 From: Gyu-Ho Lee Date: Fri, 16 Jun 2017 14:24:51 -0700 Subject: [PATCH] clientv3: add 'CheckHealth' method Signed-off-by: Gyu-Ho Lee --- clientv3/client.go | 12 ++++++++++++ clientv3/integration/kv_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/clientv3/client.go b/clientv3/client.go index a0e059d5e35c..e040d0fe3bdc 100644 --- a/clientv3/client.go +++ b/clientv3/client.go @@ -31,6 +31,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" + healthpb "google.golang.org/grpc/health/grpc_health_v1" "google.golang.org/grpc/metadata" ) @@ -47,6 +48,7 @@ type Client struct { Watcher Auth Maintenance + healthpb.HealthClient conn *grpc.ClientConn dialerrc chan error @@ -408,6 +410,7 @@ func newClient(cfg *Config) (*Client, error) { client.Watcher = NewWatcher(client) client.Auth = NewAuth(client) client.Maintenance = NewMaintenance(client) + client.HealthClient = healthpb.NewHealthClient(client.conn) if cfg.RejectOldCluster { if err := client.checkVersion(); err != nil { @@ -463,6 +466,15 @@ func (c *Client) checkVersion() (err error) { // ActiveConnection returns the current in-use connection func (c *Client) ActiveConnection() *grpc.ClientConn { return c.conn } +// CheckHealth checks the health status of gRPC server of current connection. +func (c *Client) CheckHealth(ctx context.Context) (healthpb.HealthCheckResponse_ServingStatus, error) { + resp, err := c.HealthClient.Check(ctx, &healthpb.HealthCheckRequest{}) + if err != nil { + return healthpb.HealthCheckResponse_UNKNOWN, err + } + return resp.Status, err +} + // isHaltErr returns true if the given error and context indicate no forward // progress can be made, even after reconnecting. func isHaltErr(ctx context.Context, err error) bool { diff --git a/clientv3/integration/kv_test.go b/clientv3/integration/kv_test.go index 49f107f76df0..cf46d2bd45e7 100644 --- a/clientv3/integration/kv_test.go +++ b/clientv3/integration/kv_test.go @@ -30,8 +30,35 @@ import ( "github.com/coreos/etcd/pkg/testutil" "golang.org/x/net/context" "google.golang.org/grpc" + healthpb "google.golang.org/grpc/health/grpc_health_v1" ) +func TestHealth(t *testing.T) { + defer testutil.AfterTest(t) + + clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) + defer clus.Terminate(t) + + cli := clus.RandClient() + st, err := cli.CheckHealth(context.TODO()) + if err != nil { + t.Fatal(err) + } + if st != healthpb.HealthCheckResponse_SERVING { + t.Fatalf("status expected %s, got %s", healthpb.HealthCheckResponse_SERVING, st) + } + + clus.TerminateMember(t, 0) + + st, err = cli.CheckHealth(context.TODO()) + if st != healthpb.HealthCheckResponse_UNKNOWN { + t.Fatalf("status expected %s, got %s", healthpb.HealthCheckResponse_UNKNOWN, st) + } + if grpc.ErrorDesc(err) != "there is no address available" { + t.Fatalf("error expected 'there is no address available', got %v", err) + } +} + func TestKVPutError(t *testing.T) { defer testutil.AfterTest(t)