Browse Source

etcdhttp: add /v2/machines endpoint

Yicheng Qin 11 years ago
parent
commit
0c1d1b7aeb
3 changed files with 60 additions and 2 deletions
  1. 27 2
      etcdserver/etcdhttp/http.go
  2. 32 0
      etcdserver/etcdhttp/http_test.go
  3. 1 0
      main.go

+ 27 - 2
etcdserver/etcdhttp/http.go

@@ -11,6 +11,7 @@ import (
 	"log"
 	"net/http"
 	"net/url"
+	"sort"
 	"strconv"
 	"strings"
 	"time"
@@ -27,7 +28,10 @@ import (
 	"github.com/coreos/etcd/third_party/code.google.com/p/go.net/context"
 )
 
-const keysPrefix = "/v2/keys"
+const (
+	keysPrefix     = "/v2/keys"
+	machinesPrefix = "/v2/machines"
+)
 
 type Peers map[int64][]string
 
@@ -36,7 +40,12 @@ func (ps Peers) Pick(id int64) string {
 	if len(addrs) == 0 {
 		return ""
 	}
-	return fmt.Sprintf("http://%s", addrs[rand.Intn(len(addrs))])
+	return addScheme(addrs[rand.Intn(len(addrs))])
+}
+
+// TODO: improve this when implementing TLS
+func addScheme(addr string) string {
+	return fmt.Sprintf("http://%s", addr)
 }
 
 // Set parses command line sets of names to ips formatted like:
@@ -138,6 +147,7 @@ func httpPost(url string, data []byte) bool {
 type Handler struct {
 	Timeout time.Duration
 	Server  *etcdserver.Server
+	Peers   Peers
 }
 
 func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@@ -156,6 +166,8 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		h.serveRaft(ctx, w, r)
 	case strings.HasPrefix(r.URL.Path, keysPrefix):
 		h.serveKeys(ctx, w, r)
+	case strings.HasPrefix(r.URL.Path, machinesPrefix):
+		h.serveMachines(w, r)
 	default:
 		http.NotFound(w, r)
 	}
@@ -188,6 +200,19 @@ func (h Handler) serveKeys(ctx context.Context, w http.ResponseWriter, r *http.R
 	}
 }
 
+// serveMachines responds address list in the format '0.0.0.0, 1.1.1.1'.
+// TODO: rethink the format of machine list because it is not json format.
+func (h Handler) serveMachines(w http.ResponseWriter, r *http.Request) {
+	urls := make([]string, 0)
+	for _, addrs := range h.Peers {
+		for _, addr := range addrs {
+			urls = append(urls, addScheme(addr))
+		}
+	}
+	sort.Sort(sort.StringSlice(urls))
+	w.Write([]byte(strings.Join(urls, ", ")))
+}
+
 func (h Handler) serveRaft(ctx context.Context, w http.ResponseWriter, r *http.Request) {
 	b, err := ioutil.ReadAll(r.Body)
 	if err != nil {

+ 32 - 0
etcdserver/etcdhttp/http_test.go

@@ -347,3 +347,35 @@ func TestWaitForEventCancelledContext(t *testing.T) {
 		t.Fatalf("nil err returned with cancelled context!")
 	}
 }
+
+func TestV2MachinesEndpoint(t *testing.T) {
+	h := Handler{Peers: Peers{}}
+
+	s := httptest.NewServer(h)
+	defer s.Close()
+
+	resp, err := http.Get(s.URL + machinesPrefix)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if resp.StatusCode != http.StatusOK {
+		t.Errorf("StatusCode = %d, expected %d", resp.StatusCode, http.StatusOK)
+	}
+}
+
+func TestServeMachines(t *testing.T) {
+	peers := Peers{}
+	peers.Set("0xBEEF0=localhost:8080&0xBEEF1=localhost:8081&0xBEEF2=localhost:8082")
+	h := Handler{Peers: peers}
+
+	writer := httptest.NewRecorder()
+	h.serveMachines(writer, nil)
+	w := "http://localhost:8080, http://localhost:8081, http://localhost:8082"
+	if g := writer.Body.String(); g != w {
+		t.Errorf("data = %s, want %s", g, w)
+	}
+	if writer.Code != http.StatusOK {
+		t.Errorf("header = %d, want %d", writer.Code, http.StatusOK)
+	}
+}

+ 1 - 0
main.go

@@ -70,6 +70,7 @@ func main() {
 	h := &etcdhttp.Handler{
 		Timeout: *timeout,
 		Server:  s,
+		Peers:   peers,
 	}
 	http.Handle("/", h)
 	log.Fatal(http.ListenAndServe(*laddr, nil))