Skip to content

Commit f34adf7

Browse files
fix: avoid duplicate BackendRefs (#104)
* fix: avoid duplicate `BackendRefs` Signed-off-by: Navendu Pottekkat <[email protected]> * fix: check for nil Signed-off-by: Navendu Pottekkat <[email protected]> * fix: change to %d Signed-off-by: Navendu Pottekkat <[email protected]> * fix: use interface and assign nil Signed-off-by: Navendu Pottekkat <[email protected]> * fix: move check after toBackendRef Signed-off-by: Navendu Pottekkat <[email protected]> * fix: move to function Signed-off-by: Navendu Pottekkat <[email protected]> * fix: merge conflict Signed-off-by: Navendu Pottekkat <[email protected]> * fix: apply suggestions from review Signed-off-by: Navendu Pottekkat <[email protected]> * fix: add test case for duplicated backends Signed-off-by: Navendu Pottekkat <[email protected]> * fix: apply suggestions Signed-off-by: Navendu Pottekkat <[email protected]> * fix: enforce group and kind Signed-off-by: Navendu Pottekkat <[email protected]> * revert last commit --------- Signed-off-by: Navendu Pottekkat <[email protected]> Co-authored-by: Lior Lieberman <[email protected]>
1 parent 5623e45 commit f34adf7

File tree

3 files changed

+144
-1
lines changed

3 files changed

+144
-1
lines changed

pkg/i2gw/providers/common/converter.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ func (rg *ingressRuleGroup) configureBackendRef(paths []ingressPath) ([]gatewayv
328328
backendRefs = append(backendRefs, gatewayv1.HTTPBackendRef{BackendRef: *backendRef})
329329
}
330330

331-
return backendRefs, errors
331+
return removeBackendRefsDuplicates(backendRefs), errors
332332
}
333333

334334
func getPathMatchKey(ip ingressPath) pathMatchKey {

pkg/i2gw/providers/common/converter_test.go

+98
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,104 @@ func Test_ingresses2GatewaysAndHttpRoutes(t *testing.T) {
311311
},
312312
expectedErrors: field.ErrorList{},
313313
},
314+
{
315+
name: "duplicated backends",
316+
ingresses: []networkingv1.Ingress{{
317+
ObjectMeta: metav1.ObjectMeta{Name: "duplicate-a", Namespace: "test"},
318+
Spec: networkingv1.IngressSpec{
319+
IngressClassName: PtrTo("example-proxy"),
320+
Rules: []networkingv1.IngressRule{{
321+
Host: "example.com",
322+
IngressRuleValue: networkingv1.IngressRuleValue{
323+
HTTP: &networkingv1.HTTPIngressRuleValue{
324+
Paths: []networkingv1.HTTPIngressPath{{
325+
Path: "/foo",
326+
PathType: &iPrefix,
327+
Backend: networkingv1.IngressBackend{
328+
Service: &networkingv1.IngressServiceBackend{
329+
Name: "example",
330+
Port: networkingv1.ServiceBackendPort{
331+
Number: 3000,
332+
},
333+
},
334+
},
335+
}},
336+
},
337+
},
338+
}},
339+
},
340+
}, {
341+
ObjectMeta: metav1.ObjectMeta{Name: "duplicate-b", Namespace: "test"},
342+
Spec: networkingv1.IngressSpec{
343+
IngressClassName: PtrTo("example-proxy"),
344+
Rules: []networkingv1.IngressRule{{
345+
Host: "example.com",
346+
IngressRuleValue: networkingv1.IngressRuleValue{
347+
HTTP: &networkingv1.HTTPIngressRuleValue{
348+
Paths: []networkingv1.HTTPIngressPath{{
349+
Path: "/foo",
350+
PathType: &iPrefix,
351+
Backend: networkingv1.IngressBackend{
352+
Service: &networkingv1.IngressServiceBackend{
353+
Name: "example",
354+
Port: networkingv1.ServiceBackendPort{
355+
Number: 3000,
356+
},
357+
},
358+
},
359+
}},
360+
},
361+
},
362+
}},
363+
},
364+
}},
365+
expectedGatewayResources: i2gw.GatewayResources{
366+
Gateways: map[types.NamespacedName]gatewayv1.Gateway{
367+
{Namespace: "test", Name: "example-proxy"}: {
368+
ObjectMeta: metav1.ObjectMeta{Name: "example-proxy", Namespace: "test"},
369+
Spec: gatewayv1.GatewaySpec{
370+
GatewayClassName: "example-proxy",
371+
Listeners: []gatewayv1.Listener{{
372+
Name: "example-com-http",
373+
Port: 80,
374+
Protocol: gatewayv1.HTTPProtocolType,
375+
Hostname: PtrTo(gatewayv1.Hostname("example.com")),
376+
}},
377+
},
378+
},
379+
},
380+
HTTPRoutes: map[types.NamespacedName]gatewayv1.HTTPRoute{
381+
{Namespace: "test", Name: "duplicate-a-example-com"}: {
382+
ObjectMeta: metav1.ObjectMeta{Name: "duplicate-a-example-com", Namespace: "test"},
383+
Spec: gatewayv1.HTTPRouteSpec{
384+
CommonRouteSpec: gatewayv1.CommonRouteSpec{
385+
ParentRefs: []gatewayv1.ParentReference{{
386+
Name: "example-proxy",
387+
}},
388+
},
389+
Hostnames: []gatewayv1.Hostname{"example.com"},
390+
Rules: []gatewayv1.HTTPRouteRule{{
391+
Matches: []gatewayv1.HTTPRouteMatch{{
392+
Path: &gatewayv1.HTTPPathMatch{
393+
Type: &gPathPrefix,
394+
Value: PtrTo("/foo"),
395+
},
396+
}},
397+
BackendRefs: []gatewayv1.HTTPBackendRef{{
398+
BackendRef: gatewayv1.BackendRef{
399+
BackendObjectReference: gatewayv1.BackendObjectReference{
400+
Name: "example",
401+
Port: PtrTo(gatewayv1.PortNumber(3000)),
402+
},
403+
},
404+
}},
405+
}},
406+
},
407+
},
408+
},
409+
},
410+
expectedErrors: field.ErrorList{},
411+
},
314412
}
315413

