From c2dadbd9f83dc9169840aaee0fe7f3a5db20bc5f Mon Sep 17 00:00:00 2001 From: Anthony Romano Date: Thu, 8 Jun 2017 09:25:44 -0700 Subject: [PATCH] v2http: put back /v2/machines and mark as non-deprecated This reverts commit 2bb33181b6c8fbe8109fc668a19ce4ab46c605ec. python-etcd seems to depend on /v2/machines and the maintainer vanished. Plus, it is prefixed with /v2/ so it probably can't be deprecated anyway. --- etcdserver/api/v2http/client.go | 34 ++++++++++++++----- etcdserver/api/v2http/client_test.go | 50 ++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/etcdserver/api/v2http/client.go b/etcdserver/api/v2http/client.go index f849562cb1b..0dd7eb07e33 100644 --- a/etcdserver/api/v2http/client.go +++ b/etcdserver/api/v2http/client.go @@ -46,15 +46,16 @@ import ( ) const ( - authPrefix = "/v2/auth" - keysPrefix = "/v2/keys" - membersPrefix = "/v2/members" - statsPrefix = "/v2/stats" - varsPath = "/debug/vars" - metricsPath = "/metrics" - healthPath = "/health" - versionPath = "/version" - configPath = "/config" + authPrefix = "/v2/auth" + keysPrefix = "/v2/keys" + machinesPrefix = "/v2/machines" + membersPrefix = "/v2/members" + statsPrefix = "/v2/stats" + varsPath = "/debug/vars" + metricsPath = "/metrics" + healthPath = "/health" + versionPath = "/version" + configPath = "/config" ) // NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests. @@ -83,6 +84,8 @@ func NewClientHandler(server *etcdserver.EtcdServer, timeout time.Duration) http clientCertAuthEnabled: server.Cfg.ClientCertAuthEnabled, } + mah := &machinesHandler{cluster: server.Cluster()} + sech := &authHandler{ sec: sec, cluster: server.Cluster(), @@ -103,6 +106,7 @@ func NewClientHandler(server *etcdserver.EtcdServer, timeout time.Duration) http mux.Handle(metricsPath, prometheus.Handler()) mux.Handle(membersPrefix, mh) mux.Handle(membersPrefix+"/", mh) + mux.Handle(machinesPrefix, mah) handleAuth(mux, sech) return requestLogger(mux) @@ -164,6 +168,18 @@ func (h *keysHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } +type machinesHandler struct { + cluster api.Cluster +} + +func (h *machinesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if !allowMethod(w, r.Method, "GET", "HEAD") { + return + } + endpoints := h.cluster.ClientURLs() + w.Write([]byte(strings.Join(endpoints, ", "))) +} + type membersHandler struct { sec auth.Store server etcdserver.Server diff --git a/etcdserver/api/v2http/client_test.go b/etcdserver/api/v2http/client_test.go index d912d16c609..4436f34a403 100644 --- a/etcdserver/api/v2http/client_test.go +++ b/etcdserver/api/v2http/client_test.go @@ -1220,6 +1220,56 @@ func TestWriteEvent(t *testing.T) { } } +func TestV2DMachinesEndpoint(t *testing.T) { + tests := []struct { + method string + wcode int + }{ + {"GET", http.StatusOK}, + {"HEAD", http.StatusOK}, + {"POST", http.StatusMethodNotAllowed}, + } + + m := &machinesHandler{cluster: &fakeCluster{}} + s := httptest.NewServer(m) + defer s.Close() + + for _, tt := range tests { + req, err := http.NewRequest(tt.method, s.URL+machinesPrefix, nil) + if err != nil { + t.Fatal(err) + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatal(err) + } + + if resp.StatusCode != tt.wcode { + t.Errorf("StatusCode = %d, expected %d", resp.StatusCode, tt.wcode) + } + } +} + +func TestServeMachines(t *testing.T) { + cluster := &fakeCluster{ + clientURLs: []string{"http://localhost:8080", "http://localhost:8081", "http://localhost:8082"}, + } + writer := httptest.NewRecorder() + req, err := http.NewRequest("GET", "", nil) + if err != nil { + t.Fatal(err) + } + h := &machinesHandler{cluster: cluster} + h.ServeHTTP(writer, req) + w := "http://localhost:8080, http://localhost:8081, http://localhost:8082" + if g := writer.Body.String(); g != w { + t.Errorf("body = %s, want %s", g, w) + } + if writer.Code != http.StatusOK { + t.Errorf("code = %d, want %d", writer.Code, http.StatusOK) + } +} + func TestGetID(t *testing.T) { tests := []struct { path string