Browse Source

etcdhttp: separate member create deserialization

Brian Waldon 11 years ago
parent
commit
8b0eaa9e15

+ 6 - 10
etcdserver/etcdhttp/client.go

@@ -36,7 +36,6 @@ import (
 	"github.com/coreos/etcd/etcdserver/etcdhttp/httptypes"
 	"github.com/coreos/etcd/etcdserver/etcdhttp/httptypes"
 	"github.com/coreos/etcd/etcdserver/etcdserverpb"
 	"github.com/coreos/etcd/etcdserver/etcdserverpb"
 	"github.com/coreos/etcd/pkg/strutil"
 	"github.com/coreos/etcd/pkg/strutil"
-	"github.com/coreos/etcd/pkg/types"
 	"github.com/coreos/etcd/store"
 	"github.com/coreos/etcd/store"
 	"github.com/coreos/etcd/version"
 	"github.com/coreos/etcd/version"
 )
 )
@@ -181,24 +180,21 @@ func (h *adminMembersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
 			writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, err.Error()))
 			writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, err.Error()))
 			return
 			return
 		}
 		}
-		raftAttr := etcdserver.RaftAttributes{}
-		if err := json.Unmarshal(b, &raftAttr); err != nil {
+		req := httptypes.MemberCreateRequest{}
+		if err := json.Unmarshal(b, &req); err != nil {
 			writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, err.Error()))
 			writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, err.Error()))
 			return
 			return
 		}
 		}
-		validURLs, err := types.NewURLs(raftAttr.PeerURLs)
-		if err != nil {
-			writeError(w, httptypes.NewHTTPError(http.StatusBadRequest, "Bad peer urls"))
-			return
-		}
+
 		now := h.clock.Now()
 		now := h.clock.Now()
-		m := etcdserver.NewMember("", validURLs, "", &now)
+		m := etcdserver.NewMember("", req.PeerURLs, "", &now)
 		if err := h.server.AddMember(ctx, *m); err != nil {
 		if err := h.server.AddMember(ctx, *m); err != nil {
 			log.Printf("etcdhttp: error adding node %x: %v", m.ID, err)
 			log.Printf("etcdhttp: error adding node %x: %v", m.ID, err)
 			writeError(w, err)
 			writeError(w, err)
 			return
 			return
 		}
 		}
-		log.Printf("etcdhttp: added node %x with peer urls %v", m.ID, raftAttr.PeerURLs)
+		log.Printf("etcdhttp: added node %x with peer urls %v", m.ID, req.PeerURLs)
+
 		w.Header().Set("Content-Type", "application/json")
 		w.Header().Set("Content-Type", "application/json")
 		w.WriteHeader(http.StatusCreated)
 		w.WriteHeader(http.StatusCreated)
 		if err := json.NewEncoder(w).Encode(m); err != nil {
 		if err := json.NewEncoder(w).Encode(m); err != nil {

+ 25 - 0
etcdserver/etcdhttp/httptypes/member.go

@@ -18,6 +18,8 @@ package httptypes
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
+
+	"github.com/coreos/etcd/pkg/types"
 )
 )
 
 
 type Member struct {
 type Member struct {
@@ -27,6 +29,29 @@ type Member struct {
 	ClientURLs []string `json:"clientURLs"`
 	ClientURLs []string `json:"clientURLs"`
 }
 }
 
 
+type MemberCreateRequest struct {
+	PeerURLs types.URLs
+}
+
+func (m *MemberCreateRequest) UnmarshalJSON(data []byte) error {
+	s := struct {
+		PeerURLs []string `json:"peerURLs"`
+	}{}
+
+	err := json.Unmarshal(data, &s)
+	if err != nil {
+		return err
+	}
+
+	urls, err := types.NewURLs(s.PeerURLs)
+	if err != nil {
+		return err
+	}
+
+	m.PeerURLs = urls
+	return nil
+}
+
 type MemberCollection []Member
 type MemberCollection []Member
 
 
 func (c *MemberCollection) MarshalJSON() ([]byte, error) {
 func (c *MemberCollection) MarshalJSON() ([]byte, error) {

+ 44 - 0
etcdserver/etcdhttp/httptypes/member_test.go

@@ -18,8 +18,11 @@ package httptypes
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
+	"net/url"
 	"reflect"
 	"reflect"
 	"testing"
 	"testing"
+
+	"github.com/coreos/etcd/pkg/types"
 )
 )
 
 
 func TestMemberUnmarshal(t *testing.T) {
 func TestMemberUnmarshal(t *testing.T) {
@@ -155,3 +158,44 @@ func TestMemberCollectionUnmarshal(t *testing.T) {
 		}
 		}
 	}
 	}
 }
 }
+
+func TestMemberCreateRequestUnmarshal(t *testing.T) {
+	body := []byte(`{"peerURLs": ["http://127.0.0.1:8081", "https://127.0.0.1:8080"]}`)
+	want := MemberCreateRequest{
+		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"},
+		}),
+	}
+
+	var req MemberCreateRequest
+	if err := json.Unmarshal(body, &req); err != nil {
+		t.Fatalf("Unmarshal returned unexpected err=%v", err)
+	}
+
+	if !reflect.DeepEqual(want, req) {
+		t.Fatalf("Failed to unmarshal MemberCreateRequest: want=%#v, got=%#v", want, req)
+	}
+}
+
+func TestMemberCreateRequestUnmarshalFail(t *testing.T) {
+	tests := [][]byte{
+		// invalid JSON
+		[]byte(``),
+		[]byte(`{`),
+
+		// spot-check validation done in types.NewURLs
+		[]byte(`{"peerURLs": "foo"}`),
+		[]byte(`{"peerURLs": ["."]}`),
+		[]byte(`{"peerURLs": []}`),
+		[]byte(`{"peerURLs": ["http://127.0.0.1:4001/foo"]}`),
+		[]byte(`{"peerURLs": ["http://127.0.0.1"]}`),
+	}
+
+	for i, tt := range tests {
+		var req MemberCreateRequest
+		if err := json.Unmarshal(tt, &req); err == nil {
+			t.Errorf("#%d: expected err, got nil", i)
+		}
+	}
+}