Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 27 additions & 17 deletions internal/gatewayapi/contexts.go
Original file line number Diff line number Diff line change
Expand Up @@ -585,25 +585,35 @@ func (r *RouteParentContext) HasCondition(route RouteContext, condType gwapiv1.R
return false
}

// BackendRefContext represents a generic BackendRef object (HTTPBackendRef, GRPCBackendRef or BackendRef itself)
type BackendRefContext any
// BackendRefContext represents a generic BackendRef object
type BackendRefContext interface {
GetBackendRef() *gwapiv1.BackendRef
GetFilters() any
}

func GetBackendRef(b BackendRefContext) *gwapiv1.BackendRef {
rv := reflect.ValueOf(b)
br := rv.FieldByName("BackendRef")
if br.IsValid() {
backendRef := br.Interface().(gwapiv1.BackendRef)
return &backendRef
}
// BackendRefWithFilters wraps backend refs that have filters (HTTPBackendRef, GRPCBackendRef)
type BackendRefWithFilters struct {
BackendRef *gwapiv1.BackendRef
Filters any // []gwapiv1.HTTPRouteFilter or []gwapiv1.GRPCRouteFilter
}

backendRef := b.(gwapiv1.BackendRef)
return &backendRef
func (b BackendRefWithFilters) GetBackendRef() *gwapiv1.BackendRef {
return b.BackendRef
}

func GetFilters(b BackendRefContext) any {
filters := reflect.ValueOf(b).FieldByName("Filters")
if !filters.IsValid() {
return nil
}
return filters.Interface()
func (b BackendRefWithFilters) GetFilters() any {
return b.Filters
}

// DirectBackendRef wraps a BackendRef directly (used by TLS/TCP/UDP routes)
type DirectBackendRef struct {
BackendRef *gwapiv1.BackendRef
}

func (d DirectBackendRef) GetBackendRef() *gwapiv1.BackendRef {
return d.BackendRef
}

func (d DirectBackendRef) GetFilters() any {
return nil
}
22 changes: 6 additions & 16 deletions internal/gatewayapi/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -969,22 +969,12 @@ func (t *Translator) processRequestMirrorFilter(
weight := int32(1)
mirrorBackend := mirrorFilter.BackendRef

// Create the appropriate BackendRef type based on the route type
var mirrorBackendRef BackendRefContext
if routeType == resource.KindGRPCRoute {
mirrorBackendRef = gwapiv1.GRPCBackendRef{
BackendRef: gwapiv1.BackendRef{
BackendObjectReference: mirrorBackend,
Weight: &weight,
},
}
} else {
mirrorBackendRef = gwapiv1.HTTPBackendRef{
BackendRef: gwapiv1.BackendRef{
BackendObjectReference: mirrorBackend,
Weight: &weight,
},
}
// Create a DirectBackendRef for the mirror backend (no filters needed)
mirrorBackendRef := DirectBackendRef{
BackendRef: &gwapiv1.BackendRef{
BackendObjectReference: mirrorBackend,
Weight: &weight,
},
}

// This sets the status on the Route, should the usage be changed so that the status message reflects that the backendRef is from the filter?
Expand Down
3 changes: 2 additions & 1 deletion internal/gatewayapi/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,8 @@ func (t *Translator) processBackendRefs(name string, backendCluster egv1a1.Backe
return nil, nil, err
}
result := make([]*ir.DestinationSetting, 0, len(backendCluster.BackendRefs))
for _, ref := range backendCluster.BackendRefs {
for i := range backendCluster.BackendRefs {
ref := &backendCluster.BackendRefs[i]
ns := NamespaceDerefOr(ref.Namespace, namespace)
kind := KindDerefOr(ref.Kind, resource.KindService)
switch kind {
Expand Down
8 changes: 4 additions & 4 deletions internal/gatewayapi/resource/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -544,15 +544,15 @@ func addMissingServices(requiredServices map[string]*corev1.Service, obj interfa
case *gwapiv1.HTTPRoute:
objNamespace = route.Namespace
for _, rule := range route.Spec.Rules {
for _, httpBakcendRef := range rule.BackendRefs {
refs = append(refs, httpBakcendRef.BackendRef)
for i := range rule.BackendRefs {
refs = append(refs, rule.BackendRefs[i].BackendRef)
}
}
case *gwapiv1.GRPCRoute:
objNamespace = route.Namespace
for _, rule := range route.Spec.Rules {
for _, gRPCBakcendRef := range rule.BackendRefs {
refs = append(refs, gRPCBakcendRef.BackendRef)
for i := range rule.BackendRefs {
refs = append(refs, rule.BackendRefs[i].BackendRef)
}
}
case *gwapiv1a2.TLSRoute:
Expand Down
46 changes: 30 additions & 16 deletions internal/gatewayapi/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,13 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
backendRefNames := make([]string, len(rule.BackendRefs))
backendCustomRefs := []*ir.UnstructuredRef{}
// process each backendRef, and calculate the destination settings for this rule
for i, backendRef := range rule.BackendRefs {
for i := range rule.BackendRefs {
settingName := irDestinationSettingName(destName, i)
ds, unstructuredRef, err := t.processDestination(settingName, backendRef, parentRef, httpRoute, resources)
backendRefCtx := BackendRefWithFilters{
BackendRef: &rule.BackendRefs[i].BackendRef,
Filters: rule.BackendRefs[i].Filters,
}
ds, unstructuredRef, err := t.processDestination(settingName, backendRefCtx, parentRef, httpRoute, resources)
if err != nil {
errs.Add(status.NewRouteStatusError(
fmt.Errorf("failed to process route rule %d backendRef %d: %w", ruleIdx, i, err),
Expand All @@ -242,8 +246,8 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
if ds.IsDynamicResolver {
hasDynamicResolver = true
}
backendNamespace := NamespaceDerefOr(backendRef.Namespace, httpRoute.GetNamespace())
backendRefNames[i] = fmt.Sprintf("%s/%s", backendNamespace, backendRef.Name)
backendNamespace := NamespaceDerefOr(rule.BackendRefs[i].Namespace, httpRoute.GetNamespace())
backendRefNames[i] = fmt.Sprintf("%s/%s", backendNamespace, rule.BackendRefs[i].Name)
}

// process each ir route
Expand Down Expand Up @@ -664,9 +668,13 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
failedProcessDestination := false

backendRefNames := make([]string, len(rule.BackendRefs))
for i, backendRef := range rule.BackendRefs {
for i := range rule.BackendRefs {
settingName := irDestinationSettingName(destName, i)
ds, _, err := t.processDestination(settingName, backendRef, parentRef, grpcRoute, resources)
backendRefCtx := BackendRefWithFilters{
BackendRef: &rule.BackendRefs[i].BackendRef,
Filters: rule.BackendRefs[i].Filters,
}
ds, _, err := t.processDestination(settingName, backendRefCtx, parentRef, grpcRoute, resources)
if err != nil {
errs.Add(status.NewRouteStatusError(
fmt.Errorf("failed to process route rule %d backendRef %d: %w", ruleIdx, i, err),
Expand All @@ -680,8 +688,8 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
continue
}
allDs = append(allDs, ds)
backendNamespace := NamespaceDerefOr(backendRef.Namespace, grpcRoute.GetNamespace())
backendRefNames[i] = fmt.Sprintf("%s/%s", backendNamespace, backendRef.Name)
backendNamespace := NamespaceDerefOr(rule.BackendRefs[i].Namespace, grpcRoute.GetNamespace())
backendRefNames[i] = fmt.Sprintf("%s/%s", backendNamespace, rule.BackendRefs[i].Name)
}

// process each ir route
Expand Down Expand Up @@ -955,9 +963,10 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour

// compute backends
for _, rule := range tlsRoute.Spec.Rules {
for i, backendRef := range rule.BackendRefs {
for i := range rule.BackendRefs {
settingName := irDestinationSettingName(destName, i)
ds, _, err := t.processDestination(settingName, backendRef, parentRef, tlsRoute, resources)
backendRefCtx := DirectBackendRef{BackendRef: &rule.BackendRefs[i]}
ds, _, err := t.processDestination(settingName, backendRefCtx, parentRef, tlsRoute, resources)
if err != nil {
resolveErrs.Add(err)
continue
Expand Down Expand Up @@ -1110,9 +1119,10 @@ func (t *Translator) processUDPRouteParentRefs(udpRoute *UDPRouteContext, resour
destName = irRouteDestinationName(udpRoute, -1 /*rule index*/)
)

for i, backendRef := range udpRoute.Spec.Rules[0].BackendRefs {
for i := range udpRoute.Spec.Rules[0].BackendRefs {
settingName := irDestinationSettingName(destName, i)
ds, _, err := t.processDestination(settingName, backendRef, parentRef, udpRoute, resources)
backendRefCtx := DirectBackendRef{BackendRef: &udpRoute.Spec.Rules[0].BackendRefs[i]}
ds, _, err := t.processDestination(settingName, backendRefCtx, parentRef, udpRoute, resources)
if err != nil {
resolveErrs.Add(err)
continue
Expand Down Expand Up @@ -1259,9 +1269,10 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour
destName = irRouteDestinationName(tcpRoute, -1 /*rule index*/)
)

for i, backendRef := range tcpRoute.Spec.Rules[0].BackendRefs {
for i := range tcpRoute.Spec.Rules[0].BackendRefs {
settingName := irDestinationSettingName(destName, i)
ds, _, err := t.processDestination(settingName, backendRef, parentRef, tcpRoute, resources)
backendRefCtx := DirectBackendRef{BackendRef: &tcpRoute.Spec.Rules[0].BackendRefs[i]}
ds, _, err := t.processDestination(settingName, backendRefCtx, parentRef, tcpRoute, resources)
// skip adding the route and provide the reason via route status.
if err != nil {
resolveErrs.Add(err)
Expand Down Expand Up @@ -1375,7 +1386,7 @@ func (t *Translator) processDestination(name string, backendRefContext BackendRe
) (ds *ir.DestinationSetting, unstructuredRef *ir.UnstructuredRef, err status.Error) {
routeType := route.GetRouteType()
weight := uint32(1)
backendRef := GetBackendRef(backendRefContext)
backendRef := backendRefContext.GetBackendRef()
if backendRef.Weight != nil {
weight = uint32(*backendRef.Weight)
}
Expand Down Expand Up @@ -1606,7 +1617,10 @@ func (t *Translator) processServiceDestinationSetting(
}

func getBackendFilters(routeType gwapiv1.Kind, backendRefContext BackendRefContext) (backendFilters any) {
filters := GetFilters(backendRefContext)
filters := backendRefContext.GetFilters()
if filters == nil {
return nil
}
switch routeType {
case resource.KindHTTPRoute:
if len(filters.([]gwapiv1.HTTPRouteFilter)) > 0 {
Expand Down
7 changes: 5 additions & 2 deletions internal/gatewayapi/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
func (t *Translator) validateBackendRef(backendRefContext BackendRefContext, route RouteContext,
resources *resource.Resources, backendNamespace string, routeKind gwapiv1.Kind,
) status.Error {
backendRef := GetBackendRef(backendRefContext)
backendRef := backendRefContext.GetBackendRef()

if err := t.validateBackendRefFilters(backendRefContext, routeKind); err != nil {
return err
Expand Down Expand Up @@ -91,7 +91,10 @@ func (t *Translator) validateBackendRefKind(backendRef *gwapiv1a2.BackendRef) st
}

func (t *Translator) validateBackendRefFilters(backendRef BackendRefContext, routeKind gwapiv1.Kind) status.Error {
filters := GetFilters(backendRef)
filters := backendRef.GetFilters()
if filters == nil {
return nil
}
var unsupportedFilters bool

switch routeKind {
Expand Down