From 02551c277d1624cd855bdc57f8b8804defcdad8a Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Thu, 23 Oct 2014 15:53:27 -0700 Subject: [PATCH] etcdserver: add member endpoint to peerurl --- etcdserver/etcdhttp/http.go | 13 ++++++- etcdserver/etcdhttp/http_test.go | 64 ++++++++++++++++++++++++-------- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/etcdserver/etcdhttp/http.go b/etcdserver/etcdhttp/http.go index 797d2e65a..d969a9174 100644 --- a/etcdserver/etcdhttp/http.go +++ b/etcdserver/etcdhttp/http.go @@ -41,11 +41,14 @@ import ( ) const ( + // prefixes of client endpoint keysPrefix = "/v2/keys" deprecatedMachinesPrefix = "/v2/machines" adminMembersPrefix = "/v2/admin/members/" - raftPrefix = "/raft" statsPrefix = "/v2/stats" + // prefixes of peer endpoint + raftPrefix = "/raft" + membersPrefix = "/members" // time to wait for response from EtcdServer requests defaultServerTimeout = 500 * time.Millisecond @@ -91,6 +94,7 @@ func NewPeerHandler(server *etcdserver.EtcdServer) http.Handler { } mux := http.NewServeMux() mux.HandleFunc(raftPrefix, sh.serveRaft) + mux.HandleFunc(membersPrefix, sh.serveMembers) mux.HandleFunc("/", http.NotFound) return mux } @@ -306,6 +310,13 @@ func (h serverHandler) serveRaft(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) } +func (h serverHandler) serveMembers(w http.ResponseWriter, r *http.Request) { + if !allowMethod(w, r.Method, "GET") { + return + } + h.serveAdminMembers(w, r) +} + // parseKeyRequest converts a received http.Request on keysPrefix to // a server Request, performing validation of supplied fields as appropriate. // If any validation fails, an empty Request and non-nil error is returned. diff --git a/etcdserver/etcdhttp/http_test.go b/etcdserver/etcdhttp/http_test.go index c399a2144..8d3af8de1 100644 --- a/etcdserver/etcdhttp/http_test.go +++ b/etcdserver/etcdhttp/http_test.go @@ -988,6 +988,34 @@ func TestServeRaft(t *testing.T) { } } +func TestServeMembersFails(t *testing.T) { + tests := []struct { + method string + wcode int + }{ + { + "POST", + http.StatusMethodNotAllowed, + }, + { + "DELETE", + http.StatusMethodNotAllowed, + }, + { + "BAD", + http.StatusMethodNotAllowed, + }, + } + for i, tt := range tests { + h := &serverHandler{} + rw := httptest.NewRecorder() + h.serveMembers(rw, &http.Request{Method: tt.method}) + if rw.Code != tt.wcode { + t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode) + } + } +} + // resServer implements the etcd.Server interface for testing. // It returns the given responsefrom any Do calls, and nil error type resServer struct { @@ -1532,7 +1560,7 @@ func (s *serverRecorder) RemoveMember(_ context.Context, id uint64) error { return nil } -func TestServeAdminMembersGet(t *testing.T) { +func TestServeAdminMembersAndMembersGet(t *testing.T) { memb1 := etcdserver.Member{ID: 1, Attributes: etcdserver.Attributes{ClientURLs: []string{"http://localhost:8080"}}} memb2 := etcdserver.Member{ID: 2, Attributes: etcdserver.Attributes{ClientURLs: []string{"http://localhost:8081"}}} cluster := &fakeCluster{ @@ -1566,22 +1594,26 @@ func TestServeAdminMembersGet(t *testing.T) { {path.Join(adminMembersPrefix, "100"), http.StatusNotFound, "text/plain; charset=utf-8", "member not found\n"}, } - for i, tt := range tests { - req, err := http.NewRequest("GET", mustNewURL(t, tt.path).String(), nil) - if err != nil { - t.Fatal(err) - } - rw := httptest.NewRecorder() - h.serveAdminMembers(rw, req) + funcs := []func(w http.ResponseWriter, r *http.Request){h.serveAdminMembers, h.serveMembers} - if rw.Code != tt.wcode { - t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode) - } - if gct := rw.Header().Get("Content-Type"); gct != tt.wct { - t.Errorf("#%d: content-type = %s, want %s", i, gct, tt.wct) - } - if rw.Body.String() != tt.wbody { - t.Errorf("#%d: body = %s, want %s", i, rw.Body.String(), tt.wbody) + for i, tt := range tests { + for j, f := range funcs { + req, err := http.NewRequest("GET", mustNewURL(t, tt.path).String(), nil) + if err != nil { + t.Fatal(err) + } + rw := httptest.NewRecorder() + f(rw, req) + + if rw.Code != tt.wcode { + t.Errorf("#%d.%d: code=%d, want %d", i, j, rw.Code, tt.wcode) + } + if gct := rw.Header().Get("Content-Type"); gct != tt.wct { + t.Errorf("#%d.%d: content-type = %s, want %s", i, j, gct, tt.wct) + } + if rw.Body.String() != tt.wbody { + t.Errorf("#%d.%d: body = %s, want %s", i, j, rw.Body.String(), tt.wbody) + } } } }