Skip to content

Commit

Permalink
Adds ReferenceGrant Support for TCPRoute
Browse files Browse the repository at this point in the history
Signed-off-by: Daneyon Hansen <[email protected]>
  • Loading branch information
danehans committed Dec 2, 2024
1 parent 8b52691 commit 1a1430b
Show file tree
Hide file tree
Showing 19 changed files with 680 additions and 38 deletions.
6 changes: 6 additions & 0 deletions changelog/v1.18.0-rc3/issue_7309.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
changelog:
- type: FIX
issueLink: https://github.com/solo-io/solo-projects/issues/7309
resolvesIssue: true
description: >-
Adds ReferenceGRant support for the TCPRoute type.
7 changes: 5 additions & 2 deletions pkg/schemes/scheme.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,14 @@ func DefaultScheme() *runtime.Scheme {
return s
}

// TestingScheme unconditionally includes the default scheme and the gwv1a2 scheme (which includes TCPRoute).
// TestingScheme unconditionally includes the default and required Gateway API schemes.
func TestingScheme() *runtime.Scheme {
s := DefaultScheme()
if err := gwv1a2.Install(s); err != nil {
panic(fmt.Sprintf("Failed to install gwv1a2 scheme: %v", err))
panic(fmt.Sprintf("Failed to install gateway v1alpha2 scheme: %v", err))
}
if err := gwv1b1.Install(s); err != nil {
panic(fmt.Sprintf("Failed to install gateway v1beta1 scheme: %v", err))
}
return s
}
2 changes: 1 addition & 1 deletion projects/gateway2/query/backendmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func backendToRefKey(ref gwv1.BackendObjectReference) backendRefKey {
const delim = "~"
return backendRefKey(
string(ptrOrDefault(ref.Group, "")) + delim +
string(ptrOrDefault(ref.Kind, "")) + delim +
string(ptrOrDefault(ref.Kind, "Service")) + delim +
string(ref.Name) + delim +
string(ptrOrDefault(ref.Namespace, "")),
)
Expand Down
116 changes: 116 additions & 0 deletions projects/gateway2/query/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,98 @@ var _ = Describe("Query", func() {
Expect(routes.ListenerResults["foo-tcp"].Routes).To(HaveLen(1))
Expect(routes.ListenerResults["bar"].Routes).To(BeEmpty())
})

It("should get service from same namespace with TCPRoute", func() {
fakeClient := fake.NewFakeClient(svc("default"))

gq := query.NewData(fakeClient, scheme)
ref := &apiv1.BackendObjectReference{
Name: "foo",
}

fromTCPRoute := tcpRoute("test-tcp-route", "default")

backend, err := gq.GetBackendForRef(context.Background(), tofrom(fromTCPRoute), ref)
Expect(err).NotTo(HaveOccurred())
Expect(backend).NotTo(BeNil())
Expect(backend.GetName()).To(Equal("foo"))
Expect(backend.GetNamespace()).To(Equal("default"))
})

It("should get service from different ns with TCPRoute if we have a ref grant", func() {
rg := refGrantForTCPRoute()
fakeClient := builder.WithObjects(svc("default2"), rg).Build()
gq := query.NewData(fakeClient, scheme)
ref := &apiv1.BackendObjectReference{
Name: "foo",
Namespace: nsptr("default2"),
}

fromTCPRoute := tcpRoute("test-tcp-route", "default")

backend, err := gq.GetBackendForRef(context.Background(), tofrom(fromTCPRoute), ref)
Expect(err).NotTo(HaveOccurred())
Expect(backend).NotTo(BeNil())
Expect(backend.GetName()).To(Equal("foo"))
Expect(backend.GetNamespace()).To(Equal("default2"))
})

It("should fail getting a service from different ns with TCPRoute when no ref grant", func() {
fakeClient := builder.WithObjects(svc("default2")).Build()
gq := query.NewData(fakeClient, scheme)
ref := &apiv1.BackendObjectReference{
Name: "foo",
Namespace: nsptr("default2"),
}

fromTCPRoute := tcpRoute("test-tcp-route", "default")

backend, err := gq.GetBackendForRef(context.Background(), tofrom(fromTCPRoute), ref)
Expect(err).To(MatchError(query.ErrMissingReferenceGrant))
Expect(backend).To(BeNil())
})

It("should fail getting a service with TCPRoute when ref grant has wrong from", func() {
rg := &apiv1beta1.ReferenceGrant{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default2",
Name: "foo",
},
Spec: apiv1beta1.ReferenceGrantSpec{
From: []apiv1beta1.ReferenceGrantFrom{
{
Group: apiv1.Group(apiv1a2.GroupName),
Kind: apiv1.Kind("NotTCPRoute"),
Namespace: apiv1.Namespace("default"),
},
{
Group: apiv1.Group(apiv1a2.GroupName),
Kind: apiv1.Kind("TCPRoute"),
Namespace: apiv1.Namespace("default2"),
},
},
To: []apiv1beta1.ReferenceGrantTo{
{
Group: apiv1.Group("core"),
Kind: apiv1.Kind("Service"),
},
},
},
}
fakeClient := builder.WithObjects(rg, svc("default2")).Build()

gq := query.NewData(fakeClient, scheme)
ref := &apiv1.BackendObjectReference{
Name: "foo",
Namespace: nsptr("default2"),
}

fromTCPRoute := tcpRoute("test-tcp-route", "default")

backend, err := gq.GetBackendForRef(context.Background(), tofrom(fromTCPRoute), ref)
Expect(err).To(MatchError(query.ErrMissingReferenceGrant))
Expect(backend).To(BeNil())
})
})
})

