Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Multiple RequestMirrors Filters per HTTPRoute Rule #1819

Merged
merged 15 commits into from
Sep 17, 2023
Merged
37 changes: 11 additions & 26 deletions internal/gatewayapi/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
processRedirectFilter(redirect *v1beta1.HTTPRequestRedirectFilter, filterContext *HTTPFiltersContext)
processRequestHeaderModifierFilter(headerModifier *v1beta1.HTTPHeaderFilter, filterContext *HTTPFiltersContext)
processResponseHeaderModifierFilter(headerModifier *v1beta1.HTTPHeaderFilter, filterContext *HTTPFiltersContext)
processRequestMirrorFilter(mirror *v1beta1.HTTPRequestMirrorFilter, filterContext *HTTPFiltersContext, resources *Resources)
processRequestMirrorFilter(filterIdx int, mirror *v1beta1.HTTPRequestMirrorFilter, filterContext *HTTPFiltersContext, resources *Resources)
processExtensionRefHTTPFilter(extRef *v1beta1.LocalObjectReference, filterContext *HTTPFiltersContext, resources *Resources)
processUnsupportedHTTPFilter(filterType string, filterContext *HTTPFiltersContext)
}
Expand All @@ -56,7 +56,7 @@
AddResponseHeaders []ir.AddHeader
RemoveResponseHeaders []string

Mirror *ir.RouteDestination
Mirror []*ir.RouteDestination

RequestAuthentication *ir.RequestAuthentication
RateLimit *ir.RateLimit
Expand All @@ -76,7 +76,6 @@
RuleIdx: ruleIdx,
HTTPFilterIR: &HTTPFilterIR{},
}

for i := range filters {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just use i

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just use i

Yes, I can use 'i' if I don't need to match the value with the index of Mirror list.

filter := filters[i]
// If an invalid filter type has been configured then skip processing any more filters
Expand All @@ -98,7 +97,7 @@
case v1beta1.HTTPRouteFilterResponseHeaderModifier:
t.processResponseHeaderModifierFilter(filter.ResponseHeaderModifier, httpFiltersContext)
case v1beta1.HTTPRouteFilterRequestMirror:
t.processRequestMirrorFilter(filter.RequestMirror, httpFiltersContext, resources)
t.processRequestMirrorFilter(i, filter.RequestMirror, httpFiltersContext, resources)
case v1beta1.HTTPRouteFilterExtensionRef:
t.processExtensionRefHTTPFilter(filter.ExtensionRef, httpFiltersContext, resources)
default:
Expand All @@ -120,7 +119,6 @@

HTTPFilterIR: &HTTPFilterIR{},
}

for i := range filters {
filter := filters[i]
// If an invalid filter type has been configured then skip processing any more filters
Expand All @@ -138,7 +136,7 @@
case v1alpha2.GRPCRouteFilterResponseHeaderModifier:
t.processResponseHeaderModifierFilter(filter.ResponseHeaderModifier, httpFiltersContext)
case v1alpha2.GRPCRouteFilterRequestMirror:
t.processRequestMirrorFilter(filter.RequestMirror, httpFiltersContext, resources)
t.processRequestMirrorFilter(i, filter.RequestMirror, httpFiltersContext, resources)

Check warning on line 139 in internal/gatewayapi/filters.go

View check run for this annotation

Codecov / codecov/patch

internal/gatewayapi/filters.go#L139

Added line #L139 was not covered by tests
case v1alpha2.GRPCRouteFilterExtensionRef:
t.processExtensionRefHTTPFilter(filter.ExtensionRef, httpFiltersContext, resources)
default:
Expand Down Expand Up @@ -808,6 +806,7 @@
}

