mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #2827 from xiang90/cluster_v
etcdhttp: version endpoint also returns cluster version.
This commit is contained in:
commit
132b12f8db
@ -53,6 +53,8 @@ type Cluster interface {
|
|||||||
// IsIDRemoved checks whether the given ID has been removed from this
|
// IsIDRemoved checks whether the given ID has been removed from this
|
||||||
// cluster at some point in the past
|
// cluster at some point in the past
|
||||||
IsIDRemoved(id types.ID) bool
|
IsIDRemoved(id types.ID) bool
|
||||||
|
// ClusterVersion is the cluster-wide minimum major.minor version.
|
||||||
|
Version() *semver.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cluster is a list of Members that belong to the same raft cluster
|
// Cluster is a list of Members that belong to the same raft cluster
|
||||||
|
@ -92,7 +92,7 @@ func NewClientHandler(server *etcdserver.EtcdServer) http.Handler {
|
|||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc("/", http.NotFound)
|
mux.HandleFunc("/", http.NotFound)
|
||||||
mux.Handle(healthPath, healthHandler(server))
|
mux.Handle(healthPath, healthHandler(server))
|
||||||
mux.HandleFunc(versionPath, serveVersion)
|
mux.HandleFunc(versionPath, versionHandler(server.Cluster(), serveVersion))
|
||||||
mux.Handle(keysPrefix, kh)
|
mux.Handle(keysPrefix, kh)
|
||||||
mux.Handle(keysPrefix+"/", kh)
|
mux.Handle(keysPrefix+"/", kh)
|
||||||
mux.HandleFunc(statsPrefix+"/store", sh.serveStore)
|
mux.HandleFunc(statsPrefix+"/store", sh.serveStore)
|
||||||
@ -357,11 +357,31 @@ func healthHandler(server *etcdserver.EtcdServer) http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func serveVersion(w http.ResponseWriter, r *http.Request) {
|
func versionHandler(c etcdserver.Cluster, fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
v := c.Version()
|
||||||
|
if v != nil {
|
||||||
|
fn(w, r, v.String())
|
||||||
|
} else {
|
||||||
|
fn(w, r, "not_decided")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func serveVersion(w http.ResponseWriter, r *http.Request, clusterV string) {
|
||||||
if !allowMethod(w, r.Method, "GET") {
|
if !allowMethod(w, r.Method, "GET") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Write(version.MarshalJSON())
|
vs := version.Versions{
|
||||||
|
Server: version.Version,
|
||||||
|
Cluster: clusterV,
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(&vs)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("version: cannot marshal versions to json (%v)", err)
|
||||||
|
}
|
||||||
|
w.Write(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseKeyRequest converts a received http.Request on keysPrefix to
|
// parseKeyRequest converts a received http.Request on keysPrefix to
|
||||||
|
@ -1326,11 +1326,18 @@ func TestServeVersion(t *testing.T) {
|
|||||||
t.Fatalf("error creating request: %v", err)
|
t.Fatalf("error creating request: %v", err)
|
||||||
}
|
}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
serveVersion(rw, req)
|
serveVersion(rw, req, "2.1.0")
|
||||||
if rw.Code != http.StatusOK {
|
if rw.Code != http.StatusOK {
|
||||||
t.Errorf("code=%d, want %d", rw.Code, http.StatusOK)
|
t.Errorf("code=%d, want %d", rw.Code, http.StatusOK)
|
||||||
}
|
}
|
||||||
w := version.MarshalJSON()
|
vs := version.Versions{
|
||||||
|
Server: version.Version,
|
||||||
|
Cluster: "2.1.0",
|
||||||
|
}
|
||||||
|
w, err := json.Marshal(&vs)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
if g := rw.Body.String(); g != string(w) {
|
if g := rw.Body.String(); g != string(w) {
|
||||||
t.Fatalf("body = %q, want %q", g, string(w))
|
t.Fatalf("body = %q, want %q", g, string(w))
|
||||||
}
|
}
|
||||||
@ -1345,7 +1352,7 @@ func TestServeVersionFails(t *testing.T) {
|
|||||||
t.Fatalf("error creating request: %v", err)
|
t.Fatalf("error creating request: %v", err)
|
||||||
}
|
}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
serveVersion(rw, req)
|
serveVersion(rw, req, "2.1.0")
|
||||||
if rw.Code != http.StatusMethodNotAllowed {
|
if rw.Code != http.StatusMethodNotAllowed {
|
||||||
t.Errorf("method %s: code=%d, want %d", m, rw.Code, http.StatusMethodNotAllowed)
|
t.Errorf("method %s: code=%d, want %d", m, rw.Code, http.StatusMethodNotAllowed)
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ func (c *fakeCluster) Members() []*etcdserver.Member {
|
|||||||
}
|
}
|
||||||
func (c *fakeCluster) Member(id types.ID) *etcdserver.Member { return c.members[uint64(id)] }
|
func (c *fakeCluster) Member(id types.ID) *etcdserver.Member { return c.members[uint64(id)] }
|
||||||
func (c *fakeCluster) IsIDRemoved(id types.ID) bool { return false }
|
func (c *fakeCluster) IsIDRemoved(id types.ID) bool { return false }
|
||||||
|
func (c *fakeCluster) Version() *semver.Version { return nil }
|
||||||
|
|
||||||
// errServer implements the etcd.Server interface for testing.
|
// errServer implements the etcd.Server interface for testing.
|
||||||
// It returns the given error from any Do/Process/AddMember/RemoveMember calls.
|
// It returns the given error from any Do/Process/AddMember/RemoveMember calls.
|
||||||
|
@ -38,7 +38,7 @@ func NewPeerHandler(cluster etcdserver.Cluster, raftHandler http.Handler) http.H
|
|||||||
mux.Handle(rafthttp.RaftPrefix, raftHandler)
|
mux.Handle(rafthttp.RaftPrefix, raftHandler)
|
||||||
mux.Handle(rafthttp.RaftPrefix+"/", raftHandler)
|
mux.Handle(rafthttp.RaftPrefix+"/", raftHandler)
|
||||||
mux.Handle(peerMembersPrefix, mh)
|
mux.Handle(peerMembersPrefix, mh)
|
||||||
mux.HandleFunc(versionPath, serveVersion)
|
mux.HandleFunc(versionPath, versionHandler(cluster, serveVersion))
|
||||||
return mux
|
return mux
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
package version
|
package version
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
@ -45,20 +43,11 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Versions struct {
|
type Versions struct {
|
||||||
Server string `json:"etcdserver"`
|
Server string `json:"etcdserver"`
|
||||||
// TODO: etcdcluster version
|
Cluster string `json:"etcdcluster"`
|
||||||
// TODO: raft state machine version
|
// TODO: raft state machine version
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON returns the JSON encoding of Versions struct.
|
|
||||||
func MarshalJSON() []byte {
|
|
||||||
b, err := json.Marshal(Versions{Server: Version})
|
|
||||||
if err != nil {
|
|
||||||
log.Panicf("version: cannot marshal versions to json (%v)", err)
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
func DetectDataDir(dirpath string) (DataDirVersion, error) {
|
func DetectDataDir(dirpath string) (DataDirVersion, error) {
|
||||||
names, err := fileutil.ReadDir(dirpath)
|
names, err := fileutil.ReadDir(dirpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user