Skip to content

Commit ac2b49f

Browse files
committed
TEST: Add a sequential e2e test for map updates
The test ensures that the controller update haproxy maps without reloading haproxy.
1 parent 2f200cf commit ac2b49f

File tree

7 files changed

+214
-12
lines changed

7 files changed

+214
-12
lines changed

deploy/tests/e2e/client.go

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import (
2424
"net"
2525
"net/http"
2626
"os"
27+
"regexp"
28+
"strconv"
2729
"strings"
2830

2931
proxyproto "github.com/pires/go-proxyproto"
@@ -178,25 +180,52 @@ func ProxyProtoConn() (result []byte, err error) {
178180
return ioutil.ReadAll(conn)
179181
}
180182

181-
func GetGlobalHAProxyInfo() (info GlobalHAProxyInfo, err error) {
183+
func runtimeCommand(command string) (result []byte, err error) {
182184
kindURL := os.Getenv("KIND_URL")
183185
if kindURL == "" {
184186
kindURL = "127.0.0.1"
185187
}
186188
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", kindURL, STATS_PORT))
187189
if err != nil {
188-
return info, err
190+
return
189191
}
190-
_, err = conn.Write([]byte("show info\n"))
192+
_, err = conn.Write([]byte(command + "\n"))
191193
if err != nil {
192-
return info, err
194+
return
193195
}
194-
reply := make([]byte, 1024)
195-
_, err = conn.Read(reply)
196+
result = make([]byte, 1024)
197+
_, err = conn.Read(result)
198+
conn.Close()
199+
return
200+
}
201+
202+
func GetHAProxyMapCount(mapName string) (count int, err error) {
203+
var result []byte
204+
result, err = runtimeCommand("show map")
196205
if err != nil {
197-
return info, err
206+
return
198207
}
199-
scanner := bufio.NewScanner(bytes.NewReader(reply))
208+
scanner := bufio.NewScanner(bytes.NewReader(result))
209+
for scanner.Scan() {
210+
line := scanner.Text()
211+
if strings.Contains(line, mapName) {
212+
r := regexp.MustCompile("entry_cnt=[0-9]*")
213+
match := r.FindString(line)
214+
nbr := strings.Split(match, "=")[1]
215+
count, err = strconv.Atoi(nbr)
216+
break
217+
}
218+
}
219+
return
220+
}
221+
222+
func GetGlobalHAProxyInfo() (info GlobalHAProxyInfo, err error) {
223+
var result []byte
224+
result, err = runtimeCommand("show info")
225+
if err != nil {
226+
return
227+
}
228+
scanner := bufio.NewScanner(bytes.NewReader(result))
200229
for scanner.Scan() {
201230
line := scanner.Text()
202231
switch {
@@ -208,6 +237,5 @@ func GetGlobalHAProxyInfo() (info GlobalHAProxyInfo, err error) {
208237
info.Pid = strings.Split(line, ": ")[1]
209238
}
210239
}
211-
conn.Close()
212-
return info, nil
240+
return
213241
}

deploy/tests/e2e/endpoints/http_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ func (suite *EndpointsSuite) Test_HTTP_Reach() {
3636
for i := 0; i < replicas*2; i++ {
3737
func() {
3838
res, cls, err := suite.client.Do()
39-
suite.NoError(err)
39+
if err != nil {
40+
suite.NoError(err)
41+
return
42+
}
4043
defer cls()
4144
if res.StatusCode == 200 {
4245
body, err := ioutil.ReadAll(res.Body)

deploy/tests/e2e/endpoints/tcp_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ func (suite *EndpointsSuite) Test_TCP_Reach() {
2525
for i := 0; i < 4; i++ {
2626
func() {
2727
res, cls, err := suite.client.Do()
28-
suite.NoError(err)
28+
if err != nil {
29+
suite.NoError(err)
30+
return
31+
}
2932
defer cls()
3033
body, err := ioutil.ReadAll(res.Body)
3134
if err != nil {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
kind: Deployment
2+
apiVersion: apps/v1
3+
metadata:
4+
name: http-echo
5+
spec:
6+
replicas: 1
7+
selector:
8+
matchLabels:
9+
app: http-echo
10+
template:
11+
metadata:
12+
labels:
13+
app: http-echo
14+
spec:
15+
containers:
16+
- name: http-echo
17+
image: mo3m3n/http-echo:v1.0.0
18+
args:
19+
ports:
20+
- name: http
21+
containerPort: 8888
22+
protocol: TCP
23+
- name: https
24+
containerPort: 8443
25+
protocol: TCP
26+
---
27+
kind: Service
28+
apiVersion: v1
29+
metadata:
30+
name: http-echo
31+
spec:
32+
ports:
33+
- name: http
34+
protocol: TCP
35+
port: 80
36+
targetPort: http
37+
- name: https
38+
protocol: TCP
39+
port: 443
40+
targetPort: https
41+
selector:
42+
app: http-echo
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
kind: Ingress
3+
apiVersion: networking.k8s.io/v1beta1
4+
metadata:
5+
name: http-echo
6+
annotations:
7+
ingress.class: haproxy
8+
spec:
9+
rules:
10+
- host: {{ .Host }}
11+
http:
12+
paths:
13+
{{- range $path := .Paths}}
14+
- path: /{{$path}}
15+
backend:
16+
serviceName: http-echo
17+
servicePort: http
18+
{{- end}}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2019 HAProxy Technologies LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//go:build e2e_sequential
16+
17+
package mapupdate
18+
19+
import (
20+
"testing"
21+
22+
"github.com/stretchr/testify/suite"
23+
24+
"github.com/haproxytech/kubernetes-ingress/deploy/tests/e2e"
25+
)
26+
27+
type MapUpdateSuite struct {
28+
suite.Suite
29+
test e2e.Test
30+
client *e2e.Client
31+
tmplData tmplData
32+
}
33+
34+
type tmplData struct {
35+
Host string
36+
Paths []string
37+
}
38+
39+
func (suite *MapUpdateSuite) SetupSuite() {
40+
var err error
41+
suite.test, err = e2e.NewTest()
42+
suite.NoError(err)
43+
suite.tmplData = tmplData{Host: suite.test.GetNS() + ".test", Paths: []string{""}}
44+
suite.client, err = e2e.NewHTTPClient(suite.tmplData.Host)
45+
suite.NoError(err)
46+
suite.NoError(suite.test.Apply("config/deploy.yaml", suite.test.GetNS(), nil))
47+
suite.NoError(suite.test.Apply("config/ingress.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
48+
suite.Require().Eventually(func() bool {
49+
r, cls, err := suite.client.Do()
50+
if err != nil {
51+
suite.T().Log(err)
52+
return false
53+
}
54+
defer cls()
55+
return r.StatusCode == 200
56+
}, e2e.WaitDuration, e2e.TickDuration)
57+
}
58+
59+
func (suite *MapUpdateSuite) TearDownSuite() {
60+
suite.test.TearDown()
61+
}
62+
63+
func TestMapUpdateSuite(t *testing.T) {
64+
suite.Run(t, new(MapUpdateSuite))
65+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2019 HAProxy Technologies LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//go:build e2e_sequential
16+
17+
package mapupdate
18+
19+
import (
20+
"strconv"
21+
22+
"github.com/haproxytech/kubernetes-ingress/deploy/tests/e2e"
23+
)
24+
25+
func (suite *MapUpdateSuite) Test_Update() {
26+
suite.Run("Update", func() {
27+
suite.tmplData.Paths = make([]string, 0, 700)
28+
for i := 0; i < 700; i++ {
29+
suite.tmplData.Paths = append(suite.tmplData.Paths, strconv.Itoa(i))
30+
}
31+
oldInfo, err := e2e.GetGlobalHAProxyInfo()
32+
suite.NoError(err)
33+
suite.NoError(suite.test.Apply("config/ingress.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
34+
suite.Require().Eventually(func() bool {
35+
newInfo, err := e2e.GetGlobalHAProxyInfo()
36+
suite.NoError(err)
37+
count, err := e2e.GetHAProxyMapCount("path-prefix")
38+
suite.NoError(err)
39+
suite.T().Log(count)
40+
return oldInfo.Pid == newInfo.Pid && count == 700
41+
}, e2e.WaitDuration, e2e.TickDuration)
42+
})
43+
}

0 commit comments

Comments
 (0)