etcdserver: getVersion returns both server and cluster version

This commit is contained in:
Xiang Li 2015-05-13 17:04:46 -07:00
parent 1a9dcd2f72
commit 988c30bfba
2 changed files with 26 additions and 19 deletions

View File

@ -111,16 +111,16 @@ func getRemotePeerURLs(cl Cluster, local string) []string {
// getVersions returns the versions of the members in the given cluster. // getVersions returns the versions of the members in the given cluster.
// The key of the returned map is the member's ID. The value of the returned map // The key of the returned map is the member's ID. The value of the returned map
// is the semver version string. If it fails to get the version of a member, the key // is the semver versions string, including server and cluster.
// will be an empty string. // If it fails to get the version of a member, the key will be nil.
func getVersions(cl Cluster, tr *http.Transport) map[string]string { func getVersions(cl Cluster, tr *http.Transport) map[string]*version.Versions {
members := cl.Members() members := cl.Members()
vers := make(map[string]string) vers := make(map[string]*version.Versions)
for _, m := range members { for _, m := range members {
ver, err := getVersion(m, tr) ver, err := getVersion(m, tr)
if err != nil { if err != nil {
log.Printf("etcdserver: cannot get the version of member %s (%v)", m.ID, err) log.Printf("etcdserver: cannot get the version of member %s (%v)", m.ID, err)
vers[m.ID.String()] = "" vers[m.ID.String()] = nil
} else { } else {
vers[m.ID.String()] = ver vers[m.ID.String()] = ver
} }
@ -129,17 +129,17 @@ func getVersions(cl Cluster, tr *http.Transport) map[string]string {
} }
// decideClusterVersion decides the cluster version based on the versions map. // decideClusterVersion decides the cluster version based on the versions map.
// The returned version is the min version in the map, or nil if the min // The returned version is the min server version in the map, or nil if the min
// version in unknown. // version in unknown.
func decideClusterVersion(vers map[string]string) *semver.Version { func decideClusterVersion(vers map[string]*version.Versions) *semver.Version {
var cv *semver.Version var cv *semver.Version
lv := semver.Must(semver.NewVersion(version.Version)) lv := semver.Must(semver.NewVersion(version.Version))
for mid, ver := range vers { for mid, ver := range vers {
if len(ver) == 0 { if ver == nil {
return nil return nil
} }
v, err := semver.NewVersion(ver) v, err := semver.NewVersion(ver.Server)
if err != nil { if err != nil {
log.Printf("etcdserver: cannot understand the version of member %s (%v)", mid, err) log.Printf("etcdserver: cannot understand the version of member %s (%v)", mid, err)
return nil return nil
@ -157,9 +157,9 @@ func decideClusterVersion(vers map[string]string) *semver.Version {
return cv return cv
} }
// getVersion returns the version of the given member via its // getVersion returns the Versions of the given member via its
// peerURLs. Returns the last error if it fails to get the version. // peerURLs. Returns the last error if it fails to get the version.
func getVersion(m *Member, tr *http.Transport) (string, error) { func getVersion(m *Member, tr *http.Transport) (*version.Versions, error) {
cc := &http.Client{ cc := &http.Client{
Transport: tr, Transport: tr,
Timeout: time.Second, Timeout: time.Second,
@ -174,6 +174,12 @@ func getVersion(m *Member, tr *http.Transport) (string, error) {
if err != nil { if err != nil {
continue continue
} }
// etcd 2.0 does not have version endpoint on peer url.
if resp.StatusCode == http.StatusNotFound {
resp.Body.Close()
return &version.Versions{"2.0.0", "2.0.0"}, nil
}
b, err := ioutil.ReadAll(resp.Body) b, err := ioutil.ReadAll(resp.Body)
resp.Body.Close() resp.Body.Close()
if err != nil { if err != nil {
@ -183,7 +189,7 @@ func getVersion(m *Member, tr *http.Transport) (string, error) {
if err := json.Unmarshal(b, &vers); err != nil { if err := json.Unmarshal(b, &vers); err != nil {
continue continue
} }
return vers.Server, nil return &vers, nil
} }
return "", err return nil, err
} }

View File

@ -19,32 +19,33 @@ import (
"testing" "testing"
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/coreos/go-semver/semver" "github.com/coreos/etcd/Godeps/_workspace/src/github.com/coreos/go-semver/semver"
"github.com/coreos/etcd/version"
) )
func TestDecideClusterVersion(t *testing.T) { func TestDecideClusterVersion(t *testing.T) {
tests := []struct { tests := []struct {
vers map[string]string vers map[string]*version.Versions
wdver *semver.Version wdver *semver.Version
}{ }{
{ {
map[string]string{"a": "2.0.0"}, map[string]*version.Versions{"a": &version.Versions{Server: "2.0.0"}},
semver.Must(semver.NewVersion("2.0.0")), semver.Must(semver.NewVersion("2.0.0")),
}, },
// unknow // unknow
{ {
map[string]string{"a": ""}, map[string]*version.Versions{"a": nil},
nil, nil,
}, },
{ {
map[string]string{"a": "2.0.0", "b": "2.1.0", "c": "2.1.0"}, map[string]*version.Versions{"a": &version.Versions{Server: "2.0.0"}, "b": &version.Versions{Server: "2.1.0"}, "c": &version.Versions{Server: "2.1.0"}},
semver.Must(semver.NewVersion("2.0.0")), semver.Must(semver.NewVersion("2.0.0")),
}, },
{ {
map[string]string{"a": "2.1.0", "b": "2.1.0", "c": "2.1.0"}, map[string]*version.Versions{"a": &version.Versions{Server: "2.1.0"}, "b": &version.Versions{Server: "2.1.0"}, "c": &version.Versions{Server: "2.1.0"}},
semver.Must(semver.NewVersion("2.1.0")), semver.Must(semver.NewVersion("2.1.0")),
}, },
{ {
map[string]string{"a": "", "b": "2.1.0", "c": "2.1.0"}, map[string]*version.Versions{"a": nil, "b": &version.Versions{Server: "2.1.0"}, "c": &version.Versions{Server: "2.1.0"}},
nil, nil,
}, },
} }