Skip to content

Commit 4e7bcca

Browse files
committed
Merge pull request kubernetes#4991 from fabioy/etcdcheck-fix
Fix the etcd version check and have it return the version string.
2 parents 4cd59e6 + c38c6f0 commit 4e7bcca

File tree

2 files changed

+71
-8
lines changed

2 files changed

+71
-8
lines changed

pkg/tools/etcd_tools.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ limitations under the License.
1717
package tools
1818

1919
import (
20+
"encoding/json"
2021
"errors"
2122
"fmt"
2223
"io/ioutil"
2324
"net/http"
2425
"os/exec"
2526
"reflect"
2627
"strconv"
27-
"strings"
2828

2929
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
3030
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
@@ -425,20 +425,35 @@ func (h *EtcdHelper) AtomicUpdate(key string, ptrToType runtime.Object, ignoreNo
425425
}
426426
}
427427

428-
func checkEtcd(host string) error {
428+
// GetEtcdVersion performs a version check against the provided Etcd server, returning a triplet
429+
// of the release version, internal version, and error (if any).
430+
func GetEtcdVersion(host string) (releaseVersion, internalVersion string, err error) {
429431
response, err := http.Get(host + "/version")
430432
if err != nil {
431-
return err
433+
return "", "", err
432434
}
433435
defer response.Body.Close()
436+
434437
body, err := ioutil.ReadAll(response.Body)
435438
if err != nil {
436-
return err
439+
return "", "", err
437440
}
438-
if !strings.HasPrefix(string(body), "etcd") {
439-
return fmt.Errorf("unknown server: %s", string(body))
441+
442+
var dat map[string]interface{}
443+
if err := json.Unmarshal(body, &dat); err != nil {
444+
return "", "", fmt.Errorf("unknown server: %s", string(body))
440445
}
441-
return nil
446+
if obj := dat["releaseVersion"]; obj != nil {
447+
if s, ok := obj.(string); ok {
448+
releaseVersion = s
449+
}
450+
}
451+
if obj := dat["internalVersion"]; obj != nil {
452+
if s, ok := obj.(string); ok {
453+
internalVersion = s
454+
}
455+
}
456+
return
442457
}
443458

444459
func startEtcd() (*exec.Cmd, error) {
@@ -451,7 +466,7 @@ func startEtcd() (*exec.Cmd, error) {
451466
}
452467

453468
func NewEtcdClientStartServerIfNecessary(server string) (EtcdClient, error) {
454-
err := checkEtcd(server)
469+
_, _, err := GetEtcdVersion(server)
455470
if err != nil {
456471
glog.Infof("Failed to find etcd, attempting to start.")
457472
_, err := startEtcd()

pkg/tools/etcd_tools_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ package tools
1919
import (
2020
"errors"
2121
"fmt"
22+
"net/http"
23+
"net/http/httptest"
2224
"reflect"
2325
"sync"
2426
"testing"
@@ -29,6 +31,7 @@ import (
2931
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
3032
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
3133
"github.com/coreos/go-etcd/etcd"
34+
"github.com/stretchr/testify/assert"
3235
)
3336

3437
type TestResource struct {
@@ -643,3 +646,48 @@ func TestAtomicUpdate_CreateCollision(t *testing.T) {
643646
t.Errorf("Some of the writes were lost. Stored value: %d", stored.Value)
644647
}
645648
}
649+
650+
func TestGetEtcdVersion_ValidVersion(t *testing.T) {
651+
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
652+
fmt.Fprintln(w, "{\"releaseVersion\":\"2.0.3\",\"internalVersion\":\"2\"}")
653+
}))
654+
defer testServer.Close()
655+
656+
var relVersion string
657+
var intVersion string
658+
var err error
659+
if relVersion, intVersion, err = GetEtcdVersion(testServer.URL); err != nil {
660+
t.Errorf("Unexpected error: %v", err)
661+
}
662+
assert.Equal(t, "2.0.3", relVersion, "Unexpected external version")
663+
assert.Equal(t, "2", intVersion, "Unexpected internal version")
664+
assert.Nil(t, err)
665+
}
666+
667+
func TestGetEtcdVersion_UnknownVersion(t *testing.T) {
668+
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
669+
fmt.Fprintln(w, "{\"unknownAttribute\":\"foobar\",\"internalVersion\":\"2\"}")
670+
}))
671+
defer testServer.Close()
672+
673+
var relVersion string
674+
var intVersion string
675+
var err error
676+
if relVersion, intVersion, err = GetEtcdVersion(testServer.URL); err != nil {
677+
t.Errorf("Unexpected error: %v", err)
678+
}
679+
assert.Equal(t, "", relVersion, "Unexpected external version")
680+
assert.Equal(t, "2", intVersion, "Unexpected internal version")
681+
assert.Nil(t, err)
682+
}
683+
684+
func TestGetEtcdVersion_ErrorStatus(t *testing.T) {
685+
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
686+
w.WriteHeader(http.StatusServiceUnavailable)
687+
}))
688+
defer testServer.Close()
689+
690+
var err error
691+
_, _, err = GetEtcdVersion(testServer.URL)
692+
assert.NotNil(t, err)
693+
}

0 commit comments

Comments
 (0)