From 02f4a9a034f65f588599eaf6d756b98b55640c98 Mon Sep 17 00:00:00 2001 From: "shaun.thium" Date: Tue, 13 Sep 2016 11:42:51 -0700 Subject: [PATCH] client: add GetVersion method For retrieving etcdserver and etcdcluster version --- client/client.go | 33 +++++++++++++++++++++++++++++++++ client/client_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/client/client.go b/client/client.go index f9131b472..498dfbcc8 100644 --- a/client/client.go +++ b/client/client.go @@ -15,6 +15,7 @@ package client import ( + "encoding/json" "errors" "fmt" "io/ioutil" @@ -27,6 +28,8 @@ import ( "sync" "time" + "github.com/coreos/etcd/version" + "golang.org/x/net/context" ) @@ -201,6 +204,9 @@ type Client interface { // returned SetEndpoints(eps []string) error + // GetVersion retrieves the current etcd server and cluster version + GetVersion(ctx context.Context) (*version.Versions, error) + httpClient } @@ -477,6 +483,33 @@ func (c *httpClusterClient) AutoSync(ctx context.Context, interval time.Duration } } +func (c *httpClusterClient) GetVersion(ctx context.Context) (*version.Versions, error) { + act := &getAction{Prefix: "/version"} + + resp, body, err := c.Do(ctx, act) + if err != nil { + return nil, err + } + + switch resp.StatusCode { + case http.StatusOK: + if len(body) == 0 { + return nil, ErrEmptyBody + } + var vresp version.Versions + if err := json.Unmarshal(body, &vresp); err != nil { + return nil, ErrInvalidJSON + } + return &vresp, nil + default: + var etcdErr Error + if err := json.Unmarshal(body, &etcdErr); err != nil { + return nil, ErrInvalidJSON + } + return nil, etcdErr + } +} + type roundTripResponse struct { resp *http.Response err error diff --git a/client/client_test.go b/client/client_test.go index 598e01c4a..4ab54d883 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -28,6 +28,7 @@ import ( "time" "github.com/coreos/etcd/pkg/testutil" + "github.com/coreos/etcd/version" "golang.org/x/net/context" ) @@ -860,6 +861,34 @@ func TestHTTPClusterClientAutoSyncFail(t *testing.T) { } } +func TestHTTPClusterClientGetVersion(t *testing.T) { + body := []byte(`{"etcdserver":"2.3.2","etcdcluster":"2.3.0"}`) + cf := newStaticHTTPClientFactory([]staticHTTPResponse{ + { + resp: http.Response{StatusCode: http.StatusOK, Header: http.Header{"Content-Length": []string{"44"}}}, + body: body, + }, + }) + + hc := &httpClusterClient{ + clientFactory: cf, + rand: rand.New(rand.NewSource(0)), + } + err := hc.SetEndpoints([]string{"http://127.0.0.1:4003", "http://127.0.0.1:2379", "http://127.0.0.1:4001", "http://127.0.0.1:4002"}) + if err != nil { + t.Fatalf("unexpected error during setup: %#v", err) + } + + actual, err := hc.GetVersion(context.Background()) + if err != nil { + t.Errorf("non-nil error: %#v", err) + } + expected := version.Versions{Server: "2.3.2", Cluster: "2.3.0"} + if !reflect.DeepEqual(&expected, actual) { + t.Errorf("incorrect Response: want=%#v got=%#v", expected, actual) + } +} + // TestHTTPClusterClientSyncPinEndpoint tests that Sync() pins the endpoint when // it gets the exactly same member list as before. func TestHTTPClusterClientSyncPinEndpoint(t *testing.T) {