diff --git a/haproxy/haproxy_cmd/run.go b/haproxy/haproxy_cmd/run.go index 5726516..61f16cd 100644 --- a/haproxy/haproxy_cmd/run.go +++ b/haproxy/haproxy_cmd/run.go @@ -105,14 +105,15 @@ func Start(sd *lib.Shutdown, cfg Config) (*dataplane.Dataplane, error) { return dataplaneClient, nil } -// execAndCapture Launch Help from program path and Find Version +// getVersion Launch Help from program path and Find Version // to capture the output and retrieve version information -func execAndCapture(path string, re *regexp.Regexp) (string, error) { +func getVersion(path string) (string, error) { cmd := exec.Command(path, "-v") out, err := cmd.CombinedOutput() if err != nil { return "", fmt.Errorf("Failed executing %s: %s", path, err.Error()) } + re := regexp.MustCompile("\\d+(\\.\\d+)+") return string(re.Find(out)), nil } @@ -121,18 +122,22 @@ func CheckEnvironment(dataplaneapiBin, haproxyBin string) error { var err error wg := &sync.WaitGroup{} wg.Add(2) - ensureVersion := func(path, rx, version string) { + ensureVersion := func(path, minVer string) { defer wg.Done() - r := regexp.MustCompile(rx) - v, e := execAndCapture(path, r) + currVer, e := getVersion(path) if e != nil { err = e - } else if strings.Compare(v, "1.2") < 0 { - err = fmt.Errorf("%s version must be > 1.2, but is: %s", path, v) + } + res, e := compareVersion(currVer, minVer) + if e != nil { + err = e + } + if res < 0 { + err = fmt.Errorf("%s version must be > %s, but is: %s", path, minVer, currVer) } } - go ensureVersion(haproxyBin, "^HA-Proxy version ([0-9]\\.[0-9]\\.[0-9])", "2.0") - go ensureVersion(dataplaneapiBin, "^HAProxy Data Plane API v([0-9]\\.[0-9]\\.[0-9])", "1.2") + go ensureVersion(haproxyBin, "2.0") + go ensureVersion(dataplaneapiBin, "1.2") wg.Wait() if err != nil { @@ -140,3 +145,60 @@ func CheckEnvironment(dataplaneapiBin, haproxyBin string) error { } return nil } + +// compareVersion compares two semver versions. +// If v1 > v2 returns 1, if v1 < v2 returns -1, if equal returns 0. +// If major versions are not the same, returns -1. +// If an error occurs, returns -1 and error. +func compareVersion(v1, v2 string) (int, error) { + a := strings.Split(v1, ".") + b := strings.Split(v2, ".") + + if len(a) < 2 { + return -1, fmt.Errorf("%s arg is not a version string", v1) + } + if len(b) < 2 { + return -1, fmt.Errorf("%s arg is not a version string", v2) + } + + if len(a) != len(b) { + switch { + case len(a) > len(b): + for i := len(b); len(b) < len(a); i++ { + b = append(b, " ") + } + break + case len(a) < len(b): + for i := len(a); len(a) < len(b); i++ { + a = append(a, " ") + } + break + } + } + + var res int + + for i, s := range a { + var ai, bi int + fmt.Sscanf(s, "%d", &ai) + fmt.Sscanf(b[i], "%d", &bi) + + if i == 0 { + //major versions should be the same + if ai != bi { + res = -1 + break + } + continue + } + if ai > bi { + res = 1 + break + } + if ai < bi { + res = -1 + break + } + } + return res, nil +} diff --git a/haproxy/haproxy_cmd/run_test.go b/haproxy/haproxy_cmd/run_test.go new file mode 100644 index 0000000..6155c51 --- /dev/null +++ b/haproxy/haproxy_cmd/run_test.go @@ -0,0 +1,35 @@ +package haproxy_cmd + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +type version struct { + v1 string + v2 string + status int +} + +func TestCompareVersion(t *testing.T) { + tests := []*version{ + {status: 1, v1: "1.3", v2: "1.2"}, + {status: 1, v1: "1.3.1", v2: "1.3"}, + {status: 1, v1: "2.0.1", v2: "2.0"}, + {status: 0, v1: "2.0", v2: "2.0"}, + {status: 0, v1: "2.0.0", v2: "2.0"}, + {status: 0, v1: "2.0", v2: "2.0.0"}, + {status: -1, v1: "1.2", v2: "1.3"}, + {status: -1, v1: "1.3", v2: "1.3.1"}, + {status: -1, v1: "2.0", v2: "2.0.1"}, + {status: -1, v1: "2", v2: "2.0.1"}, + {status: -1, v1: "2.0", v2: "2"}, + {status: -1, v1: "3.0", v2: "2.2.2"}, + {status: -1, v1: "2.2", v2: "3.0"}, + } + for _, test := range tests { + res, _ := compareVersion(test.v1, test.v2) + require.Equal(t, res, test.status) + } +}