Skip to content

Commit 4974a22

Browse files
committed
TEST: add non regression test for use_backend multiplication
This test addresses #476 Many identical use_backend lines in haproxy.cfg when using haproxy.org/route-acl
1 parent 3445475 commit 4974a22

File tree

3 files changed

+232
-1
lines changed

3 files changed

+232
-1
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
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, softwarehaproxyConfig
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+
package routeacl
16+
17+
import (
18+
"io/ioutil"
19+
"os"
20+
"testing"
21+
22+
c "github.com/haproxytech/kubernetes-ingress/pkg/controller"
23+
"github.com/haproxytech/kubernetes-ingress/pkg/haproxy/env"
24+
"github.com/haproxytech/kubernetes-ingress/pkg/ingress"
25+
"github.com/haproxytech/kubernetes-ingress/pkg/k8s"
26+
"github.com/haproxytech/kubernetes-ingress/pkg/store"
27+
"github.com/haproxytech/kubernetes-ingress/pkg/utils"
28+
"github.com/jessevdk/go-flags"
29+
"github.com/stretchr/testify/suite"
30+
networkingv1 "k8s.io/api/networking/v1"
31+
"k8s.io/apimachinery/pkg/watch"
32+
)
33+
34+
type UseBackendSuite struct {
35+
suite.Suite
36+
test Test
37+
}
38+
39+
func TestUseBackend(t *testing.T) {
40+
suite.Run(t, new(UseBackendSuite))
41+
}
42+
43+
type Test struct {
44+
TempDir string
45+
Controller *c.HAProxyController
46+
}
47+
48+
func (suite *UseBackendSuite) BeforeTest(suiteName, testName string) {
49+
tempDir, err := ioutil.TempDir("", "tnr-"+testName+"-*")
50+
if err != nil {
51+
suite.T().Fatalf("Suite '%s': Test '%s' : error : %s", suiteName, testName, err)
52+
}
53+
suite.test.TempDir = tempDir
54+
suite.T().Logf("temporary configuration dir %s", suite.test.TempDir)
55+
}
56+
57+
var haproxyConfig = `global
58+
daemon
59+
master-worker
60+
pidfile /var/run/haproxy.pid
61+
stats socket /var/run/haproxy-runtime-api.sock level admin expose-fd listeners
62+
default-path config
63+
64+
peers localinstance
65+
peer local 127.0.0.1:10000
66+
67+
frontend https
68+
mode http
69+
bind 127.0.0.1:8080 name v4
70+
http-request set-var(txn.base) base
71+
use_backend %[var(txn.path_match),field(1,.)]
72+
73+
frontend http
74+
mode http
75+
bind 127.0.0.1:4443 name v4
76+
http-request set-var(txn.base) base
77+
use_backend %[var(txn.path_match),field(1,.)]
78+
79+
frontend healthz
80+
bind 127.0.0.1:1042 name v4
81+
mode http
82+
monitor-uri /healthz
83+
option dontlog-normal
84+
85+
frontend stats
86+
mode http
87+
bind *:1024 name stats
88+
stats enable
89+
stats uri /
90+
stats refresh 10s
91+
http-request set-var(txn.base) base
92+
http-request use-service prometheus-exporter if { path /metrics }
93+
`
94+
95+
func (suite *UseBackendSuite) UseBackendFixture() (eventChan chan k8s.SyncDataEvent) {
96+
var osArgs utils.OSArgs
97+
os.Args = []string{os.Args[0], "-e", "-t", "--config-dir=" + suite.test.TempDir}
98+
parser := flags.NewParser(&osArgs, flags.IgnoreUnknown)
99+
_, errParsing := parser.Parse()
100+
if errParsing != nil {
101+
suite.T().Fatal(errParsing)
102+
}
103+
104+
s := store.NewK8sStore(osArgs)
105+
106+
haproxyEnv := env.Env{
107+
Proxies: env.Proxies{
108+
FrontHTTP: "http",
109+
FrontHTTPS: "https",
110+
FrontSSL: "ssl",
111+
BackSSL: "ssl",
112+
},
113+
}
114+
115+
eventChan = make(chan k8s.SyncDataEvent, watch.DefaultChanSize*6)
116+
controller := c.NewBuilder().
117+
WithHaproxyCfgFile([]byte(haproxyConfig)).
118+
WithEventChan(eventChan).
119+
WithStore(s).
120+
WithHaproxyEnv(haproxyEnv).
121+
WithUpdatePublishServiceFunc(func(ingresses []*ingress.Ingress, publishServiceAddresses []string) {}).
122+
WithArgs(osArgs).Build()
123+
124+
go controller.Start()
125+
126+
// Now sending store events for test setup
127+
ns := store.Namespace{Name: "ns", Status: store.ADDED}
128+
eventChan <- k8s.SyncDataEvent{SyncType: k8s.NAMESPACE, Namespace: ns.Name, Data: &ns}
129+
130+
endpoints := &store.Endpoints{
131+
SliceName: "myappservice",
132+
Service: "myappservice",
133+
Namespace: ns.Name,
134+
Ports: map[string]*store.PortEndpoints{
135+
"https": {
136+
Port: int64(3001),
137+
Addresses: map[string]struct{}{"10.244.0.9": {}},
138+
},
139+
},
140+
Status: store.ADDED,
141+
}
142+
143+
eventChan <- k8s.SyncDataEvent{SyncType: k8s.ENDPOINTS, Namespace: endpoints.Namespace, Data: endpoints}
144+
145+
service := &store.Service{
146+
Name: "myappservice",
147+
Namespace: ns.Name,
148+
Annotations: map[string]string{"route-acl": "cookie(staging) -m found"},
149+
Ports: []store.ServicePort{
150+
{Name: "https",
151+
Protocol: "TCP",
152+
Port: 443,
153+
Status: store.ADDED,
154+
},
155+
},
156+
Status: store.ADDED,
157+
}
158+
eventChan <- k8s.SyncDataEvent{SyncType: k8s.SERVICE, Namespace: service.Namespace, Data: service}
159+
160+
prefixPathType := networkingv1.PathTypePrefix
161+
ingress := &store.Ingress{
162+
IngressCore: store.IngressCore{
163+
APIVersion: store.NETWORKINGV1,
164+
Name: "myapping",
165+
Namespace: ns.Name,
166+
Annotations: map[string]string{"haproxy.org/ingress.class": "haproxy"},
167+
Rules: map[string]*store.IngressRule{
168+
"": {
169+
170+
Paths: map[string]*store.IngressPath{
171+
string(prefixPathType) + "-/": {
172+
Path: "/",
173+
PathTypeMatch: string(prefixPathType),
174+
SvcNamespace: service.Namespace,
175+
SvcPortString: "https",
176+
SvcName: service.Name,
177+
},
178+
},
179+
},
180+
},
181+
},
182+
Status: store.ADDED,
183+
}
184+
185+
eventChan <- k8s.SyncDataEvent{SyncType: k8s.INGRESS, Namespace: ingress.Namespace, Data: ingress}
186+
eventChan <- k8s.SyncDataEvent{SyncType: k8s.COMMAND}
187+
// The service is modified by the addition of an annotation.
188+
// It should not duplicate this line in haproxy.cfg:
189+
// use_backend ns_myappservice_https if { path -m beg / } { cookie(staging) -m found }
190+
serviceClone := *service
191+
serviceClone.Status = store.MODIFIED
192+
serviceClone.Annotations["anyannotation"] = "anyvalue"
193+
eventChan <- k8s.SyncDataEvent{SyncType: k8s.SERVICE, Namespace: serviceClone.Namespace, Data: &serviceClone}
194+
controllerHasWorked := make(chan struct{})
195+
eventChan <- k8s.SyncDataEvent{SyncType: k8s.COMMAND, EventProcessed: controllerHasWorked}
196+
<-controllerHasWorked
197+
return
198+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
package routeacl
16+
17+
import (
18+
"io/ioutil"
19+
"path/filepath"
20+
"strings"
21+
)
22+
23+
func (suite *UseBackendSuite) TestUseBackend() {
24+
// This test addresses https://github.com/haproxytech/kubernetes-ingress/issues/476
25+
suite.UseBackendFixture()
26+
suite.Run("Modifying service annotations should not duplicate use_backend clause", func() {
27+
contents, err := ioutil.ReadFile(filepath.Join(suite.test.TempDir, "haproxy.cfg"))
28+
if err != nil {
29+
suite.T().Error(err.Error())
30+
}
31+
c := strings.Count(string(contents), "use_backend ns_myappservice_https if { path -m beg / } { cookie(staging) -m found }")
32+
suite.Exactly(c, 2, "use_backend for route-acl is repeated %d times but expected 2", c)
33+
})
34+
}

pkg/controller/monitor.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ func (c *HAProxyController) SyncData() {
7878
if job.EventProcessed != nil {
7979
close(job.EventProcessed)
8080
}
81-
8281
}
8382
}
8483

0 commit comments

Comments
 (0)