From ad397922222a1076a2303f3104d02d6f9df2710a Mon Sep 17 00:00:00 2001
From: Jessica Yuen <im.jessicayuen@gmail.com>
Date: Tue, 6 Mar 2018 13:43:05 -0800
Subject: [PATCH] Parse server version from GitVersion

We currently attempt to parse the server version from the Major / Minor
version provided by client-go's ServerVersion object. It is not always
the case that these fields are populated; and is more accurate to use
the GitVersion.

Signed-off-by: Jessica Yuen <im.jessicayuen@gmail.com>
---
 utils/meta.go      | 34 ++++++++++++++++++++++++++++++++++
 utils/meta_test.go | 14 ++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/utils/meta.go b/utils/meta.go
index e21fcecb..9548969b 100644
--- a/utils/meta.go
+++ b/utils/meta.go
@@ -6,6 +6,7 @@ import (
 	"strconv"
 	"strings"
 
+	"github.com/blang/semver"
 	log "github.com/sirupsen/logrus"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
@@ -21,6 +22,38 @@ type ServerVersion struct {
 
 // ParseVersion parses version.Info into a ServerVersion struct
 func ParseVersion(v *version.Info) (ret ServerVersion, err error) {
+	//
+	// Note: It is not advisable to use the Major / Minor version pair returned
+	// by The ServerVersion as it may be empty. We will use the GitVersion as
+	// it appears to always be populated, and is the return value provided by
+	// client-go's v.String().
+	//
+	// As a safety precaution, we will still default to the Major / Minor version,
+	// if the GitVersion fails.
+	//
+
+	versionString := v.String()
+	if len(versionString) >= 1 {
+		// trim off "v" infront of version since it is invalid semver syntax.
+		versionString = versionString[1:]
+	}
+
+	version, err := semver.Make(versionString)
+	if err != nil {
+		ret, err = parseFromMajorMinor(v)
+		if err != nil {
+			err = fmt.Errorf("Server version '%s' does not conform to semver format", versionString)
+		}
+		return
+	}
+
+	ret.Major = int(version.Major)
+	ret.Minor = int(version.Minor)
+
+	return
+}
+
+func parseFromMajorMinor(v *version.Info) (ret ServerVersion, err error) {
 	re := regexp.MustCompile("[0-9]+")
 
 	major := re.FindAllString(v.Major, 1)
@@ -44,6 +77,7 @@ func ParseVersion(v *version.Info) (ret ServerVersion, err error) {
 	if err != nil {
 		return
 	}
+
 	return
 }
 
diff --git a/utils/meta_test.go b/utils/meta_test.go
index ea9f30bb..ac570c5e 100644
--- a/utils/meta_test.go
+++ b/utils/meta_test.go
@@ -17,6 +17,20 @@ func TestParseVersion(t *testing.T) {
 		expected ServerVersion
 		error    bool
 	}{
+		{
+			input:    version.Info{GitVersion: "v1.7.0"},
+			expected: ServerVersion{Major: 1, Minor: 7},
+		},
+		{
+			input:    version.Info{GitVersion: "v1.7.11-gke.1"},
+			expected: ServerVersion{Major: 1, Minor: 7},
+		},
+		// Bad GitVersion case
+		{
+			input:    version.Info{Major: "1", Minor: "6", GitVersion: "invalid"},
+			expected: ServerVersion{Major: 1, Minor: 6},
+		},
+		// GitVersion does not exist cases
 		{
 			input:    version.Info{Major: "1", Minor: "6"},
 			expected: ServerVersion{Major: 1, Minor: 6},
-- 
GitLab