Check for router filter in validation step

This commit is contained in:
Michael Lumish 2021-07-22 12:42:11 -07:00
parent f03b4dd87f
commit 215cdcd134
3 changed files with 19 additions and 39 deletions

View File

@ -46,8 +46,6 @@ import { createHttpFilter, HttpFilterConfig, parseOverrideFilterConfig, parseTop
import { EXPERIMENTAL_FAULT_INJECTION } from './environment';
import Filter = experimental.Filter;
import FilterFactory = experimental.FilterFactory;
import BaseFilter = experimental.BaseFilter;
import CallStream = experimental.CallStream;
const TRACER_NAME = 'xds_resolver';
@ -209,25 +207,6 @@ function protoDurationToDuration(duration: Duration__Output): Duration {
}
}
class NoRouterFilter extends BaseFilter implements Filter {
constructor(private call: CallStream) {
super();
}
sendMetadata(metadata: Promise<Metadata>): Promise<Metadata> {
this.call.cancelWithStatus(status.UNAVAILABLE, 'no xDS HTTP router filter configured');
return Promise.reject<Metadata>(new Error('no xDS HTTP router filter configured'));
}
}
class NoRouterFilterFactory implements FilterFactory<NoRouterFilter> {
createFilter(callStream: CallStream): NoRouterFilter {
return new NoRouterFilter(callStream);
}
}
const ROUTER_FILTER_URL = 'type.googleapis.com/envoy.extensions.filters.http.router.v3.Router';
class XdsResolver implements Resolver {
private hasReportedSuccess = false;
@ -247,7 +226,6 @@ class XdsResolver implements Resolver {
private latestDefaultTimeout: Duration | undefined = undefined;
private ldsHttpFilterConfigs: {name: string, config: HttpFilterConfig}[] = [];
private hasRouterFilter = false;
constructor(
private target: GrpcUri,
@ -265,12 +243,7 @@ class XdsResolver implements Resolver {
}
if (EXPERIMENTAL_FAULT_INJECTION) {
this.ldsHttpFilterConfigs = [];
this.hasRouterFilter = false;
for (const filter of httpConnectionManager.http_filters) {
if (filter.typed_config?.type_url === ROUTER_FILTER_URL) {
this.hasRouterFilter = true;
break;
}
// typed_config must be set here, or validation would have failed
const filterConfig = parseTopLevelFilterConfig(filter.typed_config!);
if (filterConfig) {
@ -421,9 +394,6 @@ class XdsResolver implements Resolver {
}
}
}
if (!this.hasRouterFilter) {
extraFilterFactories.push(new NoRouterFilterFactory());
}
}
routeAction = new SingleClusterRouteAction(cluster, timeout, extraFilterFactories);
break;
@ -464,9 +434,6 @@ class XdsResolver implements Resolver {
}
}
}
if (!this.hasRouterFilter) {
extraFilterFactories.push(new NoRouterFilterFactory());
}
}
weightedClusters.push({name: clusterWeight.name, weight: clusterWeight.weight?.value ?? 0, dynamicFilterFactories: extraFilterFactories});
}

View File

@ -31,6 +31,8 @@ function trace(text: string): void {
experimental.trace(logVerbosity.DEBUG, TRACER_NAME, text);
}
const ROUTER_FILTER_URL = 'type.googleapis.com/envoy.extensions.filters.http.router.v3.Router';
export class LdsState implements XdsStreamState<Listener__Output> {
versionInfo = '';
nonce = '';
@ -103,10 +105,26 @@ export class LdsState implements XdsStreamState<Listener__Output> {
}
const httpConnectionManager = decodeSingleResource(HTTP_CONNECTION_MANGER_TYPE_URL_V3, message.api_listener!.api_listener.value);
if (EXPERIMENTAL_FAULT_INJECTION) {
for (const httpFilter of httpConnectionManager.http_filters) {
const filterNames = new Set<string>();
for (const [index, httpFilter] of httpConnectionManager.http_filters.entries()) {
if (filterNames.has(httpFilter.name)) {
return false;
}
filterNames.add(httpFilter.name);
if (!validateTopLevelFilter(httpFilter)) {
return false;
}
/* Validate that the last filter, and only the last filter, is the
* router filter. */
if (index < httpConnectionManager.http_filters.length - 1) {
if (httpFilter.name === ROUTER_FILTER_URL) {
return false;
}
} else {
if (httpFilter.name !== ROUTER_FILTER_URL) {
return false;
}
}
}
}
switch (httpConnectionManager.route_specifier) {

View File

@ -141,12 +141,7 @@ export class RdsState implements XdsStreamState<RouteConfiguration__Output> {
return false;
}
if (EXPERIMENTAL_FAULT_INJECTION) {
const filterNames = new Set<string>();
for (const [name, filterConfig] of Object.entries(route.typed_per_filter_config ?? {})) {
if (filterNames.has(name)) {
return false;
}
filterNames.add(name);
if (!validateOverrideFilter(filterConfig)) {
return false;
}