316414
for _, tc := range testCases {

pkg/i2gw/providers/common/utils.go

+45
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,48 @@ func groupIngressPathsByMatchKey(rules []ingressRule) orderedIngressPathsByMatch
155155
func PtrTo[T any](a T) *T {
156156
return &a
157157
}
158+
159+
type uniqueBackendRefsKey struct {
160+
Name gatewayv1.ObjectName
161+
Namespace gatewayv1.Namespace
162+
Port gatewayv1.PortNumber
163+
Group gatewayv1.Group
164+
Kind gatewayv1.Kind
165+
}
166+
167+
// removeBackendRefsDuplicates removes duplicate backendRefs from a list of backendRefs.
168+
func removeBackendRefsDuplicates(backendRefs []gatewayv1.HTTPBackendRef) []gatewayv1.HTTPBackendRef {
169+
var uniqueBackendRefs []gatewayv1.HTTPBackendRef
170+
uniqueKeys := map[uniqueBackendRefsKey]struct{}{}
171+
172+
for _, backendRef := range backendRefs {
173+
var k uniqueBackendRefsKey
174+
175+
group := gatewayv1.Group("")
176+
kind := gatewayv1.Kind("Service")
177+
178+
if backendRef.Group != nil && *backendRef.Group != "core" {
179+
group = *backendRef.Group
180+
}
181+
182+
if backendRef.Kind != nil {
183+
kind = *backendRef.Kind
184+
}
185+
186+
k.Name = backendRef.Name
187+
k.Group = group
188+
k.Kind = kind
189+
190+
if backendRef.Port != nil {
191+
k.Port = *backendRef.Port
192+
}
193+
194+
if _, exists := uniqueKeys[k]; exists {
195+
continue
196+
}
197+
198+
uniqueKeys[k] = struct{}{}
199+
uniqueBackendRefs = append(uniqueBackendRefs, backendRef)
200+
}
201+
return uniqueBackendRefs
202+
}

0 commit comments

Comments
 (0)