@@ -290,55 +290,91 @@ func bindRouteToListeners(r *Route, gw *Gateway) {
290290
291291 // Case 4 - winning Gateway
292292
293- // Find a listener
293+ // Try to attach Route to all matching listeners
294+ cond , attached := tryToAttachRouteToListeners (routeRef , r , gw .Listeners )
295+ if ! attached {
296+ attachment .FailedCondition = cond
297+ continue
298+ }
294299
295- // FIXME(pleshakov)
296- // For now, let's do simple matching.
297- // However, we need to also support wildcard matching.
300+ attachment . Attached = true
301+ }
302+ }
298303
299- bind := func (l * Listener ) (valid bool ) {
300- if ! l .Valid {
301- return false
302- }
304+ // tryToAttachRouteToListeners tries to attach the route to the listeners that match the parentRef and the hostnames.
305+ // If it succeeds in attaching at least one listener it will return true and the condition will be empty.
306+ // If it fails to attach the route, it will return false and the failure condition.
307+ // FIXME(pleshakov)
308+ // For now, let's do simple matching.
309+ // However, we need to also support wildcard matching.
310+ func tryToAttachRouteToListeners (
311+ ref v1beta1.ParentReference ,
312+ route * Route ,
313+ listeners map [string ]* Listener ,
314+ ) (conditions.Condition , bool ) {
315+ validListeners , listenerExists := findValidListeners (getSectionName (ref .SectionName ), listeners )
303316
304- hostnames := findAcceptedHostnames (l .Source .Hostname , r .Source .Spec .Hostnames )
305- if len (hostnames ) == 0 {
306- return true // listener is valid, but return without attaching due to no matching hostnames
307- }
317+ if ! listenerExists {
318+ // FIXME(pleshakov): Add a proper condition once it is available in the Gateway API.
319+ // https://github.com/nginxinc/nginx-kubernetes-gateway/issues/306
320+ return conditions .NewTODO ("listener is not found" ), false
321+ }
308322
309- attachment .Attached = true
310- for _ , h := range hostnames {
311- l .AcceptedHostnames [h ] = struct {}{}
312- }
313- l .Routes [client .ObjectKeyFromObject (r .Source )] = r
323+ if len (validListeners ) == 0 {
324+ return conditions .NewRouteInvalidListener (), false
325+ }
314326
315- return true
327+ bind := func (l * Listener ) (attached bool ) {
328+ hostnames := findAcceptedHostnames (l .Source .Hostname , route .Source .Spec .Hostnames )
329+ if len (hostnames ) == 0 {
330+ return false
316331 }
317332
318- var validListener bool
319- if getSectionName (routeRef .SectionName ) == "" {
320- for _ , l := range gw .Listeners {
321- validListener = bind (l ) || validListener
322- }
323- } else {
324- l , exists := gw .Listeners [string (* routeRef .SectionName )]
325- if ! exists {
326- // FIXME(pleshakov): Add a proper condition once it is available in the Gateway API.
327- // https://github.com/nginxinc/nginx-kubernetes-gateway/issues/306
328- attachment .FailedCondition = conditions .NewTODO ("listener is not found" )
329- continue
330- }
331-
332- validListener = bind (l )
333+ for _ , h := range hostnames {
334+ l .AcceptedHostnames [h ] = struct {}{}
333335 }
334- if ! validListener {
335- attachment .FailedCondition = conditions .NewRouteInvalidListener ()
336- continue
336+ l .Routes [client .ObjectKeyFromObject (route .Source )] = route
337+
338+ return true
339+ }
340+
341+ attached := false
342+ for _ , l := range validListeners {
343+ attached = attached || bind (l )
344+ }
345+
346+ if ! attached {
347+ return conditions .NewRouteNoMatchingListenerHostname (), false
348+ }
349+
350+ return conditions.Condition {}, true
351+ }
352+
353+ // findValidListeners returns a list of valid listeners and whether the listener exists for a non-empty sectionName.
354+ func findValidListeners (sectionName string , listeners map [string ]* Listener ) ([]* Listener , bool ) {
355+ if sectionName != "" {
356+ l , exists := listeners [sectionName ]
357+ if ! exists {
358+ return nil , false
337359 }
338- if ! attachment .Attached {
339- attachment .FailedCondition = conditions .NewRouteNoMatchingListenerHostname ()
360+
361+ if l .Valid {
362+ return []* Listener {l }, true
340363 }
364+
365+ return nil , true
341366 }
367+
368+ validListeners := make ([]* Listener , 0 , len (listeners ))
369+ for _ , l := range listeners {
370+ if ! l .Valid {
371+ continue
372+ }
373+
374+ validListeners = append (validListeners , l )
375+ }
376+
377+ return validListeners , true
342378}
343379
344380func findAcceptedHostnames (listenerHostname * v1beta1.Hostname , routeHostnames []v1beta1.Hostname ) []string {
0 commit comments