Expand Down Expand Up @@ -829,3 +921,27 @@ func nsptr(s string) *apiv1.Namespace {
var ns apiv1.Namespace = apiv1.Namespace(s)
return &ns
}

func refGrantForTCPRoute() *apiv1beta1.ReferenceGrant {
return &apiv1beta1.ReferenceGrant{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default2",
Name: "foo",
},
Spec: apiv1beta1.ReferenceGrantSpec{
From: []apiv1beta1.ReferenceGrantFrom{
{
Group: apiv1.Group(apiv1a2.GroupName),
Kind: apiv1.Kind("TCPRoute"),
Namespace: apiv1.Namespace("default"),
},
},
To: []apiv1beta1.ReferenceGrantTo{
{
Group: apiv1.Group("core"),
Kind: apiv1.Kind("Service"),
},
},
},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,9 @@ func (ml *MergedListeners) AppendTcpListener(
})
}

// buildTcpHost builds a Gateway API TcpHost from backend references.
// buildTcpHost builds a Gloo TcpHost from the provided parameters.
func buildTcpHost(
ctx context.Context,
routeInfo *query.RouteInfo,
tRoute *gwv1a2.TCPRoute,
parentRefReporters []reports.ParentRefReporter,
tcpRouteName string,
defaultPort gwv1.PortNumber,
Expand All @@ -264,6 +262,7 @@ func buildTcpHost(

var weightedDestinations []*v1.WeightedDestination
resolvedRefs := true
hasValidBackend := false

for _, ref := range backendRefs {
// Try to get the backend object
Expand All @@ -276,6 +275,7 @@ func buildTcpHost(
}
continue
}
hasValidBackend = true

// Process the backend object
var destination *v1.Destination
Expand Down Expand Up @@ -314,15 +314,32 @@ func buildTcpHost(
})
}

if resolvedRefs {
// Set ResolvedRefs condition to True
if !hasValidBackend {
// No valid backends, do not create TcpHost
return nil
}

// Handle ResolvedRefs condition
if !resolvedRefs {
// Set ResolvedRefs condition to False
for _, parentRefReporter := range parentRefReporters {
parentRefReporter.SetCondition(reports.RouteCondition{
Type: gwv1.RouteConditionResolvedRefs,
Status: metav1.ConditionTrue,
Reason: gwv1.RouteReasonResolvedRefs,
Status: metav1.ConditionFalse,
Reason: gwv1.RouteReasonRefNotPermitted,
})
}
// Do not create TcpHost
return nil
}

// Set ResolvedRefs condition to True
for _, parentRefReporter := range parentRefReporters {
parentRefReporter.SetCondition(reports.RouteCondition{
Type: gwv1.RouteConditionResolvedRefs,
Status: metav1.ConditionTrue,
Reason: gwv1.RouteReasonResolvedRefs,
})
}

if len(weightedDestinations) == 0 {
Expand All @@ -335,6 +352,7 @@ func buildTcpHost(
},
}
} else {
// Multiple destinations, set up a Multi destination
tcpHost.Destination = &v1.TcpHost_TcpAction{
Destination: &v1.TcpHost_TcpAction_Multi{
Multi: &v1.MultiDestination{
Expand Down Expand Up @@ -459,10 +477,11 @@ func (ml *MergedListener) TranslateListener(

// Translate TCP listeners (if any exist)
for _, tfc := range ml.TcpFilterChains {
tcpListener := tfc.translateTcpFilterChain(ctx, ml.listener, pluginRegistry, reporter)
matchedTcpListeners = append(matchedTcpListeners, &v1.MatchedTcpListener{
TcpListener: tcpListener,
})
if tcpListener := tfc.translateTcpFilterChain(ml.listener, reporter); tcpListener != nil {
matchedTcpListeners = append(matchedTcpListeners, &v1.MatchedTcpListener{
TcpListener: tcpListener,
})
}
}

// Create and return the listener with all filter chains and TCP listeners
Expand Down Expand Up @@ -497,12 +516,7 @@ type tcpFilterChainParent struct {
routesWithHosts []*query.RouteInfo
}

func (tc *tcpFilterChain) translateTcpFilterChain(
ctx context.Context,
listener gwv1.Listener,
pluginRegistry registry.PluginRegistry,
reporter reports.Reporter,
) *v1.TcpListener {
func (tc *tcpFilterChain) translateTcpFilterChain(listener gwv1.Listener, reporter reports.Reporter) *v1.TcpListener {
var tcpHosts []*v1.TcpHost
for _, parent := range tc.parents {
for _, r := range parent.routesWithHosts {
Expand All @@ -526,14 +540,19 @@ func (tc *tcpFilterChain) translateTcpFilterChain(
for i, rule := range tRoute.Spec.Rules {
// Ensure unique names by appending the rule index to the TCPRoute name
tcpHostName := fmt.Sprintf("%s-rule-%d", tRoute.Name, i)
tcpHost := buildTcpHost(ctx, r, tRoute, parentRefReporters, tcpHostName, listener.Port, rule.BackendRefs)
tcpHost := buildTcpHost(r, parentRefReporters, tcpHostName, listener.Port, rule.BackendRefs)
if tcpHost != nil {
tcpHosts = append(tcpHosts, tcpHost)
}
}
}
}

// Avoid creating a TcpListener if there are no TcpHosts
if len(tcpHosts) == 0 {
return nil
}

return &v1.TcpListener{
TcpHosts: tcpHosts,
}
Expand Down
Loading

0 comments on commit 1a1430b

Please sign in to comment.