Skip to content

Commit

Permalink
Cleanup Gateway API Route Destination Logic
Browse files Browse the repository at this point in the history
* Use common `processRouteDestinations` functions
for all xRoute

* Precursor to envoyproxy#1256

Signed-off-by: Arko Dasgupta <[email protected]>
  • Loading branch information
arkodg committed Jun 1, 2023
1 parent 22bd06b commit 4330d99
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 75 deletions.
12 changes: 6 additions & 6 deletions internal/gatewayapi/contexts.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ type RouteContext interface {

// GetRouteType returns the Kind of the Route object, HTTPRoute,
// TLSRoute, TCPRoute, UDPRoute etc.
GetRouteType() string
GetRouteType() v1beta1.Kind

// GetRouteStatus returns the RouteStatus object associated with the Route.
GetRouteStatus() *v1beta1.RouteStatus
Expand Down Expand Up @@ -188,7 +188,7 @@ type HTTPRouteContext struct {
parentRefs map[v1beta1.ParentReference]*RouteParentContext
}

func (h *HTTPRouteContext) GetRouteType() string {
func (h *HTTPRouteContext) GetRouteType() v1beta1.Kind {
return KindHTTPRoute
}

Expand Down Expand Up @@ -265,7 +265,7 @@ type GRPCRouteContext struct {
parentRefs map[v1beta1.ParentReference]*RouteParentContext
}

func (g *GRPCRouteContext) GetRouteType() string {
func (g *GRPCRouteContext) GetRouteType() v1beta1.Kind {
return KindGRPCRoute
}

Expand Down Expand Up @@ -352,7 +352,7 @@ type TLSRouteContext struct {
parentRefs map[v1beta1.ParentReference]*RouteParentContext
}

func (t *TLSRouteContext) GetRouteType() string {
func (t *TLSRouteContext) GetRouteType() v1beta1.Kind {
return KindTLSRoute
}

Expand Down Expand Up @@ -443,7 +443,7 @@ type UDPRouteContext struct {
parentRefs map[v1beta1.ParentReference]*RouteParentContext
}

func (u *UDPRouteContext) GetRouteType() string {
func (u *UDPRouteContext) GetRouteType() v1beta1.Kind {
return KindUDPRoute
}

Expand Down Expand Up @@ -530,7 +530,7 @@ type TCPRouteContext struct {
parentRefs map[v1beta1.ParentReference]*RouteParentContext
}

func (t *TCPRouteContext) GetRouteType() string {
func (t *TCPRouteContext) GetRouteType() v1beta1.Kind {
return KindTCPRoute
}

Expand Down
25 changes: 14 additions & 11 deletions internal/gatewayapi/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -821,20 +821,23 @@ func (t *Translator) processRequestMirrorFilter(
return
}

mirrorDest, _ := t.processRouteDestination(mirrorBackendRef, filterContext.ParentRef, filterContext.Route, resources)

// If we're already mirroring requests to this backend then there is no need to configure it twice
for _, mirror := range filterContext.Mirrors {
if mirror != nil {
if mirror.Host == mirrorDest.Host &&
mirror.Port == mirrorDest.Port {
return
mirrorDests, _ := t.processRouteDestinations(mirrorBackendRef, filterContext.ParentRef, filterContext.Route, resources)

// Only add missing mirror destinations
for _, mirrorDest := range mirrorDests {
var found bool
for _, mirror := range filterContext.Mirrors {
if mirror != nil {
if mirror.Host == mirrorDest.Host && mirror.Port == mirrorDest.Port {
found = true
}
}
}
}

filterContext.Mirrors = append(filterContext.Mirrors, mirrorDest)

if !found {
filterContext.Mirrors = append(filterContext.Mirrors, mirrorDest)
}
}
}

func (t *Translator) processUnresolvedHTTPFilter(errMsg string, filterContext *HTTPFiltersContext) {
Expand Down
93 changes: 35 additions & 58 deletions internal/gatewayapi/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,13 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
var ruleRoutes = t.processHTTPRouteRule(httpRoute, ruleIdx, httpFiltersContext, rule)

for _, backendRef := range rule.BackendRefs {
destination, backendWeight := t.processRouteDestination(backendRef.BackendRef, parentRef, httpRoute, resources)
destinations, backendWeight := t.processRouteDestinations(backendRef.BackendRef, parentRef, httpRoute, resources)
for _, route := range ruleRoutes {
// If the route already has a direct response or redirect configured, then it was from a filter so skip
// processing any destinations for this route.
if route.DirectResponse == nil && route.Redirect == nil {
if destination != nil {
route.Destinations = append(route.Destinations, destination)
if len(destinations) > 0 {
route.Destinations = append(route.Destinations, destinations...)
route.BackendWeights.Valid += backendWeight

} else {
Expand Down Expand Up @@ -354,13 +354,13 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
var ruleRoutes = t.processGRPCRouteRule(grpcRoute, ruleIdx, httpFiltersContext, rule)

for _, backendRef := range rule.BackendRefs {
destination, backendWeight := t.processRouteDestination(backendRef.BackendRef, parentRef, grpcRoute, resources)
destinations, backendWeight := t.processRouteDestinations(backendRef.BackendRef, parentRef, grpcRoute, resources)
for _, route := range ruleRoutes {
// If the route already has a direct response or redirect configured, then it was from a filter so skip
// processing any destinations for this route.
if route.DirectResponse == nil && route.Redirect == nil {
if destination != nil {
route.Destinations = append(route.Destinations, destination)
if len(destinations) > 0 {
route.Destinations = append(route.Destinations, destinations...)
route.BackendWeights.Valid += backendWeight

} else {
Expand Down Expand Up @@ -604,24 +604,8 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour
for _, rule := range tlsRoute.Spec.Rules {
for _, backendRef := range rule.BackendRefs {
backendRef := backendRef
// TODO: [v1alpha2-v1beta1] Replace with NamespaceDerefOr when TLSRoute graduates to v1beta1.
serviceNamespace := NamespaceDerefOrAlpha(backendRef.Namespace, tlsRoute.Namespace)
service := resources.GetService(serviceNamespace, string(backendRef.Name))

if !t.validateBackendRef(&backendRef, parentRef, tlsRoute, resources, serviceNamespace, KindTLSRoute) {
continue
}

weight := uint32(1)
if backendRef.Weight != nil {
weight = uint32(*backendRef.Weight)
}

routeDestinations = append(routeDestinations, ir.NewRouteDestWithWeight(
service.Spec.ClusterIP,
uint32(*backendRef.Port),
weight,
))
destinations, _ := t.processRouteDestinations(backendRef, parentRef, tlsRoute, resources)
routeDestinations = append(routeDestinations, destinations...)
}

// TODO handle:
Expand Down Expand Up @@ -758,20 +742,13 @@ func (t *Translator) processUDPRouteParentRefs(udpRoute *UDPRouteContext, resour
}

backendRef := udpRoute.Spec.Rules[0].BackendRefs[0]
// TODO: [v1alpha2-v1beta1] Replace with NamespaceDerefOr when UDPRoute graduates to v1beta1.
serviceNamespace := NamespaceDerefOrAlpha(backendRef.Namespace, udpRoute.Namespace)
service := resources.GetService(serviceNamespace, string(backendRef.Name))

if !t.validateBackendRef(&backendRef, parentRef, udpRoute, resources, serviceNamespace, KindUDPRoute) {
destinations, _ := t.processRouteDestinations(backendRef, parentRef, udpRoute, resources)
// Skip further processing if route destination is not valid
if len(destinations) == 0 {
continue
}

// weight is not used in udp route destinations
routeDestinations = append(routeDestinations, ir.NewRouteDest(
service.Spec.ClusterIP,
uint32(*backendRef.Port),
))

routeDestinations = append(routeDestinations, destinations...)
// If no negative condition has been set for ResolvedRefs, set "ResolvedRefs=True"
if !parentRef.HasCondition(udpRoute, v1beta1.RouteConditionResolvedRefs, metav1.ConditionFalse) {
parentRef.SetCondition(udpRoute,
Expand Down Expand Up @@ -898,20 +875,12 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour
}

backendRef := tcpRoute.Spec.Rules[0].BackendRefs[0]
// TODO: [v1alpha2-v1beta1] Replace with NamespaceDerefOr when TCPRoute graduates to v1beta1.
serviceNamespace := NamespaceDerefOrAlpha(backendRef.Namespace, tcpRoute.Namespace)
service := resources.GetService(serviceNamespace, string(backendRef.Name))

if !t.validateBackendRef(&backendRef, parentRef, tcpRoute, resources, serviceNamespace, KindTCPRoute) {
destinations, _ := t.processRouteDestinations(backendRef, parentRef, tcpRoute, resources)
// Skip further processing if route destination is not valid
if len(destinations) == 0 {
continue
}

// weight is not used in tcp route destinations
routeDestinations = append(routeDestinations, ir.NewRouteDest(
service.Spec.ClusterIP,
uint32(*backendRef.Port),
))

routeDestinations = append(routeDestinations, destinations...)
// If no negative condition has been set for ResolvedRefs, set "ResolvedRefs=True"
if !parentRef.HasCondition(tcpRoute, v1beta1.RouteConditionResolvedRefs, metav1.ConditionFalse) {
parentRef.SetCondition(tcpRoute,
Expand Down Expand Up @@ -981,13 +950,13 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour
}
}

// processRouteDestination takes a backendRef and translates it into a destination or sets error statuses and
// processRouteDestinations takes a backendRef and translates it into route destinations or sets error statuses and
// returns the weight for the backend so that 500 error responses can be returned for invalid backends in
// the same proportion as the backend would have otherwise received
func (t *Translator) processRouteDestination(backendRef v1beta1.BackendRef,
func (t *Translator) processRouteDestinations(backendRef v1beta1.BackendRef,
parentRef *RouteParentContext,
route RouteContext,
resources *Resources) (destination *ir.RouteDestination, backendWeight uint32) {
resources *Resources) (destinations []*ir.RouteDestination, backendWeight uint32) {

weight := uint32(1)
if backendRef.Weight != nil {
Expand All @@ -997,17 +966,25 @@ func (t *Translator) processRouteDestination(backendRef v1beta1.BackendRef,
serviceNamespace := NamespaceDerefOr(backendRef.Namespace, route.GetNamespace())
service := resources.GetService(serviceNamespace, string(backendRef.Name))

if !t.validateBackendRef(&backendRef, parentRef, route, resources, serviceNamespace, KindHTTPRoute) {
routeType := route.GetRouteType()
if !t.validateBackendRef(&backendRef, parentRef, route, resources, serviceNamespace, routeType) {
return nil, weight
}

// we need to validate backendRef first before using its data to create routeDestination
return ir.NewRouteDestWithWeight(
service.Spec.ClusterIP,
uint32(*backendRef.Port),
weight,
), weight

var dest *ir.RouteDestination
// Weights are not relevant for TCP and UDP Routes
if routeType == KindTCPRoute || routeType == KindUDPRoute {
dest = ir.NewRouteDest(
service.Spec.ClusterIP,
uint32(*backendRef.Port))
} else {
dest = ir.NewRouteDestWithWeight(
service.Spec.ClusterIP,
uint32(*backendRef.Port),
weight)
}
destinations = append(destinations, dest)
return destinations, weight
}

// processAllowedListenersForParentRefs finds out if the route attaches to one of our
Expand Down

0 comments on commit 4330d99

Please sign in to comment.