From 6e3769d39ec1b997576fbf88d5b91c159ebb034c Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Wed, 1 Jul 2015 13:38:03 -0700 Subject: [PATCH] client: add member update --- client/members.go | 51 +++++++++++++++++++++++++++++++++++++++--- client/members_test.go | 29 +++++++++++++++++++++++- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/client/members.go b/client/members.go index 2e3cc2866..b6f33ed76 100644 --- a/client/members.go +++ b/client/members.go @@ -67,11 +67,11 @@ func (c *memberCollection) UnmarshalJSON(data []byte) error { return nil } -type memberCreateRequest struct { +type memberCreateOrUpdateRequest struct { PeerURLs types.URLs } -func (m *memberCreateRequest) MarshalJSON() ([]byte, error) { +func (m *memberCreateOrUpdateRequest) MarshalJSON() ([]byte, error) { s := struct { PeerURLs []string `json:"peerURLs"` }{ @@ -102,6 +102,9 @@ type MembersAPI interface { // Remove demotes an existing Member out of the cluster. Remove(ctx context.Context, mID string) error + + // Update instructs etcd to update an existing Member in the cluster. + Update(ctx context.Context, mID string, peerURLs []string) error } type httpMembersAPI struct { @@ -159,6 +162,33 @@ func (m *httpMembersAPI) Add(ctx context.Context, peerURL string) (*Member, erro return &memb, nil } +func (m *httpMembersAPI) Update(ctx context.Context, memberID string, peerURLs []string) error { + urls, err := types.NewURLs(peerURLs) + if err != nil { + return err + } + + req := &membersAPIActionUpdate{peerURLs: urls, memberID: memberID} + resp, body, err := m.client.Do(ctx, req) + if err != nil { + return err + } + + if err := assertStatusCode(resp.StatusCode, http.StatusNoContent, http.StatusNotFound, http.StatusConflict); err != nil { + return err + } + + if resp.StatusCode != http.StatusNoContent { + var merr membersError + if err := json.Unmarshal(body, &merr); err != nil { + return err + } + return merr + } + + return nil +} + func (m *httpMembersAPI) Remove(ctx context.Context, memberID string) error { req := &membersAPIActionRemove{memberID: memberID} resp, _, err := m.client.Do(ctx, req) @@ -194,13 +224,28 @@ type membersAPIActionAdd struct { func (a *membersAPIActionAdd) HTTPRequest(ep url.URL) *http.Request { u := v2MembersURL(ep) - m := memberCreateRequest{PeerURLs: a.peerURLs} + m := memberCreateOrUpdateRequest{PeerURLs: a.peerURLs} b, _ := json.Marshal(&m) req, _ := http.NewRequest("POST", u.String(), bytes.NewReader(b)) req.Header.Set("Content-Type", "application/json") return req } +type membersAPIActionUpdate struct { + memberID string + peerURLs types.URLs +} + +func (a *membersAPIActionUpdate) HTTPRequest(ep url.URL) *http.Request { + u := v2MembersURL(ep) + m := memberCreateOrUpdateRequest{PeerURLs: a.peerURLs} + u.Path = path.Join(u.Path, a.memberID) + b, _ := json.Marshal(&m) + req, _ := http.NewRequest("PUT", u.String(), bytes.NewReader(b)) + req.Header.Set("Content-Type", "application/json") + return req +} + func assertStatusCode(got int, want ...int) (err error) { for _, w := range want { if w == got { diff --git a/client/members_test.go b/client/members_test.go index 240b81ead..eb0a36eb8 100644 --- a/client/members_test.go +++ b/client/members_test.go @@ -70,6 +70,33 @@ func TestMembersAPIActionAdd(t *testing.T) { } } +func TestMembersAPIActionUpdate(t *testing.T) { + ep := url.URL{Scheme: "http", Host: "example.com"} + act := &membersAPIActionUpdate{ + memberID: "0xabcd", + peerURLs: types.URLs([]url.URL{ + url.URL{Scheme: "https", Host: "127.0.0.1:8081"}, + url.URL{Scheme: "http", Host: "127.0.0.1:8080"}, + }), + } + + wantURL := &url.URL{ + Scheme: "http", + Host: "example.com", + Path: "/v2/members/0xabcd", + } + wantHeader := http.Header{ + "Content-Type": []string{"application/json"}, + } + wantBody := []byte(`{"peerURLs":["https://127.0.0.1:8081","http://127.0.0.1:8080"]}`) + + got := *act.HTTPRequest(ep) + err := assertRequest(got, "PUT", wantURL, wantHeader, wantBody) + if err != nil { + t.Error(err.Error()) + } +} + func TestMembersAPIActionRemove(t *testing.T) { ep := url.URL{Scheme: "http", Host: "example.com"} act := &membersAPIActionRemove{memberID: "XXX"} @@ -260,7 +287,7 @@ func TestMemberCollectionUnmarshal(t *testing.T) { } func TestMemberCreateRequestMarshal(t *testing.T) { - req := memberCreateRequest{ + req := memberCreateOrUpdateRequest{ PeerURLs: types.URLs([]url.URL{ url.URL{Scheme: "http", Host: "127.0.0.1:8081"}, url.URL{Scheme: "https", Host: "127.0.0.1:8080"},