@@ -15,7 +15,7 @@ import (
1515// listenerAttachmentHelper is an internal utility interface that can be used to determine if a listener will allow
1616// a route to attach to it.
1717type listenerAttachmentHelper interface {
18- listenerAllowsAttachment (ctx context.Context , gw gwv1.Gateway , listener gwv1.Listener , route preLoadRouteDescriptor , hostnamesFromHttpRoutes map [types.NamespacedName ][]gwv1.Hostname , hostnamesFromGrpcRoutes map [types.NamespacedName ][]gwv1.Hostname ) (bool , * RouteData , error )
18+ listenerAllowsAttachment (ctx context.Context , gw gwv1.Gateway , listener gwv1.Listener , route preLoadRouteDescriptor , hostnamesFromHttpRoutes map [types.NamespacedName ][]gwv1.Hostname , hostnamesFromGrpcRoutes map [types.NamespacedName ][]gwv1.Hostname ) ([]gwv1. Hostname , bool , * RouteData , error )
1919}
2020
2121var _ listenerAttachmentHelper = & listenerAttachmentHelperImpl {}
@@ -35,33 +35,36 @@ func newListenerAttachmentHelper(k8sClient client.Client, logger logr.Logger) li
3535
3636// listenerAllowsAttachment utility method to determine if a listener will allow a route to connect using
3737// Gateway API rules to determine compatibility between lister and route.
38- func (attachmentHelper * listenerAttachmentHelperImpl ) listenerAllowsAttachment (ctx context.Context , gw gwv1.Gateway , listener gwv1.Listener , route preLoadRouteDescriptor , hostnamesFromHttpRoutes map [types.NamespacedName ][]gwv1.Hostname , hostnamesFromGrpcRoutes map [types.NamespacedName ][]gwv1.Hostname ) (bool , * RouteData , error ) {
38+ // Returns: (compatibleHostnames, allowed, failedRouteData, error)
39+ func (attachmentHelper * listenerAttachmentHelperImpl ) listenerAllowsAttachment (ctx context.Context , gw gwv1.Gateway , listener gwv1.Listener , route preLoadRouteDescriptor , hostnamesFromHttpRoutes map [types.NamespacedName ][]gwv1.Hostname , hostnamesFromGrpcRoutes map [types.NamespacedName ][]gwv1.Hostname ) ([]gwv1.Hostname , bool , * RouteData , error ) {
3940 // check namespace
4041 namespaceOK , err := attachmentHelper .namespaceCheck (ctx , gw , listener , route )
4142 if err != nil {
42- return false , nil , err
43+ return nil , false , nil , err
4344 }
4445 if ! namespaceOK {
4546 rd := GenerateRouteData (false , true , string (gwv1 .RouteReasonNotAllowedByListeners ), RouteStatusInfoRejectedMessageNamespaceNotMatch , route .GetRouteNamespacedName (), route .GetRouteKind (), route .GetRouteGeneration (), gw )
46- return false , & rd , nil
47+ return nil , false , & rd , nil
4748 }
4849
4950 // check kind
5051 kindOK := attachmentHelper .kindCheck (listener , route )
5152 if ! kindOK {
5253 rd := GenerateRouteData (false , true , string (gwv1 .RouteReasonNotAllowedByListeners ), RouteStatusInfoRejectedMessageKindNotMatch , route .GetRouteNamespacedName (), route .GetRouteKind (), route .GetRouteGeneration (), gw )
53- return false , & rd , nil
54+ return nil , false , & rd , nil
5455 }
5556
56- // check hostname
57- if (route .GetRouteKind () == HTTPRouteKind || route .GetRouteKind () == GRPCRouteKind || route .GetRouteKind () == TLSRouteKind ) && route .GetHostnames () != nil {
58- hostnameOK , err := attachmentHelper .hostnameCheck (listener , route )
57+ // check hostname and get compatible hostnames
58+ var compatibleHostnames []gwv1.Hostname
59+ if route .GetRouteKind () == HTTPRouteKind || route .GetRouteKind () == GRPCRouteKind || route .GetRouteKind () == TLSRouteKind {
60+ var hostnameOK bool
61+ compatibleHostnames , hostnameOK , err = attachmentHelper .hostnameCheck (listener , route )
5962 if err != nil {
60- return false , nil , err
63+ return nil , false , nil , err
6164 }
6265 if ! hostnameOK {
6366 rd := GenerateRouteData (false , true , string (gwv1 .RouteReasonNoMatchingListenerHostname ), RouteStatusInfoRejectedMessageNoMatchingHostname , route .GetRouteNamespacedName (), route .GetRouteKind (), route .GetRouteGeneration (), gw )
64- return false , & rd , nil
67+ return nil , false , & rd , nil
6568 }
6669 }
6770
@@ -71,11 +74,11 @@ func (attachmentHelper *listenerAttachmentHelperImpl) listenerAllowsAttachment(c
7174 if ! hostnameUniquenessOK {
7275 message := fmt .Sprintf ("HTTPRoute and GRPCRoute have overlap hostname, attachment is rejected. Conflict route: %s" , conflictRoute )
7376 rd := GenerateRouteData (false , true , string (gwv1 .RouteReasonNotAllowedByListeners ), message , route .GetRouteNamespacedName (), route .GetRouteKind (), route .GetRouteGeneration (), gw )
74- return false , & rd , nil
77+ return nil , false , & rd , nil
7578 }
7679 }
7780
78- return true , nil , nil
81+ return compatibleHostnames , true , nil , nil
7982}
8083
8184// namespaceCheck namespace check implements the Gateway API spec for namespace matching between listener
@@ -170,24 +173,33 @@ func (attachmentHelper *listenerAttachmentHelperImpl) kindCheck(listener gwv1.Li
170173 return true
171174}
172175
173- func (attachmentHelper * listenerAttachmentHelperImpl ) hostnameCheck (listener gwv1.Listener , route preLoadRouteDescriptor ) (bool , error ) {
174- // A route can attach to listener if it does not have hostname or listener does not have hostname
175- if listener .Hostname == nil || len (route .GetHostnames ()) == 0 {
176- return true , nil
176+ func (attachmentHelper * listenerAttachmentHelperImpl ) hostnameCheck (listener gwv1.Listener , route preLoadRouteDescriptor ) ([]gwv1.Hostname , bool , error ) {
177+ // If route has no hostnames but listener does, use listener hostname
178+ if route .GetHostnames () == nil || len (route .GetHostnames ()) == 0 {
179+ if listener .Hostname != nil {
180+ return []gwv1.Hostname {* listener .Hostname }, true , nil
181+ }
182+ return nil , true , nil
183+ }
184+
185+ // If listener has no hostname, route can attach
186+ if listener .Hostname == nil {
187+ return nil , true , nil
177188 }
178189
179190 // validate listener hostname, return if listener hostname is not valid
180191 isListenerHostnameValid , err := IsHostNameInValidFormat (string (* listener .Hostname ))
181192 if err != nil {
182193 attachmentHelper .logger .Error (err , "listener hostname is not valid" , "listener" , listener .Name , "hostname" , * listener .Hostname )
183194 initialErrorMessage := fmt .Sprintf ("listener hostname %s is not valid (listener name %s)" , listener .Name , * listener .Hostname )
184- return false , wrapError (errors .Errorf ("%s" , initialErrorMessage ), gwv1 .GatewayReasonListenersNotValid , gwv1 .RouteReasonUnsupportedValue , nil , nil )
195+ return nil , false , wrapError (errors .Errorf ("%s" , initialErrorMessage ), gwv1 .GatewayReasonListenersNotValid , gwv1 .RouteReasonUnsupportedValue , nil , nil )
185196 }
186197
187198 if ! isListenerHostnameValid {
188- return false , nil
199+ return nil , false , nil
189200 }
190201
202+ compatibleHostnames := []gwv1.Hostname {}
191203 for _ , hostname := range route .GetHostnames () {
192204 // validate route hostname, skip invalid hostname
193205 isHostnameValid , err := IsHostNameInValidFormat (string (hostname ))
@@ -196,12 +208,18 @@ func (attachmentHelper *listenerAttachmentHelperImpl) hostnameCheck(listener gwv
196208 continue
197209 }
198210
199- // check if two hostnames have overlap (compatible)
200- if isHostnameCompatible (string (hostname ), string (* listener .Hostname )) {
201- return true , nil
211+ // check if two hostnames have overlap (compatible) and get the more specific one
212+ if compatible , ok := getCompatibleHostname (string (hostname ), string (* listener .Hostname )); ok {
213+ compatibleHostnames = append ( compatibleHostnames , gwv1 . Hostname ( compatible ))
202214 }
203215 }
204- return false , nil
216+
217+ if len (compatibleHostnames ) == 0 {
218+ return nil , false , nil
219+ }
220+
221+ // Return computed compatible hostnames without storing in route
222+ return compatibleHostnames , true , nil
205223}
206224
207225func (attachmentHelper * listenerAttachmentHelperImpl ) crossServingHostnameUniquenessCheck (route preLoadRouteDescriptor , hostnamesFromHttpRoutes map [types.NamespacedName ][]gwv1.Hostname , hostnamesFromGrpcRoutes map [types.NamespacedName ][]gwv1.Hostname ) (bool , string ) {
0 commit comments