Skip to content

Commit

Permalink
fix: multiple reference grants in same namespace (envoyproxy#4008)
Browse files Browse the repository at this point in the history
* fix: multiple reference grants in same namespace

Signed-off-by: Ardika Bagus <me@ardikabs.com>

* test: add e2e test

Signed-off-by: Ardika Bagus <me@ardikabs.com>

* chore: wrong service port

Signed-off-by: Ardika Bagus <me@ardikabs.com>

---------

Signed-off-by: Ardika Bagus <me@ardikabs.com>
  • Loading branch information
ardikabs authored Aug 8, 2024
1 parent 975b1e8 commit b82f4b2
Show file tree
Hide file tree
Showing 4 changed files with 346 additions and 5 deletions.
32 changes: 27 additions & 5 deletions internal/provider/kubernetes/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -769,13 +769,35 @@ func (r *gatewayAPIReconciler) findReferenceGrant(ctx context.Context, from, to
}

for _, refGrant := range refGrants {
if refGrant.Namespace == to.namespace {
for _, src := range refGrant.Spec.From {
if src.Kind == gwapiv1a2.Kind(from.kind) && string(src.Namespace) == from.namespace {
return &refGrant, nil
}
if refGrant.Namespace != to.namespace {
continue
}

var fromAllowed bool
for _, refGrantFrom := range refGrant.Spec.From {
if string(refGrantFrom.Kind) == from.kind && string(refGrantFrom.Namespace) == from.namespace {
fromAllowed = true
break
}
}

if !fromAllowed {
continue
}

var toAllowed bool
for _, refGrantTo := range refGrant.Spec.To {
if string(refGrantTo.Kind) == to.kind && (refGrantTo.Name == nil || *refGrantTo.Name == "" || string(*refGrantTo.Name) == to.name) {
toAllowed = true
break
}
}

if !toAllowed {
continue
}

return &refGrant, nil
}

// No ReferenceGrant found.
Expand Down
148 changes: 148 additions & 0 deletions test/e2e/testdata/multi-referencegrants-same-namespace-services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
apiVersion: v1
kind: Namespace
metadata:
name: multireferencegrants-ns
---
apiVersion: v1
kind: Service
metadata:
name: app-backend-v1
namespace: multireferencegrants-ns
spec:
selector:
app: app-backend-v1
ports:
- protocol: TCP
port: 8080
targetPort: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-backend-v1
namespace: multireferencegrants-ns
labels:
app: app-backend-v1
spec:
replicas: 1
selector:
matchLabels:
app: app-backend-v1
template:
metadata:
labels:
app: app-backend-v1
spec:
containers:
- name: app-backend-v1
image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: SERVICE_NAME
value: app-backend-v1
resources:
requests:
cpu: 10m
---
apiVersion: v1
kind: Service
metadata:
name: app-backend-v2
namespace: multireferencegrants-ns
spec:
selector:
app: app-backend-v2
ports:
- protocol: TCP
port: 8080
targetPort: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-backend-v2
namespace: multireferencegrants-ns
labels:
app: app-backend-v2
spec:
replicas: 1
selector:
matchLabels:
app: app-backend-v2
template:
metadata:
labels:
app: app-backend-v2
spec:
containers:
- name: app-backend-v2
image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: SERVICE_NAME
value: app-backend-v2
resources:
requests:
cpu: 10m
---
apiVersion: v1
kind: Service
metadata:
name: app-backend-v3
namespace: multireferencegrants-ns
spec:
selector:
app: app-backend-v3
ports:
- protocol: TCP
port: 8080
targetPort: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-backend-v3
namespace: multireferencegrants-ns
labels:
app: app-backend-v3
spec:
replicas: 1
selector:
matchLabels:
app: app-backend-v3
template:
metadata:
labels:
app: app-backend-v3
spec:
containers:
- name: app-backend-v3
image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: SERVICE_NAME
value: app-backend-v3
resources:
requests:
cpu: 10m
92 changes: 92 additions & 0 deletions test/e2e/testdata/multi-referencegrants-same-namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: multi-referencegrant-same-namespace
namespace: gateway-conformance-infra
spec:
hostnames:
- multireferencegrant.local
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: same-namespace
namespace: gateway-conformance-infra
rules:
- backendRefs:
- group: ""
kind: Service
name: app-backend-v3
namespace: multireferencegrants-ns
port: 8080
weight: 1
matches:
- path:
type: PathPrefix
value: /v3/echo
- backendRefs:
- group: ""
kind: Service
name: app-backend-v2
namespace: multireferencegrants-ns
port: 8080
weight: 1
matches:
- path:
type: PathPrefix
value: /v2/echo
- backendRefs:
- group: ""
kind: Service
name: app-backend-v1
namespace: multireferencegrants-ns
port: 8080
weight: 1
matches:
- path:
type: PathPrefix
value: /v1/echo
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: app-backend-v1-rg
namespace: multireferencegrants-ns
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: gateway-conformance-infra
to:
- group: ""
kind: Service
name: app-backend-v1
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: app-backend-v2-rg
namespace: multireferencegrants-ns
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: gateway-conformance-infra
to:
- group: ""
kind: Service
name: app-backend-v2
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: app-backend-v3-rg
namespace: multireferencegrants-ns
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: gateway-conformance-infra
to:
- group: ""
kind: Service
name: app-backend-v3
79 changes: 79 additions & 0 deletions test/e2e/tests/referencegrants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright Envoy Gateway Authors
// SPDX-License-Identifier: Apache-2.0
// The full text of the Apache license is available in the LICENSE file at
// the root of the repo.

//go:build e2e
// +build e2e

package tests

import (
"testing"

"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/gateway-api/conformance/utils/http"
"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
"sigs.k8s.io/gateway-api/conformance/utils/suite"
)

func init() {
ConformanceTests = append(ConformanceTests, MultiReferenceGrantsSameNamespaceTest)
}

var MultiReferenceGrantsSameNamespaceTest = suite.ConformanceTest{
ShortName: "MultiReferenceGrantsSameNamespace",
Description: "Test for multiple reference grants in the same namespace",
Manifests: []string{"testdata/multi-referencegrants-same-namespace-services.yaml", "testdata/multi-referencegrants-same-namespace.yaml"},
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
resourceNS := "gateway-conformance-infra"
routeNN := types.NamespacedName{Name: "multi-referencegrant-same-namespace", Namespace: resourceNS}
gwNN := types.NamespacedName{Name: "same-namespace", Namespace: resourceNS}
gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)

targetHost := "multireferencegrant.local"
targetNS := "multireferencegrants-ns"
testcases := []http.ExpectedResponse{
{
Request: http.Request{
Host: targetHost,
Path: "/v1/echo",
},
Response: http.Response{
StatusCode: 200,
},
Backend: "app-backend-v1",
Namespace: targetNS,
},
{
Request: http.Request{
Host: targetHost,
Path: "/v2/echo",
},
Response: http.Response{
StatusCode: 200,
},
Backend: "app-backend-v2",
Namespace: targetNS,
},
{
Request: http.Request{
Host: targetHost,
Path: "/v3/echo",
},
Response: http.Response{
StatusCode: 200,
},
Backend: "app-backend-v3",
Namespace: targetNS,
},
}

for i, tc := range testcases {
t.Run(tc.GetTestCaseName(i), func(t *testing.T) {
t.Parallel()
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc)
})
}
},
}

0 comments on commit b82f4b2

Please sign in to comment.