Skip to content

Commit

Permalink
[wip] fix: filter hosts in httproutes
Browse files Browse the repository at this point in the history
  • Loading branch information
randmonkey committed Nov 21, 2022
1 parent 85048ca commit 2b17cf2
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 7 deletions.
7 changes: 6 additions & 1 deletion internal/controllers/gateway/httproute_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,12 @@ func (r *HTTPRouteReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
// perform operations on the kong store only if the route is in accepted status
if isRouteAccepted(gateways) {
// remove all the hostnames that don't match with at least one Listener's Hostname
filteredHTTPRoute := filterHostnames(gateways, httproute.DeepCopy())
filteredHTTPRoute, err := filterHostnames(gateways, httproute.DeepCopy())

if err != nil {
debug(log, httproute, "no matching hostnames after filtering")
return ctrl.Result{}, err
}

// if the gateways are ready, and the HTTPRoute is destined for them, ensure that
// the object is pushed to the dataplane.
Expand Down
26 changes: 21 additions & 5 deletions internal/controllers/gateway/route_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,20 +313,33 @@ func listenerHostnameIntersectWithRouteHostnames[H types.HostnameT, L types.List
return false
}

// shouldListenerSpecifyHostname if the listener could specify an effective hostname to match hostnames in requests.
// it will return true when the protocol of listener is HTTP, HTTPS, or TLS.
func shouldListenerSpecifyHostname(listener *gatewayv1beta1.Listener) bool {
return listener.Protocol == gatewayv1beta1.HTTPProtocolType ||
listener.Protocol == gatewayv1beta1.HTTPSProtocolType ||
listener.Protocol == gatewayv1beta1.TLSProtocolType
}

// filterHostnames accepts a HTTPRoute and returns a version of the same object with only a subset of the
// hostnames, the ones matching with the listeners' hostname.
func filterHostnames(gateways []supportedGatewayWithCondition, httpRoute *gatewayv1beta1.HTTPRoute) *gatewayv1beta1.HTTPRoute {
// it returns an error if the intersection of hostname match in httproute and listeners is empty.
func filterHostnames(gateways []supportedGatewayWithCondition, httpRoute *gatewayv1beta1.HTTPRoute) (*gatewayv1beta1.HTTPRoute, error) {
filteredHostnames := make([]gatewayv1beta1.Hostname, 0)

// if no hostnames are specified in the route spec, get all the hostnames from
// the gateway
if len(httpRoute.Spec.Hostnames) == 0 {
for _, gateway := range gateways {
for _, listener := range gateway.gateway.Spec.Listeners {
if listenerName := gateway.listenerName; listenerName == "" || listenerName == string(listener.Name) {
if listener.Hostname != nil {
filteredHostnames = append(filteredHostnames, (*listener.Hostname))
if listenerName := gateway.listenerName; listenerName == "" || listenerName == string(listener.Name) &&
shouldListenerSpecifyHostname(&listener) {
// httpRoute remains an empty hostname if any of the listeners
// has not specified hostname to match any host.
if listener.Hostname == nil {
return httpRoute, nil
}
filteredHostnames = append(filteredHostnames, (*listener.Hostname))
}
}
}
Expand All @@ -336,10 +349,13 @@ func filterHostnames(gateways []supportedGatewayWithCondition, httpRoute *gatewa
filteredHostnames = append(filteredHostnames, hostnameMatching)
}
}
if len(filteredHostnames) == 0 {
return nil, fmt.Errorf("no matching host")
}
}

httpRoute.Spec.Hostnames = filteredHostnames
return httpRoute
return httpRoute, nil
}

// getMinimumHostnameIntersection returns the minimum intersecting hostname, in the sense that:
Expand Down
3 changes: 2 additions & 1 deletion internal/controllers/gateway/route_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ func TestFilterHostnames(t *testing.T) {
}

for _, tc := range testCases {
filteredHTTPRoute := filterHostnames(tc.gateways, tc.httpRoute)
filteredHTTPRoute, err := filterHostnames(tc.gateways, tc.httpRoute)
assert.NoError(t, err)
assert.Equal(t, tc.expectedHTTPRoute.Spec, filteredHTTPRoute.Spec, tc.name)
}
}
Expand Down

0 comments on commit 2b17cf2

Please sign in to comment.