@@ -290,55 +290,91 @@ func bindRouteToListeners(r *Route, gw *Gateway) {
290
290
291
291
// Case 4 - winning Gateway
292
292
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
+ }
294
299
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
+ }
298
303
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 )
303
316
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
+ }
308
322
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
+ }
314
326
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
316
331
}
317
332
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 {}{}
333
335
}
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
337
359
}
338
- if ! attachment .Attached {
339
- attachment .FailedCondition = conditions .NewRouteNoMatchingListenerHostname ()
360
+
361
+ if l .Valid {
362
+ return []* Listener {l }, true
340
363
}
364
+
365
+ return nil , true
341
366
}
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
342
378
}
343
379
344
380
func findAcceptedHostnames (listenerHostname * v1beta1.Hostname , routeHostnames []v1beta1.Hostname ) []string {
0 commit comments