func (t *Translator) processRequestMirrorFilter(
filterIdx int,
mirrorFilter *v1beta1.HTTPRequestMirrorFilter,
filterContext *HTTPFiltersContext,
resources *Resources) {
Expand Down Expand Up @@ -836,27 +835,13 @@

mirrorEndpoints, _ := t.processDestEndpoints(mirrorBackendRef, filterContext.ParentRef, filterContext.Route, resources)

// Only add missing mirror destinations
for _, mirrorEp := range mirrorEndpoints {
var found bool
if filterContext.Mirror != nil {
for _, mirror := range filterContext.Mirror.Endpoints {
if mirror != nil {
if mirror.Host == mirrorEp.Host && mirror.Port == mirrorEp.Port {
found = true
}
}
}
}
if !found {
if filterContext.Mirror == nil {
filterContext.Mirror = &ir.RouteDestination{
Name: fmt.Sprintf("%s-mirror", irRouteDestinationName(filterContext.Route, filterContext.RuleIdx)),
}
}
filterContext.Mirror.Endpoints = append(filterContext.Mirror.Endpoints, mirrorEp)
}
newMirror := &ir.RouteDestination{
Name: fmt.Sprintf("%s-mirror-%d", irRouteDestinationName(filterContext.Route, filterContext.RuleIdx), filterIdx),
}
filterContext.Mirror = append(filterContext.Mirror, newMirror)
// Get the index of the last mirror added
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need L842-L844, can't we just assign Endpoints on L839 when creating RouteDestination ?

lastMirrorIdx := len(filterContext.Mirror) - 1
filterContext.Mirror[lastMirrorIdx].Endpoints = append(filterContext.Mirror[lastMirrorIdx].Endpoints, mirrorEndpoints...)
}

func (t *Translator) processUnresolvedHTTPFilter(errMsg string, filterContext *HTTPFiltersContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,17 @@ xdsIR:
weight: 1
name: httproute/default/httproute-1/rule/0
hostname: gateway.envoyproxy.io
mirror:
endpoints:
mirrors:
- endpoints:
- host: 7.7.7.7
port: 8080
weight: 1
name: httproute/default/httproute-1/rule/0-mirror-0
- endpoints:
- host: 7.7.7.7
port: 8080
weight: 1
name: httproute/default/httproute-1/rule/0-mirror
name: httproute/default/httproute-1/rule/0-mirror-1
name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io
pathMatch:
distinct: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ httpRoutes:
- name: service-1
port: 8080
filters:
- type: RequestHeaderModifier
requestHeaderModifier:
set:
- name: X-Header-Set
value: set-overwrites-values
add:
- name: X-Header-Add
value: header-val-1
- name: X-Header-Add-Append
value: header-val-2
remove:
- X-Header-Remove
- type: RequestMirror
requestMirror:
backendRef:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ httpRoutes:
- name: service-1
port: 8080
filters:
- requestHeaderModifier:
add:
- name: X-Header-Add
value: header-val-1
- name: X-Header-Add-Append
value: header-val-2
remove:
- X-Header-Remove
set:
- name: X-Header-Set
value: set-overwrites-values
type: RequestHeaderModifier
- requestMirror:
backendRef:
kind: Service
Expand Down Expand Up @@ -115,7 +127,17 @@ xdsIR:
name: envoy-gateway/gateway-1/http
port: 10080
routes:
- backendWeights:
- addRequestHeaders:
- append: true
name: X-Header-Add
value: header-val-1
- append: true
name: X-Header-Add-Append
value: header-val-2
- append: false
name: X-Header-Set
value: set-overwrites-values
backendWeights:
invalid: 0
valid: 0
destination:
Expand All @@ -125,17 +147,21 @@ xdsIR:
weight: 1
name: httproute/default/httproute-1/rule/0
hostname: gateway.envoyproxy.io
mirror:
endpoints:
mirrors:
- endpoints:
- host: 7.7.7.7
port: 8080
weight: 1
name: httproute/default/httproute-1/rule/0-mirror-1
- endpoints:
- host: 7.6.5.4
port: 8080
weight: 1
name: httproute/default/httproute-1/rule/0-mirror
name: httproute/default/httproute-1/rule/0-mirror-2
name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io
pathMatch:
distinct: false
name: ""
prefix: /
removeRequestHeaders:
- X-Header-Remove
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,12 @@ xdsIR:
weight: 1
name: httproute/default/httproute-1/rule/0
hostname: gateway.envoyproxy.io
mirror:
endpoints:
mirrors:
- endpoints:
- host: 7.7.7.7
port: 8080
weight: 1
name: httproute/default/httproute-1/rule/0-mirror
name: httproute/default/httproute-1/rule/0-mirror-0
name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io
pathMatch:
distinct: false
Expand Down
8 changes: 5 additions & 3 deletions internal/ir/xds.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@
// Redirections to be returned for this route. Takes precedence over Destinations.
Redirect *Redirect `json:"redirect,omitempty" yaml:"redirect,omitempty"`
// Destination that requests to this HTTPRoute will be mirrored to
Mirror *RouteDestination `json:"mirror,omitempty" yaml:"mirror,omitempty"`
Mirror []*RouteDestination `json:"mirrors,omitempty" yaml:"mirrors,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Mirror []*RouteDestination `json:"mirrors,omitempty" yaml:"mirrors,omitempty"`
Mirrors []*RouteDestination `json:"mirrors,omitempty" yaml:"mirrors,omitempty"`

// Destination associated with this matched route.
Destination *RouteDestination `json:"destination,omitempty" yaml:"destination,omitempty"`
// Rewrite to be changed for this route.
Expand Down Expand Up @@ -352,8 +352,10 @@
}
}
if h.Mirror != nil {
if err := h.Mirror.Validate(); err != nil {
errs = multierror.Append(errs, err)
for _, mirror := range h.Mirror {
if err := mirror.Validate(); err != nil {
errs = multierror.Append(errs, err)
}

Check warning on line 358 in internal/ir/xds.go

View check run for this annotation

Codecov / codecov/patch

internal/ir/xds.go#L357-L358

Added lines #L357 - L358 were not covered by tests
}
}
if len(h.AddRequestHeaders) > 0 {
Expand Down
2 changes: 1 addition & 1 deletion internal/ir/xds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ var (
PathMatch: &StringMatch{
Exact: ptrTo("mirrorfilter"),
},
Mirror: &happyRouteDestination,
Mirror: []*RouteDestination{&happyRouteDestination},
}

// RouteDestination
Expand Down
10 changes: 8 additions & 2 deletions internal/ir/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 10 additions & 8 deletions internal/xds/translator/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
case httpRoute.URLRewrite != nil:
routeAction := buildXdsURLRewriteAction(httpRoute.Destination.Name, httpRoute.URLRewrite)
if httpRoute.Mirror != nil {
routeAction.RequestMirrorPolicies = buildXdsRequestMirrorPolicies(httpRoute.Mirror.Name)
routeAction.RequestMirrorPolicies = buildXdsRequestMirrorPolicies(httpRoute.Mirror)

Check warning on line 48 in internal/xds/translator/route.go

View check run for this annotation

Codecov / codecov/patch

internal/xds/translator/route.go#L48

Added line #L48 was not covered by tests
}

router.Action = &routev3.Route_Route{Route: routeAction}
Expand All @@ -54,13 +54,13 @@
// If there are invalid backends then a weighted cluster is required for the route
routeAction := buildXdsWeightedRouteAction(httpRoute)
if httpRoute.Mirror != nil {
routeAction.RequestMirrorPolicies = buildXdsRequestMirrorPolicies(httpRoute.Mirror.Name)
routeAction.RequestMirrorPolicies = buildXdsRequestMirrorPolicies(httpRoute.Mirror)

Check warning on line 57 in internal/xds/translator/route.go

View check run for this annotation

Codecov / codecov/patch

internal/xds/translator/route.go#L57

Added line #L57 was not covered by tests
}
router.Action = &routev3.Route_Route{Route: routeAction}
} else {
routeAction := buildXdsRouteAction(httpRoute.Destination.Name)
if httpRoute.Mirror != nil {
routeAction.RequestMirrorPolicies = buildXdsRequestMirrorPolicies(httpRoute.Mirror.Name)
routeAction.RequestMirrorPolicies = buildXdsRequestMirrorPolicies(httpRoute.Mirror)
}
router.Action = &routev3.Route_Route{Route: routeAction}
}
Expand Down Expand Up @@ -293,11 +293,13 @@
return routeAction
}

func buildXdsRequestMirrorPolicies(destName string) []*routev3.RouteAction_RequestMirrorPolicy {
mirrorPolicies := []*routev3.RouteAction_RequestMirrorPolicy{
{
Cluster: destName,
},
func buildXdsRequestMirrorPolicies(mirrorDestinations []*ir.RouteDestination) []*routev3.RouteAction_RequestMirrorPolicy {
var mirrorPolicies []*routev3.RouteAction_RequestMirrorPolicy

for _, mirrorDest := range mirrorDestinations {
mirrorPolicies = append(mirrorPolicies, &routev3.RouteAction_RequestMirrorPolicy{
Cluster: mirrorDest.Name,
})
}

return mirrorPolicies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ http:
endpoints:
- host: "1.2.3.4"
port: 50000
mirror:
name: "mirror-route-dest"
mirrors:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets keep this example as is, and create one more test file for multiple-mirrors ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sound good, will do.

- name: "mirror-route-dest"
endpoints:
- host: "2.3.4.5"
- name: "mirror-route-dest1"
endpoints:
- host: "3.4.5.6"
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,16 @@
outlierDetection: {}
perConnectionBufferLimitBytes: 32768
type: EDS
- commonLbConfig:
localityWeightedLbConfig: {}
connectTimeout: 10s
dnsLookupFamily: V4_ONLY
edsClusterConfig:
edsConfig:
ads: {}
resourceApiVersion: V3
serviceName: mirror-route-dest1
name: mirror-route-dest1
outlierDetection: {}
perConnectionBufferLimitBytes: 32768
type: EDS
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,13 @@
portValue: 0
loadBalancingWeight: 1
locality: {}
- clusterName: mirror-route-dest1
endpoints:
- lbEndpoints:
- endpoint:
address:
socketAddress:
address: 3.4.5.6
portValue: 0
loadBalancingWeight: 1
locality: {}
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
cluster: route-dest
requestMirrorPolicies:
- cluster: mirror-route-dest
- cluster: mirror-route-dest1
18 changes: 10 additions & 8 deletions internal/xds/translator/translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,16 @@
}

if httpRoute.Mirror != nil {
if err := addXdsCluster(tCtx, addXdsClusterArgs{
name: httpRoute.Mirror.Name,
endpoints: httpRoute.Mirror.Endpoints,
tSocket: nil,
protocol: protocol,
endpointType: Static,
}); err != nil && !errors.Is(err, ErrXdsClusterExists) {
return err
for _, mirrorDest := range httpRoute.Mirror {
if err := addXdsCluster(tCtx, addXdsClusterArgs{
name: mirrorDest.Name,
endpoints: mirrorDest.Endpoints,
tSocket: nil,
protocol: protocol,
endpointType: Static,
}); err != nil && !errors.Is(err, ErrXdsClusterExists) {
return err
}

Check warning on line 213 in internal/xds/translator/translator.go

View check run for this annotation

Codecov / codecov/patch

internal/xds/translator/translator.go#L212-L213

Added lines #L212 - L213 were not covered by tests
}
}
}
Expand Down