in pilot/pkg/networking/core/v1alpha3/envoyfilter/rc_patch.go [150:240]
func patchHTTPRoutes(patchContext networking.EnvoyFilter_PatchContext,
patches map[networking.EnvoyFilter_ApplyTo][]*model.EnvoyFilterConfigPatchWrapper,
routeConfiguration *route.RouteConfiguration, virtualHost *route.VirtualHost, portMap model.GatewayPortMap) {
routesRemoved := false
// Apply the route level removes/merges if any.
for index := range virtualHost.Routes {
patchHTTPRoute(patchContext, patches, routeConfiguration, virtualHost, index, &routesRemoved, portMap)
}
// now for the adds
for _, rp := range patches[networking.EnvoyFilter_HTTP_ROUTE] {
applied := false
if !commonConditionMatch(patchContext, rp) ||
!routeConfigurationMatch(patchContext, routeConfiguration, rp, portMap) ||
!virtualHostMatch(virtualHost, rp) {
IncrementEnvoyFilterMetric(rp.Key(), Route, applied)
continue
}
if rp.Operation == networking.EnvoyFilter_Patch_ADD {
virtualHost.Routes = append(virtualHost.Routes, proto.Clone(rp.Value).(*route.Route))
applied = true
} else if rp.Operation == networking.EnvoyFilter_Patch_INSERT_AFTER {
// Insert after without a route match is same as ADD in the end
if !hasRouteMatch(rp) {
virtualHost.Routes = append(virtualHost.Routes, proto.Clone(rp.Value).(*route.Route))
continue
}
// find the matching route first
insertPosition := -1
for i := 0; i < len(virtualHost.Routes); i++ {
if routeMatch(virtualHost.Routes[i], rp) {
insertPosition = i + 1
break
}
}
if insertPosition == -1 {
continue
}
applied = true
clonedVal := proto.Clone(rp.Value).(*route.Route)
virtualHost.Routes = append(virtualHost.Routes, clonedVal)
if insertPosition < len(virtualHost.Routes)-1 {
copy(virtualHost.Routes[insertPosition+1:], virtualHost.Routes[insertPosition:])
virtualHost.Routes[insertPosition] = clonedVal
}
} else if rp.Operation == networking.EnvoyFilter_Patch_INSERT_BEFORE || rp.Operation == networking.EnvoyFilter_Patch_INSERT_FIRST {
// insert before/first without a route match is same as insert in the beginning
if !hasRouteMatch(rp) {
virtualHost.Routes = append([]*route.Route{proto.Clone(rp.Value).(*route.Route)}, virtualHost.Routes...)
continue
}
// find the matching route first
insertPosition := -1
for i := 0; i < len(virtualHost.Routes); i++ {
if routeMatch(virtualHost.Routes[i], rp) {
insertPosition = i
break
}
}
// If matching route is not found, then don't insert and continue.
if insertPosition == -1 {
continue
}
applied = true
// In case of INSERT_FIRST, if a match is found, still insert it at the top of the routes.
if rp.Operation == networking.EnvoyFilter_Patch_INSERT_FIRST {
insertPosition = 0
}
clonedVal := proto.Clone(rp.Value).(*route.Route)
virtualHost.Routes = append(virtualHost.Routes, clonedVal)
copy(virtualHost.Routes[insertPosition+1:], virtualHost.Routes[insertPosition:])
virtualHost.Routes[insertPosition] = clonedVal
}
IncrementEnvoyFilterMetric(rp.Key(), Route, applied)
}
if routesRemoved {
trimmedRoutes := make([]*route.Route, 0, len(virtualHost.Routes))
for i := range virtualHost.Routes {
if virtualHost.Routes[i] == nil {
continue
}
trimmedRoutes = append(trimmedRoutes, virtualHost.Routes[i])
}
virtualHost.Routes = trimmedRoutes
}
}