Skip to content

Commit

Permalink
xds: gate HttpFilter parsing by env flag
Browse files Browse the repository at this point in the history
  • Loading branch information
dapengzhang0 committed Feb 18, 2021
1 parent da86eea commit e870584
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 77 deletions.
80 changes: 47 additions & 33 deletions xds/src/main/java/io/grpc/xds/ClientXdsClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ final class ClientXdsClient extends AbstractXdsClient {
@VisibleForTesting
static final String AGGREGATE_CLUSTER_TYPE_NAME = "envoy.clusters.aggregate";
private static final String HTTP_FAULT_FILTER_NAME = "envoy.fault";
@VisibleForTesting
static boolean enableFaultInjection =
Boolean.parseBoolean(System.getenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"));

private static final String TYPE_URL_HTTP_CONNECTION_MANAGER_V2 =
"type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2"
+ ".HttpConnectionManager";
Expand Down Expand Up @@ -184,22 +188,26 @@ protected void handleLdsResponse(String versionInfo, List<Any> resources, String
}
boolean hasFaultInjection = false;
HttpFault httpFault = null;
List<HttpFilter> httpFilters = hcm.getHttpFiltersList();
for (HttpFilter httpFilter : httpFilters) {
if (HTTP_FAULT_FILTER_NAME.equals(httpFilter.getName())) {
hasFaultInjection = true;
if (httpFilter.hasTypedConfig()) {
StructOrError<HttpFault> httpFaultOrError =
decodeFaultFilterConfig(httpFilter.getTypedConfig());
if (httpFaultOrError.getErrorDetail() != null) {
nackResponse(ResourceType.LDS, nonce,
"Listener " + listenerName + " contains invalid HttpFault filter: "
+ httpFaultOrError.getErrorDetail());
return;
if (enableFaultInjection) {
List<HttpFilter> httpFilters = hcm.getHttpFiltersList();
for (HttpFilter httpFilter : httpFilters) {
if (HTTP_FAULT_FILTER_NAME.equals(httpFilter.getName())) {
hasFaultInjection = true;
if (httpFilter.hasTypedConfig()) {
StructOrError<HttpFault> httpFaultOrError =
decodeFaultFilterConfig(httpFilter.getTypedConfig());
if (httpFaultOrError != null) {
if (httpFaultOrError.getErrorDetail() != null) {
nackResponse(ResourceType.LDS, nonce,
"Listener " + listenerName + " contains invalid HttpFault filter: "
+ httpFaultOrError.getErrorDetail());
return;
}
httpFault = httpFaultOrError.getStruct();
}
}
httpFault = httpFaultOrError.getStruct();
break;
}
break;
}
}
if (hcm.hasRouteConfig()) {
Expand Down Expand Up @@ -271,12 +279,14 @@ private static StructOrError<VirtualHost> parseVirtualHost(
if (filterConfigMap.containsKey(HTTP_FAULT_FILTER_NAME)) {
Any rawFaultFilterConfig = filterConfigMap.get(HTTP_FAULT_FILTER_NAME);
StructOrError<HttpFault> httpFaultOrError = decodeFaultFilterConfig(rawFaultFilterConfig);
if (httpFaultOrError.getErrorDetail() != null) {
return StructOrError.fromError(
"Virtual host [" + name + "] contains invalid HttpFault filter : "
+ httpFaultOrError.getErrorDetail());
if (httpFaultOrError != null) {
if (httpFaultOrError.getErrorDetail() != null) {
return StructOrError.fromError(
"Virtual host [" + name + "] contains invalid HttpFault filter : "
+ httpFaultOrError.getErrorDetail());
}
httpFault = httpFaultOrError.getStruct();
}
httpFault = httpFaultOrError.getStruct();
}
return StructOrError.fromStruct(VirtualHost.create(
name, proto.getDomainsList(), routes, httpFault));
Expand Down Expand Up @@ -322,12 +332,14 @@ static StructOrError<Route> parseRoute(io.envoyproxy.envoy.config.route.v3.Route
if (filterConfigMap.containsKey(HTTP_FAULT_FILTER_NAME)) {
Any rawFaultFilterConfig = filterConfigMap.get(HTTP_FAULT_FILTER_NAME);
StructOrError<HttpFault> httpFaultOrError = decodeFaultFilterConfig(rawFaultFilterConfig);
if (httpFaultOrError.getErrorDetail() != null) {
return StructOrError.fromError(
"Route [" + proto.getName() + "] contains invalid HttpFault filter: "
+ httpFaultOrError.getErrorDetail());
if (httpFaultOrError != null) {
if (httpFaultOrError.getErrorDetail() != null) {
return StructOrError.fromError(
"Route [" + proto.getName() + "] contains invalid HttpFault filter: "
+ httpFaultOrError.getErrorDetail());
}
httpFault = httpFaultOrError.getStruct();
}
httpFault = httpFaultOrError.getStruct();
}
return StructOrError.fromStruct(Route.create(
routeMatch.getStruct(), routeAction.getStruct(), httpFault));
Expand Down Expand Up @@ -508,22 +520,24 @@ static StructOrError<ClusterWeight> parseClusterWeight(
if (filterConfigMap.containsKey(HTTP_FAULT_FILTER_NAME)) {
Any rawFaultFilterConfig = filterConfigMap.get(HTTP_FAULT_FILTER_NAME);
StructOrError<HttpFault> httpFaultOrError = decodeFaultFilterConfig(rawFaultFilterConfig);
if (httpFaultOrError.getErrorDetail() != null) {
return StructOrError.fromError(
"ClusterWeight [" + proto.getName() + "] contains invalid HttpFault filter: "
+ httpFaultOrError.getErrorDetail());
if (httpFaultOrError != null) {
if (httpFaultOrError.getErrorDetail() != null) {
return StructOrError.fromError(
"ClusterWeight [" + proto.getName() + "] contains invalid HttpFault filter: "
+ httpFaultOrError.getErrorDetail());
}
httpFault = httpFaultOrError.getStruct();
}
httpFault = httpFaultOrError.getStruct();
}
return StructOrError.fromStruct(
ClusterWeight.create(proto.getName(), proto.getWeight().getValue(), httpFault));
}

@Nullable
private static StructOrError<HttpFault> decodeFaultFilterConfig(Any rawFaultFilterConfig) {
if (rawFaultFilterConfig.getTypeUrl().equals(
"type.googleapis.com/envoy.config.filter.http.fault.v2.HTTPFault")) {
rawFaultFilterConfig = rawFaultFilterConfig.toBuilder().setTypeUrl(
"type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault").build();
if (!rawFaultFilterConfig.getTypeUrl().equals(
"type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault")) {
return null;
}
HTTPFault httpFaultProto;
try {
Expand Down
6 changes: 6 additions & 0 deletions xds/src/test/java/io/grpc/xds/ClientXdsClientTestBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nullable;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
Expand Down Expand Up @@ -172,9 +173,12 @@ public boolean shouldAccept(Runnable command) {

private ManagedChannel channel;
private ClientXdsClient xdsClient;
private boolean originalEnableFaultInjection;

@Before
public void setUp() throws IOException {
originalEnableFaultInjection = ClientXdsClient.enableFaultInjection;
ClientXdsClient.enableFaultInjection = true;
MockitoAnnotations.initMocks(this);
when(backoffPolicyProvider.get()).thenReturn(backoffPolicy1, backoffPolicy2);
when(backoffPolicy1.nextBackoffNanos()).thenReturn(10L, 100L);
Expand Down Expand Up @@ -207,6 +211,7 @@ public void setUp() throws IOException {

@After
public void tearDown() {
ClientXdsClient.enableFaultInjection = originalEnableFaultInjection;
xdsClient.shutdown();
channel.shutdown(); // channel not owned by XdsClient
assertThat(adsEnded.get()).isTrue();
Expand Down Expand Up @@ -333,6 +338,7 @@ public void ldsResourceUpdated() {

@Test
public void ldsResourceUpdate_withFaultInjection() {
Assume.assumeTrue(useProtocolV3());
DiscoveryRpcCall call =
startResourceWatcher(ResourceType.LDS, LDS_RESOURCE, ldsResourceWatcher);
List<Any> listeners = ImmutableList.of(
Expand Down
46 changes: 2 additions & 44 deletions xds/src/test/java/io/grpc/xds/ClientXdsClientV2Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@
import io.envoyproxy.envoy.api.v2.route.RouteMatch;
import io.envoyproxy.envoy.api.v2.route.VirtualHost;
import io.envoyproxy.envoy.config.cluster.aggregate.v2alpha.ClusterConfig;
import io.envoyproxy.envoy.config.filter.fault.v2.FaultDelay;
import io.envoyproxy.envoy.config.filter.fault.v2.FaultDelay.HeaderDelay;
import io.envoyproxy.envoy.config.filter.http.fault.v2.FaultAbort;
import io.envoyproxy.envoy.config.filter.http.fault.v2.FaultAbort.HeaderAbort;
import io.envoyproxy.envoy.config.filter.http.fault.v2.HTTPFault;
import io.envoyproxy.envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager;
import io.envoyproxy.envoy.config.filter.network.http_connection_manager.v2.HttpFilter;
import io.envoyproxy.envoy.config.filter.network.http_connection_manager.v2.Rds;
Expand Down Expand Up @@ -279,52 +274,15 @@ protected Message buildListenerForRds(String name, String rdsResourceName) {

@Override
protected Message buildHttpFilter(String name, @Nullable Any typedConfig) {
HttpFilter.Builder builder = HttpFilter.newBuilder().setName(name);
if (typedConfig != null) {
builder.setTypedConfig(typedConfig);
}
return builder.build();
throw new UnsupportedOperationException();
}

@Override
protected Any buildHttpFaultTypedConfig(
@Nullable Long delayNanos, @Nullable Integer delayRate, String upstreamCluster,
List<String> downstreamNodes, @Nullable Integer maxActiveFaults, @Nullable Status status,
@Nullable Integer httpCode, @Nullable Integer abortRate) {
HTTPFault.Builder builder = HTTPFault.newBuilder();
if (delayRate != null) {
FaultDelay.Builder delayBuilder
= FaultDelay.newBuilder();
delayBuilder.setPercentage(
FractionalPercent.newBuilder()
.setNumerator(delayRate).setDenominator(DenominatorType.MILLION));
if (delayNanos != null) {
delayBuilder.setFixedDelay(Durations.fromNanos(delayNanos));
} else {
delayBuilder.setHeaderDelay(HeaderDelay.newBuilder());
}
builder.setDelay(delayBuilder);
}
if (abortRate != null) {
FaultAbort.Builder abortBuilder = FaultAbort.newBuilder();
abortBuilder.setPercentage(
FractionalPercent.newBuilder()
.setNumerator(abortRate).setDenominator(DenominatorType.MILLION));
if (status != null) {
throw new UnsupportedOperationException();
} else if (httpCode != null) {
abortBuilder.setHttpStatus(httpCode);
} else {
abortBuilder.setHeaderAbort(HeaderAbort.newBuilder());
}
builder.setAbort(abortBuilder);
}
builder.setUpstreamCluster(upstreamCluster);
builder.addAllDownstreamNodes(downstreamNodes);
if (maxActiveFaults != null) {
builder.setMaxActiveFaults(UInt32Value.of(maxActiveFaults));
}
return Any.pack(builder.build());
throw new UnsupportedOperationException();
}

@Override
Expand Down

0 comments on commit e870584

Please sign in to comment.