Skip to content

Commit b82f4b2

Browse files
authored
fix: multiple reference grants in same namespace (#4008)
* fix: multiple reference grants in same namespace Signed-off-by: Ardika Bagus <[email protected]> * test: add e2e test Signed-off-by: Ardika Bagus <[email protected]> * chore: wrong service port Signed-off-by: Ardika Bagus <[email protected]> --------- Signed-off-by: Ardika Bagus <[email protected]>
1 parent 975b1e8 commit b82f4b2

File tree

4 files changed

+346
-5
lines changed

4 files changed

+346
-5
lines changed

internal/provider/kubernetes/controller.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -769,13 +769,35 @@ func (r *gatewayAPIReconciler) findReferenceGrant(ctx context.Context, from, to
769769
}
770770

771771
for _, refGrant := range refGrants {
772-
if refGrant.Namespace == to.namespace {
773-
for _, src := range refGrant.Spec.From {
774-
if src.Kind == gwapiv1a2.Kind(from.kind) && string(src.Namespace) == from.namespace {
775-
return &refGrant, nil
776-
}
772+
if refGrant.Namespace != to.namespace {
773+
continue
774+
}
775+
776+
var fromAllowed bool
777+
for _, refGrantFrom := range refGrant.Spec.From {
778+
if string(refGrantFrom.Kind) == from.kind && string(refGrantFrom.Namespace) == from.namespace {
779+
fromAllowed = true
780+
break
777781
}
778782
}
783+
784+
if !fromAllowed {
785+
continue
786+
}
787+
788+
var toAllowed bool
789+
for _, refGrantTo := range refGrant.Spec.To {
790+
if string(refGrantTo.Kind) == to.kind && (refGrantTo.Name == nil || *refGrantTo.Name == "" || string(*refGrantTo.Name) == to.name) {
791+
toAllowed = true
792+
break
793+
}
794+
}
795+
796+
if !toAllowed {
797+
continue
798+
}
799+
800+
return &refGrant, nil
779801
}
780802

781803
// No ReferenceGrant found.
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: multireferencegrants-ns
5+
---
6+
apiVersion: v1
7+
kind: Service
8+
metadata:
9+
name: app-backend-v1
10+
namespace: multireferencegrants-ns
11+
spec:
12+
selector:
13+
app: app-backend-v1
14+
ports:
15+
- protocol: TCP
16+
port: 8080
17+
targetPort: 3000
18+
---
19+
apiVersion: apps/v1
20+
kind: Deployment
21+
metadata:
22+
name: app-backend-v1
23+
namespace: multireferencegrants-ns
24+
labels:
25+
app: app-backend-v1
26+
spec:
27+
replicas: 1
28+
selector:
29+
matchLabels:
30+
app: app-backend-v1
31+
template:
32+
metadata:
33+
labels:
34+
app: app-backend-v1
35+
spec:
36+
containers:
37+
- name: app-backend-v1
38+
image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
39+
env:
40+
- name: POD_NAME
41+
valueFrom:
42+
fieldRef:
43+
fieldPath: metadata.name
44+
- name: NAMESPACE
45+
valueFrom:
46+
fieldRef:
47+
fieldPath: metadata.namespace
48+
- name: SERVICE_NAME
49+
value: app-backend-v1
50+
resources:
51+
requests:
52+
cpu: 10m
53+
---
54+
apiVersion: v1
55+
kind: Service
56+
metadata:
57+
name: app-backend-v2
58+
namespace: multireferencegrants-ns
59+
spec:
60+
selector:
61+
app: app-backend-v2
62+
ports:
63+
- protocol: TCP
64+
port: 8080
65+
targetPort: 3000
66+
---
67+
apiVersion: apps/v1
68+
kind: Deployment
69+
metadata:
70+
name: app-backend-v2
71+
namespace: multireferencegrants-ns
72+
labels:
73+
app: app-backend-v2
74+
spec:
75+
replicas: 1
76+
selector:
77+
matchLabels:
78+
app: app-backend-v2
79+
template:
80+
metadata:
81+
labels:
82+
app: app-backend-v2
83+
spec:
84+
containers:
85+
- name: app-backend-v2
86+
image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
87+
env:
88+
- name: POD_NAME
89+
valueFrom:
90+
fieldRef:
91+
fieldPath: metadata.name
92+
- name: NAMESPACE
93+
valueFrom:
94+
fieldRef:
95+
fieldPath: metadata.namespace
96+
- name: SERVICE_NAME
97+
value: app-backend-v2
98+
resources:
99+
requests:
100+
cpu: 10m
101+
---
102+
apiVersion: v1
103+
kind: Service
104+
metadata:
105+
name: app-backend-v3
106+
namespace: multireferencegrants-ns
107+
spec:
108+
selector:
109+
app: app-backend-v3
110+
ports:
111+
- protocol: TCP
112+
port: 8080
113+
targetPort: 3000
114+
---
115+
apiVersion: apps/v1
116+
kind: Deployment
117+
metadata:
118+
name: app-backend-v3
119+
namespace: multireferencegrants-ns
120+
labels:
121+
app: app-backend-v3
122+
spec:
123+
replicas: 1
124+
selector:
125+
matchLabels:
126+
app: app-backend-v3
127+
template:
128+
metadata:
129+
labels:
130+
app: app-backend-v3
131+
spec:
132+
containers:
133+
- name: app-backend-v3
134+
image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
135+
env:
136+
- name: POD_NAME
137+
valueFrom:
138+
fieldRef:
139+
fieldPath: metadata.name
140+
- name: NAMESPACE
141+
valueFrom:
142+
fieldRef:
143+
fieldPath: metadata.namespace
144+
- name: SERVICE_NAME
145+
value: app-backend-v3
146+
resources:
147+
requests:
148+
cpu: 10m
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
apiVersion: gateway.networking.k8s.io/v1beta1
2+
kind: HTTPRoute
3+
metadata:
4+
name: multi-referencegrant-same-namespace
5+
namespace: gateway-conformance-infra
6+
spec:
7+
hostnames:
8+
- multireferencegrant.local
9+
parentRefs:
10+
- group: gateway.networking.k8s.io
11+
kind: Gateway
12+
name: same-namespace
13+
namespace: gateway-conformance-infra
14+
rules:
15+
- backendRefs:
16+
- group: ""
17+
kind: Service
18+
name: app-backend-v3
19+
namespace: multireferencegrants-ns
20+
port: 8080
21+
weight: 1
22+
matches:
23+
- path:
24+
type: PathPrefix
25+
value: /v3/echo
26+
- backendRefs:
27+
- group: ""
28+
kind: Service
29+
name: app-backend-v2
30+
namespace: multireferencegrants-ns
31+
port: 8080
32+
weight: 1
33+
matches:
34+
- path:
35+
type: PathPrefix
36+
value: /v2/echo
37+
- backendRefs:
38+
- group: ""
39+
kind: Service
40+
name: app-backend-v1
41+
namespace: multireferencegrants-ns
42+
port: 8080
43+
weight: 1
44+
matches:
45+
- path:
46+
type: PathPrefix
47+
value: /v1/echo
48+
---
49+
apiVersion: gateway.networking.k8s.io/v1beta1
50+
kind: ReferenceGrant
51+
metadata:
52+
name: app-backend-v1-rg
53+
namespace: multireferencegrants-ns
54+
spec:
55+
from:
56+
- group: gateway.networking.k8s.io
57+
kind: HTTPRoute
58+
namespace: gateway-conformance-infra
59+
to:
60+
- group: ""
61+
kind: Service
62+
name: app-backend-v1
63+
---
64+
apiVersion: gateway.networking.k8s.io/v1beta1
65+
kind: ReferenceGrant
66+
metadata:
67+
name: app-backend-v2-rg
68+
namespace: multireferencegrants-ns
69+
spec:
70+
from:
71+
- group: gateway.networking.k8s.io
72+
kind: HTTPRoute
73+
namespace: gateway-conformance-infra
74+
to:
75+
- group: ""
76+
kind: Service
77+
name: app-backend-v2
78+
---
79+
apiVersion: gateway.networking.k8s.io/v1beta1
80+
kind: ReferenceGrant
81+
metadata:
82+
name: app-backend-v3-rg
83+
namespace: multireferencegrants-ns
84+
spec:
85+
from:
86+
- group: gateway.networking.k8s.io
87+
kind: HTTPRoute
88+
namespace: gateway-conformance-infra
89+
to:
90+
- group: ""
91+
kind: Service
92+
name: app-backend-v3

test/e2e/tests/referencegrants.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright Envoy Gateway Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
// The full text of the Apache license is available in the LICENSE file at
4+
// the root of the repo.
5+
6+
//go:build e2e
7+
// +build e2e
8+
9+
package tests
10+
11+
import (
12+
"testing"
13+
14+
"k8s.io/apimachinery/pkg/types"
15+
"sigs.k8s.io/gateway-api/conformance/utils/http"
16+
"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
17+
"sigs.k8s.io/gateway-api/conformance/utils/suite"
18+
)
19+
20+
func init() {
21+
ConformanceTests = append(ConformanceTests, MultiReferenceGrantsSameNamespaceTest)
22+
}
23+
24+
var MultiReferenceGrantsSameNamespaceTest = suite.ConformanceTest{
25+
ShortName: "MultiReferenceGrantsSameNamespace",
26+
Description: "Test for multiple reference grants in the same namespace",
27+
Manifests: []string{"testdata/multi-referencegrants-same-namespace-services.yaml", "testdata/multi-referencegrants-same-namespace.yaml"},
28+
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
29+
resourceNS := "gateway-conformance-infra"
30+
routeNN := types.NamespacedName{Name: "multi-referencegrant-same-namespace", Namespace: resourceNS}
31+
gwNN := types.NamespacedName{Name: "same-namespace", Namespace: resourceNS}
32+
gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
33+
34+
targetHost := "multireferencegrant.local"
35+
targetNS := "multireferencegrants-ns"
36+
testcases := []http.ExpectedResponse{
37+
{
38+
Request: http.Request{
39+
Host: targetHost,
40+
Path: "/v1/echo",
41+
},
42+
Response: http.Response{
43+
StatusCode: 200,
44+
},
45+
Backend: "app-backend-v1",
46+
Namespace: targetNS,
47+
},
48+
{
49+
Request: http.Request{
50+
Host: targetHost,
51+
Path: "/v2/echo",
52+
},
53+
Response: http.Response{
54+
StatusCode: 200,
55+
},
56+
Backend: "app-backend-v2",
57+
Namespace: targetNS,
58+
},
59+
{
60+
Request: http.Request{
61+
Host: targetHost,
62+
Path: "/v3/echo",
63+
},
64+
Response: http.Response{
65+
StatusCode: 200,
66+
},
67+
Backend: "app-backend-v3",
68+
Namespace: targetNS,
69+
},
70+
}
71+
72+
for i, tc := range testcases {
73+
t.Run(tc.GetTestCaseName(i), func(t *testing.T) {
74+
t.Parallel()
75+
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc)
76+
})
77+
}
78+
},
79+
}

0 commit comments

Comments
 (0)