Skip to content

Commit 9b0cea0

Browse files
authored
BUG/MAJOR: version-compare: fix comparison for minimum required and current program version (#56)
Fixed regex used to extract program version. `version` arg was unused. Now, it is renamed as `minVer` and used in comparison. Additional `compareVersion` func added to compare minVer with currVer. Comparision with `strings.Compare` didn't worked for cases like `0.1.10 > 0.1.2` and therefore it is removed. Added unit test for `compareVersion` func.
1 parent 31ce192 commit 9b0cea0

File tree

2 files changed

+106
-9
lines changed

2 files changed

+106
-9
lines changed

haproxy/haproxy_cmd/run.go

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,15 @@ func Start(sd *lib.Shutdown, cfg Config) (*dataplane.Dataplane, error) {
105105
return dataplaneClient, nil
106106
}
107107

108-
// execAndCapture Launch Help from program path and Find Version
108+
// getVersion Launch Help from program path and Find Version
109109
// to capture the output and retrieve version information
110-
func execAndCapture(path string, re *regexp.Regexp) (string, error) {
110+
func getVersion(path string) (string, error) {
111111
cmd := exec.Command(path, "-v")
112112
out, err := cmd.CombinedOutput()
113113
if err != nil {
114114
return "", fmt.Errorf("Failed executing %s: %s", path, err.Error())
115115
}
116+
re := regexp.MustCompile("\\d+(\\.\\d+)+")
116117
return string(re.Find(out)), nil
117118
}
118119

@@ -121,22 +122,83 @@ func CheckEnvironment(dataplaneapiBin, haproxyBin string) error {
121122
var err error
122123
wg := &sync.WaitGroup{}
123124
wg.Add(2)
124-
ensureVersion := func(path, rx, version string) {
125+
ensureVersion := func(path, minVer string) {
125126
defer wg.Done()
126-
r := regexp.MustCompile(rx)
127-
v, e := execAndCapture(path, r)
127+
currVer, e := getVersion(path)
128128
if e != nil {
129129
err = e
130-
} else if strings.Compare(v, "1.2") < 0 {
131-
err = fmt.Errorf("%s version must be > 1.2, but is: %s", path, v)
130+
}
131+
res, e := compareVersion(currVer, minVer)
132+
if e != nil {
133+
err = e
134+
}
135+
if res < 0 {
136+
err = fmt.Errorf("%s version must be > %s, but is: %s", path, minVer, currVer)
132137
}
133138
}
134-
go ensureVersion(haproxyBin, "^HA-Proxy version ([0-9]\\.[0-9]\\.[0-9])", "2.0")
135-
go ensureVersion(dataplaneapiBin, "^HAProxy Data Plane API v([0-9]\\.[0-9]\\.[0-9])", "1.2")
139+
go ensureVersion(haproxyBin, "2.0")
140+
go ensureVersion(dataplaneapiBin, "1.2")
136141

137142
wg.Wait()
138143
if err != nil {
139144
return err
140145
}
141146
return nil
142147
}
148+
149+
// compareVersion compares two semver versions.
150+
// If v1 > v2 returns 1, if v1 < v2 returns -1, if equal returns 0.
151+
// If major versions are not the same, returns -1.
152+
// If an error occurs, returns -1 and error.
153+
func compareVersion(v1, v2 string) (int, error) {
154+
a := strings.Split(v1, ".")
155+
b := strings.Split(v2, ".")
156+
157+
if len(a) < 2 {
158+
return -1, fmt.Errorf("%s arg is not a version string", v1)
159+
}
160+
if len(b) < 2 {
161+
return -1, fmt.Errorf("%s arg is not a version string", v2)
162+
}
163+
164+
if len(a) != len(b) {
165+
switch {
166+
case len(a) > len(b):
167+
for i := len(b); len(b) < len(a); i++ {
168+
b = append(b, " ")
169+
}
170+
break
171+
case len(a) < len(b):
172+
for i := len(a); len(a) < len(b); i++ {
173+
a = append(a, " ")
174+
}
175+
break
176+
}
177+
}
178+
179+
var res int
180+
181+
for i, s := range a {
182+
var ai, bi int
183+
fmt.Sscanf(s, "%d", &ai)
184+
fmt.Sscanf(b[i], "%d", &bi)
185+
186+
if i == 0 {
187+
//major versions should be the same
188+
if ai != bi {
189+
res = -1
190+
break
191+
}
192+
continue
193+
}
194+
if ai > bi {
195+
res = 1
196+
break
197+
}
198+
if ai < bi {
199+
res = -1
200+
break
201+
}
202+
}
203+
return res, nil
204+
}

haproxy/haproxy_cmd/run_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package haproxy_cmd
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
8+
9+
type version struct {
10+
v1 string
11+
v2 string
12+
status int
13+
}
14+
15+
func TestCompareVersion(t *testing.T) {
16+
tests := []*version{
17+
{status: 1, v1: "1.3", v2: "1.2"},
18+
{status: 1, v1: "1.3.1", v2: "1.3"},
19+
{status: 1, v1: "2.0.1", v2: "2.0"},
20+
{status: 0, v1: "2.0", v2: "2.0"},
21+
{status: 0, v1: "2.0.0", v2: "2.0"},
22+
{status: 0, v1: "2.0", v2: "2.0.0"},
23+
{status: -1, v1: "1.2", v2: "1.3"},
24+
{status: -1, v1: "1.3", v2: "1.3.1"},
25+
{status: -1, v1: "2.0", v2: "2.0.1"},
26+
{status: -1, v1: "2", v2: "2.0.1"},
27+
{status: -1, v1: "2.0", v2: "2"},
28+
{status: -1, v1: "3.0", v2: "2.2.2"},
29+
{status: -1, v1: "2.2", v2: "3.0"},
30+
}
31+
for _, test := range tests {
32+
res, _ := compareVersion(test.v1, test.v2)
33+
require.Equal(t, res, test.status)
34+
}
35+
}

0 commit comments

Comments
 (0)