From 15cdcc849e9c8856bd07c310f58def6dd392f331 Mon Sep 17 00:00:00 2001 From: Lin Yang Date: Wed, 13 Sep 2023 11:34:48 +0800 Subject: [PATCH] fix: rule level filters and backend level filters Signed-off-by: Lin Yang --- pkg/gateway/cache/cache.go | 130 ++++++++++++++++---------------- pkg/gateway/cache/cacheutils.go | 48 ++++++++++-- pkg/gateway/cache/types.go | 2 +- pkg/gateway/routecfg/types.go | 15 +++- 4 files changed, 119 insertions(+), 76 deletions(-) diff --git a/pkg/gateway/cache/cache.go b/pkg/gateway/cache/cache.go index 99fc70769..6b3db1c8e 100644 --- a/pkg/gateway/cache/cache.go +++ b/pkg/gateway/cache/cache.go @@ -564,8 +564,8 @@ func (c *GatewayCache) routeRules(gw *gwv1beta1.Gateway, validListeners []gwtype httpRoute := route.(*gwv1beta1.HTTPRoute) log.Debug().Msgf("Processing HTTPRoute %v", httpRoute) - processHTTPRoute(gw, validListeners, httpRoute, rules) - processHTTPRouteBackendFilters(httpRoute, services) + processHTTPRoute(gw, validListeners, httpRoute, rules, services) + //processHTTPRouteBackendFilters(httpRoute, services) } log.Debug().Msgf("Processing %d GRPCRoutes", len(c.grpcroutes)) @@ -582,8 +582,8 @@ func (c *GatewayCache) routeRules(gw *gwv1beta1.Gateway, validListeners []gwtype } grpcRoute := route.(*gwv1alpha2.GRPCRoute) - processGRPCRoute(gw, validListeners, grpcRoute, rules) - processGRPCRouteBackendFilters(grpcRoute, services) + processGRPCRoute(gw, validListeners, grpcRoute, rules, services) + //processGRPCRouteBackendFilters(grpcRoute, services) } log.Debug().Msgf("Processing %d TLSRoutes", len(c.tlsroutes)) @@ -625,7 +625,7 @@ func (c *GatewayCache) routeRules(gw *gwv1beta1.Gateway, validListeners []gwtype return rules, services } -func processHTTPRoute(gw *gwv1beta1.Gateway, validListeners []gwtypes.Listener, httpRoute *gwv1beta1.HTTPRoute, rules map[int32]routecfg.RouteRule) { +func processHTTPRoute(gw *gwv1beta1.Gateway, validListeners []gwtypes.Listener, httpRoute *gwv1beta1.HTTPRoute, rules map[int32]routecfg.RouteRule, services map[string]serviceInfo) { for _, ref := range httpRoute.Spec.ParentRefs { if !gwutils.IsRefToGateway(ref, gwutils.ObjectKey(gw)) { continue @@ -648,7 +648,7 @@ func processHTTPRoute(gw *gwv1beta1.Gateway, validListeners []gwtypes.Listener, httpRule := routecfg.L7RouteRule{} for _, hostname := range hostnames { - httpRule[hostname] = generateHTTPRouteConfig(httpRoute) + httpRule[hostname] = generateHTTPRouteConfig(httpRoute, services) } port := int32(listener.Port) @@ -663,7 +663,7 @@ func processHTTPRoute(gw *gwv1beta1.Gateway, validListeners []gwtypes.Listener, } } -func processGRPCRoute(gw *gwv1beta1.Gateway, validListeners []gwtypes.Listener, grpcRoute *gwv1alpha2.GRPCRoute, rules map[int32]routecfg.RouteRule) { +func processGRPCRoute(gw *gwv1beta1.Gateway, validListeners []gwtypes.Listener, grpcRoute *gwv1alpha2.GRPCRoute, rules map[int32]routecfg.RouteRule, services map[string]serviceInfo) { for _, ref := range grpcRoute.Spec.ParentRefs { if !gwutils.IsRefToGateway(ref, gwutils.ObjectKey(gw)) { continue @@ -684,7 +684,7 @@ func processGRPCRoute(gw *gwv1beta1.Gateway, validListeners []gwtypes.Listener, grpcRule := routecfg.L7RouteRule{} for _, hostname := range hostnames { - grpcRule[hostname] = generateGRPCRouteCfg(grpcRoute) + grpcRule[hostname] = generateGRPCRouteCfg(grpcRoute, services) } port := int32(listener.Port) @@ -792,63 +792,63 @@ func processTCPRoute(gw *gwv1beta1.Gateway, validListeners []gwtypes.Listener, t } } -func processHTTPRouteBackendFilters(httpRoute *gwv1beta1.HTTPRoute, services map[string]serviceInfo) { - // For now, ONLY supports unique filter types, cannot specify one type filter multiple times - for _, rule := range httpRoute.Spec.Rules { - ruleLevelFilters := make(map[gwv1beta1.HTTPRouteFilterType]routecfg.Filter) - - for _, ruleFilter := range rule.Filters { - ruleLevelFilters[ruleFilter.Type] = ruleFilter - } - - for _, backend := range rule.BackendRefs { - if svcPort := backendRefToServicePortName(backend.BackendRef, httpRoute.Namespace); svcPort != nil { - svcFilters := copyMap(ruleLevelFilters) - for _, svcFilter := range backend.Filters { - svcFilters[svcFilter.Type] = svcFilter - } - - svcInfo := serviceInfo{ - svcPortName: *svcPort, - filters: make([]routecfg.Filter, 0), - } - for _, f := range svcFilters { - svcInfo.filters = append(svcInfo.filters, f) - } - services[svcPort.String()] = svcInfo - } - } - } -} - -func processGRPCRouteBackendFilters(grpcRoute *gwv1alpha2.GRPCRoute, services map[string]serviceInfo) { - // For now, ONLY supports unique filter types, cannot specify one type filter multiple times - for _, rule := range grpcRoute.Spec.Rules { - ruleLevelFilters := make(map[gwv1alpha2.GRPCRouteFilterType]routecfg.Filter) - - for _, ruleFilter := range rule.Filters { - ruleLevelFilters[ruleFilter.Type] = ruleFilter - } - - for _, backend := range rule.BackendRefs { - if svcPort := backendRefToServicePortName(backend.BackendRef, grpcRoute.Namespace); svcPort != nil { - svcFilters := copyMap(ruleLevelFilters) - for _, svcFilter := range backend.Filters { - svcFilters[svcFilter.Type] = svcFilter - } +//func processHTTPRouteBackendFilters(httpRoute *gwv1beta1.HTTPRoute, services map[string]serviceInfo) { +// // For now, ONLY supports unique filter types, cannot specify one type filter multiple times +// for _, rule := range httpRoute.Spec.Rules { +// ruleLevelFilters := make(map[gwv1beta1.HTTPRouteFilterType]routecfg.Filter) +// +// for _, ruleFilter := range rule.Filters { +// ruleLevelFilters[ruleFilter.Type] = ruleFilter +// } +// +// for _, backend := range rule.BackendRefs { +// if svcPort := backendRefToServicePortName(backend.BackendRef, httpRoute.Namespace); svcPort != nil { +// svcFilters := copyMap(ruleLevelFilters) +// for _, svcFilter := range backend.Filters { +// svcFilters[svcFilter.Type] = svcFilter +// } +// +// svcInfo := serviceInfo{ +// svcPortName: *svcPort, +// filters: make([]routecfg.Filter, 0), +// } +// for _, f := range svcFilters { +// svcInfo.filters = append(svcInfo.filters, f) +// } +// services[svcPort.String()] = svcInfo +// } +// } +// } +//} - svcInfo := serviceInfo{ - svcPortName: *svcPort, - filters: make([]routecfg.Filter, 0), - } - for _, f := range svcFilters { - svcInfo.filters = append(svcInfo.filters, f) - } - services[svcPort.String()] = svcInfo - } - } - } -} +//func processGRPCRouteBackendFilters(grpcRoute *gwv1alpha2.GRPCRoute, services map[string]serviceInfo) { +// // For now, ONLY supports unique filter types, cannot specify one type filter multiple times +// for _, rule := range grpcRoute.Spec.Rules { +// ruleLevelFilters := make(map[gwv1alpha2.GRPCRouteFilterType]routecfg.Filter) +// +// for _, ruleFilter := range rule.Filters { +// ruleLevelFilters[ruleFilter.Type] = ruleFilter +// } +// +// for _, backend := range rule.BackendRefs { +// if svcPort := backendRefToServicePortName(backend.BackendRef, grpcRoute.Namespace); svcPort != nil { +// svcFilters := copyMap(ruleLevelFilters) +// for _, svcFilter := range backend.Filters { +// svcFilters[svcFilter.Type] = svcFilter +// } +// +// svcInfo := serviceInfo{ +// svcPortName: *svcPort, +// filters: make([]routecfg.Filter, 0), +// } +// for _, f := range svcFilters { +// svcInfo.filters = append(svcInfo.filters, f) +// } +// services[svcPort.String()] = svcInfo +// } +// } +// } +//} func processTLSBackends(_ *gwv1alpha2.TLSRoute, _ map[string]serviceInfo) { // DO nothing for now @@ -931,7 +931,7 @@ func (c *GatewayCache) serviceConfigs(services map[string]serviceInfo) map[strin } svcCfg := routecfg.ServiceConfig{ - Filters: svcInfo.filters, + //Filters: svcInfo.filters, Endpoints: make(map[string]routecfg.Endpoint), } diff --git a/pkg/gateway/cache/cacheutils.go b/pkg/gateway/cache/cacheutils.go index 5b79a221d..8691ec3ac 100644 --- a/pkg/gateway/cache/cacheutils.go +++ b/pkg/gateway/cache/cacheutils.go @@ -26,24 +26,42 @@ func getSecretRefNamespace(gw *gwv1beta1.Gateway, secretRef gwv1beta1.SecretObje return string(*secretRef.Namespace) } -func generateHTTPRouteConfig(httpRoute *gwv1beta1.HTTPRoute) routecfg.HTTPRouteRuleSpec { +func generateHTTPRouteConfig(httpRoute *gwv1beta1.HTTPRoute, services map[string]serviceInfo) routecfg.HTTPRouteRuleSpec { httpSpec := routecfg.HTTPRouteRuleSpec{ RouteType: routecfg.L7RouteTypeHTTP, Matches: make([]routecfg.HTTPTrafficMatch, 0), } for _, rule := range httpRoute.Spec.Rules { - backends := map[string]int32{} + backends := map[string]routecfg.BackendServiceConfig{} for _, bk := range rule.BackendRefs { if svcPort := backendRefToServicePortName(bk.BackendRef, httpRoute.Namespace); svcPort != nil { - backends[svcPort.String()] = backendWeight(bk.BackendRef) + svcLevelFilters := make([]routecfg.Filter, 0) + for _, filter := range bk.Filters { + svcLevelFilters = append(svcLevelFilters, filter) + } + + backends[svcPort.String()] = routecfg.BackendServiceConfig{ + Weight: backendWeight(bk.BackendRef), + Filters: svcLevelFilters, + } + + services[svcPort.String()] = serviceInfo{ + svcPortName: *svcPort, + } } } + ruleLevelFilters := make([]routecfg.Filter, 0) + for _, ruleFilter := range rule.Filters { + ruleLevelFilters = append(ruleLevelFilters, ruleFilter) + } + for _, m := range rule.Matches { match := routecfg.HTTPTrafficMatch{ BackendService: backends, + Filters: ruleLevelFilters, } if m.Path != nil { @@ -157,24 +175,42 @@ func httpMatchQueryParams(m gwv1beta1.HTTPRouteMatch) map[routecfg.MatchType]map return params } -func generateGRPCRouteCfg(grpcRoute *gwv1alpha2.GRPCRoute) routecfg.GRPCRouteRuleSpec { +func generateGRPCRouteCfg(grpcRoute *gwv1alpha2.GRPCRoute, services map[string]serviceInfo) routecfg.GRPCRouteRuleSpec { grpcSpec := routecfg.GRPCRouteRuleSpec{ RouteType: routecfg.L7RouteTypeGRPC, Matches: make([]routecfg.GRPCTrafficMatch, 0), } for _, rule := range grpcRoute.Spec.Rules { - backends := map[string]int32{} + backends := map[string]routecfg.BackendServiceConfig{} for _, bk := range rule.BackendRefs { if svcPort := backendRefToServicePortName(bk.BackendRef, grpcRoute.Namespace); svcPort != nil { - backends[svcPort.String()] = backendWeight(bk.BackendRef) + svcLevelFilters := make([]routecfg.Filter, 0) + for _, filter := range bk.Filters { + svcLevelFilters = append(svcLevelFilters, filter) + } + + backends[svcPort.String()] = routecfg.BackendServiceConfig{ + Weight: backendWeight(bk.BackendRef), + Filters: svcLevelFilters, + } + + services[svcPort.String()] = serviceInfo{ + svcPortName: *svcPort, + } } } + ruleLevelFilters := make([]routecfg.Filter, 0) + for _, ruleFilter := range rule.Filters { + ruleLevelFilters = append(ruleLevelFilters, ruleFilter) + } + for _, m := range rule.Matches { match := routecfg.GRPCTrafficMatch{ BackendService: backends, + Filters: ruleLevelFilters, } if m.Method != nil { diff --git a/pkg/gateway/cache/types.go b/pkg/gateway/cache/types.go index c864e8047..02b657c18 100644 --- a/pkg/gateway/cache/types.go +++ b/pkg/gateway/cache/types.go @@ -100,7 +100,7 @@ type Cache interface { type serviceInfo struct { svcPortName routecfg.ServicePortName - filters []routecfg.Filter + //filters []routecfg.Filter } type endpointInfo struct { diff --git a/pkg/gateway/routecfg/types.go b/pkg/gateway/routecfg/types.go index 2cd22864e..683e2b375 100644 --- a/pkg/gateway/routecfg/types.go +++ b/pkg/gateway/routecfg/types.go @@ -152,21 +152,28 @@ type UDPRouteRule map[string]int32 var _ RouteRule = &UDPRouteRule{} +type BackendServiceConfig struct { + Weight int32 `json:"Weight"` + Filters []Filter `json:"Filters,omitempty" hash:"set"` +} + // HTTPTrafficMatch is the HTTP traffic match configuration type HTTPTrafficMatch struct { Path *Path `json:"Path,omitempty"` Headers map[MatchType]map[string]string `json:"Headers,omitempty"` RequestParams map[MatchType]map[string]string `json:"RequestParams,omitempty"` Methods []string `json:"Methods,omitempty" hash:"set"` - BackendService map[string]int32 `json:"BackendService"` + BackendService map[string]BackendServiceConfig `json:"BackendService"` RateLimit *RateLimit `json:"RateLimit,omitempty"` + Filters []Filter `json:"Filters,omitempty" hash:"set"` } // GRPCTrafficMatch is the GRPC traffic match configuration type GRPCTrafficMatch struct { Headers map[MatchType]map[string]string `json:"Headers,omitempty"` Method *GRPCMethod `json:"Method,omitempty"` - BackendService map[string]int32 `json:"BackendService"` + BackendService map[string]BackendServiceConfig `json:"BackendService"` + Filters []Filter `json:"Filters,omitempty" hash:"set"` } // Path is the path configuration @@ -197,8 +204,8 @@ type PassthroughRouteMapping map[string]string // ServiceConfig is the service configuration type ServiceConfig struct { - Endpoints map[string]Endpoint `json:"Endpoints"` - Filters []Filter `json:"Filters,omitempty" hash:"set"` + Endpoints map[string]Endpoint `json:"Endpoints"` + //Filters []Filter `json:"Filters,omitempty" hash:"set"` ConnectionSettings *ConnectionSettings `json:"ConnectionSettings,omitempty"` RetryPolicy *RetryPolicy `json:"RetryPolicy,omitempty"` MTLS bool `json:"mTLS,omitempty"`