@@ -233,6 +233,7 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
233233 BackendRef : & rule .BackendRefs [i ].BackendRef ,
234234 Filters : rule .BackendRefs [i ].Filters ,
235235 }
236+ // ds will never be nil here because processDestination returns an empty DestinationSetting for invalid backendRefs.
236237 ds , unstructuredRef , err := t .processDestination (settingName , backendRefCtx , parentRef , httpRoute , resources )
237238 if err != nil {
238239 // Gateway API conformance: When backendRef Service exists but has no endpoints,
@@ -250,13 +251,12 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
250251 ))
251252 processDestinationError = err
252253 }
253- continue
254254 }
255255 if unstructuredRef != nil {
256256 backendCustomRefs = append (backendCustomRefs , unstructuredRef )
257257 }
258- // ds can be nil if the backendRef weight is 0
259- if ds == nil {
258+ // skip backendRefs with weight 0 as they do not affect the traffic distribution
259+ if ds . Weight != nil && * ds . Weight == 0 {
260260 continue
261261 }
262262 allDs = append (allDs , ds )
@@ -275,9 +275,9 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
275275 Metadata : routeRuleMetadata ,
276276 }
277277 switch {
278- // return 500 if any destination setting is invalid
278+ // return 500 if no valid destination settings exist
279279 // the error is already added to the error list when processing the destination
280- case processDestinationError != nil :
280+ case processDestinationError != nil && destination . ToBackendWeights (). Valid == 0 :
281281 routesWithDirectResponse := sets .New [string ]()
282282 for _ , irRoute := range ruleRoutes {
283283 // If the route already has a direct response or redirect configured, then it was from a filter so skip
@@ -297,9 +297,9 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
297297 "error" , processDestinationError ,
298298 )
299299 }
300- // return 503 if endpoints does not exist
300+ // return 503 if no ready endpoints exist
301301 // the error is already added to the error list when processing the destination
302- case failedNoReadyEndpoints && len ( allDs ) == 0 :
302+ case failedNoReadyEndpoints && destination . ToBackendWeights (). Valid == 0 :
303303 routesWithDirectResponse := sets .New [string ]()
304304 for _ , irRoute := range ruleRoutes {
305305 // If the route already has a direct response or redirect configured, then it was from a filter so skip
@@ -334,8 +334,8 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
334334 t .Logger .Info ("setting 500 direct response in routes due to all valid destinations having 0 weight" ,
335335 "routes" , sets .List (routesWithDirectResponse ))
336336 }
337- // A route can only have one destination if this destination is a dynamic resolver, because the behavior of
338- // multiple destinations with one being a dynamic resolver just doesn't make sense.
337+ // A route can only have one destination if this destination is a dynamic resolver, because the behavior of
338+ // multiple destinations with one being a dynamic resolver just doesn't make sense.
339339 case hasDynamicResolver && len (rule .BackendRefs ) > 1 :
340340 routesWithDirectResponse := sets .New [string ]()
341341 for _ , irRoute := range ruleRoutes {
@@ -388,10 +388,6 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
388388 }
389389 }
390390
391- // TODO handle:
392- // - sum of weights for valid backend refs is 0
393- // - etc.
394-
395391 irRoutes = append (irRoutes , ruleRoutes ... )
396392 }
397393 if errorCollector .Empty () {
@@ -826,6 +822,7 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
826822 BackendRef : & rule .BackendRefs [i ].BackendRef ,
827823 Filters : rule .BackendRefs [i ].Filters ,
828824 }
825+ // ds will never be nil here because processDestination returns an empty DestinationSetting for invalid backendRefs.
829826 ds , _ , err := t .processDestination (settingName , backendRefCtx , parentRef , grpcRoute , resources )
830827 if err != nil {
831828 // Gateway API conformance: When backendRef Service exists but has no endpoints,
@@ -843,10 +840,10 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
843840 ))
844841 processDestinationError = err
845842 }
846- continue
847843 }
848844
849- if ds == nil {
845+ // skip backendRefs with weight 0 as they do not affect the traffic distribution
846+ if ds .Weight != nil && * ds .Weight == 0 {
850847 continue
851848 }
852849 allDs = append (allDs , ds )
@@ -862,7 +859,7 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
862859 switch {
863860 // return 500 if any destination setting is invalid
864861 // the error is already added to the error list when processing the destination
865- case processDestinationError != nil :
862+ case processDestinationError != nil && destination . ToBackendWeights (). Valid == 0 :
866863 routesWithDirectResponse := sets .New [string ]()
867864 for _ , irRoute := range ruleRoutes {
868865 // If the route already has a direct response or redirect configured, then it was from a filter so skip
@@ -883,7 +880,7 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
883880 }
884881 // return 503 if endpoints does not exist
885882 // the error is already added to the error list when processing the destination
886- case failedNoReadyEndpoints && len ( allDs ) == 0 :
883+ case failedNoReadyEndpoints && destination . ToBackendWeights (). Valid == 0 :
887884 routesWithDirectResponse := sets .New [string ]()
888885 for _ , irRoute := range ruleRoutes {
889886 // If the route already has a direct response or redirect configured, then it was from a filter so skip
@@ -945,10 +942,6 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
945942 }
946943 }
947944
948- // TODO handle:
949- // - sum of weights for valid backend refs is 0
950- // - etc.
951-
952945 irRoutes = append (irRoutes , ruleRoutes ... )
953946 }
954947
@@ -1195,12 +1188,14 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour
11951188 for i := range rule .BackendRefs {
11961189 settingName := irDestinationSettingName (destName , i )
11971190 backendRefCtx := DirectBackendRef {BackendRef : & rule .BackendRefs [i ]}
1191+ // ds will never be nil here because processDestination returns an empty DestinationSetting for invalid backendRefs.
11981192 ds , _ , err := t .processDestination (settingName , backendRefCtx , parentRef , tlsRoute , resources )
11991193 if err != nil {
12001194 resolveErrs .Add (err )
12011195 continue
12021196 }
1203- if ds != nil {
1197+ // skip backendRefs with weight 0 as they do not affect the traffic distribution
1198+ if ds .Weight != nil && * ds .Weight > 0 {
12041199 destSettings = append (destSettings , ds )
12051200 }
12061201 }
@@ -1351,14 +1346,15 @@ func (t *Translator) processUDPRouteParentRefs(udpRoute *UDPRouteContext, resour
13511346 for i := range udpRoute .Spec .Rules [0 ].BackendRefs {
13521347 settingName := irDestinationSettingName (destName , i )
13531348 backendRefCtx := DirectBackendRef {BackendRef : & udpRoute .Spec .Rules [0 ].BackendRefs [i ]}
1349+ // ds will never be nil here because processDestination returns an empty DestinationSetting for invalid backendRefs.
13541350 ds , _ , err := t .processDestination (settingName , backendRefCtx , parentRef , udpRoute , resources )
13551351 if err != nil {
13561352 resolveErrs .Add (err )
13571353 continue
13581354 }
13591355
1360- // Skip nil destination settings
1361- if ds != nil {
1356+ // skip backendRefs with weight 0 as they do not affect the traffic distribution
1357+ if ds . Weight != nil && * ds . Weight > 0 {
13621358 destSettings = append (destSettings , ds )
13631359 }
13641360 }
@@ -1507,8 +1503,8 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour
15071503 resolveErrs .Add (err )
15081504 continue
15091505 }
1510- // Skip nil destination settings
1511- if ds != nil {
1506+ // skip backendRefs with weight 0 as they do not affect the traffic distribution
1507+ if ds . Weight != nil && * ds . Weight > 0 {
15121508 destSettings = append (destSettings , ds )
15131509 }
15141510 }
@@ -1613,27 +1609,33 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour
16131609func (t * Translator ) processDestination (name string , backendRefContext BackendRefContext ,
16141610 parentRef * RouteParentContext , route RouteContext , resources * resource.Resources ,
16151611) (ds * ir.DestinationSetting , unstructuredRef * ir.UnstructuredRef , err status.Error ) {
1616- routeType := route .GetRouteType ()
1617- weight := uint32 (1 )
1618- backendRef := backendRefContext .GetBackendRef ()
1619- if backendRef .Weight != nil {
1620- weight = uint32 (* backendRef .Weight )
1612+ var (
1613+ routeType = route .GetRouteType ()
1614+ weight = (uint32 (ptr .Deref (backendRefContext .GetBackendRef ().Weight , int32 (1 ))))
1615+ backendRef = backendRefContext .GetBackendRef ()
1616+ )
1617+
1618+ // Create an empty DS without endpoints
1619+ // This represents an invalid DS.
1620+ emptyDS := & ir.DestinationSetting {
1621+ Name : name ,
1622+ Weight : & weight ,
16211623 }
16221624
16231625 backendNamespace := NamespaceDerefOr (backendRef .Namespace , route .GetNamespace ())
16241626 if ! t .isCustomBackendResource (backendRef .Group , KindDerefOr (backendRef .Kind , resource .KindService )) {
16251627 err = t .validateBackendRef (backendRefContext , route , resources , backendNamespace , routeType )
16261628 {
1627- // return with empty endpoint means the backend is invalid and an error to fail the associated route.
1629+ // Empty DS means the backend is invalid and an error to fail the associated route.
16281630 if err != nil {
1629- return nil , nil , err
1631+ return emptyDS , nil , err
16301632 }
16311633 }
16321634 }
16331635
16341636 // Skip processing backends with 0 weight
16351637 if weight == 0 {
1636- return nil , nil , nil
1638+ return emptyDS , nil , nil
16371639 }
16381640
16391641 var envoyProxy * egv1a1.EnvoyProxy
@@ -1660,19 +1662,19 @@ func (t *Translator) processDestination(name string, backendRefContext BackendRe
16601662 envoyProxy ,
16611663 )
16621664 if tlsErr != nil {
1663- return nil , nil , status .NewRouteStatusError (tlsErr , status .RouteReasonInvalidBackendTLS )
1665+ return emptyDS , nil , status .NewRouteStatusError (tlsErr , status .RouteReasonInvalidBackendTLS )
16641666 }
16651667
16661668 switch KindDerefOr (backendRef .Kind , resource .KindService ) {
16671669 case resource .KindServiceImport :
16681670 ds , err = t .processServiceImportDestinationSetting (name , backendRef .BackendObjectReference , backendNamespace , protocol , resources , envoyProxy )
16691671 if err != nil {
1670- return nil , nil , err
1672+ return emptyDS , nil , err
16711673 }
16721674 case resource .KindService :
16731675 ds , err = t .processServiceDestinationSetting (name , backendRef .BackendObjectReference , backendNamespace , protocol , resources , envoyProxy )
16741676 if err != nil {
1675- return nil , nil , err
1677+ return emptyDS , nil , err
16761678 }
16771679 svc := resources .GetService (backendNamespace , string (backendRef .Name ))
16781680 ds .IPFamily = getServiceIPFamily (svc )
@@ -1687,7 +1689,7 @@ func (t *Translator) processDestination(name string, backendRefContext BackendRe
16871689
16881690 // Check if the custom backend resource was found
16891691 if unstructuredRef == nil {
1690- return nil , nil , status .NewRouteStatusError (
1692+ return emptyDS , nil , status .NewRouteStatusError (
16911693 fmt .Errorf ("custom backend %s %s/%s not found" ,
16921694 KindDerefOr (backendRef .Kind , resource .KindService ),
16931695 backendNamespace ,
@@ -1709,11 +1711,11 @@ func (t *Translator) processDestination(name string, backendRefContext BackendRe
17091711 var filtersErr error
17101712 ds .Filters , filtersErr = t .processDestinationFilters (routeType , backendRefContext , parentRef , route , resources )
17111713 if filtersErr != nil {
1712- return nil , nil , status .NewRouteStatusError (filtersErr , status .RouteReasonInvalidBackendFilters )
1714+ return emptyDS , nil , status .NewRouteStatusError (filtersErr , status .RouteReasonInvalidBackendFilters )
17131715 }
17141716
17151717 if err := validateDestinationSettings (ds , t .IsEnvoyServiceRouting (envoyProxy ), backendRef .Kind ); err != nil {
1716- return nil , nil , err
1718+ return emptyDS , nil , err
17171719 }
17181720
17191721 ds .Weight = & weight
0 commit comments