mirror of https://github.com/grpc/grpc-java.git
xds: unify client and server handling HttpConnectionManager (#8228)
Enables parsing HttpConnectionManager filter for the server side TCP listener, with the same codepath for handling it on the client side. Major changes include: - Remodeled LdsUpdate with HttpConnectionManager. Now LdsUpdate is an oneof of HttpConnectionManager (for client side) or Listener (for server side). Each of Listener's FiliterChain contains an HttpConnectionManager (required). Refactored code for validating and parsing the TCP Listener (for server side), put it into ClientXdsClient. The common part of validating/parsing HttpConnectionManager is reused/shared for client side. - Included the name of FilterChain in the parsed form. As specified by the API, each FilterChain has a unique name. If the name is not provided by the control plane, a UUID is used. FilterChain names can be used for bookkeeping a set of FilterChain easily (e.g., used as map key). - Added methods isSupportedOnClients() and isSupportedOnServers() to the Filter interface. Parsing the top-level HttpFilter requires knowing if the HttpFilter implementation is supported for the target usage (client-side or server-side). Note, parsing override HttpFilter configs does not need to know whether the config is used for an HttpFilter that is only supported for the client-side or server side. - Added a new kind of Route: Route with non-forwarding action. Updated the XdsNameResolver being able to handle Route with non-forwarding action: if such a Route is matched to an RPC, that RPC is failed. Note, it is possible that XdsNameResolver receives xDS updates with all Routes with non-forwarding action. That is, the service config will not reference any cluster. Such case can be handled by cluster_manager LB policy's LB config parser: the parser returns the error to Channel and the Channel will handle it as error service config.
This commit is contained in:
parent
2258d2e3e9
commit
9a8bc10f51
|
|
@ -18,7 +18,6 @@ package io.grpc.xds;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static io.grpc.xds.EnvoyServerProtoData.TRANSPORT_SOCKET_NAME_TLS;
|
|
||||||
|
|
||||||
import com.github.udpa.udpa.type.v1.TypedStruct;
|
import com.github.udpa.udpa.type.v1.TypedStruct;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
@ -43,11 +42,13 @@ import io.envoyproxy.envoy.config.core.v3.HttpProtocolOptions;
|
||||||
import io.envoyproxy.envoy.config.core.v3.RoutingPriority;
|
import io.envoyproxy.envoy.config.core.v3.RoutingPriority;
|
||||||
import io.envoyproxy.envoy.config.core.v3.SocketAddress;
|
import io.envoyproxy.envoy.config.core.v3.SocketAddress;
|
||||||
import io.envoyproxy.envoy.config.core.v3.SocketAddress.PortSpecifierCase;
|
import io.envoyproxy.envoy.config.core.v3.SocketAddress.PortSpecifierCase;
|
||||||
|
import io.envoyproxy.envoy.config.core.v3.TrafficDirection;
|
||||||
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment;
|
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment;
|
||||||
import io.envoyproxy.envoy.config.listener.v3.Listener;
|
import io.envoyproxy.envoy.config.listener.v3.Listener;
|
||||||
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
|
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
|
||||||
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
|
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
|
||||||
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.Rds;
|
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.Rds;
|
||||||
|
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext;
|
||||||
import io.envoyproxy.envoy.type.v3.FractionalPercent;
|
import io.envoyproxy.envoy.type.v3.FractionalPercent;
|
||||||
import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType;
|
import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType;
|
||||||
import io.grpc.Context;
|
import io.grpc.Context;
|
||||||
|
|
@ -60,10 +61,16 @@ import io.grpc.internal.TimeProvider;
|
||||||
import io.grpc.xds.Endpoints.DropOverload;
|
import io.grpc.xds.Endpoints.DropOverload;
|
||||||
import io.grpc.xds.Endpoints.LbEndpoint;
|
import io.grpc.xds.Endpoints.LbEndpoint;
|
||||||
import io.grpc.xds.Endpoints.LocalityLbEndpoints;
|
import io.grpc.xds.Endpoints.LocalityLbEndpoints;
|
||||||
|
import io.grpc.xds.EnvoyServerProtoData.CidrRange;
|
||||||
|
import io.grpc.xds.EnvoyServerProtoData.ConnectionSourceType;
|
||||||
|
import io.grpc.xds.EnvoyServerProtoData.FilterChain;
|
||||||
|
import io.grpc.xds.EnvoyServerProtoData.FilterChainMatch;
|
||||||
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
|
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
|
||||||
|
import io.grpc.xds.Filter.ClientInterceptorBuilder;
|
||||||
import io.grpc.xds.Filter.ConfigOrError;
|
import io.grpc.xds.Filter.ConfigOrError;
|
||||||
import io.grpc.xds.Filter.FilterConfig;
|
import io.grpc.xds.Filter.FilterConfig;
|
||||||
import io.grpc.xds.Filter.NamedFilterConfig;
|
import io.grpc.xds.Filter.NamedFilterConfig;
|
||||||
|
import io.grpc.xds.Filter.ServerInterceptorBuilder;
|
||||||
import io.grpc.xds.LoadStatsManager2.ClusterDropStats;
|
import io.grpc.xds.LoadStatsManager2.ClusterDropStats;
|
||||||
import io.grpc.xds.LoadStatsManager2.ClusterLocalityStats;
|
import io.grpc.xds.LoadStatsManager2.ClusterLocalityStats;
|
||||||
import io.grpc.xds.VirtualHost.Route;
|
import io.grpc.xds.VirtualHost.Route;
|
||||||
|
|
@ -76,8 +83,10 @@ import io.grpc.xds.XdsLogger.XdsLogLevel;
|
||||||
import io.grpc.xds.internal.Matchers.FractionMatcher;
|
import io.grpc.xds.internal.Matchers.FractionMatcher;
|
||||||
import io.grpc.xds.internal.Matchers.HeaderMatcher;
|
import io.grpc.xds.internal.Matchers.HeaderMatcher;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
|
@ -85,6 +94,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
@ -97,6 +107,7 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
// Longest time to wait, since the subscription to some resource, for concluding its absence.
|
// Longest time to wait, since the subscription to some resource, for concluding its absence.
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final int INITIAL_RESOURCE_FETCH_TIMEOUT_SEC = 15;
|
static final int INITIAL_RESOURCE_FETCH_TIMEOUT_SEC = 15;
|
||||||
|
private static final String TRANSPORT_SOCKET_NAME_TLS = "envoy.transport_sockets.tls";
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final long DEFAULT_RING_HASH_LB_POLICY_MIN_RING_SIZE = 1024L;
|
static final long DEFAULT_RING_HASH_LB_POLICY_MIN_RING_SIZE = 1024L;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
|
@ -131,6 +142,7 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
private static final String TYPE_URL_FILTER_CONFIG =
|
private static final String TYPE_URL_FILTER_CONFIG =
|
||||||
"type.googleapis.com/envoy.config.route.v3.FilterConfig";
|
"type.googleapis.com/envoy.config.route.v3.FilterConfig";
|
||||||
|
|
||||||
|
private final FilterRegistry filterRegistry = FilterRegistry.getDefaultRegistry();
|
||||||
private final Map<String, ResourceSubscriber> ldsResourceSubscribers = new HashMap<>();
|
private final Map<String, ResourceSubscriber> ldsResourceSubscribers = new HashMap<>();
|
||||||
private final Map<String, ResourceSubscriber> rdsResourceSubscribers = new HashMap<>();
|
private final Map<String, ResourceSubscriber> rdsResourceSubscribers = new HashMap<>();
|
||||||
private final Map<String, ResourceSubscriber> cdsResourceSubscribers = new HashMap<>();
|
private final Map<String, ResourceSubscriber> cdsResourceSubscribers = new HashMap<>();
|
||||||
|
|
@ -182,9 +194,11 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
LdsUpdate ldsUpdate;
|
LdsUpdate ldsUpdate;
|
||||||
try {
|
try {
|
||||||
if (listener.hasApiListener()) {
|
if (listener.hasApiListener()) {
|
||||||
ldsUpdate = processClientSideListener(listener, enableFaultInjection && isResourceV3);
|
ldsUpdate = processClientSideListener(
|
||||||
|
listener, retainedRdsResources, enableFaultInjection && isResourceV3);
|
||||||
} else {
|
} else {
|
||||||
ldsUpdate = processServerSideListener(listener);
|
ldsUpdate = processServerSideListener(
|
||||||
|
listener, retainedRdsResources, enableFaultInjection && isResourceV3);
|
||||||
}
|
}
|
||||||
} catch (ResourceInvalidException e) {
|
} catch (ResourceInvalidException e) {
|
||||||
errors.add(
|
errors.add(
|
||||||
|
|
@ -194,9 +208,6 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
|
|
||||||
// LdsUpdate parsed successfully.
|
// LdsUpdate parsed successfully.
|
||||||
parsedResources.put(listenerName, new ParsedResource(ldsUpdate, resource));
|
parsedResources.put(listenerName, new ParsedResource(ldsUpdate, resource));
|
||||||
if (ldsUpdate.rdsName != null) {
|
|
||||||
retainedRdsResources.add(ldsUpdate.rdsName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
getLogger().log(XdsLogLevel.INFO,
|
getLogger().log(XdsLogLevel.INFO,
|
||||||
"Received LDS Response version {0} nonce {1}. Parsed resources: {2}",
|
"Received LDS Response version {0} nonce {1}. Parsed resources: {2}",
|
||||||
|
|
@ -216,7 +227,8 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LdsUpdate processClientSideListener(Listener listener, boolean parseFilter)
|
private LdsUpdate processClientSideListener(
|
||||||
|
Listener listener, Set<String> rdsResources, boolean parseHttpFilter)
|
||||||
throws ResourceInvalidException {
|
throws ResourceInvalidException {
|
||||||
// Unpack HttpConnectionManager from the Listener.
|
// Unpack HttpConnectionManager from the Listener.
|
||||||
HttpConnectionManager hcm;
|
HttpConnectionManager hcm;
|
||||||
|
|
@ -228,86 +240,262 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
throw new ResourceInvalidException(
|
throw new ResourceInvalidException(
|
||||||
"Could not parse HttpConnectionManager config from ApiListener", e);
|
"Could not parse HttpConnectionManager config from ApiListener", e);
|
||||||
}
|
}
|
||||||
|
return LdsUpdate.forApiListener(parseHttpConnectionManager(
|
||||||
|
hcm, rdsResources, filterRegistry, parseHttpFilter, true /* isForClient */));
|
||||||
|
}
|
||||||
|
|
||||||
|
private LdsUpdate processServerSideListener(
|
||||||
|
Listener proto, Set<String> rdsResources, boolean parseHttpFilter)
|
||||||
|
throws ResourceInvalidException {
|
||||||
|
return LdsUpdate.forTcpListener(parseServerSideListener(
|
||||||
|
proto, rdsResources, tlsContextManager, filterRegistry, parseHttpFilter));
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static EnvoyServerProtoData.Listener parseServerSideListener(
|
||||||
|
Listener proto, Set<String> rdsResources, TlsContextManager tlsContextManager,
|
||||||
|
FilterRegistry filterRegistry, boolean parseHttpFilter) throws ResourceInvalidException {
|
||||||
|
if (!proto.getTrafficDirection().equals(TrafficDirection.INBOUND)) {
|
||||||
|
throw new ResourceInvalidException(
|
||||||
|
"Listener " + proto.getName() + " with invalid traffic direction: "
|
||||||
|
+ proto.getTrafficDirection());
|
||||||
|
}
|
||||||
|
if (!proto.getListenerFiltersList().isEmpty()) {
|
||||||
|
throw new ResourceInvalidException(
|
||||||
|
"Listener " + proto.getName() + " cannot have listener_filters");
|
||||||
|
}
|
||||||
|
if (proto.hasUseOriginalDst()) {
|
||||||
|
throw new ResourceInvalidException(
|
||||||
|
"Listener " + proto.getName() + " cannot have use_original_dst set to true");
|
||||||
|
}
|
||||||
|
|
||||||
|
String address = null;
|
||||||
|
if (proto.getAddress().hasSocketAddress()) {
|
||||||
|
SocketAddress socketAddress = proto.getAddress().getSocketAddress();
|
||||||
|
address = socketAddress.getAddress();
|
||||||
|
switch (socketAddress.getPortSpecifierCase()) {
|
||||||
|
case NAMED_PORT:
|
||||||
|
address = address + ":" + socketAddress.getNamedPort();
|
||||||
|
break;
|
||||||
|
case PORT_VALUE:
|
||||||
|
address = address + ":" + socketAddress.getPortValue();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<FilterChain> filterChains = new ArrayList<>();
|
||||||
|
for (io.envoyproxy.envoy.config.listener.v3.FilterChain fc : proto.getFilterChainsList()) {
|
||||||
|
filterChains.add(
|
||||||
|
parseFilterChain(fc, rdsResources, tlsContextManager, filterRegistry, parseHttpFilter));
|
||||||
|
}
|
||||||
|
FilterChain defaultFilterChain = null;
|
||||||
|
if (proto.hasDefaultFilterChain()) {
|
||||||
|
defaultFilterChain = parseFilterChain(
|
||||||
|
proto.getDefaultFilterChain(), rdsResources, tlsContextManager, filterRegistry,
|
||||||
|
parseHttpFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new EnvoyServerProtoData.Listener(
|
||||||
|
proto.getName(), address, Collections.unmodifiableList(filterChains), defaultFilterChain);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static FilterChain parseFilterChain(
|
||||||
|
io.envoyproxy.envoy.config.listener.v3.FilterChain proto, Set<String> rdsResources,
|
||||||
|
TlsContextManager tlsContextManager, FilterRegistry filterRegistry, boolean parseHttpFilters)
|
||||||
|
throws ResourceInvalidException {
|
||||||
|
io.grpc.xds.HttpConnectionManager httpConnectionManager = null;
|
||||||
|
HashSet<String> uniqueNames = new HashSet<>();
|
||||||
|
for (io.envoyproxy.envoy.config.listener.v3.Filter filter : proto.getFiltersList()) {
|
||||||
|
if (!uniqueNames.add(filter.getName())) {
|
||||||
|
throw new ResourceInvalidException(
|
||||||
|
"FilterChain " + proto.getName() + " with duplicated filter: " + filter.getName());
|
||||||
|
}
|
||||||
|
if (!filter.hasTypedConfig()) {
|
||||||
|
throw new ResourceInvalidException(
|
||||||
|
"FilterChain " + proto.getName() + " contains filter " + filter.getName()
|
||||||
|
+ " without typed_config");
|
||||||
|
}
|
||||||
|
Any any = filter.getTypedConfig();
|
||||||
|
// HttpConnectionManager is the only supported network filter at the moment.
|
||||||
|
if (!any.getTypeUrl().equals(TYPE_URL_HTTP_CONNECTION_MANAGER)) {
|
||||||
|
throw new ResourceInvalidException(
|
||||||
|
"FilterChain " + proto.getName() + " contains filter " + filter.getName()
|
||||||
|
+ " with unsupported typed_config type " + any.getTypeUrl());
|
||||||
|
}
|
||||||
|
if (httpConnectionManager == null) {
|
||||||
|
HttpConnectionManager hcmProto;
|
||||||
|
try {
|
||||||
|
hcmProto = any.unpack(HttpConnectionManager.class);
|
||||||
|
} catch (InvalidProtocolBufferException e) {
|
||||||
|
throw new ResourceInvalidException("FilterChain " + proto.getName() + " with filter "
|
||||||
|
+ filter.getName() + " failed to unpack message", e);
|
||||||
|
}
|
||||||
|
httpConnectionManager = parseHttpConnectionManager(
|
||||||
|
hcmProto, rdsResources, filterRegistry, parseHttpFilters, false /* isForClient */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (httpConnectionManager == null) {
|
||||||
|
throw new ResourceInvalidException("FilterChain " + proto.getName()
|
||||||
|
+ " missing required HttpConnectionManager filter");
|
||||||
|
}
|
||||||
|
|
||||||
|
EnvoyServerProtoData.DownstreamTlsContext downstreamTlsContext = null;
|
||||||
|
if (TRANSPORT_SOCKET_NAME_TLS.equals(proto.getTransportSocket().getName())) {
|
||||||
|
DownstreamTlsContext downstreamTlsContextProto;
|
||||||
|
try {
|
||||||
|
downstreamTlsContextProto =
|
||||||
|
proto.getTransportSocket().getTypedConfig().unpack(DownstreamTlsContext.class);
|
||||||
|
} catch (InvalidProtocolBufferException e) {
|
||||||
|
throw new ResourceInvalidException("FilterChain " + proto.getName()
|
||||||
|
+ " failed to unpack message", e);
|
||||||
|
}
|
||||||
|
downstreamTlsContext =
|
||||||
|
EnvoyServerProtoData.DownstreamTlsContext.fromEnvoyProtoDownstreamTlsContext(
|
||||||
|
downstreamTlsContextProto);
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = proto.getName();
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
name = UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
return new FilterChain(
|
||||||
|
name,
|
||||||
|
parseFilterChainMatch(proto.getFilterChainMatch()),
|
||||||
|
httpConnectionManager,
|
||||||
|
downstreamTlsContext,
|
||||||
|
tlsContextManager
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FilterChainMatch parseFilterChainMatch(
|
||||||
|
io.envoyproxy.envoy.config.listener.v3.FilterChainMatch proto)
|
||||||
|
throws ResourceInvalidException {
|
||||||
|
List<CidrRange> prefixRanges = new ArrayList<>();
|
||||||
|
List<CidrRange> sourcePrefixRanges = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
for (io.envoyproxy.envoy.config.core.v3.CidrRange range : proto.getPrefixRangesList()) {
|
||||||
|
prefixRanges.add(new CidrRange(range.getAddressPrefix(), range.getPrefixLen().getValue()));
|
||||||
|
}
|
||||||
|
for (io.envoyproxy.envoy.config.core.v3.CidrRange range
|
||||||
|
: proto.getSourcePrefixRangesList()) {
|
||||||
|
sourcePrefixRanges.add(
|
||||||
|
new CidrRange(range.getAddressPrefix(), range.getPrefixLen().getValue()));
|
||||||
|
}
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new ResourceInvalidException("Failed to create CidrRange", e);
|
||||||
|
}
|
||||||
|
ConnectionSourceType sourceType;
|
||||||
|
switch (proto.getSourceType()) {
|
||||||
|
case ANY:
|
||||||
|
sourceType = ConnectionSourceType.ANY;
|
||||||
|
break;
|
||||||
|
case EXTERNAL:
|
||||||
|
sourceType = ConnectionSourceType.EXTERNAL;
|
||||||
|
break;
|
||||||
|
case SAME_IP_OR_LOOPBACK:
|
||||||
|
sourceType = ConnectionSourceType.SAME_IP_OR_LOOPBACK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ResourceInvalidException("Unknown source-type: " + proto.getSourceType());
|
||||||
|
}
|
||||||
|
return new FilterChainMatch(
|
||||||
|
proto.getDestinationPort().getValue(),
|
||||||
|
prefixRanges,
|
||||||
|
proto.getApplicationProtocolsList(),
|
||||||
|
sourcePrefixRanges,
|
||||||
|
sourceType,
|
||||||
|
proto.getSourcePortsList(),
|
||||||
|
proto.getServerNamesList(),
|
||||||
|
proto.getTransportProtocol());
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static io.grpc.xds.HttpConnectionManager parseHttpConnectionManager(
|
||||||
|
HttpConnectionManager proto, Set<String> rdsResources, FilterRegistry filterRegistry,
|
||||||
|
boolean parseHttpFilter, boolean isForClient) throws ResourceInvalidException {
|
||||||
|
if (proto.getXffNumTrustedHops() != 0) {
|
||||||
|
throw new ResourceInvalidException(
|
||||||
|
"HttpConnectionManager with xff_num_trusted_hops unsupported");
|
||||||
|
}
|
||||||
// Obtain max_stream_duration from Http Protocol Options.
|
// Obtain max_stream_duration from Http Protocol Options.
|
||||||
long maxStreamDuration = 0;
|
long maxStreamDuration = 0;
|
||||||
if (hcm.hasCommonHttpProtocolOptions()) {
|
if (proto.hasCommonHttpProtocolOptions()) {
|
||||||
HttpProtocolOptions options = hcm.getCommonHttpProtocolOptions();
|
HttpProtocolOptions options = proto.getCommonHttpProtocolOptions();
|
||||||
if (options.hasMaxStreamDuration()) {
|
if (options.hasMaxStreamDuration()) {
|
||||||
maxStreamDuration = Durations.toNanos(options.getMaxStreamDuration());
|
maxStreamDuration = Durations.toNanos(options.getMaxStreamDuration());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse filters.
|
// Parse http filters.
|
||||||
List<NamedFilterConfig> filterChain = null;
|
List<NamedFilterConfig> filterConfigs = null;
|
||||||
if (parseFilter) {
|
if (parseHttpFilter) {
|
||||||
filterChain = new ArrayList<>();
|
filterConfigs = new ArrayList<>();
|
||||||
List<io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter>
|
Set<String> names = new HashSet<>();
|
||||||
httpFilters = hcm.getHttpFiltersList();
|
|
||||||
for (io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter
|
for (io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter
|
||||||
httpFilter : httpFilters) {
|
httpFilter : proto.getHttpFiltersList()) {
|
||||||
String filterName = httpFilter.getName();
|
String filterName = httpFilter.getName();
|
||||||
StructOrError<FilterConfig> filterConfig = parseHttpFilter(httpFilter);
|
if (!names.add(filterName)) {
|
||||||
|
throw new ResourceInvalidException(
|
||||||
|
"HttpConnectionManager contains duplicate HttpFilter: " + filterName);
|
||||||
|
}
|
||||||
|
StructOrError<FilterConfig> filterConfig =
|
||||||
|
parseHttpFilter(httpFilter, filterRegistry, isForClient);
|
||||||
if (filterConfig == null) {
|
if (filterConfig == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (filterConfig.getErrorDetail() != null) {
|
if (filterConfig.getErrorDetail() != null) {
|
||||||
throw new ResourceInvalidException(
|
throw new ResourceInvalidException(
|
||||||
"HttpConnectionManager contains invalid HttpFault filter: "
|
"HttpConnectionManager contains invalid HttpFilter: "
|
||||||
+ filterConfig.getErrorDetail());
|
+ filterConfig.getErrorDetail());
|
||||||
}
|
}
|
||||||
filterChain.add(new NamedFilterConfig(filterName, filterConfig.struct));
|
filterConfigs.add(new NamedFilterConfig(filterName, filterConfig.struct));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse RDS info.
|
// Parse inlined RouteConfiguration or RDS.
|
||||||
if (hcm.hasRouteConfig()) {
|
if (proto.hasRouteConfig()) {
|
||||||
// Found inlined route_config. Parse it to find the cluster_name.
|
|
||||||
List<VirtualHost> virtualHosts = new ArrayList<>();
|
List<VirtualHost> virtualHosts = new ArrayList<>();
|
||||||
for (io.envoyproxy.envoy.config.route.v3.VirtualHost virtualHostProto
|
for (io.envoyproxy.envoy.config.route.v3.VirtualHost virtualHostProto
|
||||||
: hcm.getRouteConfig().getVirtualHostsList()) {
|
: proto.getRouteConfig().getVirtualHostsList()) {
|
||||||
StructOrError<VirtualHost> virtualHost = parseVirtualHost(virtualHostProto, parseFilter);
|
StructOrError<VirtualHost> virtualHost =
|
||||||
|
parseVirtualHost(virtualHostProto, filterRegistry, parseHttpFilter);
|
||||||
if (virtualHost.getErrorDetail() != null) {
|
if (virtualHost.getErrorDetail() != null) {
|
||||||
throw new ResourceInvalidException("HttpConnectionManager contains invalid virtual host: "
|
throw new ResourceInvalidException(
|
||||||
|
"HttpConnectionManager contains invalid virtual host: "
|
||||||
+ virtualHost.getErrorDetail());
|
+ virtualHost.getErrorDetail());
|
||||||
}
|
}
|
||||||
virtualHosts.add(virtualHost.getStruct());
|
virtualHosts.add(virtualHost.getStruct());
|
||||||
}
|
}
|
||||||
return new LdsUpdate(maxStreamDuration, virtualHosts, filterChain);
|
return io.grpc.xds.HttpConnectionManager.forVirtualHosts(
|
||||||
|
maxStreamDuration, virtualHosts, filterConfigs);
|
||||||
}
|
}
|
||||||
|
if (proto.hasRds()) {
|
||||||
if (hcm.hasRds()) {
|
Rds rds = proto.getRds();
|
||||||
// Found RDS.
|
|
||||||
Rds rds = hcm.getRds();
|
|
||||||
if (!rds.hasConfigSource()) {
|
if (!rds.hasConfigSource()) {
|
||||||
throw new ResourceInvalidException("HttpConnectionManager missing config_source for RDS.");
|
throw new ResourceInvalidException(
|
||||||
|
"HttpConnectionManager contains invalid RDS: missing config_source");
|
||||||
}
|
}
|
||||||
if (!rds.getConfigSource().hasAds()) {
|
if (!rds.getConfigSource().hasAds()) {
|
||||||
throw new ResourceInvalidException(
|
throw new ResourceInvalidException(
|
||||||
"HttpConnectionManager ConfigSource for RDS does not specify ADS.");
|
"HttpConnectionManager contains invalid RDS: must specify ADS");
|
||||||
}
|
}
|
||||||
return new LdsUpdate(maxStreamDuration, rds.getRouteConfigName(), filterChain);
|
// Collect the RDS resource referenced by this HttpConnectionManager.
|
||||||
|
rdsResources.add(rds.getRouteConfigName());
|
||||||
|
return io.grpc.xds.HttpConnectionManager.forRdsName(
|
||||||
|
maxStreamDuration, rds.getRouteConfigName(), filterConfigs);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ResourceInvalidException(
|
throw new ResourceInvalidException(
|
||||||
"HttpConnectionManager neither has inlined route_config nor RDS.");
|
"HttpConnectionManager neither has inlined route_config nor RDS");
|
||||||
}
|
|
||||||
|
|
||||||
private LdsUpdate processServerSideListener(Listener listener)
|
|
||||||
throws ResourceInvalidException {
|
|
||||||
StructOrError<EnvoyServerProtoData.Listener> convertedListener =
|
|
||||||
parseServerSideListener(listener, tlsContextManager);
|
|
||||||
if (convertedListener.getErrorDetail() != null) {
|
|
||||||
throw new ResourceInvalidException(convertedListener.getErrorDetail());
|
|
||||||
}
|
|
||||||
return new LdsUpdate(convertedListener.getStruct());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@Nullable // Returns null if the filter is optional but not supported.
|
@Nullable // Returns null if the filter is optional but not supported.
|
||||||
static StructOrError<FilterConfig> parseHttpFilter(
|
static StructOrError<FilterConfig> parseHttpFilter(
|
||||||
io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter
|
io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter
|
||||||
httpFilter) {
|
httpFilter, FilterRegistry filterRegistry, boolean isForClient) {
|
||||||
String filterName = httpFilter.getName();
|
String filterName = httpFilter.getName();
|
||||||
boolean isOptional = httpFilter.getIsOptional();
|
boolean isOptional = httpFilter.getIsOptional();
|
||||||
if (!httpFilter.hasTypedConfig()) {
|
if (!httpFilter.hasTypedConfig()) {
|
||||||
|
|
@ -318,36 +506,12 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
"HttpFilter [" + filterName + "] is not optional and has no typed config");
|
"HttpFilter [" + filterName + "] is not optional and has no typed config");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return parseRawFilterConfig(filterName, httpFilter.getTypedConfig(), isOptional, false);
|
Message rawConfig = httpFilter.getTypedConfig();
|
||||||
}
|
String typeUrl = httpFilter.getTypedConfig().getTypeUrl();
|
||||||
|
if (typeUrl.equals(TYPE_URL_TYPED_STRUCT)) {
|
||||||
@Nullable // Returns null if the filter should be ignored.
|
|
||||||
private static StructOrError<FilterConfig> parseRawFilterConfig(
|
|
||||||
String filterName, Any anyConfig, Boolean isOptional, boolean isOverrideConfig) {
|
|
||||||
checkArgument(
|
|
||||||
isOptional != null || isOverrideConfig, "isOptional can't be null for top-level config");
|
|
||||||
String typeUrl = anyConfig.getTypeUrl();
|
|
||||||
if (isOverrideConfig) {
|
|
||||||
isOptional = false;
|
|
||||||
if (typeUrl.equals(TYPE_URL_FILTER_CONFIG)) {
|
|
||||||
io.envoyproxy.envoy.config.route.v3.FilterConfig filterConfig;
|
|
||||||
try {
|
|
||||||
filterConfig =
|
|
||||||
anyConfig.unpack(io.envoyproxy.envoy.config.route.v3.FilterConfig.class);
|
|
||||||
} catch (InvalidProtocolBufferException e) {
|
|
||||||
return StructOrError.fromError(
|
|
||||||
"HttpFilter [" + filterName + "] contains invalid proto: " + e);
|
|
||||||
}
|
|
||||||
isOptional = filterConfig.getIsOptional();
|
|
||||||
anyConfig = filterConfig.getConfig();
|
|
||||||
typeUrl = anyConfig.getTypeUrl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Message rawConfig = anyConfig;
|
|
||||||
if (anyConfig.getTypeUrl().equals(TYPE_URL_TYPED_STRUCT)) {
|
|
||||||
TypedStruct typedStruct;
|
TypedStruct typedStruct;
|
||||||
try {
|
try {
|
||||||
typedStruct = anyConfig.unpack(TypedStruct.class);
|
typedStruct = httpFilter.getTypedConfig().unpack(TypedStruct.class);
|
||||||
} catch (InvalidProtocolBufferException e) {
|
} catch (InvalidProtocolBufferException e) {
|
||||||
return StructOrError.fromError(
|
return StructOrError.fromError(
|
||||||
"HttpFilter [" + filterName + "] contains invalid proto: " + e);
|
"HttpFilter [" + filterName + "] contains invalid proto: " + e);
|
||||||
|
|
@ -355,18 +519,18 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
typeUrl = typedStruct.getTypeUrl();
|
typeUrl = typedStruct.getTypeUrl();
|
||||||
rawConfig = typedStruct.getValue();
|
rawConfig = typedStruct.getValue();
|
||||||
}
|
}
|
||||||
Filter filter = FilterRegistry.getDefaultRegistry().get(typeUrl);
|
Filter filter = filterRegistry.get(typeUrl);
|
||||||
if (filter == null) {
|
if ((isForClient && !(filter instanceof ClientInterceptorBuilder))
|
||||||
|
|| (!isForClient && !(filter instanceof ServerInterceptorBuilder))) {
|
||||||
if (isOptional) {
|
if (isOptional) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return StructOrError.fromError(
|
return StructOrError.fromError(
|
||||||
"HttpFilter [" + filterName + "] is not optional and has an unsupported config type: "
|
"HttpFilter [" + filterName + "](" + typeUrl + ") is required but unsupported for "
|
||||||
+ typeUrl);
|
+ (isForClient ? "client" : "server"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConfigOrError<? extends FilterConfig> filterConfig = isOverrideConfig
|
ConfigOrError<? extends FilterConfig> filterConfig = filter.parseFilterConfig(rawConfig);
|
||||||
? filter.parseFilterConfigOverride(rawConfig) : filter.parseFilterConfig(rawConfig);
|
|
||||||
if (filterConfig.errorDetail != null) {
|
if (filterConfig.errorDetail != null) {
|
||||||
return StructOrError.fromError(
|
return StructOrError.fromError(
|
||||||
"Invalid filter config for HttpFilter [" + filterName + "]: " + filterConfig.errorDetail);
|
"Invalid filter config for HttpFilter [" + filterName + "]: " + filterConfig.errorDetail);
|
||||||
|
|
@ -374,25 +538,13 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
return StructOrError.fromStruct(filterConfig.config);
|
return StructOrError.fromStruct(filterConfig.config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting static StructOrError<EnvoyServerProtoData.Listener> parseServerSideListener(
|
|
||||||
Listener listener, TlsContextManager tlsContextManager) {
|
|
||||||
try {
|
|
||||||
return StructOrError.fromStruct(
|
|
||||||
EnvoyServerProtoData.Listener.fromEnvoyProtoListener(listener, tlsContextManager));
|
|
||||||
} catch (InvalidProtocolBufferException e) {
|
|
||||||
return StructOrError.fromError(
|
|
||||||
"Failed to unpack Listener " + listener.getName() + ":" + e.getMessage());
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return StructOrError.fromError(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static StructOrError<VirtualHost> parseVirtualHost(
|
private static StructOrError<VirtualHost> parseVirtualHost(
|
||||||
io.envoyproxy.envoy.config.route.v3.VirtualHost proto, boolean parseFilter) {
|
io.envoyproxy.envoy.config.route.v3.VirtualHost proto, FilterRegistry filterRegistry,
|
||||||
|
boolean parseHttpFilter) {
|
||||||
String name = proto.getName();
|
String name = proto.getName();
|
||||||
List<Route> routes = new ArrayList<>(proto.getRoutesCount());
|
List<Route> routes = new ArrayList<>(proto.getRoutesCount());
|
||||||
for (io.envoyproxy.envoy.config.route.v3.Route routeProto : proto.getRoutesList()) {
|
for (io.envoyproxy.envoy.config.route.v3.Route routeProto : proto.getRoutesList()) {
|
||||||
StructOrError<Route> route = parseRoute(routeProto, parseFilter);
|
StructOrError<Route> route = parseRoute(routeProto, filterRegistry, parseHttpFilter);
|
||||||
if (route == null) {
|
if (route == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -402,12 +554,12 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
}
|
}
|
||||||
routes.add(route.getStruct());
|
routes.add(route.getStruct());
|
||||||
}
|
}
|
||||||
if (!parseFilter) {
|
if (!parseHttpFilter) {
|
||||||
return StructOrError.fromStruct(VirtualHost.create(
|
return StructOrError.fromStruct(VirtualHost.create(
|
||||||
name, proto.getDomainsList(), routes, new HashMap<String, FilterConfig>()));
|
name, proto.getDomainsList(), routes, new HashMap<String, FilterConfig>()));
|
||||||
}
|
}
|
||||||
StructOrError<Map<String, FilterConfig>> overrideConfigs =
|
StructOrError<Map<String, FilterConfig>> overrideConfigs =
|
||||||
parseOverrideFilterConfigs(proto.getTypedPerFilterConfigMap());
|
parseOverrideFilterConfigs(proto.getTypedPerFilterConfigMap(), filterRegistry);
|
||||||
if (overrideConfigs.errorDetail != null) {
|
if (overrideConfigs.errorDetail != null) {
|
||||||
return StructOrError.fromError(
|
return StructOrError.fromError(
|
||||||
"VirtualHost [" + proto.getName() + "] contains invalid HttpFilter config: "
|
"VirtualHost [" + proto.getName() + "] contains invalid HttpFilter config: "
|
||||||
|
|
@ -419,18 +571,52 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static StructOrError<Map<String, FilterConfig>> parseOverrideFilterConfigs(
|
static StructOrError<Map<String, FilterConfig>> parseOverrideFilterConfigs(
|
||||||
Map<String, Any> rawFilterConfigMap) {
|
Map<String, Any> rawFilterConfigMap, FilterRegistry filterRegistry) {
|
||||||
Map<String, FilterConfig> overrideConfigs = new HashMap<>();
|
Map<String, FilterConfig> overrideConfigs = new HashMap<>();
|
||||||
for (String name : rawFilterConfigMap.keySet()) {
|
for (String name : rawFilterConfigMap.keySet()) {
|
||||||
Any anyConfig = rawFilterConfigMap.get(name);
|
Any anyConfig = rawFilterConfigMap.get(name);
|
||||||
StructOrError<FilterConfig> filterConfig = parseRawFilterConfig(name, anyConfig, null, true);
|
String typeUrl = anyConfig.getTypeUrl();
|
||||||
if (filterConfig == null) {
|
boolean isOptional = false;
|
||||||
|
if (typeUrl.equals(TYPE_URL_FILTER_CONFIG)) {
|
||||||
|
io.envoyproxy.envoy.config.route.v3.FilterConfig filterConfig;
|
||||||
|
try {
|
||||||
|
filterConfig =
|
||||||
|
anyConfig.unpack(io.envoyproxy.envoy.config.route.v3.FilterConfig.class);
|
||||||
|
} catch (InvalidProtocolBufferException e) {
|
||||||
|
return StructOrError.fromError(
|
||||||
|
"FilterConfig [" + name + "] contains invalid proto: " + e);
|
||||||
|
}
|
||||||
|
isOptional = filterConfig.getIsOptional();
|
||||||
|
anyConfig = filterConfig.getConfig();
|
||||||
|
typeUrl = anyConfig.getTypeUrl();
|
||||||
|
}
|
||||||
|
Message rawConfig = anyConfig;
|
||||||
|
if (typeUrl.equals(TYPE_URL_TYPED_STRUCT)) {
|
||||||
|
TypedStruct typedStruct;
|
||||||
|
try {
|
||||||
|
typedStruct = anyConfig.unpack(TypedStruct.class);
|
||||||
|
} catch (InvalidProtocolBufferException e) {
|
||||||
|
return StructOrError.fromError(
|
||||||
|
"FilterConfig [" + name + "] contains invalid proto: " + e);
|
||||||
|
}
|
||||||
|
typeUrl = typedStruct.getTypeUrl();
|
||||||
|
rawConfig = typedStruct.getValue();
|
||||||
|
}
|
||||||
|
Filter filter = filterRegistry.get(typeUrl);
|
||||||
|
if (filter == null) {
|
||||||
|
if (isOptional) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (filterConfig.errorDetail != null) {
|
return StructOrError.fromError(
|
||||||
return StructOrError.fromError(filterConfig.errorDetail);
|
"HttpFilter [" + name + "](" + typeUrl + ") is required but unsupported");
|
||||||
}
|
}
|
||||||
overrideConfigs.put(name, filterConfig.struct);
|
ConfigOrError<? extends FilterConfig> filterConfig =
|
||||||
|
filter.parseFilterConfigOverride(rawConfig);
|
||||||
|
if (filterConfig.errorDetail != null) {
|
||||||
|
return StructOrError.fromError(
|
||||||
|
"Invalid filter config for HttpFilter [" + name + "]: " + filterConfig.errorDetail);
|
||||||
|
}
|
||||||
|
overrideConfigs.put(name, filterConfig.config);
|
||||||
}
|
}
|
||||||
return StructOrError.fromStruct(overrideConfigs);
|
return StructOrError.fromStruct(overrideConfigs);
|
||||||
}
|
}
|
||||||
|
|
@ -438,51 +624,55 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@Nullable
|
@Nullable
|
||||||
static StructOrError<Route> parseRoute(
|
static StructOrError<Route> parseRoute(
|
||||||
io.envoyproxy.envoy.config.route.v3.Route proto, boolean parseFilter) {
|
io.envoyproxy.envoy.config.route.v3.Route proto, FilterRegistry filterRegistry,
|
||||||
|
boolean parseHttpFilter) {
|
||||||
StructOrError<RouteMatch> routeMatch = parseRouteMatch(proto.getMatch());
|
StructOrError<RouteMatch> routeMatch = parseRouteMatch(proto.getMatch());
|
||||||
if (routeMatch == null) {
|
if (routeMatch == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (routeMatch.getErrorDetail() != null) {
|
if (routeMatch.getErrorDetail() != null) {
|
||||||
return StructOrError.fromError(
|
return StructOrError.fromError(
|
||||||
"Invalid route [" + proto.getName() + "]: " + routeMatch.getErrorDetail());
|
"Route [" + proto.getName() + "] contains invalid RouteMatch: "
|
||||||
|
+ routeMatch.getErrorDetail());
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, FilterConfig> overrideConfigs = Collections.emptyMap();
|
||||||
|
if (parseHttpFilter) {
|
||||||
|
StructOrError<Map<String, FilterConfig>> overrideConfigsOrError =
|
||||||
|
parseOverrideFilterConfigs(proto.getTypedPerFilterConfigMap(), filterRegistry);
|
||||||
|
if (overrideConfigsOrError.errorDetail != null) {
|
||||||
|
return StructOrError.fromError(
|
||||||
|
"Route [" + proto.getName() + "] contains invalid HttpFilter config: "
|
||||||
|
+ overrideConfigsOrError.errorDetail);
|
||||||
|
}
|
||||||
|
overrideConfigs = overrideConfigsOrError.struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
StructOrError<RouteAction> routeAction;
|
|
||||||
switch (proto.getActionCase()) {
|
switch (proto.getActionCase()) {
|
||||||
case ROUTE:
|
case ROUTE:
|
||||||
routeAction = parseRouteAction(proto.getRoute(), parseFilter);
|
StructOrError<RouteAction> routeAction =
|
||||||
break;
|
parseRouteAction(proto.getRoute(), filterRegistry, parseHttpFilter);
|
||||||
case REDIRECT:
|
|
||||||
return StructOrError.fromError("Unsupported action type: redirect");
|
|
||||||
case DIRECT_RESPONSE:
|
|
||||||
return StructOrError.fromError("Unsupported action type: direct_response");
|
|
||||||
case FILTER_ACTION:
|
|
||||||
return StructOrError.fromError("Unsupported action type: filter_action");
|
|
||||||
case ACTION_NOT_SET:
|
|
||||||
default:
|
|
||||||
return StructOrError.fromError("Unknown action type: " + proto.getActionCase());
|
|
||||||
}
|
|
||||||
if (routeAction == null) {
|
if (routeAction == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (routeAction.getErrorDetail() != null) {
|
if (routeAction.errorDetail != null) {
|
||||||
return StructOrError.fromError(
|
return StructOrError.fromError(
|
||||||
"Invalid route [" + proto.getName() + "]: " + routeAction.getErrorDetail());
|
"Route [" + proto.getName() + "] contains invalid RouteAction: "
|
||||||
|
+ routeAction.getErrorDetail());
|
||||||
}
|
}
|
||||||
if (!parseFilter) {
|
return StructOrError.fromStruct(
|
||||||
return StructOrError.fromStruct(Route.create(
|
Route.forAction(routeMatch.struct, routeAction.struct, overrideConfigs));
|
||||||
routeMatch.getStruct(), routeAction.getStruct(), new HashMap<String, FilterConfig>()));
|
case NON_FORWARDING_ACTION:
|
||||||
}
|
return StructOrError.fromStruct(
|
||||||
StructOrError<Map<String, FilterConfig>> overrideConfigs =
|
Route.forNonForwardingAction(routeMatch.struct, overrideConfigs));
|
||||||
parseOverrideFilterConfigs(proto.getTypedPerFilterConfigMap());
|
case REDIRECT:
|
||||||
if (overrideConfigs.errorDetail != null) {
|
case DIRECT_RESPONSE:
|
||||||
|
case FILTER_ACTION:
|
||||||
|
case ACTION_NOT_SET:
|
||||||
|
default:
|
||||||
return StructOrError.fromError(
|
return StructOrError.fromError(
|
||||||
"Route [" + proto.getName() + "] contains invalid HttpFilter config: "
|
"Route [" + proto.getName() + "] with unknown action type: " + proto.getActionCase());
|
||||||
+ overrideConfigs.errorDetail);
|
|
||||||
}
|
}
|
||||||
return StructOrError.fromStruct(Route.create(
|
|
||||||
routeMatch.getStruct(), routeAction.getStruct(), overrideConfigs.struct));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
|
@ -605,10 +795,16 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the RouteAction config. The returned result may contain a (parsed form)
|
||||||
|
* {@link RouteAction} or an error message. Returns {@code null} if the RouteAction
|
||||||
|
* should be ignored.
|
||||||
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@Nullable
|
@Nullable
|
||||||
static StructOrError<RouteAction> parseRouteAction(
|
static StructOrError<RouteAction> parseRouteAction(
|
||||||
io.envoyproxy.envoy.config.route.v3.RouteAction proto, boolean parseFilter) {
|
io.envoyproxy.envoy.config.route.v3.RouteAction proto, FilterRegistry filterRegistry,
|
||||||
|
boolean parseHttpFilter) {
|
||||||
Long timeoutNano = null;
|
Long timeoutNano = null;
|
||||||
if (proto.hasMaxStreamDuration()) {
|
if (proto.hasMaxStreamDuration()) {
|
||||||
io.envoyproxy.envoy.config.route.v3.RouteAction.MaxStreamDuration maxStreamDuration
|
io.envoyproxy.envoy.config.route.v3.RouteAction.MaxStreamDuration maxStreamDuration
|
||||||
|
|
@ -667,7 +863,7 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
for (io.envoyproxy.envoy.config.route.v3.WeightedCluster.ClusterWeight clusterWeight
|
for (io.envoyproxy.envoy.config.route.v3.WeightedCluster.ClusterWeight clusterWeight
|
||||||
: clusterWeights) {
|
: clusterWeights) {
|
||||||
StructOrError<ClusterWeight> clusterWeightOrError =
|
StructOrError<ClusterWeight> clusterWeightOrError =
|
||||||
parseClusterWeight(clusterWeight, parseFilter);
|
parseClusterWeight(clusterWeight, filterRegistry, parseHttpFilter);
|
||||||
if (clusterWeightOrError.getErrorDetail() != null) {
|
if (clusterWeightOrError.getErrorDetail() != null) {
|
||||||
return StructOrError.fromError("RouteAction contains invalid ClusterWeight: "
|
return StructOrError.fromError("RouteAction contains invalid ClusterWeight: "
|
||||||
+ clusterWeightOrError.getErrorDetail());
|
+ clusterWeightOrError.getErrorDetail());
|
||||||
|
|
@ -687,13 +883,13 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static StructOrError<ClusterWeight> parseClusterWeight(
|
static StructOrError<ClusterWeight> parseClusterWeight(
|
||||||
io.envoyproxy.envoy.config.route.v3.WeightedCluster.ClusterWeight proto,
|
io.envoyproxy.envoy.config.route.v3.WeightedCluster.ClusterWeight proto,
|
||||||
boolean parseFilter) {
|
FilterRegistry filterRegistry, boolean parseHttpFilter) {
|
||||||
if (!parseFilter) {
|
if (!parseHttpFilter) {
|
||||||
return StructOrError.fromStruct(ClusterWeight.create(
|
return StructOrError.fromStruct(ClusterWeight.create(
|
||||||
proto.getName(), proto.getWeight().getValue(), new HashMap<String, FilterConfig>()));
|
proto.getName(), proto.getWeight().getValue(), new HashMap<String, FilterConfig>()));
|
||||||
}
|
}
|
||||||
StructOrError<Map<String, FilterConfig>> overrideConfigs =
|
StructOrError<Map<String, FilterConfig>> overrideConfigs =
|
||||||
parseOverrideFilterConfigs(proto.getTypedPerFilterConfigMap());
|
parseOverrideFilterConfigs(proto.getTypedPerFilterConfigMap(), filterRegistry);
|
||||||
if (overrideConfigs.errorDetail != null) {
|
if (overrideConfigs.errorDetail != null) {
|
||||||
return StructOrError.fromError(
|
return StructOrError.fromError(
|
||||||
"ClusterWeight [" + proto.getName() + "] contains invalid HttpFilter config: "
|
"ClusterWeight [" + proto.getName() + "] contains invalid HttpFilter config: "
|
||||||
|
|
@ -728,7 +924,8 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
RdsUpdate rdsUpdate;
|
RdsUpdate rdsUpdate;
|
||||||
boolean isResourceV3 = resource.getTypeUrl().equals(ResourceType.RDS.typeUrl());
|
boolean isResourceV3 = resource.getTypeUrl().equals(ResourceType.RDS.typeUrl());
|
||||||
try {
|
try {
|
||||||
rdsUpdate = processRouteConfiguration(routeConfig, enableFaultInjection && isResourceV3);
|
rdsUpdate = processRouteConfiguration(
|
||||||
|
routeConfig, filterRegistry, enableFaultInjection && isResourceV3);
|
||||||
} catch (ResourceInvalidException e) {
|
} catch (ResourceInvalidException e) {
|
||||||
errors.add(
|
errors.add(
|
||||||
"RDS response RouteConfiguration '" + routeConfigName + "' validation error: " + e
|
"RDS response RouteConfiguration '" + routeConfigName + "' validation error: " + e
|
||||||
|
|
@ -750,11 +947,13 @@ final class ClientXdsClient extends AbstractXdsClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RdsUpdate processRouteConfiguration(
|
private static RdsUpdate processRouteConfiguration(
|
||||||
RouteConfiguration routeConfig, boolean parseFilter) throws ResourceInvalidException {
|
RouteConfiguration routeConfig, FilterRegistry filterRegistry, boolean parseHttpFilter)
|
||||||
|
throws ResourceInvalidException {
|
||||||
List<VirtualHost> virtualHosts = new ArrayList<>(routeConfig.getVirtualHostsCount());
|
List<VirtualHost> virtualHosts = new ArrayList<>(routeConfig.getVirtualHostsCount());
|
||||||
for (io.envoyproxy.envoy.config.route.v3.VirtualHost virtualHostProto
|
for (io.envoyproxy.envoy.config.route.v3.VirtualHost virtualHostProto
|
||||||
: routeConfig.getVirtualHostsList()) {
|
: routeConfig.getVirtualHostsList()) {
|
||||||
StructOrError<VirtualHost> virtualHost = parseVirtualHost(virtualHostProto, parseFilter);
|
StructOrError<VirtualHost> virtualHost =
|
||||||
|
parseVirtualHost(virtualHostProto, filterRegistry, parseHttpFilter);
|
||||||
if (virtualHost.getErrorDetail() != null) {
|
if (virtualHost.getErrorDetail() != null) {
|
||||||
throw new ResourceInvalidException(
|
throw new ResourceInvalidException(
|
||||||
"RouteConfiguration contains invalid virtual host: " + virtualHost.getErrorDetail());
|
"RouteConfiguration contains invalid virtual host: " + virtualHost.getErrorDetail());
|
||||||
|
|
|
||||||
|
|
@ -16,24 +16,16 @@
|
||||||
|
|
||||||
package io.grpc.xds;
|
package io.grpc.xds;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.protobuf.Any;
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.Address;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.SocketAddress;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.TrafficDirection;
|
|
||||||
import io.envoyproxy.envoy.config.listener.v3.Filter;
|
|
||||||
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
|
|
||||||
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter;
|
|
||||||
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext;
|
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext;
|
||||||
import io.grpc.Internal;
|
import io.grpc.Internal;
|
||||||
import io.grpc.xds.internal.sds.SslContextProviderSupplier;
|
import io.grpc.xds.internal.sds.SslContextProviderSupplier;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
@ -45,8 +37,6 @@ import javax.annotation.Nullable;
|
||||||
@Internal
|
@Internal
|
||||||
public final class EnvoyServerProtoData {
|
public final class EnvoyServerProtoData {
|
||||||
|
|
||||||
static final String TRANSPORT_SOCKET_NAME_TLS = "envoy.transport_sockets.tls";
|
|
||||||
|
|
||||||
// Prevent instantiation.
|
// Prevent instantiation.
|
||||||
private EnvoyServerProtoData() {
|
private EnvoyServerProtoData() {
|
||||||
}
|
}
|
||||||
|
|
@ -156,21 +146,11 @@ public final class EnvoyServerProtoData {
|
||||||
private final InetAddress addressPrefix;
|
private final InetAddress addressPrefix;
|
||||||
private final int prefixLen;
|
private final int prefixLen;
|
||||||
|
|
||||||
@VisibleForTesting
|
CidrRange(String addressPrefix, int prefixLen) throws UnknownHostException {
|
||||||
CidrRange(String addressPrefix, int prefixLen) throws InvalidProtocolBufferException {
|
|
||||||
try {
|
|
||||||
this.addressPrefix = InetAddress.getByName(addressPrefix);
|
this.addressPrefix = InetAddress.getByName(addressPrefix);
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
throw new InvalidProtocolBufferException(e.getMessage());
|
|
||||||
}
|
|
||||||
this.prefixLen = prefixLen;
|
this.prefixLen = prefixLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CidrRange fromEnvoyProtoCidrRange(
|
|
||||||
io.envoyproxy.envoy.config.core.v3.CidrRange proto) throws InvalidProtocolBufferException {
|
|
||||||
return new CidrRange(proto.getAddressPrefix(), proto.getPrefixLen().getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
public InetAddress getAddressPrefix() {
|
public InetAddress getAddressPrefix() {
|
||||||
return addressPrefix;
|
return addressPrefix;
|
||||||
}
|
}
|
||||||
|
|
@ -251,50 +231,6 @@ public final class EnvoyServerProtoData {
|
||||||
this.transportProtocol = transportProtocol;
|
this.transportProtocol = transportProtocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FilterChainMatch fromEnvoyProtoFilterChainMatch(
|
|
||||||
io.envoyproxy.envoy.config.listener.v3.FilterChainMatch proto)
|
|
||||||
throws InvalidProtocolBufferException {
|
|
||||||
List<CidrRange> prefixRanges = new ArrayList<>();
|
|
||||||
for (io.envoyproxy.envoy.config.core.v3.CidrRange range : proto.getPrefixRangesList()) {
|
|
||||||
prefixRanges.add(CidrRange.fromEnvoyProtoCidrRange(range));
|
|
||||||
}
|
|
||||||
List<CidrRange> sourcePrefixRanges = new ArrayList<>();
|
|
||||||
for (io.envoyproxy.envoy.config.core.v3.CidrRange range : proto.getSourcePrefixRangesList()) {
|
|
||||||
sourcePrefixRanges.add(CidrRange.fromEnvoyProtoCidrRange(range));
|
|
||||||
}
|
|
||||||
List<String> applicationProtocols = new ArrayList<>();
|
|
||||||
for (String appProtocol : proto.getApplicationProtocolsList()) {
|
|
||||||
applicationProtocols.add(appProtocol);
|
|
||||||
}
|
|
||||||
ConnectionSourceType sourceType = null;
|
|
||||||
switch (proto.getSourceType()) {
|
|
||||||
case ANY:
|
|
||||||
sourceType = ConnectionSourceType.ANY;
|
|
||||||
break;
|
|
||||||
case EXTERNAL:
|
|
||||||
sourceType = ConnectionSourceType.EXTERNAL;
|
|
||||||
break;
|
|
||||||
case SAME_IP_OR_LOOPBACK:
|
|
||||||
sourceType = ConnectionSourceType.SAME_IP_OR_LOOPBACK;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new InvalidProtocolBufferException("Unknown source-type:" + proto.getSourceType());
|
|
||||||
}
|
|
||||||
List<String> serverNames = new ArrayList<>();
|
|
||||||
for (String serverName : proto.getServerNamesList()) {
|
|
||||||
serverNames.add(serverName);
|
|
||||||
}
|
|
||||||
return new FilterChainMatch(
|
|
||||||
proto.getDestinationPort().getValue(),
|
|
||||||
prefixRanges,
|
|
||||||
applicationProtocols,
|
|
||||||
sourcePrefixRanges,
|
|
||||||
sourceType,
|
|
||||||
proto.getSourcePortsList(),
|
|
||||||
serverNames,
|
|
||||||
proto.getTransportProtocol());
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDestinationPort() {
|
public int getDestinationPort() {
|
||||||
return destinationPort;
|
return destinationPort;
|
||||||
}
|
}
|
||||||
|
|
@ -378,116 +314,43 @@ public final class EnvoyServerProtoData {
|
||||||
* Corresponds to Envoy proto message {@link io.envoyproxy.envoy.api.v2.listener.FilterChain}.
|
* Corresponds to Envoy proto message {@link io.envoyproxy.envoy.api.v2.listener.FilterChain}.
|
||||||
*/
|
*/
|
||||||
static final class FilterChain {
|
static final class FilterChain {
|
||||||
|
// Unique name for the FilterChain.
|
||||||
|
private final String name;
|
||||||
// TODO(sanjaypujare): flatten structure by moving FilterChainMatch class members here.
|
// TODO(sanjaypujare): flatten structure by moving FilterChainMatch class members here.
|
||||||
private final FilterChainMatch filterChainMatch;
|
private final FilterChainMatch filterChainMatch;
|
||||||
|
private final HttpConnectionManager httpConnectionManager;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final SslContextProviderSupplier sslContextProviderSupplier;
|
private final SslContextProviderSupplier sslContextProviderSupplier;
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
FilterChain(
|
FilterChain(
|
||||||
FilterChainMatch filterChainMatch, @Nullable DownstreamTlsContext downstreamTlsContext,
|
String name,
|
||||||
|
FilterChainMatch filterChainMatch,
|
||||||
|
HttpConnectionManager httpConnectionManager,
|
||||||
|
@Nullable DownstreamTlsContext downstreamTlsContext,
|
||||||
TlsContextManager tlsContextManager) {
|
TlsContextManager tlsContextManager) {
|
||||||
SslContextProviderSupplier sslContextProviderSupplier1 = downstreamTlsContext == null ? null
|
SslContextProviderSupplier sslContextProviderSupplier1 = downstreamTlsContext == null ? null
|
||||||
: new SslContextProviderSupplier(downstreamTlsContext, tlsContextManager);
|
: new SslContextProviderSupplier(downstreamTlsContext, tlsContextManager);
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
// TODO(chengyuanzhang): enforce non-null, change tests to use a default/empty
|
||||||
|
// FilterChainMatch instead of null, as that's how the proto is converted.
|
||||||
this.filterChainMatch = filterChainMatch;
|
this.filterChainMatch = filterChainMatch;
|
||||||
this.sslContextProviderSupplier = sslContextProviderSupplier1;
|
this.sslContextProviderSupplier = sslContextProviderSupplier1;
|
||||||
|
this.httpConnectionManager = checkNotNull(httpConnectionManager, "httpConnectionManager");
|
||||||
}
|
}
|
||||||
|
|
||||||
static FilterChain fromEnvoyProtoFilterChain(
|
String getName() {
|
||||||
io.envoyproxy.envoy.config.listener.v3.FilterChain proto,
|
return name;
|
||||||
TlsContextManager tlsContextManager, boolean isDefaultFilterChain)
|
|
||||||
throws InvalidProtocolBufferException {
|
|
||||||
if (!isDefaultFilterChain && proto.getFiltersList().isEmpty()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"filerChain " + proto.getName() + " has to have envoy.http_connection_manager");
|
|
||||||
}
|
|
||||||
HashSet<String> uniqueNames = new HashSet<>();
|
|
||||||
for (Filter filter : proto.getFiltersList()) {
|
|
||||||
if (!uniqueNames.add(filter.getName())) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"filerChain " + proto.getName() + " has non-unique filter name:" + filter.getName());
|
|
||||||
}
|
|
||||||
validateFilter(filter);
|
|
||||||
}
|
|
||||||
return new FilterChain(
|
|
||||||
FilterChainMatch.fromEnvoyProtoFilterChainMatch(proto.getFilterChainMatch()),
|
|
||||||
getTlsContextFromFilterChain(proto),
|
|
||||||
tlsContextManager
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void validateFilter(Filter filter)
|
|
||||||
throws InvalidProtocolBufferException, IllegalArgumentException {
|
|
||||||
if (filter.hasConfigDiscovery()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"filter " + filter.getName() + " with config_discovery not supported");
|
|
||||||
}
|
|
||||||
if (!filter.hasTypedConfig()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"filter " + filter.getName() + " expected to have typed_config");
|
|
||||||
}
|
|
||||||
Any any = filter.getTypedConfig();
|
|
||||||
if (!any.getTypeUrl().equals(ClientXdsClient.TYPE_URL_HTTP_CONNECTION_MANAGER)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"filter " + filter.getName() + " with unsupported typed_config type:" + any
|
|
||||||
.getTypeUrl());
|
|
||||||
}
|
|
||||||
validateHttpConnectionManager(any.unpack(HttpConnectionManager.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void validateHttpConnectionManager(HttpConnectionManager hcm)
|
|
||||||
throws IllegalArgumentException {
|
|
||||||
List<HttpFilter> httpFilters = hcm.getHttpFiltersList();
|
|
||||||
HashSet<String> uniqueNames = new HashSet<>();
|
|
||||||
for (HttpFilter httpFilter : httpFilters) {
|
|
||||||
String httpFilterName = httpFilter.getName();
|
|
||||||
if (!uniqueNames.add(httpFilterName)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"http-connection-manager has non-unique http-filter name:" + httpFilterName);
|
|
||||||
}
|
|
||||||
if (!httpFilter.getIsOptional()) {
|
|
||||||
if (httpFilter.hasConfigDiscovery()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"http-connection-manager http-filter " + httpFilterName
|
|
||||||
+ " uses config-discovery which is unsupported");
|
|
||||||
}
|
|
||||||
if (httpFilter.hasTypedConfig()) {
|
|
||||||
Any any = httpFilter.getTypedConfig();
|
|
||||||
if (!any.getTypeUrl()
|
|
||||||
.equals("type.googleapis.com/envoy.extensions.filters.http.router.v3.Router")) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"http-connection-manager http-filter " + httpFilterName
|
|
||||||
+ " has unsupported typed-config type:" + any.getTypeUrl());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"http-connection-manager http-filter "
|
|
||||||
+ httpFilterName
|
|
||||||
+ " should have typed-config type "
|
|
||||||
+ "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static DownstreamTlsContext getTlsContextFromFilterChain(
|
|
||||||
io.envoyproxy.envoy.config.listener.v3.FilterChain filterChain)
|
|
||||||
throws InvalidProtocolBufferException {
|
|
||||||
if (filterChain.hasTransportSocket()
|
|
||||||
&& TRANSPORT_SOCKET_NAME_TLS.equals(filterChain.getTransportSocket().getName())) {
|
|
||||||
Any any = filterChain.getTransportSocket().getTypedConfig();
|
|
||||||
return DownstreamTlsContext.fromEnvoyProtoDownstreamTlsContext(
|
|
||||||
io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext.parseFrom(
|
|
||||||
any.getValue()));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FilterChainMatch getFilterChainMatch() {
|
public FilterChainMatch getFilterChainMatch() {
|
||||||
return filterChainMatch;
|
return filterChainMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpConnectionManager getHttpConnectionManager() {
|
||||||
|
return httpConnectionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public SslContextProviderSupplier getSslContextProviderSupplier() {
|
public SslContextProviderSupplier getSslContextProviderSupplier() {
|
||||||
return sslContextProviderSupplier;
|
return sslContextProviderSupplier;
|
||||||
}
|
}
|
||||||
|
|
@ -501,21 +364,26 @@ public final class EnvoyServerProtoData {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
FilterChain that = (FilterChain) o;
|
FilterChain that = (FilterChain) o;
|
||||||
return java.util.Objects.equals(filterChainMatch, that.filterChainMatch)
|
return Objects.equals(name, that.name)
|
||||||
&& java.util.Objects.equals(sslContextProviderSupplier, that.sslContextProviderSupplier);
|
&& Objects.equals(filterChainMatch, that.filterChainMatch)
|
||||||
|
&& Objects.equals(httpConnectionManager, that.httpConnectionManager)
|
||||||
|
&& Objects.equals(sslContextProviderSupplier, that.sslContextProviderSupplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return java.util.Objects.hash(filterChainMatch, sslContextProviderSupplier);
|
return Objects.hash(
|
||||||
|
name, filterChainMatch, httpConnectionManager, sslContextProviderSupplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "FilterChain{"
|
return MoreObjects.toStringHelper(this)
|
||||||
+ "filterChainMatch=" + filterChainMatch
|
.add("name", name)
|
||||||
+ ", sslContextProviderSupplier=" + sslContextProviderSupplier
|
.add("filterChainMatch", filterChainMatch)
|
||||||
+ '}';
|
.add("httpConnectionManager", httpConnectionManager)
|
||||||
|
.add("sslContextProviderSupplier", sslContextProviderSupplier)
|
||||||
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -528,73 +396,22 @@ public final class EnvoyServerProtoData {
|
||||||
@Nullable
|
@Nullable
|
||||||
private final String address;
|
private final String address;
|
||||||
private final List<FilterChain> filterChains;
|
private final List<FilterChain> filterChains;
|
||||||
|
@Nullable
|
||||||
private final FilterChain defaultFilterChain;
|
private final FilterChain defaultFilterChain;
|
||||||
|
|
||||||
@VisibleForTesting
|
Listener(String name, @Nullable String address,
|
||||||
Listener(String name, String address,
|
List<FilterChain> filterChains, @Nullable FilterChain defaultFilterChain) {
|
||||||
List<FilterChain> filterChains, FilterChain defaultFilterChain) {
|
this.name = checkNotNull(name, "name");
|
||||||
this.name = name;
|
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.filterChains = Collections.unmodifiableList(filterChains);
|
this.filterChains = Collections.unmodifiableList(checkNotNull(filterChains, "filterChains"));
|
||||||
this.defaultFilterChain = defaultFilterChain;
|
this.defaultFilterChain = defaultFilterChain;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String convertEnvoyAddressToString(Address proto) {
|
|
||||||
if (proto.hasSocketAddress()) {
|
|
||||||
SocketAddress socketAddress = proto.getSocketAddress();
|
|
||||||
String address = socketAddress.getAddress();
|
|
||||||
switch (socketAddress.getPortSpecifierCase()) {
|
|
||||||
case NAMED_PORT:
|
|
||||||
return address + ":" + socketAddress.getNamedPort();
|
|
||||||
case PORT_VALUE:
|
|
||||||
return address + ":" + socketAddress.getPortValue();
|
|
||||||
default:
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Listener fromEnvoyProtoListener(io.envoyproxy.envoy.config.listener.v3.Listener proto,
|
|
||||||
TlsContextManager tlsContextManager)
|
|
||||||
throws InvalidProtocolBufferException {
|
|
||||||
if (!proto.getTrafficDirection().equals(TrafficDirection.INBOUND)) {
|
|
||||||
throw new IllegalArgumentException("Listener " + proto.getName() + " is not INBOUND");
|
|
||||||
}
|
|
||||||
if (!proto.getListenerFiltersList().isEmpty()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Listener " + proto.getName() + " cannot have listener_filters");
|
|
||||||
}
|
|
||||||
if (proto.hasUseOriginalDst()) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Listener " + proto.getName() + " cannot have use_original_dst set to true");
|
|
||||||
}
|
|
||||||
List<FilterChain> filterChains = validateAndSelectFilterChains(proto.getFilterChainsList(),
|
|
||||||
tlsContextManager);
|
|
||||||
return new Listener(
|
|
||||||
proto.getName(),
|
|
||||||
convertEnvoyAddressToString(proto.getAddress()),
|
|
||||||
filterChains, FilterChain
|
|
||||||
.fromEnvoyProtoFilterChain(proto.getDefaultFilterChain(), tlsContextManager, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<FilterChain> validateAndSelectFilterChains(
|
|
||||||
List<io.envoyproxy.envoy.config.listener.v3.FilterChain> inputFilterChains,
|
|
||||||
TlsContextManager tlsContextManager)
|
|
||||||
throws InvalidProtocolBufferException {
|
|
||||||
List<FilterChain> filterChains = new ArrayList<>(inputFilterChains.size());
|
|
||||||
for (io.envoyproxy.envoy.config.listener.v3.FilterChain filterChain :
|
|
||||||
inputFilterChains) {
|
|
||||||
filterChains
|
|
||||||
.add(FilterChain.fromEnvoyProtoFilterChain(filterChain, tlsContextManager, false));
|
|
||||||
}
|
|
||||||
return filterChains;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public String getAddress() {
|
public String getAddress() {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
@ -603,6 +420,7 @@ public final class EnvoyServerProtoData {
|
||||||
return filterChains;
|
return filterChains;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public FilterChain getDefaultFilterChain() {
|
public FilterChain getDefaultFilterChain() {
|
||||||
return defaultFilterChain;
|
return defaultFilterChain;
|
||||||
}
|
}
|
||||||
|
|
@ -629,18 +447,12 @@ public final class EnvoyServerProtoData {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Listener{"
|
return MoreObjects.toStringHelper(this)
|
||||||
+ "name='"
|
.add("name", name)
|
||||||
+ name
|
.add("address", address)
|
||||||
+ '\''
|
.add("filterChains", filterChains)
|
||||||
+ ", address='"
|
.add("defaultFilterChain", defaultFilterChain)
|
||||||
+ address
|
.toString();
|
||||||
+ '\''
|
|
||||||
+ ", filterChains="
|
|
||||||
+ filterChains
|
|
||||||
+ ", defaultFilterChain="
|
|
||||||
+ defaultFilterChain
|
|
||||||
+ '}';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021 The gRPC Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.grpc.xds;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import com.google.auto.value.AutoValue;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import io.grpc.xds.Filter.NamedFilterConfig;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HttpConnectionManager is a network filter for proxying HTTP requests.
|
||||||
|
*/
|
||||||
|
@AutoValue
|
||||||
|
abstract class HttpConnectionManager {
|
||||||
|
// Total number of nanoseconds to keep alive an HTTP request/response stream.
|
||||||
|
abstract long httpMaxStreamDurationNano();
|
||||||
|
|
||||||
|
// Name of the route configuration to be used for RDS resource discovery.
|
||||||
|
@Nullable
|
||||||
|
abstract String rdsName();
|
||||||
|
|
||||||
|
// List of virtual hosts that make up the route table.
|
||||||
|
@Nullable
|
||||||
|
abstract ImmutableList<VirtualHost> virtualHosts();
|
||||||
|
|
||||||
|
// List of http filter configs. Null if HttpFilter support is not enabled.
|
||||||
|
@Nullable
|
||||||
|
abstract ImmutableList<NamedFilterConfig> httpFilterConfigs();
|
||||||
|
|
||||||
|
static HttpConnectionManager forRdsName(long httpMaxStreamDurationNano, String rdsName,
|
||||||
|
@Nullable List<NamedFilterConfig> httpFilterConfigs) {
|
||||||
|
checkNotNull(rdsName, "rdsName");
|
||||||
|
return create(httpMaxStreamDurationNano, rdsName, null, httpFilterConfigs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HttpConnectionManager forVirtualHosts(long httpMaxStreamDurationNano,
|
||||||
|
List<VirtualHost> virtualHosts, @Nullable List<NamedFilterConfig> httpFilterConfigs) {
|
||||||
|
checkNotNull(virtualHosts, "virtualHosts");
|
||||||
|
return create(httpMaxStreamDurationNano, null, virtualHosts,
|
||||||
|
httpFilterConfigs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpConnectionManager create(long httpMaxStreamDurationNano,
|
||||||
|
@Nullable String rdsName, @Nullable List<VirtualHost> virtualHosts,
|
||||||
|
@Nullable List<NamedFilterConfig> httpFilterConfigs) {
|
||||||
|
return new AutoValue_HttpConnectionManager(
|
||||||
|
httpMaxStreamDurationNano, rdsName,
|
||||||
|
virtualHosts == null ? null : ImmutableList.copyOf(virtualHosts),
|
||||||
|
httpFilterConfigs == null ? null : ImmutableList.copyOf(httpFilterConfigs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,14 +19,16 @@ package io.grpc.xds;
|
||||||
import com.google.protobuf.Message;
|
import com.google.protobuf.Message;
|
||||||
import io.grpc.ClientInterceptor;
|
import io.grpc.ClientInterceptor;
|
||||||
import io.grpc.LoadBalancer.PickSubchannelArgs;
|
import io.grpc.LoadBalancer.PickSubchannelArgs;
|
||||||
|
import io.grpc.ServerInterceptor;
|
||||||
import io.grpc.xds.Filter.ClientInterceptorBuilder;
|
import io.grpc.xds.Filter.ClientInterceptorBuilder;
|
||||||
|
import io.grpc.xds.Filter.ServerInterceptorBuilder;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Router filter implementation. Currently this filter does not parse any field in the config.
|
* Router filter implementation. Currently this filter does not parse any field in the config.
|
||||||
*/
|
*/
|
||||||
enum RouterFilter implements Filter, ClientInterceptorBuilder {
|
enum RouterFilter implements Filter, ClientInterceptorBuilder, ServerInterceptorBuilder {
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
static final String TYPE_URL =
|
static final String TYPE_URL =
|
||||||
|
|
@ -66,4 +68,11 @@ enum RouterFilter implements Filter, ClientInterceptorBuilder {
|
||||||
ScheduledExecutorService scheduler) {
|
ScheduledExecutorService scheduler) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public ServerInterceptor buildServerInterceptor(
|
||||||
|
FilterConfig config, @Nullable Filter.FilterConfig overrideConfig) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,12 +57,23 @@ abstract class VirtualHost {
|
||||||
abstract static class Route {
|
abstract static class Route {
|
||||||
abstract RouteMatch routeMatch();
|
abstract RouteMatch routeMatch();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
abstract RouteAction routeAction();
|
abstract RouteAction routeAction();
|
||||||
|
|
||||||
abstract ImmutableMap<String, FilterConfig> filterConfigOverrides();
|
abstract ImmutableMap<String, FilterConfig> filterConfigOverrides();
|
||||||
|
|
||||||
static Route create(
|
static Route forAction(RouteMatch routeMatch, RouteAction routeAction,
|
||||||
RouteMatch routeMatch, RouteAction routeAction,
|
Map<String, FilterConfig> filterConfigOverrides) {
|
||||||
|
return create(routeMatch, routeAction, filterConfigOverrides);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Route forNonForwardingAction(RouteMatch routeMatch,
|
||||||
|
Map<String, FilterConfig> filterConfigOverrides) {
|
||||||
|
return create(routeMatch, null, filterConfigOverrides);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Route create(
|
||||||
|
RouteMatch routeMatch, @Nullable RouteAction routeAction,
|
||||||
Map<String, FilterConfig> filterConfigOverrides) {
|
Map<String, FilterConfig> filterConfigOverrides) {
|
||||||
return new AutoValue_VirtualHost_Route(
|
return new AutoValue_VirtualHost_Route(
|
||||||
routeMatch, routeAction, ImmutableMap.copyOf(filterConfigOverrides));
|
routeMatch, routeAction, ImmutableMap.copyOf(filterConfigOverrides));
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import com.google.auto.value.AutoValue;
|
import com.google.auto.value.AutoValue;
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.base.MoreObjects.ToStringHelper;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.protobuf.Any;
|
import com.google.protobuf.Any;
|
||||||
import io.grpc.Status;
|
import io.grpc.Status;
|
||||||
|
|
@ -29,7 +28,6 @@ import io.grpc.xds.Endpoints.DropOverload;
|
||||||
import io.grpc.xds.Endpoints.LocalityLbEndpoints;
|
import io.grpc.xds.Endpoints.LocalityLbEndpoints;
|
||||||
import io.grpc.xds.EnvoyServerProtoData.Listener;
|
import io.grpc.xds.EnvoyServerProtoData.Listener;
|
||||||
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
|
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
|
||||||
import io.grpc.xds.Filter.NamedFilterConfig;
|
|
||||||
import io.grpc.xds.LoadStatsManager2.ClusterDropStats;
|
import io.grpc.xds.LoadStatsManager2.ClusterDropStats;
|
||||||
import io.grpc.xds.LoadStatsManager2.ClusterLocalityStats;
|
import io.grpc.xds.LoadStatsManager2.ClusterLocalityStats;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -48,92 +46,25 @@ import javax.annotation.Nullable;
|
||||||
*/
|
*/
|
||||||
abstract class XdsClient {
|
abstract class XdsClient {
|
||||||
|
|
||||||
static final class LdsUpdate implements ResourceUpdate {
|
@AutoValue
|
||||||
// Total number of nanoseconds to keep alive an HTTP request/response stream.
|
abstract static class LdsUpdate implements ResourceUpdate {
|
||||||
final long httpMaxStreamDurationNano;
|
// Http level api listener configuration.
|
||||||
// The name of the route configuration to be used for RDS resource discovery.
|
|
||||||
@Nullable
|
@Nullable
|
||||||
final String rdsName;
|
abstract HttpConnectionManager httpConnectionManager();
|
||||||
// The list virtual hosts that make up the route table.
|
|
||||||
|
// Tcp level listener configuration.
|
||||||
@Nullable
|
@Nullable
|
||||||
final List<VirtualHost> virtualHosts;
|
abstract Listener listener();
|
||||||
// Filter instance names. Null if HttpFilter support is not enabled.
|
|
||||||
@Nullable final List<NamedFilterConfig> filterChain;
|
|
||||||
// Server side Listener.
|
|
||||||
@Nullable
|
|
||||||
final Listener listener;
|
|
||||||
|
|
||||||
LdsUpdate(
|
static LdsUpdate forApiListener(HttpConnectionManager httpConnectionManager) {
|
||||||
long httpMaxStreamDurationNano, String rdsName,
|
checkNotNull(httpConnectionManager, "httpConnectionManager");
|
||||||
@Nullable List<NamedFilterConfig> filterChain) {
|
return new AutoValue_XdsClient_LdsUpdate(httpConnectionManager, null);
|
||||||
this(httpMaxStreamDurationNano, rdsName, null, filterChain);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LdsUpdate(
|
static LdsUpdate forTcpListener(Listener listener) {
|
||||||
long httpMaxStreamDurationNano, List<VirtualHost> virtualHosts,
|
checkNotNull(listener, "listener");
|
||||||
@Nullable List<NamedFilterConfig> filterChain) {
|
return new AutoValue_XdsClient_LdsUpdate(null, listener);
|
||||||
this(httpMaxStreamDurationNano, null, virtualHosts, filterChain);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LdsUpdate(
|
|
||||||
long httpMaxStreamDurationNano, @Nullable String rdsName,
|
|
||||||
@Nullable List<VirtualHost> virtualHosts, @Nullable List<NamedFilterConfig> filterChain) {
|
|
||||||
this.httpMaxStreamDurationNano = httpMaxStreamDurationNano;
|
|
||||||
this.rdsName = rdsName;
|
|
||||||
this.virtualHosts = virtualHosts == null
|
|
||||||
? null : Collections.unmodifiableList(new ArrayList<>(virtualHosts));
|
|
||||||
this.filterChain = filterChain == null ? null : Collections.unmodifiableList(filterChain);
|
|
||||||
this.listener = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
LdsUpdate(Listener listener) {
|
|
||||||
this.listener = listener;
|
|
||||||
this.httpMaxStreamDurationNano = 0L;
|
|
||||||
this.rdsName = null;
|
|
||||||
this.filterChain = null;
|
|
||||||
this.virtualHosts = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(
|
|
||||||
httpMaxStreamDurationNano, rdsName, virtualHosts, filterChain, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
LdsUpdate that = (LdsUpdate) o;
|
|
||||||
return httpMaxStreamDurationNano == that.httpMaxStreamDurationNano
|
|
||||||
&& Objects.equals(rdsName, that.rdsName)
|
|
||||||
&& Objects.equals(virtualHosts, that.virtualHosts)
|
|
||||||
&& Objects.equals(filterChain, that.filterChain)
|
|
||||||
&& Objects.equals(listener, that.listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
ToStringHelper toStringHelper = MoreObjects.toStringHelper(this);
|
|
||||||
toStringHelper.add("httpMaxStreamDurationNano", httpMaxStreamDurationNano);
|
|
||||||
if (rdsName != null) {
|
|
||||||
toStringHelper.add("rdsName", rdsName);
|
|
||||||
} else {
|
|
||||||
toStringHelper.add("virtualHosts", virtualHosts);
|
|
||||||
}
|
|
||||||
if (filterChain != null) {
|
|
||||||
toStringHelper.add("filterChain", filterChain);
|
|
||||||
}
|
|
||||||
if (listener != null) {
|
|
||||||
toStringHelper.add("listener", listener);
|
|
||||||
}
|
|
||||||
return toStringHelper.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class RdsUpdate implements ResourceUpdate {
|
static final class RdsUpdate implements ResourceUpdate {
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ public final class XdsClientWrapperForServerSds {
|
||||||
new XdsClient.LdsResourceWatcher() {
|
new XdsClient.LdsResourceWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(XdsClient.LdsUpdate update) {
|
public void onChanged(XdsClient.LdsUpdate update) {
|
||||||
releaseOldSuppliers(curListener.getAndSet(update.listener));
|
releaseOldSuppliers(curListener.getAndSet(update.listener()));
|
||||||
reportSuccess();
|
reportSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -359,6 +359,10 @@ final class XdsNameResolver extends NameResolver {
|
||||||
return Result.forError(
|
return Result.forError(
|
||||||
Status.UNAVAILABLE.withDescription("Could not find xDS route matching RPC"));
|
Status.UNAVAILABLE.withDescription("Could not find xDS route matching RPC"));
|
||||||
}
|
}
|
||||||
|
if (selectedRoute.routeAction() == null) {
|
||||||
|
return Result.forError(Status.UNAVAILABLE.withDescription(
|
||||||
|
"Could not route RPC to Route with non-forwarding action"));
|
||||||
|
}
|
||||||
RouteAction action = selectedRoute.routeAction();
|
RouteAction action = selectedRoute.routeAction();
|
||||||
if (action.cluster() != null) {
|
if (action.cluster() != null) {
|
||||||
cluster = action.cluster();
|
cluster = action.cluster();
|
||||||
|
|
@ -648,14 +652,17 @@ final class XdsNameResolver extends NameResolver {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.log(XdsLogLevel.INFO, "Receive LDS resource update: {0}", update);
|
logger.log(XdsLogLevel.INFO, "Receive LDS resource update: {0}", update);
|
||||||
List<VirtualHost> virtualHosts = update.virtualHosts;
|
HttpConnectionManager httpConnectionManager = update.httpConnectionManager();
|
||||||
String rdsName = update.rdsName;
|
List<VirtualHost> virtualHosts = httpConnectionManager.virtualHosts();
|
||||||
|
String rdsName = httpConnectionManager.rdsName();
|
||||||
cleanUpRouteDiscoveryState();
|
cleanUpRouteDiscoveryState();
|
||||||
if (virtualHosts != null) {
|
if (virtualHosts != null) {
|
||||||
updateRoutes(virtualHosts, update.httpMaxStreamDurationNano, update.filterChain);
|
updateRoutes(virtualHosts, httpConnectionManager.httpMaxStreamDurationNano(),
|
||||||
|
httpConnectionManager.httpFilterConfigs());
|
||||||
} else {
|
} else {
|
||||||
routeDiscoveryState = new RouteDiscoveryState(
|
routeDiscoveryState = new RouteDiscoveryState(
|
||||||
rdsName, update.httpMaxStreamDurationNano, update.filterChain);
|
rdsName, httpConnectionManager.httpMaxStreamDurationNano(),
|
||||||
|
httpConnectionManager.httpFilterConfigs());
|
||||||
logger.log(XdsLogLevel.INFO, "Start watching RDS resource {0}", rdsName);
|
logger.log(XdsLogLevel.INFO, "Start watching RDS resource {0}", rdsName);
|
||||||
xdsClient.watchRdsResource(rdsName, routeDiscoveryState);
|
xdsClient.watchRdsResource(rdsName, routeDiscoveryState);
|
||||||
}
|
}
|
||||||
|
|
@ -739,6 +746,7 @@ final class XdsNameResolver extends NameResolver {
|
||||||
Set<String> clusters = new HashSet<>();
|
Set<String> clusters = new HashSet<>();
|
||||||
for (Route route : routes) {
|
for (Route route : routes) {
|
||||||
RouteAction action = route.routeAction();
|
RouteAction action = route.routeAction();
|
||||||
|
if (action != null) {
|
||||||
if (action.cluster() != null) {
|
if (action.cluster() != null) {
|
||||||
clusters.add(action.cluster());
|
clusters.add(action.cluster());
|
||||||
} else if (action.weightedClusters() != null) {
|
} else if (action.weightedClusters() != null) {
|
||||||
|
|
@ -747,6 +755,7 @@ final class XdsNameResolver extends NameResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Updates channel's load balancing config whenever the set of selectable clusters changes.
|
// Updates channel's load balancing config whenever the set of selectable clusters changes.
|
||||||
boolean shouldUpdateResult = existingClusters == null;
|
boolean shouldUpdateResult = existingClusters == null;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ import io.envoyproxy.envoy.config.cluster.v3.Cluster.RingHashLbConfig.HashFuncti
|
||||||
import io.envoyproxy.envoy.config.core.v3.Address;
|
import io.envoyproxy.envoy.config.core.v3.Address;
|
||||||
import io.envoyproxy.envoy.config.core.v3.AggregatedConfigSource;
|
import io.envoyproxy.envoy.config.core.v3.AggregatedConfigSource;
|
||||||
import io.envoyproxy.envoy.config.core.v3.ConfigSource;
|
import io.envoyproxy.envoy.config.core.v3.ConfigSource;
|
||||||
import io.envoyproxy.envoy.config.core.v3.ExtensionConfigSource;
|
import io.envoyproxy.envoy.config.core.v3.HttpProtocolOptions;
|
||||||
import io.envoyproxy.envoy.config.core.v3.Locality;
|
import io.envoyproxy.envoy.config.core.v3.Locality;
|
||||||
import io.envoyproxy.envoy.config.core.v3.RuntimeFractionalPercent;
|
import io.envoyproxy.envoy.config.core.v3.RuntimeFractionalPercent;
|
||||||
import io.envoyproxy.envoy.config.core.v3.SocketAddress;
|
import io.envoyproxy.envoy.config.core.v3.SocketAddress;
|
||||||
|
|
@ -47,8 +47,14 @@ import io.envoyproxy.envoy.config.listener.v3.FilterChain;
|
||||||
import io.envoyproxy.envoy.config.listener.v3.FilterChainMatch;
|
import io.envoyproxy.envoy.config.listener.v3.FilterChainMatch;
|
||||||
import io.envoyproxy.envoy.config.listener.v3.Listener;
|
import io.envoyproxy.envoy.config.listener.v3.Listener;
|
||||||
import io.envoyproxy.envoy.config.listener.v3.ListenerFilter;
|
import io.envoyproxy.envoy.config.listener.v3.ListenerFilter;
|
||||||
|
import io.envoyproxy.envoy.config.rbac.v3.Permission;
|
||||||
|
import io.envoyproxy.envoy.config.rbac.v3.Policy;
|
||||||
|
import io.envoyproxy.envoy.config.rbac.v3.Principal;
|
||||||
|
import io.envoyproxy.envoy.config.rbac.v3.RBAC;
|
||||||
|
import io.envoyproxy.envoy.config.rbac.v3.RBAC.Action;
|
||||||
import io.envoyproxy.envoy.config.route.v3.DirectResponseAction;
|
import io.envoyproxy.envoy.config.route.v3.DirectResponseAction;
|
||||||
import io.envoyproxy.envoy.config.route.v3.FilterAction;
|
import io.envoyproxy.envoy.config.route.v3.FilterAction;
|
||||||
|
import io.envoyproxy.envoy.config.route.v3.NonForwardingAction;
|
||||||
import io.envoyproxy.envoy.config.route.v3.RedirectAction;
|
import io.envoyproxy.envoy.config.route.v3.RedirectAction;
|
||||||
import io.envoyproxy.envoy.config.route.v3.RouteAction.HashPolicy.ConnectionProperties;
|
import io.envoyproxy.envoy.config.route.v3.RouteAction.HashPolicy.ConnectionProperties;
|
||||||
import io.envoyproxy.envoy.config.route.v3.RouteAction.HashPolicy.FilterState;
|
import io.envoyproxy.envoy.config.route.v3.RouteAction.HashPolicy.FilterState;
|
||||||
|
|
@ -57,21 +63,23 @@ import io.envoyproxy.envoy.config.route.v3.RouteAction.HashPolicy.QueryParameter
|
||||||
import io.envoyproxy.envoy.config.route.v3.RouteAction.MaxStreamDuration;
|
import io.envoyproxy.envoy.config.route.v3.RouteAction.MaxStreamDuration;
|
||||||
import io.envoyproxy.envoy.config.route.v3.WeightedCluster;
|
import io.envoyproxy.envoy.config.route.v3.WeightedCluster;
|
||||||
import io.envoyproxy.envoy.extensions.filters.common.fault.v3.FaultDelay;
|
import io.envoyproxy.envoy.extensions.filters.common.fault.v3.FaultDelay;
|
||||||
|
import io.envoyproxy.envoy.extensions.filters.http.fault.v3.FaultAbort;
|
||||||
import io.envoyproxy.envoy.extensions.filters.http.fault.v3.HTTPFault;
|
import io.envoyproxy.envoy.extensions.filters.http.fault.v3.HTTPFault;
|
||||||
|
import io.envoyproxy.envoy.extensions.filters.http.rbac.v3.RBACPerRoute;
|
||||||
|
import io.envoyproxy.envoy.extensions.filters.http.router.v3.Router;
|
||||||
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
|
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
|
||||||
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter;
|
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpFilter;
|
||||||
|
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.Rds;
|
||||||
import io.envoyproxy.envoy.type.matcher.v3.RegexMatchAndSubstitute;
|
import io.envoyproxy.envoy.type.matcher.v3.RegexMatchAndSubstitute;
|
||||||
import io.envoyproxy.envoy.type.matcher.v3.RegexMatcher;
|
import io.envoyproxy.envoy.type.matcher.v3.RegexMatcher;
|
||||||
import io.envoyproxy.envoy.type.matcher.v3.RegexMatcher.GoogleRE2;
|
import io.envoyproxy.envoy.type.matcher.v3.RegexMatcher.GoogleRE2;
|
||||||
import io.envoyproxy.envoy.type.v3.FractionalPercent;
|
import io.envoyproxy.envoy.type.v3.FractionalPercent;
|
||||||
import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType;
|
import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType;
|
||||||
import io.envoyproxy.envoy.type.v3.Int64Range;
|
import io.envoyproxy.envoy.type.v3.Int64Range;
|
||||||
import io.grpc.Status.Code;
|
|
||||||
import io.grpc.xds.ClientXdsClient.ResourceInvalidException;
|
import io.grpc.xds.ClientXdsClient.ResourceInvalidException;
|
||||||
import io.grpc.xds.ClientXdsClient.StructOrError;
|
import io.grpc.xds.ClientXdsClient.StructOrError;
|
||||||
import io.grpc.xds.Endpoints.LbEndpoint;
|
import io.grpc.xds.Endpoints.LbEndpoint;
|
||||||
import io.grpc.xds.Endpoints.LocalityLbEndpoints;
|
import io.grpc.xds.Endpoints.LocalityLbEndpoints;
|
||||||
import io.grpc.xds.FaultConfig.FaultAbort;
|
|
||||||
import io.grpc.xds.Filter.FilterConfig;
|
import io.grpc.xds.Filter.FilterConfig;
|
||||||
import io.grpc.xds.VirtualHost.Route;
|
import io.grpc.xds.VirtualHost.Route;
|
||||||
import io.grpc.xds.VirtualHost.Route.RouteAction;
|
import io.grpc.xds.VirtualHost.Route.RouteAction;
|
||||||
|
|
@ -100,6 +108,7 @@ public class ClientXdsClientDataTest {
|
||||||
@SuppressWarnings("deprecation") // https://github.com/grpc/grpc-java/issues/7467
|
@SuppressWarnings("deprecation") // https://github.com/grpc/grpc-java/issues/7467
|
||||||
@Rule
|
@Rule
|
||||||
public final ExpectedException thrown = ExpectedException.none();
|
public final ExpectedException thrown = ExpectedException.none();
|
||||||
|
private final FilterRegistry filterRegistry = FilterRegistry.newRegistry();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseRoute_withRouteAction() {
|
public void parseRoute_withRouteAction() {
|
||||||
|
|
@ -113,17 +122,36 @@ public class ClientXdsClientDataTest {
|
||||||
io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder()
|
io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder()
|
||||||
.setCluster("cluster-foo"))
|
.setCluster("cluster-foo"))
|
||||||
.build();
|
.build();
|
||||||
StructOrError<Route> struct = ClientXdsClient.parseRoute(proto, false);
|
StructOrError<Route> struct = ClientXdsClient.parseRoute(proto, filterRegistry, false);
|
||||||
assertThat(struct.getErrorDetail()).isNull();
|
assertThat(struct.getErrorDetail()).isNull();
|
||||||
assertThat(struct.getStruct())
|
assertThat(struct.getStruct())
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.create(PathMatcher.fromPath("/service/method", false),
|
RouteMatch.create(PathMatcher.fromPath("/service/method", false),
|
||||||
Collections.<HeaderMatcher>emptyList(), null),
|
Collections.<HeaderMatcher>emptyList(), null),
|
||||||
RouteAction.forCluster("cluster-foo", Collections.<HashPolicy>emptyList(), null),
|
RouteAction.forCluster("cluster-foo", Collections.<HashPolicy>emptyList(), null),
|
||||||
ImmutableMap.<String, FilterConfig>of()));
|
ImmutableMap.<String, FilterConfig>of()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseRoute_withNonForwardingAction() {
|
||||||
|
io.envoyproxy.envoy.config.route.v3.Route proto =
|
||||||
|
io.envoyproxy.envoy.config.route.v3.Route.newBuilder()
|
||||||
|
.setName("route-blade")
|
||||||
|
.setMatch(
|
||||||
|
io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder()
|
||||||
|
.setPath("/service/method"))
|
||||||
|
.setNonForwardingAction(NonForwardingAction.getDefaultInstance())
|
||||||
|
.build();
|
||||||
|
StructOrError<Route> struct = ClientXdsClient.parseRoute(proto, filterRegistry, false);
|
||||||
|
assertThat(struct.getStruct())
|
||||||
|
.isEqualTo(
|
||||||
|
Route.forNonForwardingAction(
|
||||||
|
RouteMatch.create(PathMatcher.fromPath("/service/method", false),
|
||||||
|
Collections.<HeaderMatcher>emptyList(), null),
|
||||||
|
ImmutableMap.<String, FilterConfig>of()));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseRoute_withUnsupportedActionTypes() {
|
public void parseRoute_withUnsupportedActionTypes() {
|
||||||
StructOrError<Route> res;
|
StructOrError<Route> res;
|
||||||
|
|
@ -133,9 +161,10 @@ public class ClientXdsClientDataTest {
|
||||||
.setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder().setPath(""))
|
.setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder().setPath(""))
|
||||||
.setRedirect(RedirectAction.getDefaultInstance())
|
.setRedirect(RedirectAction.getDefaultInstance())
|
||||||
.build();
|
.build();
|
||||||
res = ClientXdsClient.parseRoute(redirectRoute, false);
|
res = ClientXdsClient.parseRoute(redirectRoute, filterRegistry, false);
|
||||||
assertThat(res.getStruct()).isNull();
|
assertThat(res.getStruct()).isNull();
|
||||||
assertThat(res.getErrorDetail()).isEqualTo("Unsupported action type: redirect");
|
assertThat(res.getErrorDetail())
|
||||||
|
.isEqualTo("Route [route-blade] with unknown action type: REDIRECT");
|
||||||
|
|
||||||
io.envoyproxy.envoy.config.route.v3.Route directResponseRoute =
|
io.envoyproxy.envoy.config.route.v3.Route directResponseRoute =
|
||||||
io.envoyproxy.envoy.config.route.v3.Route.newBuilder()
|
io.envoyproxy.envoy.config.route.v3.Route.newBuilder()
|
||||||
|
|
@ -143,9 +172,10 @@ public class ClientXdsClientDataTest {
|
||||||
.setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder().setPath(""))
|
.setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder().setPath(""))
|
||||||
.setDirectResponse(DirectResponseAction.getDefaultInstance())
|
.setDirectResponse(DirectResponseAction.getDefaultInstance())
|
||||||
.build();
|
.build();
|
||||||
res = ClientXdsClient.parseRoute(directResponseRoute, false);
|
res = ClientXdsClient.parseRoute(directResponseRoute, filterRegistry, false);
|
||||||
assertThat(res.getStruct()).isNull();
|
assertThat(res.getStruct()).isNull();
|
||||||
assertThat(res.getErrorDetail()).isEqualTo("Unsupported action type: direct_response");
|
assertThat(res.getErrorDetail())
|
||||||
|
.isEqualTo("Route [route-blade] with unknown action type: DIRECT_RESPONSE");
|
||||||
|
|
||||||
io.envoyproxy.envoy.config.route.v3.Route filterRoute =
|
io.envoyproxy.envoy.config.route.v3.Route filterRoute =
|
||||||
io.envoyproxy.envoy.config.route.v3.Route.newBuilder()
|
io.envoyproxy.envoy.config.route.v3.Route.newBuilder()
|
||||||
|
|
@ -153,9 +183,10 @@ public class ClientXdsClientDataTest {
|
||||||
.setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder().setPath(""))
|
.setMatch(io.envoyproxy.envoy.config.route.v3.RouteMatch.newBuilder().setPath(""))
|
||||||
.setFilterAction(FilterAction.getDefaultInstance())
|
.setFilterAction(FilterAction.getDefaultInstance())
|
||||||
.build();
|
.build();
|
||||||
res = ClientXdsClient.parseRoute(filterRoute, false);
|
res = ClientXdsClient.parseRoute(filterRoute, filterRegistry, false);
|
||||||
assertThat(res.getStruct()).isNull();
|
assertThat(res.getStruct()).isNull();
|
||||||
assertThat(res.getErrorDetail()).isEqualTo("Unsupported action type: filter_action");
|
assertThat(res.getErrorDetail())
|
||||||
|
.isEqualTo("Route [route-blade] with unknown action type: FILTER_ACTION");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -173,7 +204,7 @@ public class ClientXdsClientDataTest {
|
||||||
io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder()
|
io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder()
|
||||||
.setCluster("cluster-foo"))
|
.setCluster("cluster-foo"))
|
||||||
.build();
|
.build();
|
||||||
assertThat(ClientXdsClient.parseRoute(proto, false)).isNull();
|
assertThat(ClientXdsClient.parseRoute(proto, filterRegistry, false)).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -188,7 +219,7 @@ public class ClientXdsClientDataTest {
|
||||||
io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder()
|
io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder()
|
||||||
.setClusterHeader("cluster header")) // cluster_header action not supported
|
.setClusterHeader("cluster header")) // cluster_header action not supported
|
||||||
.build();
|
.build();
|
||||||
assertThat(ClientXdsClient.parseRoute(proto, false)).isNull();
|
assertThat(ClientXdsClient.parseRoute(proto, filterRegistry, false)).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -367,7 +398,8 @@ public class ClientXdsClientDataTest {
|
||||||
io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder()
|
io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder()
|
||||||
.setCluster("cluster-foo")
|
.setCluster("cluster-foo")
|
||||||
.build();
|
.build();
|
||||||
StructOrError<RouteAction> struct = ClientXdsClient.parseRouteAction(proto, false);
|
StructOrError<RouteAction> struct =
|
||||||
|
ClientXdsClient.parseRouteAction(proto, filterRegistry, false);
|
||||||
assertThat(struct.getErrorDetail()).isNull();
|
assertThat(struct.getErrorDetail()).isNull();
|
||||||
assertThat(struct.getStruct().cluster()).isEqualTo("cluster-foo");
|
assertThat(struct.getStruct().cluster()).isEqualTo("cluster-foo");
|
||||||
assertThat(struct.getStruct().weightedClusters()).isNull();
|
assertThat(struct.getStruct().weightedClusters()).isNull();
|
||||||
|
|
@ -389,7 +421,8 @@ public class ClientXdsClientDataTest {
|
||||||
.setName("cluster-bar")
|
.setName("cluster-bar")
|
||||||
.setWeight(UInt32Value.newBuilder().setValue(70))))
|
.setWeight(UInt32Value.newBuilder().setValue(70))))
|
||||||
.build();
|
.build();
|
||||||
StructOrError<RouteAction> struct = ClientXdsClient.parseRouteAction(proto, false);
|
StructOrError<RouteAction> struct =
|
||||||
|
ClientXdsClient.parseRouteAction(proto, filterRegistry, false);
|
||||||
assertThat(struct.getErrorDetail()).isNull();
|
assertThat(struct.getErrorDetail()).isNull();
|
||||||
assertThat(struct.getStruct().cluster()).isNull();
|
assertThat(struct.getStruct().cluster()).isNull();
|
||||||
assertThat(struct.getStruct().weightedClusters()).containsExactly(
|
assertThat(struct.getStruct().weightedClusters()).containsExactly(
|
||||||
|
|
@ -407,7 +440,8 @@ public class ClientXdsClientDataTest {
|
||||||
.setGrpcTimeoutHeaderMax(Durations.fromSeconds(5L))
|
.setGrpcTimeoutHeaderMax(Durations.fromSeconds(5L))
|
||||||
.setMaxStreamDuration(Durations.fromMillis(20L)))
|
.setMaxStreamDuration(Durations.fromMillis(20L)))
|
||||||
.build();
|
.build();
|
||||||
StructOrError<RouteAction> struct = ClientXdsClient.parseRouteAction(proto, false);
|
StructOrError<RouteAction> struct =
|
||||||
|
ClientXdsClient.parseRouteAction(proto, filterRegistry, false);
|
||||||
assertThat(struct.getStruct().timeoutNano()).isEqualTo(TimeUnit.SECONDS.toNanos(5L));
|
assertThat(struct.getStruct().timeoutNano()).isEqualTo(TimeUnit.SECONDS.toNanos(5L));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -420,7 +454,8 @@ public class ClientXdsClientDataTest {
|
||||||
MaxStreamDuration.newBuilder()
|
MaxStreamDuration.newBuilder()
|
||||||
.setMaxStreamDuration(Durations.fromSeconds(5L)))
|
.setMaxStreamDuration(Durations.fromSeconds(5L)))
|
||||||
.build();
|
.build();
|
||||||
StructOrError<RouteAction> struct = ClientXdsClient.parseRouteAction(proto, false);
|
StructOrError<RouteAction> struct =
|
||||||
|
ClientXdsClient.parseRouteAction(proto, filterRegistry, false);
|
||||||
assertThat(struct.getStruct().timeoutNano()).isEqualTo(TimeUnit.SECONDS.toNanos(5L));
|
assertThat(struct.getStruct().timeoutNano()).isEqualTo(TimeUnit.SECONDS.toNanos(5L));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -430,7 +465,8 @@ public class ClientXdsClientDataTest {
|
||||||
io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder()
|
io.envoyproxy.envoy.config.route.v3.RouteAction.newBuilder()
|
||||||
.setCluster("cluster-foo")
|
.setCluster("cluster-foo")
|
||||||
.build();
|
.build();
|
||||||
StructOrError<RouteAction> struct = ClientXdsClient.parseRouteAction(proto, false);
|
StructOrError<RouteAction> struct =
|
||||||
|
ClientXdsClient.parseRouteAction(proto, filterRegistry, false);
|
||||||
assertThat(struct.getStruct().timeoutNano()).isNull();
|
assertThat(struct.getStruct().timeoutNano()).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -465,7 +501,8 @@ public class ClientXdsClientDataTest {
|
||||||
.setQueryParameter(
|
.setQueryParameter(
|
||||||
QueryParameter.newBuilder().setName("param"))) // unsupported
|
QueryParameter.newBuilder().setName("param"))) // unsupported
|
||||||
.build();
|
.build();
|
||||||
StructOrError<RouteAction> struct = ClientXdsClient.parseRouteAction(proto, false);
|
StructOrError<RouteAction> struct =
|
||||||
|
ClientXdsClient.parseRouteAction(proto, filterRegistry, false);
|
||||||
List<HashPolicy> policies = struct.getStruct().hashPolicies();
|
List<HashPolicy> policies = struct.getStruct().hashPolicies();
|
||||||
assertThat(policies).hasSize(2);
|
assertThat(policies).hasSize(2);
|
||||||
assertThat(policies.get(0).type()).isEqualTo(HashPolicy.Type.HEADER);
|
assertThat(policies.get(0).type()).isEqualTo(HashPolicy.Type.HEADER);
|
||||||
|
|
@ -485,39 +522,12 @@ public class ClientXdsClientDataTest {
|
||||||
.setName("cluster-foo")
|
.setName("cluster-foo")
|
||||||
.setWeight(UInt32Value.newBuilder().setValue(30))
|
.setWeight(UInt32Value.newBuilder().setValue(30))
|
||||||
.build();
|
.build();
|
||||||
ClusterWeight clusterWeight = ClientXdsClient.parseClusterWeight(proto, false).getStruct();
|
ClusterWeight clusterWeight =
|
||||||
|
ClientXdsClient.parseClusterWeight(proto, filterRegistry, false).getStruct();
|
||||||
assertThat(clusterWeight.name()).isEqualTo("cluster-foo");
|
assertThat(clusterWeight.name()).isEqualTo("cluster-foo");
|
||||||
assertThat(clusterWeight.weight()).isEqualTo(30);
|
assertThat(clusterWeight.weight()).isEqualTo(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void parseFaultAbort_withHttpStatus() {
|
|
||||||
io.envoyproxy.envoy.extensions.filters.http.fault.v3.FaultAbort proto =
|
|
||||||
io.envoyproxy.envoy.extensions.filters.http.fault.v3.FaultAbort.newBuilder()
|
|
||||||
.setPercentage(FractionalPercent.newBuilder()
|
|
||||||
.setNumerator(100).setDenominator(DenominatorType.TEN_THOUSAND))
|
|
||||||
.setHttpStatus(400).build();
|
|
||||||
FaultAbort res = FaultFilter.parseFaultAbort(proto).config;
|
|
||||||
assertThat(res.percent().numerator()).isEqualTo(100);
|
|
||||||
assertThat(res.percent().denominatorType())
|
|
||||||
.isEqualTo(FaultConfig.FractionalPercent.DenominatorType.TEN_THOUSAND);
|
|
||||||
assertThat(res.status().getCode()).isEqualTo(Code.INTERNAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void parseFaultAbort_withGrpcStatus() {
|
|
||||||
io.envoyproxy.envoy.extensions.filters.http.fault.v3.FaultAbort proto =
|
|
||||||
io.envoyproxy.envoy.extensions.filters.http.fault.v3.FaultAbort.newBuilder()
|
|
||||||
.setPercentage(FractionalPercent.newBuilder()
|
|
||||||
.setNumerator(600).setDenominator(DenominatorType.MILLION))
|
|
||||||
.setGrpcStatus(Code.DEADLINE_EXCEEDED.value()).build();
|
|
||||||
FaultAbort faultAbort = FaultFilter.parseFaultAbort(proto).config;
|
|
||||||
assertThat(faultAbort.percent().numerator()).isEqualTo(600);
|
|
||||||
assertThat(faultAbort.percent().denominatorType())
|
|
||||||
.isEqualTo(FaultConfig.FractionalPercent.DenominatorType.MILLION);
|
|
||||||
assertThat(faultAbort.status().getCode()).isEqualTo(Code.DEADLINE_EXCEEDED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseLocalityLbEndpoints_withHealthyEndpoints() {
|
public void parseLocalityLbEndpoints_withHealthyEndpoints() {
|
||||||
io.envoyproxy.envoy.config.endpoint.v3.LocalityLbEndpoints proto =
|
io.envoyproxy.envoy.config.endpoint.v3.LocalityLbEndpoints proto =
|
||||||
|
|
@ -637,7 +647,7 @@ public class ClientXdsClientDataTest {
|
||||||
.setIsOptional(true)
|
.setIsOptional(true)
|
||||||
.setTypedConfig(Any.pack(StringValue.of("unsupported")))
|
.setTypedConfig(Any.pack(StringValue.of("unsupported")))
|
||||||
.build();
|
.build();
|
||||||
assertThat(ClientXdsClient.parseHttpFilter(httpFilter)).isNull();
|
assertThat(ClientXdsClient.parseHttpFilter(httpFilter, filterRegistry, true)).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -647,13 +657,181 @@ public class ClientXdsClientDataTest {
|
||||||
.setName("unsupported.filter")
|
.setName("unsupported.filter")
|
||||||
.setTypedConfig(Any.pack(StringValue.of("string value")))
|
.setTypedConfig(Any.pack(StringValue.of("string value")))
|
||||||
.build();
|
.build();
|
||||||
assertThat(ClientXdsClient.parseHttpFilter(httpFilter).getErrorDetail()).isEqualTo(
|
assertThat(ClientXdsClient.parseHttpFilter(httpFilter, filterRegistry, true)
|
||||||
"HttpFilter [unsupported.filter] is not optional and has an unsupported config type: "
|
.getErrorDetail()).isEqualTo(
|
||||||
+ "type.googleapis.com/google.protobuf.StringValue");
|
"HttpFilter [unsupported.filter]"
|
||||||
|
+ "(type.googleapis.com/google.protobuf.StringValue) is required but unsupported "
|
||||||
|
+ "for client");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseHttpFilter_routerFilterForClient() {
|
||||||
|
filterRegistry.register(RouterFilter.INSTANCE);
|
||||||
|
HttpFilter httpFilter =
|
||||||
|
HttpFilter.newBuilder()
|
||||||
|
.setIsOptional(false)
|
||||||
|
.setName("envoy.router")
|
||||||
|
.setTypedConfig(Any.pack(Router.getDefaultInstance()))
|
||||||
|
.build();
|
||||||
|
FilterConfig config = ClientXdsClient.parseHttpFilter(
|
||||||
|
httpFilter, filterRegistry, true /* isForClient */).getStruct();
|
||||||
|
assertThat(config.typeUrl()).isEqualTo(RouterFilter.TYPE_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseHttpFilter_routerFilterForServer() {
|
||||||
|
filterRegistry.register(RouterFilter.INSTANCE);
|
||||||
|
HttpFilter httpFilter =
|
||||||
|
HttpFilter.newBuilder()
|
||||||
|
.setIsOptional(false)
|
||||||
|
.setName("envoy.router")
|
||||||
|
.setTypedConfig(Any.pack(Router.getDefaultInstance()))
|
||||||
|
.build();
|
||||||
|
FilterConfig config = ClientXdsClient.parseHttpFilter(
|
||||||
|
httpFilter, filterRegistry, false /* isForClient */).getStruct();
|
||||||
|
assertThat(config.typeUrl()).isEqualTo(RouterFilter.TYPE_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseHttpFilter_faultConfigForClient() {
|
||||||
|
filterRegistry.register(FaultFilter.INSTANCE);
|
||||||
|
HttpFilter httpFilter =
|
||||||
|
HttpFilter.newBuilder()
|
||||||
|
.setIsOptional(false)
|
||||||
|
.setName("envoy.fault")
|
||||||
|
.setTypedConfig(
|
||||||
|
Any.pack(
|
||||||
|
HTTPFault.newBuilder()
|
||||||
|
.setDelay(
|
||||||
|
FaultDelay.newBuilder()
|
||||||
|
.setFixedDelay(Durations.fromNanos(1234L)))
|
||||||
|
.setAbort(
|
||||||
|
FaultAbort.newBuilder()
|
||||||
|
.setHttpStatus(300)
|
||||||
|
.setPercentage(
|
||||||
|
FractionalPercent.newBuilder()
|
||||||
|
.setNumerator(10)
|
||||||
|
.setDenominator(DenominatorType.HUNDRED)))
|
||||||
|
.build()))
|
||||||
|
.build();
|
||||||
|
FilterConfig config = ClientXdsClient.parseHttpFilter(
|
||||||
|
httpFilter, filterRegistry, true /* isForClient */).getStruct();
|
||||||
|
assertThat(config).isInstanceOf(FaultConfig.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseHttpFilter_faultConfigUnsupportedForServer() {
|
||||||
|
filterRegistry.register(FaultFilter.INSTANCE);
|
||||||
|
HttpFilter httpFilter =
|
||||||
|
HttpFilter.newBuilder()
|
||||||
|
.setIsOptional(false)
|
||||||
|
.setName("envoy.fault")
|
||||||
|
.setTypedConfig(
|
||||||
|
Any.pack(
|
||||||
|
HTTPFault.newBuilder()
|
||||||
|
.setDelay(
|
||||||
|
FaultDelay.newBuilder()
|
||||||
|
.setFixedDelay(Durations.fromNanos(1234L)))
|
||||||
|
.setAbort(
|
||||||
|
FaultAbort.newBuilder()
|
||||||
|
.setHttpStatus(300)
|
||||||
|
.setPercentage(
|
||||||
|
FractionalPercent.newBuilder()
|
||||||
|
.setNumerator(10)
|
||||||
|
.setDenominator(DenominatorType.HUNDRED)))
|
||||||
|
.build()))
|
||||||
|
.build();
|
||||||
|
StructOrError<FilterConfig> config =
|
||||||
|
ClientXdsClient.parseHttpFilter(httpFilter, filterRegistry, false /* isForClient */);
|
||||||
|
assertThat(config.getErrorDetail()).isEqualTo(
|
||||||
|
"HttpFilter [envoy.fault](" + FaultFilter.TYPE_URL + ") is required but "
|
||||||
|
+ "unsupported for server");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseHttpFilter_rbacConfigForServer() {
|
||||||
|
filterRegistry.register(RbacFilter.INSTANCE);
|
||||||
|
HttpFilter httpFilter =
|
||||||
|
HttpFilter.newBuilder()
|
||||||
|
.setIsOptional(false)
|
||||||
|
.setName("envoy.auth")
|
||||||
|
.setTypedConfig(
|
||||||
|
Any.pack(
|
||||||
|
io.envoyproxy.envoy.extensions.filters.http.rbac.v3.RBAC.newBuilder()
|
||||||
|
.setRules(
|
||||||
|
RBAC.newBuilder()
|
||||||
|
.setAction(Action.ALLOW)
|
||||||
|
.putPolicies(
|
||||||
|
"allow-all",
|
||||||
|
Policy.newBuilder()
|
||||||
|
.addPrincipals(Principal.newBuilder().setAny(true))
|
||||||
|
.addPermissions(Permission.newBuilder().setAny(true))
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.build()))
|
||||||
|
.build();
|
||||||
|
FilterConfig config = ClientXdsClient.parseHttpFilter(
|
||||||
|
httpFilter, filterRegistry, false /* isForClient */).getStruct();
|
||||||
|
assertThat(config).isInstanceOf(RbacConfig.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseHttpFilter_rbacConfigUnsupportedForClient() {
|
||||||
|
filterRegistry.register(RbacFilter.INSTANCE);
|
||||||
|
HttpFilter httpFilter =
|
||||||
|
HttpFilter.newBuilder()
|
||||||
|
.setIsOptional(false)
|
||||||
|
.setName("envoy.auth")
|
||||||
|
.setTypedConfig(
|
||||||
|
Any.pack(
|
||||||
|
io.envoyproxy.envoy.extensions.filters.http.rbac.v3.RBAC.newBuilder()
|
||||||
|
.setRules(
|
||||||
|
RBAC.newBuilder()
|
||||||
|
.setAction(Action.ALLOW)
|
||||||
|
.putPolicies(
|
||||||
|
"allow-all",
|
||||||
|
Policy.newBuilder()
|
||||||
|
.addPrincipals(Principal.newBuilder().setAny(true))
|
||||||
|
.addPermissions(Permission.newBuilder().setAny(true))
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.build()))
|
||||||
|
.build();
|
||||||
|
StructOrError<FilterConfig> config =
|
||||||
|
ClientXdsClient.parseHttpFilter(httpFilter, filterRegistry, true /* isForClient */);
|
||||||
|
assertThat(config.getErrorDetail()).isEqualTo(
|
||||||
|
"HttpFilter [envoy.auth](" + RbacFilter.TYPE_URL + ") is required but "
|
||||||
|
+ "unsupported for client");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseOverrideRbacFilterConfig() {
|
||||||
|
filterRegistry.register(RbacFilter.INSTANCE);
|
||||||
|
RBACPerRoute rbacPerRoute =
|
||||||
|
RBACPerRoute.newBuilder()
|
||||||
|
.setRbac(
|
||||||
|
io.envoyproxy.envoy.extensions.filters.http.rbac.v3.RBAC.newBuilder()
|
||||||
|
.setRules(
|
||||||
|
RBAC.newBuilder()
|
||||||
|
.setAction(Action.ALLOW)
|
||||||
|
.putPolicies(
|
||||||
|
"allow-all",
|
||||||
|
Policy.newBuilder()
|
||||||
|
.addPrincipals(Principal.newBuilder().setAny(true))
|
||||||
|
.addPermissions(Permission.newBuilder().setAny(true))
|
||||||
|
.build())))
|
||||||
|
.build();
|
||||||
|
Map<String, Any> configOverrides = ImmutableMap.of("envoy.auth", Any.pack(rbacPerRoute));
|
||||||
|
Map<String, FilterConfig> parsedConfigs =
|
||||||
|
ClientXdsClient.parseOverrideFilterConfigs(configOverrides, filterRegistry).getStruct();
|
||||||
|
assertThat(parsedConfigs).hasSize(1);
|
||||||
|
assertThat(parsedConfigs).containsKey("envoy.auth");
|
||||||
|
assertThat(parsedConfigs.get("envoy.auth")).isInstanceOf(RbacConfig.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseOverrideFilterConfigs_unsupportedButOptional() {
|
public void parseOverrideFilterConfigs_unsupportedButOptional() {
|
||||||
|
filterRegistry.register(FaultFilter.INSTANCE);
|
||||||
HTTPFault httpFault = HTTPFault.newBuilder()
|
HTTPFault httpFault = HTTPFault.newBuilder()
|
||||||
.setDelay(FaultDelay.newBuilder().setFixedDelay(Durations.fromNanos(3000)))
|
.setDelay(FaultDelay.newBuilder().setFixedDelay(Durations.fromNanos(3000)))
|
||||||
.build();
|
.build();
|
||||||
|
|
@ -665,13 +843,14 @@ public class ClientXdsClientDataTest {
|
||||||
.setIsOptional(true).setConfig(Any.pack(StringValue.of("string value")))
|
.setIsOptional(true).setConfig(Any.pack(StringValue.of("string value")))
|
||||||
.build()));
|
.build()));
|
||||||
Map<String, FilterConfig> parsedConfigs =
|
Map<String, FilterConfig> parsedConfigs =
|
||||||
ClientXdsClient.parseOverrideFilterConfigs(configOverrides).getStruct();
|
ClientXdsClient.parseOverrideFilterConfigs(configOverrides, filterRegistry).getStruct();
|
||||||
assertThat(parsedConfigs).hasSize(1);
|
assertThat(parsedConfigs).hasSize(1);
|
||||||
assertThat(parsedConfigs).containsKey("envoy.fault");
|
assertThat(parsedConfigs).containsKey("envoy.fault");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseOverrideFilterConfigs_unsupportedAndRequired() {
|
public void parseOverrideFilterConfigs_unsupportedAndRequired() {
|
||||||
|
filterRegistry.register(FaultFilter.INSTANCE);
|
||||||
HTTPFault httpFault = HTTPFault.newBuilder()
|
HTTPFault httpFault = HTTPFault.newBuilder()
|
||||||
.setDelay(FaultDelay.newBuilder().setFixedDelay(Durations.fromNanos(3000)))
|
.setDelay(FaultDelay.newBuilder().setFixedDelay(Durations.fromNanos(3000)))
|
||||||
.build();
|
.build();
|
||||||
|
|
@ -682,20 +861,66 @@ public class ClientXdsClientDataTest {
|
||||||
Any.pack(io.envoyproxy.envoy.config.route.v3.FilterConfig.newBuilder()
|
Any.pack(io.envoyproxy.envoy.config.route.v3.FilterConfig.newBuilder()
|
||||||
.setIsOptional(false).setConfig(Any.pack(StringValue.of("string value")))
|
.setIsOptional(false).setConfig(Any.pack(StringValue.of("string value")))
|
||||||
.build()));
|
.build()));
|
||||||
assertThat(ClientXdsClient.parseOverrideFilterConfigs(configOverrides).getErrorDetail())
|
assertThat(ClientXdsClient.parseOverrideFilterConfigs(configOverrides, filterRegistry)
|
||||||
.isEqualTo(
|
.getErrorDetail()).isEqualTo(
|
||||||
"HttpFilter [unsupported.filter] is not optional and has an unsupported config type: "
|
"HttpFilter [unsupported.filter]"
|
||||||
+ "type.googleapis.com/google.protobuf.StringValue");
|
+ "(type.googleapis.com/google.protobuf.StringValue) is required but unsupported");
|
||||||
|
|
||||||
configOverrides = ImmutableMap.of(
|
configOverrides = ImmutableMap.of(
|
||||||
"envoy.fault",
|
"envoy.fault",
|
||||||
Any.pack(httpFault),
|
Any.pack(httpFault),
|
||||||
"unsupported.filter",
|
"unsupported.filter",
|
||||||
Any.pack(StringValue.of("string value")));
|
Any.pack(StringValue.of("string value")));
|
||||||
assertThat(ClientXdsClient.parseOverrideFilterConfigs(configOverrides).getErrorDetail())
|
assertThat(ClientXdsClient.parseOverrideFilterConfigs(configOverrides, filterRegistry)
|
||||||
.isEqualTo(
|
.getErrorDetail()).isEqualTo(
|
||||||
"HttpFilter [unsupported.filter] is not optional and has an unsupported config type: "
|
"HttpFilter [unsupported.filter]"
|
||||||
+ "type.googleapis.com/google.protobuf.StringValue");
|
+ "(type.googleapis.com/google.protobuf.StringValue) is required but unsupported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseHttpConnectionManager_xffNumTrustedHopsUnsupported()
|
||||||
|
throws ResourceInvalidException {
|
||||||
|
HttpConnectionManager hcm =
|
||||||
|
HttpConnectionManager.newBuilder()
|
||||||
|
.setXffNumTrustedHops(2)
|
||||||
|
.build();
|
||||||
|
thrown.expect(ResourceInvalidException.class);
|
||||||
|
thrown.expectMessage("HttpConnectionManager with xff_num_trusted_hops unsupported");
|
||||||
|
ClientXdsClient.parseHttpConnectionManager(
|
||||||
|
hcm, new HashSet<String>(), filterRegistry, false /* does not matter */,
|
||||||
|
true /* does not matter */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseHttpConnectionManager_missingRdsAndInlinedRouteConfiguration()
|
||||||
|
throws ResourceInvalidException {
|
||||||
|
HttpConnectionManager hcm =
|
||||||
|
HttpConnectionManager.newBuilder()
|
||||||
|
.setCommonHttpProtocolOptions(
|
||||||
|
HttpProtocolOptions.newBuilder()
|
||||||
|
.setMaxStreamDuration(Durations.fromNanos(1000L)))
|
||||||
|
.build();
|
||||||
|
thrown.expect(ResourceInvalidException.class);
|
||||||
|
thrown.expectMessage("HttpConnectionManager neither has inlined route_config nor RDS");
|
||||||
|
ClientXdsClient.parseHttpConnectionManager(
|
||||||
|
hcm, new HashSet<String>(), filterRegistry, false /* does not matter */,
|
||||||
|
true /* does not matter */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseHttpConnectionManager_duplicateHttpFilters() throws ResourceInvalidException {
|
||||||
|
HttpConnectionManager hcm =
|
||||||
|
HttpConnectionManager.newBuilder()
|
||||||
|
.addHttpFilters(
|
||||||
|
HttpFilter.newBuilder().setName("envoy.filter.foo").setIsOptional(true))
|
||||||
|
.addHttpFilters(
|
||||||
|
HttpFilter.newBuilder().setName("envoy.filter.foo").setIsOptional(true))
|
||||||
|
.build();
|
||||||
|
thrown.expect(ResourceInvalidException.class);
|
||||||
|
thrown.expectMessage("HttpConnectionManager contains duplicate HttpFilter: envoy.filter.foo");
|
||||||
|
ClientXdsClient.parseHttpConnectionManager(
|
||||||
|
hcm, new HashSet<String>(), filterRegistry, true /* parseHttpFilter */,
|
||||||
|
true /* does not matter */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -773,250 +998,162 @@ public class ClientXdsClientDataTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseServerSideListener_invalidTrafficDirection() {
|
public void parseServerSideListener_invalidTrafficDirection() throws ResourceInvalidException {
|
||||||
Listener listener =
|
Listener listener =
|
||||||
Listener.newBuilder()
|
Listener.newBuilder()
|
||||||
.setName("listener1")
|
.setName("listener1")
|
||||||
.setTrafficDirection(TrafficDirection.OUTBOUND)
|
.setTrafficDirection(TrafficDirection.OUTBOUND)
|
||||||
.build();
|
.build();
|
||||||
StructOrError<io.grpc.xds.EnvoyServerProtoData.Listener> struct =
|
thrown.expect(ResourceInvalidException.class);
|
||||||
ClientXdsClient.parseServerSideListener(listener, null);
|
thrown.expectMessage("Listener listener1 with invalid traffic direction: OUTBOUND");
|
||||||
assertThat(struct.getErrorDetail()).isEqualTo("Listener listener1 is not INBOUND");
|
ClientXdsClient.parseServerSideListener(
|
||||||
|
listener, new HashSet<String>(), null, filterRegistry, true /* does not matter */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseServerSideListener_listenerFiltersPresent() {
|
public void parseServerSideListener_listenerFiltersPresent() throws ResourceInvalidException {
|
||||||
Listener listener =
|
Listener listener =
|
||||||
Listener.newBuilder()
|
Listener.newBuilder()
|
||||||
.setName("listener1")
|
.setName("listener1")
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
.setTrafficDirection(TrafficDirection.INBOUND)
|
||||||
.addListenerFilters(ListenerFilter.newBuilder().build())
|
.addListenerFilters(ListenerFilter.newBuilder().build())
|
||||||
.build();
|
.build();
|
||||||
StructOrError<io.grpc.xds.EnvoyServerProtoData.Listener> struct =
|
thrown.expect(ResourceInvalidException.class);
|
||||||
ClientXdsClient.parseServerSideListener(listener, null);
|
thrown.expectMessage("Listener listener1 cannot have listener_filters");
|
||||||
assertThat(struct.getErrorDetail())
|
ClientXdsClient.parseServerSideListener(
|
||||||
.isEqualTo("Listener listener1 cannot have listener_filters");
|
listener, new HashSet<String>(), null, filterRegistry, true /* does not matter */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseServerSideListener_useOriginalDst() {
|
public void parseServerSideListener_useOriginalDst() throws ResourceInvalidException {
|
||||||
Listener listener =
|
Listener listener =
|
||||||
Listener.newBuilder()
|
Listener.newBuilder()
|
||||||
.setName("listener1")
|
.setName("listener1")
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
.setTrafficDirection(TrafficDirection.INBOUND)
|
||||||
.setUseOriginalDst(BoolValue.of(true))
|
.setUseOriginalDst(BoolValue.of(true))
|
||||||
.build();
|
.build();
|
||||||
StructOrError<io.grpc.xds.EnvoyServerProtoData.Listener> struct =
|
thrown.expect(ResourceInvalidException.class);
|
||||||
ClientXdsClient.parseServerSideListener(listener, null);
|
thrown.expectMessage("Listener listener1 cannot have use_original_dst set to true");
|
||||||
assertThat(struct.getErrorDetail())
|
ClientXdsClient.parseServerSideListener(
|
||||||
.isEqualTo("Listener listener1 cannot have use_original_dst set to true");
|
listener, new HashSet<String>(), null, filterRegistry, true /* does not matter */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseServerSideListener_noHcm() {
|
public void parseFilterChain_noHcm() throws ResourceInvalidException {
|
||||||
Listener listener =
|
|
||||||
Listener.newBuilder()
|
|
||||||
.setName("listener1")
|
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
|
||||||
.addFilterChains(FilterChain.newBuilder().build())
|
|
||||||
.build();
|
|
||||||
StructOrError<io.grpc.xds.EnvoyServerProtoData.Listener> struct =
|
|
||||||
ClientXdsClient.parseServerSideListener(listener, null);
|
|
||||||
assertThat(struct.getErrorDetail())
|
|
||||||
.isEqualTo("filerChain has to have envoy.http_connection_manager");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void parseServerSideListener_duplicateFilterName() {
|
|
||||||
FilterChain filterChain =
|
FilterChain filterChain =
|
||||||
buildFilterChain(
|
FilterChain.newBuilder()
|
||||||
Filter.newBuilder()
|
.setName("filter-chain-foo")
|
||||||
.setName("envoy.http_connection_manager")
|
.setFilterChainMatch(FilterChainMatch.getDefaultInstance())
|
||||||
.setTypedConfig(Any.pack(HttpConnectionManager.getDefaultInstance()))
|
.setTransportSocket(TransportSocket.getDefaultInstance())
|
||||||
.build(),
|
|
||||||
Filter.newBuilder()
|
|
||||||
.setName("envoy.http_connection_manager")
|
|
||||||
.setTypedConfig(Any.pack(HttpConnectionManager.getDefaultInstance()))
|
|
||||||
.build());
|
|
||||||
Listener listener =
|
|
||||||
Listener.newBuilder()
|
|
||||||
.setName("listener1")
|
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
|
||||||
.addFilterChains(filterChain)
|
|
||||||
.build();
|
.build();
|
||||||
StructOrError<io.grpc.xds.EnvoyServerProtoData.Listener> struct =
|
thrown.expect(ResourceInvalidException.class);
|
||||||
ClientXdsClient.parseServerSideListener(listener, null);
|
thrown.expectMessage(
|
||||||
assertThat(struct.getErrorDetail())
|
"FilterChain filter-chain-foo missing required HttpConnectionManager filter");
|
||||||
.isEqualTo("filerChain has non-unique filter name:envoy.http_connection_manager");
|
ClientXdsClient.parseFilterChain(
|
||||||
|
filterChain, new HashSet<String>(), null, filterRegistry, true /* does not matter */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseServerSideListener_configDiscoveryFilter() {
|
public void parseFilterChain_duplicateFilter() throws ResourceInvalidException {
|
||||||
Filter filter =
|
Filter filter = buildHttpConnectionManagerFilter(
|
||||||
Filter.newBuilder()
|
HttpFilter.newBuilder().setName("http-filter-foo").setIsOptional(true).build());
|
||||||
.setName("envoy.http_connection_manager")
|
FilterChain filterChain =
|
||||||
.setConfigDiscovery(ExtensionConfigSource.newBuilder().build())
|
FilterChain.newBuilder()
|
||||||
|
.setName("filter-chain-foo")
|
||||||
|
.setFilterChainMatch(FilterChainMatch.getDefaultInstance())
|
||||||
|
.setTransportSocket(TransportSocket.getDefaultInstance())
|
||||||
|
.addAllFilters(Arrays.asList(filter, filter))
|
||||||
.build();
|
.build();
|
||||||
FilterChain filterChain = buildFilterChain(filter);
|
thrown.expect(ResourceInvalidException.class);
|
||||||
Listener listener =
|
thrown.expectMessage(
|
||||||
Listener.newBuilder()
|
"FilterChain filter-chain-foo with duplicated filter: envoy.http_connection_manager");
|
||||||
.setName("listener1")
|
ClientXdsClient.parseFilterChain(
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
filterChain, new HashSet<String>(), null, filterRegistry, true /* does not matter */);
|
||||||
.addFilterChains(filterChain)
|
|
||||||
.build();
|
|
||||||
StructOrError<io.grpc.xds.EnvoyServerProtoData.Listener> struct =
|
|
||||||
ClientXdsClient.parseServerSideListener(listener, null);
|
|
||||||
assertThat(struct.getErrorDetail())
|
|
||||||
.isEqualTo("filter envoy.http_connection_manager with config_discovery not supported");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseServerSideListener_expectTypedConfigFilter() {
|
public void parseFilterChain_filterMissingTypedConfig() throws ResourceInvalidException {
|
||||||
Filter filter = Filter.newBuilder().setName("envoy.http_connection_manager").build();
|
Filter filter = Filter.newBuilder().setName("envoy.http_connection_manager").build();
|
||||||
FilterChain filterChain = buildFilterChain(filter);
|
FilterChain filterChain =
|
||||||
Listener listener =
|
FilterChain.newBuilder()
|
||||||
Listener.newBuilder()
|
.setName("filter-chain-foo")
|
||||||
.setName("listener1")
|
.setFilterChainMatch(FilterChainMatch.getDefaultInstance())
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
.setTransportSocket(TransportSocket.getDefaultInstance())
|
||||||
.addFilterChains(filterChain)
|
.addFilters(filter)
|
||||||
.build();
|
.build();
|
||||||
StructOrError<io.grpc.xds.EnvoyServerProtoData.Listener> struct =
|
thrown.expect(ResourceInvalidException.class);
|
||||||
ClientXdsClient.parseServerSideListener(listener, null);
|
thrown.expectMessage(
|
||||||
assertThat(struct.getErrorDetail())
|
"FilterChain filter-chain-foo contains filter envoy.http_connection_manager "
|
||||||
.isEqualTo("filter envoy.http_connection_manager expected to have typed_config");
|
+ "without typed_config");
|
||||||
|
ClientXdsClient.parseFilterChain(
|
||||||
|
filterChain, new HashSet<String>(), null, filterRegistry, true /* does not matter */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseServerSideListener_wrongTypeUrl() {
|
public void parseFilterChain_unsupportedFilter() throws ResourceInvalidException {
|
||||||
Filter filter =
|
Filter filter =
|
||||||
Filter.newBuilder()
|
Filter.newBuilder()
|
||||||
.setName("envoy.http_connection_manager")
|
.setName("unsupported")
|
||||||
.setTypedConfig(Any.newBuilder().setTypeUrl("badTypeUrl"))
|
.setTypedConfig(Any.newBuilder().setTypeUrl("unsupported-type-url"))
|
||||||
.build();
|
.build();
|
||||||
FilterChain filterChain = buildFilterChain(filter);
|
FilterChain filterChain =
|
||||||
Listener listener =
|
FilterChain.newBuilder()
|
||||||
Listener.newBuilder()
|
.setName("filter-chain-foo")
|
||||||
.setName("listener1")
|
.setFilterChainMatch(FilterChainMatch.getDefaultInstance())
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
.setTransportSocket(TransportSocket.getDefaultInstance())
|
||||||
.addFilterChains(filterChain)
|
.addFilters(filter)
|
||||||
.build();
|
.build();
|
||||||
StructOrError<io.grpc.xds.EnvoyServerProtoData.Listener> struct =
|
thrown.expect(ResourceInvalidException.class);
|
||||||
ClientXdsClient.parseServerSideListener(listener, null);
|
thrown.expectMessage(
|
||||||
assertThat(struct.getErrorDetail())
|
"FilterChain filter-chain-foo contains filter unsupported with unsupported "
|
||||||
.isEqualTo(
|
+ "typed_config type unsupported-type-url");
|
||||||
"filter envoy.http_connection_manager with unsupported typed_config type:badTypeUrl");
|
ClientXdsClient.parseFilterChain(
|
||||||
|
filterChain, new HashSet<String>(), null, filterRegistry, true /* does not matter */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseServerSideListener_duplicateHttpFilter() {
|
public void parseFilterChain_noName_generatedUuid() throws ResourceInvalidException {
|
||||||
Filter filter =
|
FilterChain filterChain1 =
|
||||||
buildHttpConnectionManager(
|
FilterChain.newBuilder()
|
||||||
"envoy.http_connection_manager",
|
.setFilterChainMatch(FilterChainMatch.getDefaultInstance())
|
||||||
HttpFilter.newBuilder().setName("hf").setIsOptional(true).build(),
|
.addFilters(buildHttpConnectionManagerFilter(
|
||||||
HttpFilter.newBuilder().setName("hf").setIsOptional(true).build());
|
|
||||||
FilterChain filterChain = buildFilterChain(filter);
|
|
||||||
Listener listener =
|
|
||||||
Listener.newBuilder()
|
|
||||||
.setName("listener1")
|
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
|
||||||
.addFilterChains(filterChain)
|
|
||||||
.build();
|
|
||||||
StructOrError<io.grpc.xds.EnvoyServerProtoData.Listener> struct =
|
|
||||||
ClientXdsClient.parseServerSideListener(listener, null);
|
|
||||||
assertThat(struct.getErrorDetail())
|
|
||||||
.isEqualTo("http-connection-manager has non-unique http-filter name:hf");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void parseServerSideListener_configDiscoveryHttpFilter() {
|
|
||||||
Filter filter =
|
|
||||||
buildHttpConnectionManager(
|
|
||||||
"envoy.http_connection_manager",
|
|
||||||
HttpFilter.newBuilder()
|
HttpFilter.newBuilder()
|
||||||
.setName("envoy.router")
|
.setName("http-filter-foo")
|
||||||
.setConfigDiscovery(ExtensionConfigSource.newBuilder().build())
|
.setIsOptional(true)
|
||||||
.build());
|
.build()))
|
||||||
FilterChain filterChain = buildFilterChain(filter);
|
|
||||||
Listener listener =
|
|
||||||
Listener.newBuilder()
|
|
||||||
.setName("listener1")
|
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
|
||||||
.addFilterChains(filterChain)
|
|
||||||
.build();
|
.build();
|
||||||
StructOrError<io.grpc.xds.EnvoyServerProtoData.Listener> struct =
|
FilterChain filterChain2 =
|
||||||
ClientXdsClient.parseServerSideListener(listener, null);
|
FilterChain.newBuilder()
|
||||||
assertThat(struct.getErrorDetail())
|
.setFilterChainMatch(FilterChainMatch.getDefaultInstance())
|
||||||
.isEqualTo(
|
.addFilters(buildHttpConnectionManagerFilter(
|
||||||
"http-connection-manager http-filter envoy.router uses "
|
|
||||||
+ "config-discovery which is unsupported");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void parseServerSideListener_badTypeUrlHttpFilter() {
|
|
||||||
HTTPFault fault = HTTPFault.newBuilder().build();
|
|
||||||
Filter filter =
|
|
||||||
buildHttpConnectionManager(
|
|
||||||
"envoy.http_connection_manager",
|
|
||||||
HttpFilter.newBuilder()
|
HttpFilter.newBuilder()
|
||||||
.setName("envoy.router")
|
.setName("http-filter-bar")
|
||||||
.setTypedConfig(Any.pack(fault, "type.googleapis.com"))
|
.setIsOptional(true)
|
||||||
.build());
|
.build()))
|
||||||
FilterChain filterChain = buildFilterChain(filter);
|
|
||||||
Listener listener =
|
|
||||||
Listener.newBuilder()
|
|
||||||
.setName("listener1")
|
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
|
||||||
.addFilterChains(filterChain)
|
|
||||||
.build();
|
.build();
|
||||||
StructOrError<io.grpc.xds.EnvoyServerProtoData.Listener> struct =
|
|
||||||
ClientXdsClient.parseServerSideListener(listener, null);
|
EnvoyServerProtoData.FilterChain parsedFilterChain1 = ClientXdsClient.parseFilterChain(
|
||||||
assertThat(struct.getErrorDetail())
|
filterChain1, new HashSet<String>(), null, filterRegistry, true /* does not matter */);
|
||||||
.isEqualTo(
|
EnvoyServerProtoData.FilterChain parsedFilterChain2 = ClientXdsClient.parseFilterChain(
|
||||||
"http-connection-manager http-filter envoy.router has unsupported typed-config type:"
|
filterChain2, new HashSet<String>(), null, filterRegistry, true /* does not matter */);
|
||||||
+ "type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault");
|
assertThat(parsedFilterChain1.getName()).isNotEqualTo(parsedFilterChain2.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
private static Filter buildHttpConnectionManagerFilter(HttpFilter... httpFilters) {
|
||||||
public void parseServerSideListener_missingTypeUrlHttpFilter() {
|
|
||||||
Filter filter =
|
|
||||||
buildHttpConnectionManager(
|
|
||||||
"envoy.http_connection_manager",
|
|
||||||
HttpFilter.newBuilder().setName("envoy.filters.http.router").build());
|
|
||||||
FilterChain filterChain = buildFilterChain(filter);
|
|
||||||
Listener listener =
|
|
||||||
Listener.newBuilder()
|
|
||||||
.setName("listener1")
|
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
|
||||||
.addFilterChains(filterChain)
|
|
||||||
.build();
|
|
||||||
StructOrError<io.grpc.xds.EnvoyServerProtoData.Listener> struct =
|
|
||||||
ClientXdsClient.parseServerSideListener(listener, null);
|
|
||||||
assertThat(struct.getErrorDetail())
|
|
||||||
.isEqualTo(
|
|
||||||
"http-connection-manager http-filter envoy.filters.http.router should have "
|
|
||||||
+ "typed-config type "
|
|
||||||
+ "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router");
|
|
||||||
}
|
|
||||||
|
|
||||||
static Filter buildHttpConnectionManager(String name, HttpFilter... httpFilters) {
|
|
||||||
return Filter.newBuilder()
|
return Filter.newBuilder()
|
||||||
.setName(name)
|
.setName("envoy.http_connection_manager")
|
||||||
.setTypedConfig(
|
.setTypedConfig(
|
||||||
Any.pack(
|
Any.pack(
|
||||||
HttpConnectionManager.newBuilder()
|
HttpConnectionManager.newBuilder()
|
||||||
|
.setRds(
|
||||||
|
Rds.newBuilder()
|
||||||
|
.setRouteConfigName("route-config.googleapis.com")
|
||||||
|
.setConfigSource(
|
||||||
|
ConfigSource.newBuilder()
|
||||||
|
.setAds(AggregatedConfigSource.getDefaultInstance())))
|
||||||
.addAllHttpFilters(Arrays.asList(httpFilters))
|
.addAllHttpFilters(Arrays.asList(httpFilters))
|
||||||
.build(),
|
.build(),
|
||||||
"type.googleapis.com"))
|
"type.googleapis.com"))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
static FilterChain buildFilterChain(Filter... filters) {
|
|
||||||
return FilterChain.newBuilder()
|
|
||||||
.setFilterChainMatch(
|
|
||||||
FilterChainMatch.newBuilder()
|
|
||||||
.build())
|
|
||||||
.setTransportSocket(TransportSocket.getDefaultInstance())
|
|
||||||
.addAllFilters(Arrays.asList(filters))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ import com.google.common.collect.Iterables;
|
||||||
import com.google.protobuf.Any;
|
import com.google.protobuf.Any;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import com.google.protobuf.Message;
|
import com.google.protobuf.Message;
|
||||||
import io.envoyproxy.envoy.config.listener.v3.Listener;
|
|
||||||
import io.envoyproxy.envoy.config.route.v3.FilterConfig;
|
import io.envoyproxy.envoy.config.route.v3.FilterConfig;
|
||||||
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.SdsSecretConfig;
|
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.SdsSecretConfig;
|
||||||
import io.grpc.BindableService;
|
import io.grpc.BindableService;
|
||||||
|
|
@ -61,6 +60,7 @@ import io.grpc.xds.Endpoints.DropOverload;
|
||||||
import io.grpc.xds.Endpoints.LbEndpoint;
|
import io.grpc.xds.Endpoints.LbEndpoint;
|
||||||
import io.grpc.xds.Endpoints.LocalityLbEndpoints;
|
import io.grpc.xds.Endpoints.LocalityLbEndpoints;
|
||||||
import io.grpc.xds.EnvoyProtoData.Node;
|
import io.grpc.xds.EnvoyProtoData.Node;
|
||||||
|
import io.grpc.xds.EnvoyServerProtoData.FilterChain;
|
||||||
import io.grpc.xds.FaultConfig.FractionalPercent.DenominatorType;
|
import io.grpc.xds.FaultConfig.FractionalPercent.DenominatorType;
|
||||||
import io.grpc.xds.LoadStatsManager2.ClusterDropStats;
|
import io.grpc.xds.LoadStatsManager2.ClusterDropStats;
|
||||||
import io.grpc.xds.XdsClient.CdsResourceWatcher;
|
import io.grpc.xds.XdsClient.CdsResourceWatcher;
|
||||||
|
|
@ -182,9 +182,10 @@ public abstract class ClientXdsClientTestBase {
|
||||||
|
|
||||||
private static final int VHOST_SIZE = 2;
|
private static final int VHOST_SIZE = 2;
|
||||||
// LDS test resources.
|
// LDS test resources.
|
||||||
private final Any testListenerVhosts = Any.pack(mf.buildListener(LDS_RESOURCE,
|
private final Any testListenerVhosts = Any.pack(mf.buildListenerWithApiListener(LDS_RESOURCE,
|
||||||
mf.buildRouteConfiguration("do not care", mf.buildOpaqueVirtualHosts(VHOST_SIZE))));
|
mf.buildRouteConfiguration("do not care", mf.buildOpaqueVirtualHosts(VHOST_SIZE))));
|
||||||
private final Any testListenerRds = Any.pack(mf.buildListenerForRds(LDS_RESOURCE, RDS_RESOURCE));
|
private final Any testListenerRds =
|
||||||
|
Any.pack(mf.buildListenerWithApiListenerForRds(LDS_RESOURCE, RDS_RESOURCE));
|
||||||
|
|
||||||
// RDS test resources.
|
// RDS test resources.
|
||||||
private final Any testRouteConfig =
|
private final Any testRouteConfig =
|
||||||
|
|
@ -420,7 +421,7 @@ public abstract class ClientXdsClientTestBase {
|
||||||
public void ldsResourceNotFound() {
|
public void ldsResourceNotFound() {
|
||||||
DiscoveryRpcCall call = startResourceWatcher(LDS, LDS_RESOURCE, ldsResourceWatcher);
|
DiscoveryRpcCall call = startResourceWatcher(LDS, LDS_RESOURCE, ldsResourceWatcher);
|
||||||
|
|
||||||
Any listener = Any.pack(mf.buildListener("bar.googleapis.com",
|
Any listener = Any.pack(mf.buildListenerWithApiListener("bar.googleapis.com",
|
||||||
mf.buildRouteConfiguration("route-bar.googleapis.com", mf.buildOpaqueVirtualHosts(1))));
|
mf.buildRouteConfiguration("route-bar.googleapis.com", mf.buildOpaqueVirtualHosts(1))));
|
||||||
call.sendResponse(LDS, listener, VERSION_1, "0000");
|
call.sendResponse(LDS, listener, VERSION_1, "0000");
|
||||||
|
|
||||||
|
|
@ -494,9 +495,9 @@ public abstract class ClientXdsClientTestBase {
|
||||||
|
|
||||||
// LDS -> {A, B, C}, version 1
|
// LDS -> {A, B, C}, version 1
|
||||||
ImmutableMap<String, Any> resourcesV1 = ImmutableMap.of(
|
ImmutableMap<String, Any> resourcesV1 = ImmutableMap.of(
|
||||||
"A", Any.pack(mf.buildListenerForRds("A", "A.1")),
|
"A", Any.pack(mf.buildListenerWithApiListenerForRds("A", "A.1")),
|
||||||
"B", Any.pack(mf.buildListenerForRds("B", "B.1")),
|
"B", Any.pack(mf.buildListenerWithApiListenerForRds("B", "B.1")),
|
||||||
"C", Any.pack(mf.buildListenerForRds("C", "C.1")));
|
"C", Any.pack(mf.buildListenerWithApiListenerForRds("C", "C.1")));
|
||||||
call.sendResponse(LDS, resourcesV1.values().asList(), VERSION_1, "0000");
|
call.sendResponse(LDS, resourcesV1.values().asList(), VERSION_1, "0000");
|
||||||
// {A, B, C} -> ACK, version 1
|
// {A, B, C} -> ACK, version 1
|
||||||
verifyResourceMetadataAcked(LDS, "A", resourcesV1.get("A"), VERSION_1, TIME_INCREMENT);
|
verifyResourceMetadataAcked(LDS, "A", resourcesV1.get("A"), VERSION_1, TIME_INCREMENT);
|
||||||
|
|
@ -507,8 +508,8 @@ public abstract class ClientXdsClientTestBase {
|
||||||
// LDS -> {A, B}, version 2
|
// LDS -> {A, B}, version 2
|
||||||
// Failed to parse endpoint B
|
// Failed to parse endpoint B
|
||||||
ImmutableMap<String, Any> resourcesV2 = ImmutableMap.of(
|
ImmutableMap<String, Any> resourcesV2 = ImmutableMap.of(
|
||||||
"A", Any.pack(mf.buildListenerForRds("A", "A.2")),
|
"A", Any.pack(mf.buildListenerWithApiListenerForRds("A", "A.2")),
|
||||||
"B", Any.pack(mf.buildListenerInvalid("B")));
|
"B", Any.pack(mf.buildListenerWithApiListenerInvalid("B")));
|
||||||
call.sendResponse(LDS, resourcesV2.values().asList(), VERSION_2, "0001");
|
call.sendResponse(LDS, resourcesV2.values().asList(), VERSION_2, "0001");
|
||||||
// {A, B} -> NACK, version 1, rejected version 2, rejected reason: Failed to parse B
|
// {A, B} -> NACK, version 1, rejected version 2, rejected reason: Failed to parse B
|
||||||
// {C} -> ACK, version 1
|
// {C} -> ACK, version 1
|
||||||
|
|
@ -522,8 +523,8 @@ public abstract class ClientXdsClientTestBase {
|
||||||
|
|
||||||
// LDS -> {B, C} version 3
|
// LDS -> {B, C} version 3
|
||||||
ImmutableMap<String, Any> resourcesV3 = ImmutableMap.of(
|
ImmutableMap<String, Any> resourcesV3 = ImmutableMap.of(
|
||||||
"B", Any.pack(mf.buildListenerForRds("B", "B.3")),
|
"B", Any.pack(mf.buildListenerWithApiListenerForRds("B", "B.3")),
|
||||||
"C", Any.pack(mf.buildListenerForRds("C", "C.3")));
|
"C", Any.pack(mf.buildListenerWithApiListenerForRds("C", "C.3")));
|
||||||
call.sendResponse(LDS, resourcesV3.values().asList(), VERSION_3, "0002");
|
call.sendResponse(LDS, resourcesV3.values().asList(), VERSION_3, "0002");
|
||||||
// {A} -> NACK, version 1, rejected version 2, rejected reason: Failed to parse B
|
// {A} -> NACK, version 1, rejected version 2, rejected reason: Failed to parse B
|
||||||
// {B, C} -> ACK, version 3
|
// {B, C} -> ACK, version 3
|
||||||
|
|
@ -542,7 +543,8 @@ public abstract class ClientXdsClientTestBase {
|
||||||
call.sendResponse(LDS, testListenerVhosts, VERSION_1, "0000");
|
call.sendResponse(LDS, testListenerVhosts, VERSION_1, "0000");
|
||||||
call.verifyRequest(LDS, LDS_RESOURCE, VERSION_1, "0000", NODE);
|
call.verifyRequest(LDS, LDS_RESOURCE, VERSION_1, "0000", NODE);
|
||||||
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
||||||
assertThat(ldsUpdateCaptor.getValue().virtualHosts).hasSize(VHOST_SIZE);
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().virtualHosts())
|
||||||
|
.hasSize(VHOST_SIZE);
|
||||||
assertThat(fakeClock.getPendingTasks(LDS_RESOURCE_FETCH_TIMEOUT_TASK_FILTER)).isEmpty();
|
assertThat(fakeClock.getPendingTasks(LDS_RESOURCE_FETCH_TIMEOUT_TASK_FILTER)).isEmpty();
|
||||||
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerVhosts, VERSION_1, TIME_INCREMENT);
|
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerVhosts, VERSION_1, TIME_INCREMENT);
|
||||||
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
|
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
|
||||||
|
|
@ -556,7 +558,8 @@ public abstract class ClientXdsClientTestBase {
|
||||||
// Client sends an ACK LDS request.
|
// Client sends an ACK LDS request.
|
||||||
call.verifyRequest(LDS, LDS_RESOURCE, VERSION_1, "0000", NODE);
|
call.verifyRequest(LDS, LDS_RESOURCE, VERSION_1, "0000", NODE);
|
||||||
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
||||||
assertThat(ldsUpdateCaptor.getValue().rdsName).isEqualTo(RDS_RESOURCE);
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().rdsName())
|
||||||
|
.isEqualTo(RDS_RESOURCE);
|
||||||
assertThat(fakeClock.getPendingTasks(LDS_RESOURCE_FETCH_TIMEOUT_TASK_FILTER)).isEmpty();
|
assertThat(fakeClock.getPendingTasks(LDS_RESOURCE_FETCH_TIMEOUT_TASK_FILTER)).isEmpty();
|
||||||
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerRds, VERSION_1, TIME_INCREMENT);
|
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerRds, VERSION_1, TIME_INCREMENT);
|
||||||
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
|
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
|
||||||
|
|
@ -573,7 +576,8 @@ public abstract class ClientXdsClientTestBase {
|
||||||
LdsResourceWatcher watcher = mock(LdsResourceWatcher.class);
|
LdsResourceWatcher watcher = mock(LdsResourceWatcher.class);
|
||||||
xdsClient.watchLdsResource(LDS_RESOURCE, watcher);
|
xdsClient.watchLdsResource(LDS_RESOURCE, watcher);
|
||||||
verify(watcher).onChanged(ldsUpdateCaptor.capture());
|
verify(watcher).onChanged(ldsUpdateCaptor.capture());
|
||||||
assertThat(ldsUpdateCaptor.getValue().rdsName).isEqualTo(RDS_RESOURCE);
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().rdsName())
|
||||||
|
.isEqualTo(RDS_RESOURCE);
|
||||||
call.verifyNoMoreRequest();
|
call.verifyNoMoreRequest();
|
||||||
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerRds, VERSION_1, TIME_INCREMENT);
|
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerRds, VERSION_1, TIME_INCREMENT);
|
||||||
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
|
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
|
||||||
|
|
@ -602,14 +606,16 @@ public abstract class ClientXdsClientTestBase {
|
||||||
call.sendResponse(LDS, testListenerVhosts, VERSION_1, "0000");
|
call.sendResponse(LDS, testListenerVhosts, VERSION_1, "0000");
|
||||||
call.verifyRequest(LDS, LDS_RESOURCE, VERSION_1, "0000", NODE);
|
call.verifyRequest(LDS, LDS_RESOURCE, VERSION_1, "0000", NODE);
|
||||||
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
||||||
assertThat(ldsUpdateCaptor.getValue().virtualHosts).hasSize(VHOST_SIZE);
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().virtualHosts())
|
||||||
|
.hasSize(VHOST_SIZE);
|
||||||
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerVhosts, VERSION_1, TIME_INCREMENT);
|
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerVhosts, VERSION_1, TIME_INCREMENT);
|
||||||
|
|
||||||
// Updated LDS response.
|
// Updated LDS response.
|
||||||
call.sendResponse(LDS, testListenerRds, VERSION_2, "0001");
|
call.sendResponse(LDS, testListenerRds, VERSION_2, "0001");
|
||||||
call.verifyRequest(LDS, LDS_RESOURCE, VERSION_2, "0001", NODE);
|
call.verifyRequest(LDS, LDS_RESOURCE, VERSION_2, "0001", NODE);
|
||||||
verify(ldsResourceWatcher, times(2)).onChanged(ldsUpdateCaptor.capture());
|
verify(ldsResourceWatcher, times(2)).onChanged(ldsUpdateCaptor.capture());
|
||||||
assertThat(ldsUpdateCaptor.getValue().rdsName).isEqualTo(RDS_RESOURCE);
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().rdsName())
|
||||||
|
.isEqualTo(RDS_RESOURCE);
|
||||||
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerRds, VERSION_2, TIME_INCREMENT * 2);
|
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerRds, VERSION_2, TIME_INCREMENT * 2);
|
||||||
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
|
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
@ -619,7 +625,7 @@ public abstract class ClientXdsClientTestBase {
|
||||||
Assume.assumeTrue(useProtocolV3());
|
Assume.assumeTrue(useProtocolV3());
|
||||||
DiscoveryRpcCall call = startResourceWatcher(LDS, LDS_RESOURCE, ldsResourceWatcher);
|
DiscoveryRpcCall call = startResourceWatcher(LDS, LDS_RESOURCE, ldsResourceWatcher);
|
||||||
Any listener = Any.pack(
|
Any listener = Any.pack(
|
||||||
mf.buildListener(
|
mf.buildListenerWithApiListener(
|
||||||
LDS_RESOURCE,
|
LDS_RESOURCE,
|
||||||
mf.buildRouteConfiguration(
|
mf.buildRouteConfiguration(
|
||||||
"do not care",
|
"do not care",
|
||||||
|
|
@ -657,9 +663,10 @@ public abstract class ClientXdsClientTestBase {
|
||||||
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
|
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
|
||||||
|
|
||||||
LdsUpdate ldsUpdate = ldsUpdateCaptor.getValue();
|
LdsUpdate ldsUpdate = ldsUpdateCaptor.getValue();
|
||||||
assertThat(ldsUpdate.virtualHosts).hasSize(2);
|
assertThat(ldsUpdate.httpConnectionManager().virtualHosts()).hasSize(2);
|
||||||
assertThat(ldsUpdate.filterChain.get(0).name).isEqualTo("envoy.fault");
|
assertThat(ldsUpdate.httpConnectionManager().httpFilterConfigs().get(0).name)
|
||||||
FaultConfig faultConfig = (FaultConfig) ldsUpdate.virtualHosts.get(0)
|
.isEqualTo("envoy.fault");
|
||||||
|
FaultConfig faultConfig = (FaultConfig) ldsUpdate.httpConnectionManager().virtualHosts().get(0)
|
||||||
.filterConfigOverrides().get("envoy.fault");
|
.filterConfigOverrides().get("envoy.fault");
|
||||||
assertThat(faultConfig.faultDelay().delayNanos()).isEqualTo(300);
|
assertThat(faultConfig.faultDelay().delayNanos()).isEqualTo(300);
|
||||||
assertThat(faultConfig.faultDelay().percent().numerator()).isEqualTo(1000);
|
assertThat(faultConfig.faultDelay().percent().numerator()).isEqualTo(1000);
|
||||||
|
|
@ -667,7 +674,7 @@ public abstract class ClientXdsClientTestBase {
|
||||||
.isEqualTo(DenominatorType.MILLION);
|
.isEqualTo(DenominatorType.MILLION);
|
||||||
assertThat(faultConfig.faultAbort()).isNull();
|
assertThat(faultConfig.faultAbort()).isNull();
|
||||||
assertThat(faultConfig.maxActiveFaults()).isEqualTo(100);
|
assertThat(faultConfig.maxActiveFaults()).isEqualTo(100);
|
||||||
faultConfig = (FaultConfig) ldsUpdate.virtualHosts.get(1)
|
faultConfig = (FaultConfig) ldsUpdate.httpConnectionManager().virtualHosts().get(1)
|
||||||
.filterConfigOverrides().get("envoy.fault");
|
.filterConfigOverrides().get("envoy.fault");
|
||||||
assertThat(faultConfig.faultDelay()).isNull();
|
assertThat(faultConfig.faultDelay()).isNull();
|
||||||
assertThat(faultConfig.faultAbort().status().getCode()).isEqualTo(Status.Code.UNAVAILABLE);
|
assertThat(faultConfig.faultAbort().status().getCode()).isEqualTo(Status.Code.UNAVAILABLE);
|
||||||
|
|
@ -686,7 +693,8 @@ public abstract class ClientXdsClientTestBase {
|
||||||
call.sendResponse(LDS, testListenerVhosts, VERSION_1, "0000");
|
call.sendResponse(LDS, testListenerVhosts, VERSION_1, "0000");
|
||||||
call.verifyRequest(LDS, LDS_RESOURCE, VERSION_1, "0000", NODE);
|
call.verifyRequest(LDS, LDS_RESOURCE, VERSION_1, "0000", NODE);
|
||||||
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
||||||
assertThat(ldsUpdateCaptor.getValue().virtualHosts).hasSize(VHOST_SIZE);
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().virtualHosts())
|
||||||
|
.hasSize(VHOST_SIZE);
|
||||||
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerVhosts, VERSION_1, TIME_INCREMENT);
|
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerVhosts, VERSION_1, TIME_INCREMENT);
|
||||||
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
|
verifySubscribedResourcesMetadataSizes(1, 0, 0, 0);
|
||||||
|
|
||||||
|
|
@ -721,19 +729,22 @@ public abstract class ClientXdsClientTestBase {
|
||||||
verifyResourceMetadataDoesNotExist(LDS, ldsResourceTwo);
|
verifyResourceMetadataDoesNotExist(LDS, ldsResourceTwo);
|
||||||
verifySubscribedResourcesMetadataSizes(2, 0, 0, 0);
|
verifySubscribedResourcesMetadataSizes(2, 0, 0, 0);
|
||||||
|
|
||||||
Any listenerTwo = Any.pack(mf.buildListenerForRds(ldsResourceTwo, RDS_RESOURCE));
|
Any listenerTwo = Any.pack(mf.buildListenerWithApiListenerForRds(ldsResourceTwo, RDS_RESOURCE));
|
||||||
call.sendResponse(LDS, ImmutableList.of(testListenerVhosts, listenerTwo), VERSION_1, "0000");
|
call.sendResponse(LDS, ImmutableList.of(testListenerVhosts, listenerTwo), VERSION_1, "0000");
|
||||||
// ldsResourceWatcher called with listenerVhosts.
|
// ldsResourceWatcher called with listenerVhosts.
|
||||||
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
||||||
assertThat(ldsUpdateCaptor.getValue().virtualHosts).hasSize(VHOST_SIZE);
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().virtualHosts())
|
||||||
|
.hasSize(VHOST_SIZE);
|
||||||
// watcher1 called with listenerTwo.
|
// watcher1 called with listenerTwo.
|
||||||
verify(watcher1).onChanged(ldsUpdateCaptor.capture());
|
verify(watcher1).onChanged(ldsUpdateCaptor.capture());
|
||||||
assertThat(ldsUpdateCaptor.getValue().rdsName).isEqualTo(RDS_RESOURCE);
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().rdsName())
|
||||||
assertThat(ldsUpdateCaptor.getValue().virtualHosts).isNull();
|
.isEqualTo(RDS_RESOURCE);
|
||||||
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().virtualHosts()).isNull();
|
||||||
// watcher2 called with listenerTwo.
|
// watcher2 called with listenerTwo.
|
||||||
verify(watcher2).onChanged(ldsUpdateCaptor.capture());
|
verify(watcher2).onChanged(ldsUpdateCaptor.capture());
|
||||||
assertThat(ldsUpdateCaptor.getValue().rdsName).isEqualTo(RDS_RESOURCE);
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().rdsName())
|
||||||
assertThat(ldsUpdateCaptor.getValue().virtualHosts).isNull();
|
.isEqualTo(RDS_RESOURCE);
|
||||||
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().virtualHosts()).isNull();
|
||||||
// Metadata of both listeners is stored.
|
// Metadata of both listeners is stored.
|
||||||
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerVhosts, VERSION_1, TIME_INCREMENT);
|
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerVhosts, VERSION_1, TIME_INCREMENT);
|
||||||
verifyResourceMetadataAcked(LDS, ldsResourceTwo, listenerTwo, VERSION_1, TIME_INCREMENT);
|
verifyResourceMetadataAcked(LDS, ldsResourceTwo, listenerTwo, VERSION_1, TIME_INCREMENT);
|
||||||
|
|
@ -933,7 +944,7 @@ public abstract class ClientXdsClientTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void rdsResourceDeletedByLds() {
|
public void rdsResourceDeletedByLdsApiListener() {
|
||||||
xdsClient.watchLdsResource(LDS_RESOURCE, ldsResourceWatcher);
|
xdsClient.watchLdsResource(LDS_RESOURCE, ldsResourceWatcher);
|
||||||
xdsClient.watchRdsResource(RDS_RESOURCE, rdsResourceWatcher);
|
xdsClient.watchRdsResource(RDS_RESOURCE, rdsResourceWatcher);
|
||||||
verifyResourceMetadataRequested(LDS, LDS_RESOURCE);
|
verifyResourceMetadataRequested(LDS, LDS_RESOURCE);
|
||||||
|
|
@ -943,7 +954,8 @@ public abstract class ClientXdsClientTestBase {
|
||||||
DiscoveryRpcCall call = resourceDiscoveryCalls.poll();
|
DiscoveryRpcCall call = resourceDiscoveryCalls.poll();
|
||||||
call.sendResponse(LDS, testListenerRds, VERSION_1, "0000");
|
call.sendResponse(LDS, testListenerRds, VERSION_1, "0000");
|
||||||
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
||||||
assertThat(ldsUpdateCaptor.getValue().rdsName).isEqualTo(RDS_RESOURCE);
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().rdsName())
|
||||||
|
.isEqualTo(RDS_RESOURCE);
|
||||||
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerRds, VERSION_1, TIME_INCREMENT);
|
verifyResourceMetadataAcked(LDS, LDS_RESOURCE, testListenerRds, VERSION_1, TIME_INCREMENT);
|
||||||
verifyResourceMetadataRequested(RDS, RDS_RESOURCE);
|
verifyResourceMetadataRequested(RDS, RDS_RESOURCE);
|
||||||
verifySubscribedResourcesMetadataSizes(1, 0, 1, 0);
|
verifySubscribedResourcesMetadataSizes(1, 0, 1, 0);
|
||||||
|
|
@ -957,7 +969,8 @@ public abstract class ClientXdsClientTestBase {
|
||||||
|
|
||||||
call.sendResponse(LDS, testListenerVhosts, VERSION_2, "0001");
|
call.sendResponse(LDS, testListenerVhosts, VERSION_2, "0001");
|
||||||
verify(ldsResourceWatcher, times(2)).onChanged(ldsUpdateCaptor.capture());
|
verify(ldsResourceWatcher, times(2)).onChanged(ldsUpdateCaptor.capture());
|
||||||
assertThat(ldsUpdateCaptor.getValue().virtualHosts).hasSize(VHOST_SIZE);
|
assertThat(ldsUpdateCaptor.getValue().httpConnectionManager().virtualHosts())
|
||||||
|
.hasSize(VHOST_SIZE);
|
||||||
verify(rdsResourceWatcher).onResourceDoesNotExist(RDS_RESOURCE);
|
verify(rdsResourceWatcher).onResourceDoesNotExist(RDS_RESOURCE);
|
||||||
verifyResourceMetadataDoesNotExist(RDS, RDS_RESOURCE);
|
verifyResourceMetadataDoesNotExist(RDS, RDS_RESOURCE);
|
||||||
verifyResourceMetadataAcked(
|
verifyResourceMetadataAcked(
|
||||||
|
|
@ -965,6 +978,68 @@ public abstract class ClientXdsClientTestBase {
|
||||||
verifySubscribedResourcesMetadataSizes(1, 0, 1, 0);
|
verifySubscribedResourcesMetadataSizes(1, 0, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void rdsResourcesDeletedByLdsTcpListener() {
|
||||||
|
Assume.assumeTrue(useProtocolV3());
|
||||||
|
xdsClient.watchLdsResource(LISTENER_RESOURCE, ldsResourceWatcher);
|
||||||
|
xdsClient.watchRdsResource(RDS_RESOURCE, rdsResourceWatcher);
|
||||||
|
verifyResourceMetadataRequested(LDS, LISTENER_RESOURCE);
|
||||||
|
verifyResourceMetadataRequested(RDS, RDS_RESOURCE);
|
||||||
|
verifySubscribedResourcesMetadataSizes(1, 0, 1, 0);
|
||||||
|
|
||||||
|
Message hcmFilter = mf.buildHttpConnectionManagerFilter(
|
||||||
|
RDS_RESOURCE, null, Collections.<Message>emptyList());
|
||||||
|
Message downstreamTlsContext = CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
|
||||||
|
"google-sds-config-default", "ROOTCA");
|
||||||
|
Message filterChain = mf.buildFilterChain(
|
||||||
|
Collections.<String>emptyList(), downstreamTlsContext, hcmFilter);
|
||||||
|
Any packedListener =
|
||||||
|
Any.pack(mf.buildListenerWithFilterChain(LISTENER_RESOURCE, 7000, "0.0.0.0", filterChain));
|
||||||
|
|
||||||
|
// Simulates receiving the requested LDS resource as a TCP listener with a filter chain
|
||||||
|
// referencing RDS_RESOURCE.
|
||||||
|
DiscoveryRpcCall call = resourceDiscoveryCalls.poll();
|
||||||
|
call.sendResponse(LDS, packedListener, VERSION_1, "0000");
|
||||||
|
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
||||||
|
|
||||||
|
assertThat(ldsUpdateCaptor.getValue().listener().getFilterChains()).hasSize(1);
|
||||||
|
FilterChain parsedFilterChain = Iterables.getOnlyElement(
|
||||||
|
ldsUpdateCaptor.getValue().listener().getFilterChains());
|
||||||
|
assertThat(parsedFilterChain.getHttpConnectionManager().rdsName()).isEqualTo(RDS_RESOURCE);
|
||||||
|
verifyResourceMetadataAcked(LDS, LISTENER_RESOURCE, packedListener, VERSION_1, TIME_INCREMENT);
|
||||||
|
verifyResourceMetadataRequested(RDS, RDS_RESOURCE);
|
||||||
|
verifySubscribedResourcesMetadataSizes(1, 0, 1, 0);
|
||||||
|
|
||||||
|
// Simulates receiving the requested RDS resource.
|
||||||
|
call.sendResponse(RDS, testRouteConfig, VERSION_1, "0000");
|
||||||
|
verify(rdsResourceWatcher).onChanged(rdsUpdateCaptor.capture());
|
||||||
|
assertThat(rdsUpdateCaptor.getValue().virtualHosts).hasSize(VHOST_SIZE);
|
||||||
|
verifyResourceMetadataAcked(RDS, RDS_RESOURCE, testRouteConfig, VERSION_1, TIME_INCREMENT * 2);
|
||||||
|
|
||||||
|
// Simulates receiving an updated version of the requested LDS resource as a TCP listener
|
||||||
|
// with a filter chain containing inlined RouteConfiguration.
|
||||||
|
hcmFilter = mf.buildHttpConnectionManagerFilter(
|
||||||
|
null,
|
||||||
|
mf.buildRouteConfiguration(
|
||||||
|
"route-bar.googleapis.com", mf.buildOpaqueVirtualHosts(VHOST_SIZE)),
|
||||||
|
Collections.<Message>emptyList());
|
||||||
|
filterChain = mf.buildFilterChain(
|
||||||
|
Collections.<String>emptyList(), downstreamTlsContext, hcmFilter);
|
||||||
|
packedListener =
|
||||||
|
Any.pack(mf.buildListenerWithFilterChain(LISTENER_RESOURCE, 7000, "0.0.0.0", filterChain));
|
||||||
|
call.sendResponse(LDS, packedListener, VERSION_2, "0001");
|
||||||
|
verify(ldsResourceWatcher, times(2)).onChanged(ldsUpdateCaptor.capture());
|
||||||
|
assertThat(ldsUpdateCaptor.getValue().listener().getFilterChains()).hasSize(1);
|
||||||
|
parsedFilterChain = Iterables.getOnlyElement(
|
||||||
|
ldsUpdateCaptor.getValue().listener().getFilterChains());
|
||||||
|
assertThat(parsedFilterChain.getHttpConnectionManager().virtualHosts()).hasSize(VHOST_SIZE);
|
||||||
|
verify(rdsResourceWatcher).onResourceDoesNotExist(RDS_RESOURCE);
|
||||||
|
verifyResourceMetadataDoesNotExist(RDS, RDS_RESOURCE);
|
||||||
|
verifyResourceMetadataAcked(
|
||||||
|
LDS, LISTENER_RESOURCE, packedListener, VERSION_2, TIME_INCREMENT * 3);
|
||||||
|
verifySubscribedResourcesMetadataSizes(1, 0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void multipleRdsWatchers() {
|
public void multipleRdsWatchers() {
|
||||||
String rdsResourceTwo = "route-bar.googleapis.com";
|
String rdsResourceTwo = "route-bar.googleapis.com";
|
||||||
|
|
@ -1873,7 +1948,7 @@ public abstract class ClientXdsClientTestBase {
|
||||||
call.verifyRequest(EDS, EDS_RESOURCE, "", "", NODE);
|
call.verifyRequest(EDS, EDS_RESOURCE, "", "", NODE);
|
||||||
|
|
||||||
List<Any> listeners = ImmutableList.of(
|
List<Any> listeners = ImmutableList.of(
|
||||||
Any.pack(mf.buildListener(LDS_RESOURCE,
|
Any.pack(mf.buildListenerWithApiListener(LDS_RESOURCE,
|
||||||
mf.buildRouteConfiguration("do not care", mf.buildOpaqueVirtualHosts(2)))));
|
mf.buildRouteConfiguration("do not care", mf.buildOpaqueVirtualHosts(2)))));
|
||||||
call.sendResponse(LDS, listeners, "63", "3242");
|
call.sendResponse(LDS, listeners, "63", "3242");
|
||||||
call.verifyRequest(LDS, LDS_RESOURCE, "63", "3242", NODE);
|
call.verifyRequest(LDS, LDS_RESOURCE, "63", "3242", NODE);
|
||||||
|
|
@ -2018,36 +2093,34 @@ public abstract class ClientXdsClientTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void serverSideListenerFound() throws InvalidProtocolBufferException {
|
public void serverSideListenerFound() {
|
||||||
Assume.assumeTrue(useProtocolV3());
|
Assume.assumeTrue(useProtocolV3());
|
||||||
ClientXdsClientTestBase.DiscoveryRpcCall call =
|
ClientXdsClientTestBase.DiscoveryRpcCall call =
|
||||||
startResourceWatcher(LDS, LISTENER_RESOURCE, ldsResourceWatcher);
|
startResourceWatcher(LDS, LISTENER_RESOURCE, ldsResourceWatcher);
|
||||||
|
Message hcmFilter = mf.buildHttpConnectionManagerFilter(
|
||||||
|
"route-foo.googleapis.com", null, Collections.<Message>emptyList());
|
||||||
|
Message downstreamTlsContext = CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
|
||||||
|
"google-sds-config-default", "ROOTCA");
|
||||||
|
Message filterChain = mf.buildFilterChain(
|
||||||
|
Collections.<String>emptyList(), downstreamTlsContext, hcmFilter);
|
||||||
Message listener =
|
Message listener =
|
||||||
mf.buildListenerWithFilterChain(
|
mf.buildListenerWithFilterChain(LISTENER_RESOURCE, 7000, "0.0.0.0", filterChain);
|
||||||
LISTENER_RESOURCE, 7000, "0.0.0.0", "google-sds-config-default", "ROOTCA");
|
|
||||||
List<Any> listeners = ImmutableList.of(Any.pack(listener));
|
List<Any> listeners = ImmutableList.of(Any.pack(listener));
|
||||||
call.sendResponse(ResourceType.LDS, listeners, "0", "0000");
|
call.sendResponse(ResourceType.LDS, listeners, "0", "0000");
|
||||||
// Client sends an ACK LDS request.
|
// Client sends an ACK LDS request.
|
||||||
call.verifyRequest(
|
call.verifyRequest(
|
||||||
ResourceType.LDS, Collections.singletonList(LISTENER_RESOURCE), "0", "0000", NODE);
|
ResourceType.LDS, Collections.singletonList(LISTENER_RESOURCE), "0", "0000", NODE);
|
||||||
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
verify(ldsResourceWatcher).onChanged(ldsUpdateCaptor.capture());
|
||||||
assertThat(ldsUpdateCaptor.getValue().listener)
|
EnvoyServerProtoData.Listener parsedListener = ldsUpdateCaptor.getValue().listener();
|
||||||
.isEqualTo(EnvoyServerProtoData.Listener
|
assertThat(parsedListener.getName()).isEqualTo(LISTENER_RESOURCE);
|
||||||
.fromEnvoyProtoListener((Listener) listener, tlsContextManager));
|
assertThat(parsedListener.getAddress()).isEqualTo("0.0.0.0:7000");
|
||||||
|
assertThat(parsedListener.getDefaultFilterChain()).isNull();
|
||||||
listener =
|
assertThat(parsedListener.getFilterChains()).hasSize(1);
|
||||||
mf.buildListenerWithFilterChain(
|
FilterChain parsedFilterChain = Iterables.getOnlyElement(parsedListener.getFilterChains());
|
||||||
LISTENER_RESOURCE, 7000, "0.0.0.0", "CERT2", "ROOTCA2");
|
assertThat(parsedFilterChain.getFilterChainMatch().getApplicationProtocols()).isEmpty();
|
||||||
listeners = ImmutableList.of(Any.pack(listener));
|
assertThat(parsedFilterChain.getHttpConnectionManager().rdsName())
|
||||||
call.sendResponse(ResourceType.LDS, listeners, "1", "0001");
|
.isEqualTo("route-foo.googleapis.com");
|
||||||
|
assertThat(parsedFilterChain.getHttpConnectionManager().httpFilterConfigs()).isEmpty();
|
||||||
// Client sends an ACK LDS request.
|
|
||||||
call.verifyRequest(
|
|
||||||
ResourceType.LDS, Collections.singletonList(LISTENER_RESOURCE), "1", "0001", NODE);
|
|
||||||
verify(ldsResourceWatcher, times(2)).onChanged(ldsUpdateCaptor.capture());
|
|
||||||
assertThat(ldsUpdateCaptor.getValue().listener)
|
|
||||||
.isEqualTo(EnvoyServerProtoData.Listener
|
|
||||||
.fromEnvoyProtoListener((Listener) listener, tlsContextManager));
|
|
||||||
|
|
||||||
assertThat(fakeClock.getPendingTasks(LDS_RESOURCE_FETCH_TIMEOUT_TASK_FILTER)).isEmpty();
|
assertThat(fakeClock.getPendingTasks(LDS_RESOURCE_FETCH_TIMEOUT_TASK_FILTER)).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
@ -2057,18 +2130,14 @@ public abstract class ClientXdsClientTestBase {
|
||||||
Assume.assumeTrue(useProtocolV3());
|
Assume.assumeTrue(useProtocolV3());
|
||||||
ClientXdsClientTestBase.DiscoveryRpcCall call =
|
ClientXdsClientTestBase.DiscoveryRpcCall call =
|
||||||
startResourceWatcher(LDS, LISTENER_RESOURCE, ldsResourceWatcher);
|
startResourceWatcher(LDS, LISTENER_RESOURCE, ldsResourceWatcher);
|
||||||
final Message filterChainInbound =
|
Message hcmFilter = mf.buildHttpConnectionManagerFilter(
|
||||||
mf.buildFilterChain(
|
"route-foo.googleapis.com", null, Collections.<Message>emptyList());
|
||||||
Arrays.asList("managed-mtls"),
|
Message downstreamTlsContext = CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
|
||||||
CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
|
"google-sds-config-default", "ROOTCA");
|
||||||
"google-sds-config-default", "ROOTCA"),
|
Message filterChain = mf.buildFilterChain(
|
||||||
mf.buildTestFilter("envoy.http_connection_manager"));
|
Collections.singletonList("managed-mtls"), downstreamTlsContext, hcmFilter);
|
||||||
Message listener =
|
Message listener = mf.buildListenerWithFilterChain(
|
||||||
mf.buildListenerWithFilterChain(
|
"grpc/server?xds.resource.listening_address=0.0.0.0:8000", 7000, "0.0.0.0", filterChain);
|
||||||
"grpc/server?xds.resource.listening_address=0.0.0.0:8000",
|
|
||||||
7000,
|
|
||||||
"0.0.0.0",
|
|
||||||
filterChainInbound);
|
|
||||||
List<Any> listeners = ImmutableList.of(Any.pack(listener));
|
List<Any> listeners = ImmutableList.of(Any.pack(listener));
|
||||||
call.sendResponse(ResourceType.LDS, listeners, "0", "0000");
|
call.sendResponse(ResourceType.LDS, listeners, "0", "0000");
|
||||||
// Client sends an ACK LDS request.
|
// Client sends an ACK LDS request.
|
||||||
|
|
@ -2162,16 +2231,18 @@ public abstract class ClientXdsClientTestBase {
|
||||||
/** Throws {@link InvalidProtocolBufferException} on {@link Any#unpack(Class)}. */
|
/** Throws {@link InvalidProtocolBufferException} on {@link Any#unpack(Class)}. */
|
||||||
protected static final Any FAILING_ANY = Any.newBuilder().setTypeUrl("fake").build();
|
protected static final Any FAILING_ANY = Any.newBuilder().setTypeUrl("fake").build();
|
||||||
|
|
||||||
protected final Message buildListener(String name, Message routeConfiguration) {
|
protected final Message buildListenerWithApiListener(String name, Message routeConfiguration) {
|
||||||
return buildListener(name, routeConfiguration, Collections.<Message>emptyList());
|
return buildListenerWithApiListener(
|
||||||
|
name, routeConfiguration, Collections.<Message>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Message buildListener(
|
protected abstract Message buildListenerWithApiListener(
|
||||||
String name, Message routeConfiguration, List<? extends Message> httpFilters);
|
String name, Message routeConfiguration, List<? extends Message> httpFilters);
|
||||||
|
|
||||||
protected abstract Message buildListenerForRds(String name, String rdsResourceName);
|
protected abstract Message buildListenerWithApiListenerForRds(
|
||||||
|
String name, String rdsResourceName);
|
||||||
|
|
||||||
protected abstract Message buildListenerInvalid(String name);
|
protected abstract Message buildListenerWithApiListenerInvalid(String name);
|
||||||
|
|
||||||
protected abstract Message buildHttpFilter(
|
protected abstract Message buildHttpFilter(
|
||||||
String name, @Nullable Any typedConfig, boolean isOptional);
|
String name, @Nullable Any typedConfig, boolean isOptional);
|
||||||
|
|
@ -2239,9 +2310,7 @@ public abstract class ClientXdsClientTestBase {
|
||||||
protected abstract Message buildListenerWithFilterChain(
|
protected abstract Message buildListenerWithFilterChain(
|
||||||
String name, int portValue, String address, Message... filterChains);
|
String name, int portValue, String address, Message... filterChains);
|
||||||
|
|
||||||
protected abstract Message buildListenerWithFilterChain(
|
protected abstract Message buildHttpConnectionManagerFilter(
|
||||||
String name, int portValue, String address, String certName, String validationContextName);
|
@Nullable String rdsName, @Nullable Message routeConfig, List<Message> httpFilters);
|
||||||
|
|
||||||
protected abstract Message buildTestFilter(String name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,7 @@ public class ClientXdsClientV2Test extends ClientXdsClientTestBase {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
protected Message buildListener(
|
protected Message buildListenerWithApiListener(
|
||||||
String name, Message routeConfiguration, List<? extends Message> httpFilters) {
|
String name, Message routeConfiguration, List<? extends Message> httpFilters) {
|
||||||
return Listener.newBuilder()
|
return Listener.newBuilder()
|
||||||
.setName(name)
|
.setName(name)
|
||||||
|
|
@ -270,7 +270,7 @@ public class ClientXdsClientV2Test extends ClientXdsClientTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Message buildListenerForRds(String name, String rdsResourceName) {
|
protected Message buildListenerWithApiListenerForRds(String name, String rdsResourceName) {
|
||||||
return Listener.newBuilder()
|
return Listener.newBuilder()
|
||||||
.setName(name)
|
.setName(name)
|
||||||
.setAddress(Address.getDefaultInstance())
|
.setAddress(Address.getDefaultInstance())
|
||||||
|
|
@ -289,7 +289,7 @@ public class ClientXdsClientV2Test extends ClientXdsClientTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Message buildListenerInvalid(String name) {
|
protected Message buildListenerWithApiListenerInvalid(String name) {
|
||||||
return Listener.newBuilder()
|
return Listener.newBuilder()
|
||||||
.setName(name)
|
.setName(name)
|
||||||
.setAddress(Address.getDefaultInstance())
|
.setAddress(Address.getDefaultInstance())
|
||||||
|
|
@ -629,13 +629,8 @@ public class ClientXdsClientV2Test extends ClientXdsClientTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Message buildListenerWithFilterChain(
|
protected Message buildHttpConnectionManagerFilter(
|
||||||
String name, int portValue, String address, String certName, String validationContextName) {
|
@Nullable String rdsName, @Nullable Message routeConfig, List<Message> httpFilters) {
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Message buildTestFilter(String name) {
|
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@ import io.grpc.Context.CancellationListener;
|
||||||
import io.grpc.Status;
|
import io.grpc.Status;
|
||||||
import io.grpc.stub.StreamObserver;
|
import io.grpc.stub.StreamObserver;
|
||||||
import io.grpc.xds.AbstractXdsClient.ResourceType;
|
import io.grpc.xds.AbstractXdsClient.ResourceType;
|
||||||
import io.grpc.xds.internal.sds.CommonTlsContextTestsUtil;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -264,7 +263,7 @@ public class ClientXdsClientV3Test extends ClientXdsClientTestBase {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
protected Message buildListener(
|
protected Message buildListenerWithApiListener(
|
||||||
String name, Message routeConfiguration, List<? extends Message> httpFilters) {
|
String name, Message routeConfiguration, List<? extends Message> httpFilters) {
|
||||||
return Listener.newBuilder()
|
return Listener.newBuilder()
|
||||||
.setName(name)
|
.setName(name)
|
||||||
|
|
@ -280,7 +279,7 @@ public class ClientXdsClientV3Test extends ClientXdsClientTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Message buildListenerForRds(String name, String rdsResourceName) {
|
protected Message buildListenerWithApiListenerForRds(String name, String rdsResourceName) {
|
||||||
return Listener.newBuilder()
|
return Listener.newBuilder()
|
||||||
.setName(name)
|
.setName(name)
|
||||||
.setAddress(Address.getDefaultInstance())
|
.setAddress(Address.getDefaultInstance())
|
||||||
|
|
@ -299,7 +298,7 @@ public class ClientXdsClientV3Test extends ClientXdsClientTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Message buildListenerInvalid(String name) {
|
protected Message buildListenerWithApiListenerInvalid(String name) {
|
||||||
return Listener.newBuilder()
|
return Listener.newBuilder()
|
||||||
.setName(name)
|
.setName(name)
|
||||||
.setAddress(Address.getDefaultInstance())
|
.setAddress(Address.getDefaultInstance())
|
||||||
|
|
@ -700,40 +699,33 @@ public class ClientXdsClientV3Test extends ClientXdsClientTestBase {
|
||||||
return Listener.newBuilder()
|
return Listener.newBuilder()
|
||||||
.setName(name)
|
.setName(name)
|
||||||
.setAddress(listenerAddress)
|
.setAddress(listenerAddress)
|
||||||
.setDefaultFilterChain(FilterChain.getDefaultInstance())
|
|
||||||
.addAllFilterChains(Arrays.asList(filterChainsArray))
|
.addAllFilterChains(Arrays.asList(filterChainsArray))
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
.setTrafficDirection(TrafficDirection.INBOUND)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Listener buildListenerWithFilterChain(
|
protected Message buildHttpConnectionManagerFilter(
|
||||||
String name, int portValue, String address, String certName, String validationContextName) {
|
@Nullable String rdsName, @Nullable Message routeConfig, List<Message> httpFilters) {
|
||||||
FilterChain filterChain =
|
HttpConnectionManager.Builder hcmBuilder = HttpConnectionManager.newBuilder();
|
||||||
buildFilterChain(
|
if (rdsName != null) {
|
||||||
Arrays.<String>asList(),
|
hcmBuilder.setRds(
|
||||||
CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
|
Rds.newBuilder()
|
||||||
certName, validationContextName),
|
.setRouteConfigName(rdsName)
|
||||||
buildTestFilter("envoy.http_connection_manager"));
|
.setConfigSource(
|
||||||
io.envoyproxy.envoy.config.core.v3.Address listenerAddress =
|
ConfigSource.newBuilder()
|
||||||
io.envoyproxy.envoy.config.core.v3.Address.newBuilder()
|
.setAds(AggregatedConfigSource.getDefaultInstance())));
|
||||||
.setSocketAddress(
|
}
|
||||||
SocketAddress.newBuilder().setPortValue(portValue).setAddress(address))
|
if (routeConfig != null) {
|
||||||
.build();
|
hcmBuilder.setRouteConfig((RouteConfiguration) routeConfig);
|
||||||
return Listener.newBuilder()
|
}
|
||||||
.setName(name)
|
for (Message httpFilter : httpFilters) {
|
||||||
.setAddress(listenerAddress)
|
hcmBuilder.addHttpFilters((HttpFilter) httpFilter);
|
||||||
.setDefaultFilterChain(FilterChain.getDefaultInstance())
|
|
||||||
.addAllFilterChains(Arrays.asList(filterChain))
|
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Filter buildTestFilter(String name) {
|
|
||||||
return Filter.newBuilder()
|
return Filter.newBuilder()
|
||||||
.setName(name)
|
.setName("envoy.http_connection_manager")
|
||||||
.setTypedConfig(Any.pack(HttpConnectionManager.getDefaultInstance()))
|
.setTypedConfig(
|
||||||
|
Any.pack(hcmBuilder.build(), "type.googleapis.com"))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ import io.grpc.LoadBalancer.Helper;
|
||||||
import io.grpc.LoadBalancerProvider;
|
import io.grpc.LoadBalancerProvider;
|
||||||
import io.grpc.LoadBalancerRegistry;
|
import io.grpc.LoadBalancerRegistry;
|
||||||
import io.grpc.NameResolver.ConfigOrError;
|
import io.grpc.NameResolver.ConfigOrError;
|
||||||
|
import io.grpc.Status;
|
||||||
|
import io.grpc.Status.Code;
|
||||||
import io.grpc.internal.JsonParser;
|
import io.grpc.internal.JsonParser;
|
||||||
import io.grpc.internal.ServiceConfigUtil.PolicySelection;
|
import io.grpc.internal.ServiceConfigUtil.PolicySelection;
|
||||||
import io.grpc.xds.ClusterManagerLoadBalancerProvider.ClusterManagerConfig;
|
import io.grpc.xds.ClusterManagerLoadBalancerProvider.ClusterManagerConfig;
|
||||||
|
|
@ -36,11 +38,12 @@ import org.junit.runners.JUnit4;
|
||||||
@RunWith(JUnit4.class)
|
@RunWith(JUnit4.class)
|
||||||
public class ClusterManagerLoadBalancerProviderTest {
|
public class ClusterManagerLoadBalancerProviderTest {
|
||||||
|
|
||||||
@Test
|
private final LoadBalancerRegistry lbRegistry = new LoadBalancerRegistry();
|
||||||
public void parseClusterManagerLoadBalancingPolicyConfig() throws IOException {
|
private final ClusterManagerLoadBalancerProvider provider =
|
||||||
LoadBalancerRegistry lbRegistry = new LoadBalancerRegistry();
|
|
||||||
ClusterManagerLoadBalancerProvider provider =
|
|
||||||
new ClusterManagerLoadBalancerProvider(lbRegistry);
|
new ClusterManagerLoadBalancerProvider(lbRegistry);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseLoadBalancingConfig_valid() throws IOException {
|
||||||
final Object fooConfig = new Object();
|
final Object fooConfig = new Object();
|
||||||
LoadBalancerProvider lbProviderFoo = new LoadBalancerProvider() {
|
LoadBalancerProvider lbProviderFoo = new LoadBalancerProvider() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -136,6 +139,20 @@ public class ClusterManagerLoadBalancerProviderTest {
|
||||||
new PolicySelection(lbProviderBar, barConfig));
|
new PolicySelection(lbProviderBar, barConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseLoadBalancingPolicyConfig_emptyChildPolicy() throws IOException {
|
||||||
|
String clusterManagerConfigJson = "{\n"
|
||||||
|
+ " \"childPolicy\": {}\n"
|
||||||
|
+ "}";
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, ?> rawLbConfigMap = (Map<String, ?>) JsonParser.parse(clusterManagerConfigJson);
|
||||||
|
ConfigOrError configOrError = provider.parseLoadBalancingPolicyConfig(rawLbConfigMap);
|
||||||
|
Status error = configOrError.getError();
|
||||||
|
assertThat(error.getCode()).isEqualTo(Code.INTERNAL);
|
||||||
|
assertThat(error.getDescription())
|
||||||
|
.startsWith("No child policy provided for cluster_manager LB policy");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void registered() {
|
public void registered() {
|
||||||
LoadBalancerProvider provider =
|
LoadBalancerProvider provider =
|
||||||
|
|
|
||||||
|
|
@ -1,185 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2020 The gRPC Authors
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.grpc.xds;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
import com.google.protobuf.Any;
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
|
||||||
import com.google.protobuf.UInt32Value;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.Address;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.CidrRange;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.SocketAddress;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.TrafficDirection;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.TransportSocket;
|
|
||||||
import io.envoyproxy.envoy.config.listener.v3.Filter;
|
|
||||||
import io.envoyproxy.envoy.config.listener.v3.FilterChain;
|
|
||||||
import io.envoyproxy.envoy.config.listener.v3.FilterChainMatch;
|
|
||||||
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext;
|
|
||||||
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.SdsSecretConfig;
|
|
||||||
import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext;
|
|
||||||
import io.grpc.xds.EnvoyServerProtoData.Listener;
|
|
||||||
import io.grpc.xds.internal.sds.CommonTlsContextTestsUtil;
|
|
||||||
import io.grpc.xds.internal.sds.SslContextProviderSupplier;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.JUnit4;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit tests for {@link EnvoyServerProtoData}.
|
|
||||||
*/
|
|
||||||
@RunWith(JUnit4.class)
|
|
||||||
public class EnvoyServerProtoDataTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void listener_convertFromListenerProto() throws InvalidProtocolBufferException {
|
|
||||||
Address address =
|
|
||||||
Address.newBuilder()
|
|
||||||
.setSocketAddress(
|
|
||||||
SocketAddress.newBuilder().setPortValue(8000).setAddress("10.2.1.34").build())
|
|
||||||
.build();
|
|
||||||
io.envoyproxy.envoy.config.listener.v3.Listener listener =
|
|
||||||
io.envoyproxy.envoy.config.listener.v3.Listener.newBuilder()
|
|
||||||
.setName("8000")
|
|
||||||
.setAddress(address)
|
|
||||||
.addFilterChains(createInFilter())
|
|
||||||
.setDefaultFilterChain(createDefaultFilterChain())
|
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
Listener xdsListener = Listener.fromEnvoyProtoListener(listener, mock(TlsContextManager.class));
|
|
||||||
assertThat(xdsListener.getName()).isEqualTo("8000");
|
|
||||||
assertThat(xdsListener.getAddress()).isEqualTo("10.2.1.34:8000");
|
|
||||||
List<EnvoyServerProtoData.FilterChain> filterChains = xdsListener.getFilterChains();
|
|
||||||
assertThat(filterChains).isNotNull();
|
|
||||||
assertThat(filterChains.size()).isEqualTo(1);
|
|
||||||
|
|
||||||
EnvoyServerProtoData.FilterChain inFilter = filterChains.get(0);
|
|
||||||
assertThat(inFilter).isNotNull();
|
|
||||||
EnvoyServerProtoData.FilterChainMatch inFilterChainMatch = inFilter.getFilterChainMatch();
|
|
||||||
assertThat(inFilterChainMatch).isNotNull();
|
|
||||||
assertThat(inFilterChainMatch.getDestinationPort()).isEqualTo(8000);
|
|
||||||
assertThat(inFilterChainMatch.getApplicationProtocols())
|
|
||||||
.containsExactlyElementsIn(Arrays.asList("managed-mtls", "h2"));
|
|
||||||
assertThat(inFilterChainMatch.getServerNames())
|
|
||||||
.containsExactlyElementsIn(Arrays.asList("server1", "server2"));
|
|
||||||
assertThat(inFilterChainMatch.getTransportProtocol()).isEqualTo("tls");
|
|
||||||
assertThat(inFilterChainMatch.getPrefixRanges())
|
|
||||||
.containsExactly(new EnvoyServerProtoData.CidrRange("10.20.0.15", 32));
|
|
||||||
assertThat(inFilterChainMatch.getSourcePrefixRanges())
|
|
||||||
.containsExactly(new EnvoyServerProtoData.CidrRange("10.30.3.0", 24));
|
|
||||||
assertThat(inFilterChainMatch.getConnectionSourceType())
|
|
||||||
.isEqualTo(EnvoyServerProtoData.ConnectionSourceType.EXTERNAL);
|
|
||||||
assertThat(inFilterChainMatch.getSourcePorts()).containsExactly(200, 300);
|
|
||||||
SslContextProviderSupplier sslContextProviderSupplier = inFilter
|
|
||||||
.getSslContextProviderSupplier();
|
|
||||||
assertThat(sslContextProviderSupplier.getTlsContext()).isInstanceOf(DownstreamTlsContext.class);
|
|
||||||
DownstreamTlsContext inFilterTlsContext = (DownstreamTlsContext) sslContextProviderSupplier
|
|
||||||
.getTlsContext();
|
|
||||||
assertThat(inFilterTlsContext.getCommonTlsContext()).isNotNull();
|
|
||||||
CommonTlsContext commonTlsContext = inFilterTlsContext.getCommonTlsContext();
|
|
||||||
List<SdsSecretConfig> tlsCertSdsConfigs = commonTlsContext
|
|
||||||
.getTlsCertificateSdsSecretConfigsList();
|
|
||||||
assertThat(tlsCertSdsConfigs).hasSize(1);
|
|
||||||
assertThat(tlsCertSdsConfigs.get(0).getName()).isEqualTo("google-sds-config-default");
|
|
||||||
|
|
||||||
EnvoyServerProtoData.FilterChain defaultFilter = xdsListener.getDefaultFilterChain();
|
|
||||||
assertThat(defaultFilter).isNotNull();
|
|
||||||
EnvoyServerProtoData.FilterChainMatch defaultFilterChainMatch =
|
|
||||||
defaultFilter.getFilterChainMatch();
|
|
||||||
assertThat(defaultFilterChainMatch).isNotNull();
|
|
||||||
assertThat(defaultFilterChainMatch.getDestinationPort()).isEqualTo(8001);
|
|
||||||
assertThat(defaultFilterChainMatch.getPrefixRanges())
|
|
||||||
.containsExactly(new EnvoyServerProtoData.CidrRange("10.20.0.16", 30));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FilterChain createInFilter() {
|
|
||||||
FilterChain filterChain =
|
|
||||||
FilterChain.newBuilder()
|
|
||||||
.setFilterChainMatch(
|
|
||||||
FilterChainMatch.newBuilder()
|
|
||||||
.setDestinationPort(UInt32Value.of(8000))
|
|
||||||
.addAllServerNames(Arrays.asList("server1", "server2"))
|
|
||||||
.setTransportProtocol("tls")
|
|
||||||
.addAllApplicationProtocols(Arrays.asList("managed-mtls", "h2"))
|
|
||||||
.addPrefixRanges(CidrRange.newBuilder()
|
|
||||||
.setAddressPrefix("10.20.0.15")
|
|
||||||
.setPrefixLen(UInt32Value.of(32))
|
|
||||||
.build())
|
|
||||||
.addSourcePrefixRanges(
|
|
||||||
CidrRange.newBuilder()
|
|
||||||
.setAddressPrefix("10.30.3.0")
|
|
||||||
.setPrefixLen(UInt32Value.of(24))
|
|
||||||
.build())
|
|
||||||
.setSourceType(FilterChainMatch.ConnectionSourceType.EXTERNAL)
|
|
||||||
.addSourcePorts(200)
|
|
||||||
.addSourcePorts(300)
|
|
||||||
.build())
|
|
||||||
.setTransportSocket(TransportSocket.newBuilder().setName("envoy.transport_sockets.tls")
|
|
||||||
.setTypedConfig(
|
|
||||||
Any.pack(CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
|
|
||||||
"google-sds-config-default", "ROOTCA")))
|
|
||||||
.build())
|
|
||||||
.addFilters(Filter.newBuilder()
|
|
||||||
.setName("envoy.http_connection_manager")
|
|
||||||
.setTypedConfig(Any.newBuilder()
|
|
||||||
.setTypeUrl(
|
|
||||||
"type.googleapis.com/"
|
|
||||||
+ "envoy.extensions.filters.network.http_connection_manager"
|
|
||||||
+ ".v3.HttpConnectionManager"))
|
|
||||||
.build())
|
|
||||||
.build();
|
|
||||||
return filterChain;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FilterChain createDefaultFilterChain() {
|
|
||||||
FilterChain filterChain =
|
|
||||||
FilterChain.newBuilder()
|
|
||||||
.setFilterChainMatch(
|
|
||||||
FilterChainMatch.newBuilder()
|
|
||||||
.setDestinationPort(UInt32Value.of(8001))
|
|
||||||
.addPrefixRanges(
|
|
||||||
CidrRange.newBuilder()
|
|
||||||
.setAddressPrefix("10.20.0.16")
|
|
||||||
.setPrefixLen(UInt32Value.of(30))
|
|
||||||
.build())
|
|
||||||
.build())
|
|
||||||
.setTransportSocket(
|
|
||||||
TransportSocket.newBuilder()
|
|
||||||
.setName("envoy.transport_sockets.tls")
|
|
||||||
.setTypedConfig(
|
|
||||||
Any.pack(
|
|
||||||
CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
|
|
||||||
"google-sds-config-default", "ROOTCA")))
|
|
||||||
.build())
|
|
||||||
.addFilters(
|
|
||||||
Filter.newBuilder()
|
|
||||||
.setName("envoy.http_connection_manager")
|
|
||||||
.setTypedConfig(
|
|
||||||
Any.newBuilder()
|
|
||||||
.setTypeUrl(
|
|
||||||
"type.googleapis.com/"
|
|
||||||
+ "envoy.extensions.filters.network.http_connection_manager"
|
|
||||||
+ ".v3.HttpConnectionManager"))
|
|
||||||
.build())
|
|
||||||
.build();
|
|
||||||
return filterChain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -24,6 +24,7 @@ import io.envoyproxy.envoy.extensions.filters.http.fault.v3.FaultAbort.HeaderAbo
|
||||||
import io.envoyproxy.envoy.extensions.filters.http.fault.v3.HTTPFault;
|
import io.envoyproxy.envoy.extensions.filters.http.fault.v3.HTTPFault;
|
||||||
import io.envoyproxy.envoy.type.v3.FractionalPercent;
|
import io.envoyproxy.envoy.type.v3.FractionalPercent;
|
||||||
import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType;
|
import io.envoyproxy.envoy.type.v3.FractionalPercent.DenominatorType;
|
||||||
|
import io.grpc.Status.Code;
|
||||||
import io.grpc.internal.GrpcUtil;
|
import io.grpc.internal.GrpcUtil;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
@ -59,4 +60,32 @@ public class FaultFilterTest {
|
||||||
assertThat(faultAbort.percent().denominatorType())
|
assertThat(faultAbort.percent().denominatorType())
|
||||||
.isEqualTo(FaultConfig.FractionalPercent.DenominatorType.HUNDRED);
|
.isEqualTo(FaultConfig.FractionalPercent.DenominatorType.HUNDRED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseFaultAbort_withHttpStatus() {
|
||||||
|
io.envoyproxy.envoy.extensions.filters.http.fault.v3.FaultAbort proto =
|
||||||
|
io.envoyproxy.envoy.extensions.filters.http.fault.v3.FaultAbort.newBuilder()
|
||||||
|
.setPercentage(FractionalPercent.newBuilder()
|
||||||
|
.setNumerator(100).setDenominator(DenominatorType.TEN_THOUSAND))
|
||||||
|
.setHttpStatus(400).build();
|
||||||
|
FaultConfig.FaultAbort res = FaultFilter.parseFaultAbort(proto).config;
|
||||||
|
assertThat(res.percent().numerator()).isEqualTo(100);
|
||||||
|
assertThat(res.percent().denominatorType())
|
||||||
|
.isEqualTo(FaultConfig.FractionalPercent.DenominatorType.TEN_THOUSAND);
|
||||||
|
assertThat(res.status().getCode()).isEqualTo(Code.INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseFaultAbort_withGrpcStatus() {
|
||||||
|
io.envoyproxy.envoy.extensions.filters.http.fault.v3.FaultAbort proto =
|
||||||
|
io.envoyproxy.envoy.extensions.filters.http.fault.v3.FaultAbort.newBuilder()
|
||||||
|
.setPercentage(FractionalPercent.newBuilder()
|
||||||
|
.setNumerator(600).setDenominator(DenominatorType.MILLION))
|
||||||
|
.setGrpcStatus(Code.DEADLINE_EXCEEDED.value()).build();
|
||||||
|
FaultConfig.FaultAbort faultAbort = FaultFilter.parseFaultAbort(proto).config;
|
||||||
|
assertThat(faultAbort.percent().numerator()).isEqualTo(600);
|
||||||
|
assertThat(faultAbort.percent().denominatorType())
|
||||||
|
.isEqualTo(FaultConfig.FractionalPercent.DenominatorType.MILLION);
|
||||||
|
assertThat(faultAbort.status().getCode()).isEqualTo(Code.DEADLINE_EXCEEDED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,18 +21,8 @@ import static org.junit.Assert.fail;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.google.protobuf.Any;
|
import io.grpc.xds.Filter.NamedFilterConfig;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import io.grpc.xds.XdsClient.LdsUpdate;
|
||||||
import com.google.protobuf.UInt32Value;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.Address;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.CidrRange;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.SocketAddress;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.TrafficDirection;
|
|
||||||
import io.envoyproxy.envoy.config.core.v3.TransportSocket;
|
|
||||||
import io.envoyproxy.envoy.config.listener.v3.Filter;
|
|
||||||
import io.envoyproxy.envoy.config.listener.v3.FilterChain;
|
|
||||||
import io.envoyproxy.envoy.config.listener.v3.FilterChainMatch;
|
|
||||||
import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext;
|
|
||||||
import io.grpc.xds.internal.sds.CommonTlsContextTestsUtil;
|
import io.grpc.xds.internal.sds.CommonTlsContextTestsUtil;
|
||||||
import io.grpc.xds.internal.sds.SslContextProviderSupplier;
|
import io.grpc.xds.internal.sds.SslContextProviderSupplier;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
|
|
@ -41,6 +31,7 @@ import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -56,6 +47,9 @@ public class FilterChainMatchTest {
|
||||||
private static final int PORT = 7000;
|
private static final int PORT = 7000;
|
||||||
private static final String LOCAL_IP = "10.1.2.3"; // dest
|
private static final String LOCAL_IP = "10.1.2.3"; // dest
|
||||||
private static final String REMOTE_IP = "10.4.2.3"; // source
|
private static final String REMOTE_IP = "10.4.2.3"; // source
|
||||||
|
private static final HttpConnectionManager HTTP_CONNECTION_MANAGER =
|
||||||
|
HttpConnectionManager.forRdsName(
|
||||||
|
10L, "route-config", Collections.<NamedFilterConfig>emptyList());
|
||||||
|
|
||||||
@Mock private Channel channel;
|
@Mock private Channel channel;
|
||||||
@Mock private TlsContextManager tlsContextManager;
|
@Mock private TlsContextManager tlsContextManager;
|
||||||
|
|
@ -77,13 +71,13 @@ public class FilterChainMatchTest {
|
||||||
xdsClientWrapperForServerSds.shutdown();
|
xdsClientWrapperForServerSds.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private DownstreamTlsContext getDownstreamTlsContext() {
|
private EnvoyServerProtoData.DownstreamTlsContext getDownstreamTlsContext() {
|
||||||
SslContextProviderSupplier sslContextProviderSupplier =
|
SslContextProviderSupplier sslContextProviderSupplier =
|
||||||
xdsClientWrapperForServerSds.getSslContextProviderSupplier(channel);
|
xdsClientWrapperForServerSds.getSslContextProviderSupplier(channel);
|
||||||
if (sslContextProviderSupplier != null) {
|
if (sslContextProviderSupplier != null) {
|
||||||
EnvoyServerProtoData.BaseTlsContext tlsContext = sslContextProviderSupplier.getTlsContext();
|
EnvoyServerProtoData.BaseTlsContext tlsContext = sslContextProviderSupplier.getTlsContext();
|
||||||
assertThat(tlsContext).isInstanceOf(DownstreamTlsContext.class);
|
assertThat(tlsContext).isInstanceOf(EnvoyServerProtoData.DownstreamTlsContext.class);
|
||||||
return (DownstreamTlsContext) tlsContext;
|
return (EnvoyServerProtoData.DownstreamTlsContext) tlsContext;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -101,15 +95,16 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<Integer>asList(),
|
Arrays.<Integer>asList(),
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
DownstreamTlsContext tlsContext =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChain filterChain =
|
EnvoyServerProtoData.FilterChain filterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch, tlsContext, tlsContextManager);
|
"filter-chain-foo", filterChainMatch, HTTP_CONNECTION_MANAGER, tlsContext,
|
||||||
|
tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener("listener1", LOCAL_IP, Arrays.asList(filterChain), null);
|
new EnvoyServerProtoData.Listener("listener1", LOCAL_IP, Arrays.asList(filterChain), null);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContext);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,43 +121,44 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<Integer>asList(),
|
Arrays.<Integer>asList(),
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
DownstreamTlsContext tlsContext =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChain filterChain =
|
EnvoyServerProtoData.FilterChain filterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch, tlsContext, tlsContextManager);
|
"filter-chain-foo", filterChainMatch, HTTP_CONNECTION_MANAGER, tlsContext,
|
||||||
DownstreamTlsContext defaultTlsContext =
|
tlsContextManager);
|
||||||
|
EnvoyServerProtoData.DownstreamTlsContext defaultTlsContext =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(null, defaultTlsContext, tlsContextManager);
|
"filter-chain-bar", null, HTTP_CONNECTION_MANAGER, defaultTlsContext,
|
||||||
EnvoyServerProtoData.Listener listener =
|
tlsContextManager);
|
||||||
new EnvoyServerProtoData.Listener("listener1", LOCAL_IP, Arrays.asList(filterChain),
|
EnvoyServerProtoData.Listener listener = new EnvoyServerProtoData.Listener(
|
||||||
defaultFilterChain);
|
"listener1", LOCAL_IP, Arrays.asList(filterChain), defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(defaultTlsContext);
|
assertThat(tlsContext1).isSameInstanceAs(defaultTlsContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void defaultFilterChain() throws UnknownHostException {
|
public void defaultFilterChain() throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContext =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChain filterChain =
|
EnvoyServerProtoData.FilterChain filterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(null, tlsContext, tlsContextManager);
|
"filter-chain-foo", null, HTTP_CONNECTION_MANAGER, tlsContext, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1", LOCAL_IP, Arrays.<EnvoyServerProtoData.FilterChain>asList(), filterChain);
|
"listener1", LOCAL_IP, Arrays.<EnvoyServerProtoData.FilterChain>asList(), filterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContext);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void destPortFails_returnDefaultFilterChain() throws UnknownHostException {
|
public void destPortFails_returnDefaultFilterChain() throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContextWithDestPort =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextWithDestPort =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchWithDestPort =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchWithDestPort =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -175,26 +171,28 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainWithDestPort =
|
EnvoyServerProtoData.FilterChain filterChainWithDestPort =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchWithDestPort, tlsContextWithDestPort,
|
new EnvoyServerProtoData.FilterChain(
|
||||||
tlsContextManager);
|
"filter-chain-foo", filterChainMatchWithDestPort, HTTP_CONNECTION_MANAGER,
|
||||||
DownstreamTlsContext tlsContextForDefaultFilterChain =
|
tlsContextWithDestPort, tlsContextManager);
|
||||||
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
||||||
new EnvoyServerProtoData.FilterChain(null, tlsContextForDefaultFilterChain,
|
new EnvoyServerProtoData.FilterChain(
|
||||||
tlsContextManager);
|
"filter-chain-bar", null, HTTP_CONNECTION_MANAGER,
|
||||||
|
tlsContextForDefaultFilterChain, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1", LOCAL_IP, Arrays.asList(filterChainWithDestPort), defaultFilterChain);
|
"listener1", LOCAL_IP, Arrays.asList(filterChainWithDestPort), defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContextForDefaultFilterChain);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContextForDefaultFilterChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void destPrefixRangeMatch() throws UnknownHostException, InvalidProtocolBufferException {
|
public void destPrefixRangeMatch() throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContextMatch =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextMatch =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchWithMatch =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchWithMatch =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -206,28 +204,28 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<Integer>asList(),
|
Arrays.<Integer>asList(),
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainWithMatch =
|
EnvoyServerProtoData.FilterChain filterChainWithMatch = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchWithMatch, tlsContextMatch,
|
"filter-chain-foo", filterChainMatchWithMatch, HTTP_CONNECTION_MANAGER,
|
||||||
tlsContextManager);
|
tlsContextMatch, tlsContextManager);
|
||||||
DownstreamTlsContext tlsContextForDefaultFilterChain =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(null, tlsContextForDefaultFilterChain,
|
"filter-chain-bar", null, HTTP_CONNECTION_MANAGER,
|
||||||
tlsContextManager);
|
tlsContextForDefaultFilterChain, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1", LOCAL_IP, Arrays.asList(filterChainWithMatch), defaultFilterChain);
|
"listener1", LOCAL_IP, Arrays.asList(filterChainWithMatch), defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContextMatch);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContextMatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void destPrefixRangeMismatch_returnDefaultFilterChain()
|
public void destPrefixRangeMismatch_returnDefaultFilterChain()
|
||||||
throws UnknownHostException, InvalidProtocolBufferException {
|
throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContextMismatch =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextMismatch =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
// 10.2.2.0/24 doesn't match LOCAL_IP
|
// 10.2.2.0/24 doesn't match LOCAL_IP
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchWithMismatch =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchWithMismatch =
|
||||||
|
|
@ -241,27 +239,28 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainWithMismatch =
|
EnvoyServerProtoData.FilterChain filterChainWithMismatch =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchWithMismatch, tlsContextMismatch,
|
new EnvoyServerProtoData.FilterChain(
|
||||||
tlsContextManager);
|
"filter-chain-foo", filterChainMatchWithMismatch, HTTP_CONNECTION_MANAGER,
|
||||||
DownstreamTlsContext tlsContextForDefaultFilterChain =
|
tlsContextMismatch, tlsContextManager);
|
||||||
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(null, tlsContextForDefaultFilterChain,
|
"filter-chain-bar", null, HTTP_CONNECTION_MANAGER,
|
||||||
tlsContextManager);
|
tlsContextForDefaultFilterChain, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1", LOCAL_IP, Arrays.asList(filterChainWithMismatch), defaultFilterChain);
|
"listener1", LOCAL_IP, Arrays.asList(filterChainWithMismatch), defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContextForDefaultFilterChain);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContextForDefaultFilterChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void dest0LengthPrefixRange()
|
public void dest0LengthPrefixRange()
|
||||||
throws UnknownHostException, InvalidProtocolBufferException {
|
throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContext0Length =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext0Length =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
// 10.2.2.0/24 doesn't match LOCAL_IP
|
// 10.2.2.0/24 doesn't match LOCAL_IP
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatch0Length =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatch0Length =
|
||||||
|
|
@ -274,28 +273,28 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<Integer>asList(),
|
Arrays.<Integer>asList(),
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChain0Length =
|
EnvoyServerProtoData.FilterChain filterChain0Length = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch0Length, tlsContext0Length,
|
"filter-chain-foo", filterChainMatch0Length, HTTP_CONNECTION_MANAGER,
|
||||||
tlsContextManager);
|
tlsContext0Length, tlsContextManager);
|
||||||
DownstreamTlsContext tlsContextForDefaultFilterChain =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(null, tlsContextForDefaultFilterChain,
|
"filter-chain-bar", null, HTTP_CONNECTION_MANAGER,
|
||||||
tlsContextManager);
|
tlsContextForDefaultFilterChain, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1", LOCAL_IP, Arrays.asList(filterChain0Length), defaultFilterChain);
|
"listener1", LOCAL_IP, Arrays.asList(filterChain0Length), defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContext0Length);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContext0Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void destPrefixRange_moreSpecificWins()
|
public void destPrefixRange_moreSpecificWins()
|
||||||
throws UnknownHostException, InvalidProtocolBufferException {
|
throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContextLessSpecific =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextLessSpecific =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -308,10 +307,11 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainLessSpecific =
|
EnvoyServerProtoData.FilterChain filterChainLessSpecific =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchLessSpecific, tlsContextLessSpecific,
|
new EnvoyServerProtoData.FilterChain(
|
||||||
tlsContextManager);
|
"filter-chain-foo", filterChainMatchLessSpecific, HTTP_CONNECTION_MANAGER,
|
||||||
|
tlsContextLessSpecific, tlsContextManager);
|
||||||
|
|
||||||
DownstreamTlsContext tlsContextMoreSpecific =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextMoreSpecific =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecific =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecific =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -324,27 +324,29 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainMoreSpecific =
|
EnvoyServerProtoData.FilterChain filterChainMoreSpecific =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchMoreSpecific, tlsContextMoreSpecific,
|
new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-bar", filterChainMatchMoreSpecific, HTTP_CONNECTION_MANAGER,
|
||||||
|
tlsContextMoreSpecific,
|
||||||
tlsContextManager);
|
tlsContextManager);
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(null, null, tlsContextManager);
|
"filter-chain-baz", null, HTTP_CONNECTION_MANAGER, null, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1",
|
"listener1",
|
||||||
LOCAL_IP,
|
LOCAL_IP,
|
||||||
Arrays.asList(filterChainLessSpecific, filterChainMoreSpecific),
|
Arrays.asList(filterChainLessSpecific, filterChainMoreSpecific),
|
||||||
defaultFilterChain);
|
defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecific);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecific);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void destPrefixRange_emptyListLessSpecific()
|
public void destPrefixRange_emptyListLessSpecific()
|
||||||
throws UnknownHostException, InvalidProtocolBufferException {
|
throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContextLessSpecific =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextLessSpecific =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -357,10 +359,11 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainLessSpecific =
|
EnvoyServerProtoData.FilterChain filterChainLessSpecific =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchLessSpecific, tlsContextLessSpecific,
|
new EnvoyServerProtoData.FilterChain(
|
||||||
tlsContextManager);
|
"filter-chain-foo", filterChainMatchLessSpecific, HTTP_CONNECTION_MANAGER,
|
||||||
|
tlsContextLessSpecific, tlsContextManager);
|
||||||
|
|
||||||
DownstreamTlsContext tlsContextMoreSpecific =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextMoreSpecific =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecific =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecific =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -373,27 +376,29 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainMoreSpecific =
|
EnvoyServerProtoData.FilterChain filterChainMoreSpecific =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchMoreSpecific, tlsContextMoreSpecific,
|
new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-bar", filterChainMatchMoreSpecific, HTTP_CONNECTION_MANAGER,
|
||||||
|
tlsContextMoreSpecific,
|
||||||
tlsContextManager);
|
tlsContextManager);
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(null, null, tlsContextManager);
|
"filter-chain-baz", null, HTTP_CONNECTION_MANAGER, null, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1",
|
"listener1",
|
||||||
LOCAL_IP,
|
LOCAL_IP,
|
||||||
Arrays.asList(filterChainLessSpecific, filterChainMoreSpecific),
|
Arrays.asList(filterChainLessSpecific, filterChainMoreSpecific),
|
||||||
defaultFilterChain);
|
defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecific);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecific);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void destPrefixRangeIpv6_moreSpecificWins()
|
public void destPrefixRangeIpv6_moreSpecificWins()
|
||||||
throws UnknownHostException, InvalidProtocolBufferException {
|
throws UnknownHostException {
|
||||||
setupChannel("FE80:0000:0000:0000:0202:B3FF:FE1E:8329", "2001:DB8::8:800:200C:417A", 15000);
|
setupChannel("FE80:0000:0000:0000:0202:B3FF:FE1E:8329", "2001:DB8::8:800:200C:417A", 15000);
|
||||||
DownstreamTlsContext tlsContextLessSpecific =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextLessSpecific =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -406,10 +411,11 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainLessSpecific =
|
EnvoyServerProtoData.FilterChain filterChainLessSpecific =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchLessSpecific, tlsContextLessSpecific,
|
new EnvoyServerProtoData.FilterChain(
|
||||||
tlsContextManager);
|
"filter-chain-foo", filterChainMatchLessSpecific, HTTP_CONNECTION_MANAGER,
|
||||||
|
tlsContextLessSpecific, tlsContextManager);
|
||||||
|
|
||||||
DownstreamTlsContext tlsContextMoreSpecific =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextMoreSpecific =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecific =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecific =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -422,27 +428,28 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainMoreSpecific =
|
EnvoyServerProtoData.FilterChain filterChainMoreSpecific =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchMoreSpecific, tlsContextMoreSpecific,
|
new EnvoyServerProtoData.FilterChain(
|
||||||
tlsContextManager);
|
"filter-chain-bar", filterChainMatchMoreSpecific, HTTP_CONNECTION_MANAGER,
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
tlsContextMoreSpecific, tlsContextManager);
|
||||||
new EnvoyServerProtoData.FilterChain(null, null, tlsContextManager);
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-baz", null, HTTP_CONNECTION_MANAGER, null, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1",
|
"listener1",
|
||||||
"FE80:0000:0000:0000:0202:B3FF:FE1E:8329",
|
"FE80:0000:0000:0000:0202:B3FF:FE1E:8329",
|
||||||
Arrays.asList(filterChainLessSpecific, filterChainMoreSpecific),
|
Arrays.asList(filterChainLessSpecific, filterChainMoreSpecific),
|
||||||
defaultFilterChain);
|
defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecific);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecific);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void destPrefixRange_moreSpecificWith2Wins()
|
public void destPrefixRange_moreSpecificWith2Wins()
|
||||||
throws UnknownHostException, InvalidProtocolBufferException {
|
throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContextMoreSpecificWith2 =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextMoreSpecificWith2 =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecificWith2 =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecificWith2 =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -458,9 +465,10 @@ public class FilterChainMatchTest {
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainMoreSpecificWith2 =
|
EnvoyServerProtoData.FilterChain filterChainMoreSpecificWith2 =
|
||||||
new EnvoyServerProtoData.FilterChain(
|
new EnvoyServerProtoData.FilterChain(
|
||||||
filterChainMatchMoreSpecificWith2, tlsContextMoreSpecificWith2, tlsContextManager);
|
"filter-chain-foo", filterChainMatchMoreSpecificWith2, HTTP_CONNECTION_MANAGER,
|
||||||
|
tlsContextMoreSpecificWith2, tlsContextManager);
|
||||||
|
|
||||||
DownstreamTlsContext tlsContextLessSpecific =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextLessSpecific =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -473,26 +481,27 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainLessSpecific =
|
EnvoyServerProtoData.FilterChain filterChainLessSpecific =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchLessSpecific, tlsContextLessSpecific,
|
new EnvoyServerProtoData.FilterChain(
|
||||||
tlsContextManager);
|
"filter-chain-bar", filterChainMatchLessSpecific, HTTP_CONNECTION_MANAGER,
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
tlsContextLessSpecific, tlsContextManager);
|
||||||
new EnvoyServerProtoData.FilterChain(null, null, tlsContextManager);
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-baz", null, HTTP_CONNECTION_MANAGER, null, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1",
|
"listener1",
|
||||||
LOCAL_IP,
|
LOCAL_IP,
|
||||||
Arrays.asList(filterChainMoreSpecificWith2, filterChainLessSpecific),
|
Arrays.asList(filterChainMoreSpecificWith2, filterChainLessSpecific),
|
||||||
defaultFilterChain);
|
defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecificWith2);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecificWith2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sourceTypeMismatch_returnDefaultFilterChain() throws UnknownHostException {
|
public void sourceTypeMismatch_returnDefaultFilterChain() throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContextMismatch =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextMismatch =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchWithMismatch =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchWithMismatch =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -505,26 +514,27 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainWithMismatch =
|
EnvoyServerProtoData.FilterChain filterChainWithMismatch =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchWithMismatch, tlsContextMismatch,
|
new EnvoyServerProtoData.FilterChain(
|
||||||
tlsContextManager);
|
"filter-chain-foo", filterChainMatchWithMismatch, HTTP_CONNECTION_MANAGER,
|
||||||
DownstreamTlsContext tlsContextForDefaultFilterChain =
|
tlsContextMismatch, tlsContextManager);
|
||||||
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(null, tlsContextForDefaultFilterChain,
|
"filter-chain-bar", null, HTTP_CONNECTION_MANAGER,tlsContextForDefaultFilterChain,
|
||||||
tlsContextManager);
|
tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1", LOCAL_IP, Arrays.asList(filterChainWithMismatch), defaultFilterChain);
|
"listener1", LOCAL_IP, Arrays.asList(filterChainWithMismatch), defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContextForDefaultFilterChain);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContextForDefaultFilterChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sourceTypeLocal() throws UnknownHostException {
|
public void sourceTypeLocal() throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, LOCAL_IP, 15000);
|
setupChannel(LOCAL_IP, LOCAL_IP, 15000);
|
||||||
DownstreamTlsContext tlsContextMatch =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextMatch =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchWithMatch =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchWithMatch =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -536,28 +546,28 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<Integer>asList(),
|
Arrays.<Integer>asList(),
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainWithMatch =
|
EnvoyServerProtoData.FilterChain filterChainWithMatch = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchWithMatch, tlsContextMatch,
|
"filter-chain-foo", filterChainMatchWithMatch, HTTP_CONNECTION_MANAGER, tlsContextMatch,
|
||||||
tlsContextManager);
|
tlsContextManager);
|
||||||
DownstreamTlsContext tlsContextForDefaultFilterChain =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(null, tlsContextForDefaultFilterChain,
|
"filter-chain-bar", null, HTTP_CONNECTION_MANAGER, tlsContextForDefaultFilterChain,
|
||||||
tlsContextManager);
|
tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1", LOCAL_IP, Arrays.asList(filterChainWithMatch), defaultFilterChain);
|
"listener1", LOCAL_IP, Arrays.asList(filterChainWithMatch), defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContextMatch);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContextMatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sourcePrefixRange_moreSpecificWith2Wins()
|
public void sourcePrefixRange_moreSpecificWith2Wins()
|
||||||
throws UnknownHostException, InvalidProtocolBufferException {
|
throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContextMoreSpecificWith2 =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextMoreSpecificWith2 =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecificWith2 =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecificWith2 =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -573,9 +583,10 @@ public class FilterChainMatchTest {
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainMoreSpecificWith2 =
|
EnvoyServerProtoData.FilterChain filterChainMoreSpecificWith2 =
|
||||||
new EnvoyServerProtoData.FilterChain(
|
new EnvoyServerProtoData.FilterChain(
|
||||||
filterChainMatchMoreSpecificWith2, tlsContextMoreSpecificWith2, tlsContextManager);
|
"filter-chain-foo", filterChainMatchMoreSpecificWith2, HTTP_CONNECTION_MANAGER,
|
||||||
|
tlsContextMoreSpecificWith2, tlsContextManager);
|
||||||
|
|
||||||
DownstreamTlsContext tlsContextLessSpecific =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextLessSpecific =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -588,27 +599,28 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainLessSpecific =
|
EnvoyServerProtoData.FilterChain filterChainLessSpecific =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatchLessSpecific, tlsContextLessSpecific,
|
new EnvoyServerProtoData.FilterChain(
|
||||||
tlsContextManager);
|
"filter-chain-bar", filterChainMatchLessSpecific, HTTP_CONNECTION_MANAGER,
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
tlsContextLessSpecific, tlsContextManager);
|
||||||
new EnvoyServerProtoData.FilterChain(null, null, tlsContextManager);
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-baz", null, HTTP_CONNECTION_MANAGER, null, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1",
|
"listener1",
|
||||||
LOCAL_IP,
|
LOCAL_IP,
|
||||||
Arrays.asList(filterChainMoreSpecificWith2, filterChainLessSpecific),
|
Arrays.asList(filterChainMoreSpecificWith2, filterChainLessSpecific),
|
||||||
defaultFilterChain);
|
defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecificWith2);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecificWith2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sourcePrefixRange_2Matchers_expectException()
|
public void sourcePrefixRange_2Matchers_expectException()
|
||||||
throws UnknownHostException, InvalidProtocolBufferException {
|
throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContext1 =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatch1 =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatch1 =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -622,10 +634,11 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<Integer>asList(),
|
Arrays.<Integer>asList(),
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChain1 =
|
EnvoyServerProtoData.FilterChain filterChain1 = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch1, tlsContext1, tlsContextManager);
|
"filter-chain-foo", filterChainMatch1, HTTP_CONNECTION_MANAGER, tlsContext1,
|
||||||
|
tlsContextManager);
|
||||||
|
|
||||||
DownstreamTlsContext tlsContext2 =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext2 =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatch2 =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatch2 =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -637,14 +650,15 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<Integer>asList(),
|
Arrays.<Integer>asList(),
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChain2 =
|
EnvoyServerProtoData.FilterChain filterChain2 = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch2, tlsContext2, tlsContextManager);
|
"filter-chain-bar", filterChainMatch2, HTTP_CONNECTION_MANAGER, tlsContext2,
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
tlsContextManager);
|
||||||
new EnvoyServerProtoData.FilterChain(null, null, null);
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-baz", null, HTTP_CONNECTION_MANAGER, null, null);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1", LOCAL_IP, Arrays.asList(filterChain1, filterChain2), defaultFilterChain);
|
"listener1", LOCAL_IP, Arrays.asList(filterChain1, filterChain2), defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
try {
|
try {
|
||||||
xdsClientWrapperForServerSds.getSslContextProviderSupplier(channel);
|
xdsClientWrapperForServerSds.getSslContextProviderSupplier(channel);
|
||||||
|
|
@ -656,9 +670,9 @@ public class FilterChainMatchTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sourcePortMatch_exactMatchWinsOverEmptyList()
|
public void sourcePortMatch_exactMatchWinsOverEmptyList()
|
||||||
throws UnknownHostException, InvalidProtocolBufferException {
|
throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContextEmptySourcePorts =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextEmptySourcePorts =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchEmptySourcePorts =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchEmptySourcePorts =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -674,9 +688,10 @@ public class FilterChainMatchTest {
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainEmptySourcePorts =
|
EnvoyServerProtoData.FilterChain filterChainEmptySourcePorts =
|
||||||
new EnvoyServerProtoData.FilterChain(
|
new EnvoyServerProtoData.FilterChain(
|
||||||
filterChainMatchEmptySourcePorts, tlsContextEmptySourcePorts, tlsContextManager);
|
"filter-chain-foo", filterChainMatchEmptySourcePorts, HTTP_CONNECTION_MANAGER,
|
||||||
|
tlsContextEmptySourcePorts, tlsContextManager);
|
||||||
|
|
||||||
DownstreamTlsContext tlsContextSourcePortMatch =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextSourcePortMatch =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatchSourcePortMatch =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatchSourcePortMatch =
|
||||||
new EnvoyServerProtoData.FilterChainMatch(
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
|
|
@ -690,18 +705,19 @@ public class FilterChainMatchTest {
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChainSourcePortMatch =
|
EnvoyServerProtoData.FilterChain filterChainSourcePortMatch =
|
||||||
new EnvoyServerProtoData.FilterChain(
|
new EnvoyServerProtoData.FilterChain(
|
||||||
filterChainMatchSourcePortMatch, tlsContextSourcePortMatch, tlsContextManager);
|
"filter-chain-bar", filterChainMatchSourcePortMatch, HTTP_CONNECTION_MANAGER,
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
tlsContextSourcePortMatch, tlsContextManager);
|
||||||
new EnvoyServerProtoData.FilterChain(null, null, tlsContextManager);
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-baz", null, HTTP_CONNECTION_MANAGER, null, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1",
|
"listener1",
|
||||||
LOCAL_IP,
|
LOCAL_IP,
|
||||||
Arrays.asList(filterChainEmptySourcePorts, filterChainSourcePortMatch),
|
Arrays.asList(filterChainEmptySourcePorts, filterChainSourcePortMatch),
|
||||||
defaultFilterChain);
|
defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext1).isSameInstanceAs(tlsContextSourcePortMatch);
|
assertThat(tlsContext1).isSameInstanceAs(tlsContextSourcePortMatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -713,19 +729,19 @@ public class FilterChainMatchTest {
|
||||||
* source-prefix range. - 5th step: out of 2 one with matching source port gets picked
|
* source-prefix range. - 5th step: out of 2 one with matching source port gets picked
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void filterChain_5stepMatch() throws UnknownHostException, InvalidProtocolBufferException {
|
public void filterChain_5stepMatch() throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
DownstreamTlsContext tlsContext1 =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
DownstreamTlsContext tlsContext2 =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext2 =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
|
||||||
DownstreamTlsContext tlsContext3 =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext3 =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT3", "VA3");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT3", "VA3");
|
||||||
DownstreamTlsContext tlsContext4 =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext4 =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT4", "VA4");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT4", "VA4");
|
||||||
DownstreamTlsContext tlsContext5 =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext5 =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT5", "VA5");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT5", "VA5");
|
||||||
DownstreamTlsContext tlsContext6 =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext6 =
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT6", "VA6");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT6", "VA6");
|
||||||
|
|
||||||
// has dest port and specific prefix ranges: gets eliminated in step 1
|
// has dest port and specific prefix ranges: gets eliminated in step 1
|
||||||
|
|
@ -739,8 +755,9 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<Integer>asList(),
|
Arrays.<Integer>asList(),
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChain1 =
|
EnvoyServerProtoData.FilterChain filterChain1 = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch1, tlsContext1, tlsContextManager);
|
"filter-chain-1", filterChainMatch1, HTTP_CONNECTION_MANAGER, tlsContext1,
|
||||||
|
tlsContextManager);
|
||||||
|
|
||||||
// next 5 use prefix range: 4 with prefixLen of 30 and last one with 29
|
// next 5 use prefix range: 4 with prefixLen of 30 and last one with 29
|
||||||
|
|
||||||
|
|
@ -755,8 +772,9 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<Integer>asList(),
|
Arrays.<Integer>asList(),
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChain2 =
|
EnvoyServerProtoData.FilterChain filterChain2 = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch2, tlsContext2, tlsContextManager);
|
"filter-chain-2", filterChainMatch2, HTTP_CONNECTION_MANAGER, tlsContext2,
|
||||||
|
tlsContextManager);
|
||||||
|
|
||||||
// has prefix ranges with one not matching and source type local: gets eliminated in step 3
|
// has prefix ranges with one not matching and source type local: gets eliminated in step 3
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatch3 =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatch3 =
|
||||||
|
|
@ -771,8 +789,9 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<Integer>asList(),
|
Arrays.<Integer>asList(),
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChain3 =
|
EnvoyServerProtoData.FilterChain filterChain3 = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch3, tlsContext3, tlsContextManager);
|
"filter-chain-3", filterChainMatch3, HTTP_CONNECTION_MANAGER, tlsContext3,
|
||||||
|
tlsContextManager);
|
||||||
|
|
||||||
// has prefix ranges with both matching and source type external but non matching source port:
|
// has prefix ranges with both matching and source type external but non matching source port:
|
||||||
// gets eliminated in step 5
|
// gets eliminated in step 5
|
||||||
|
|
@ -789,7 +808,9 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChain4 =
|
EnvoyServerProtoData.FilterChain filterChain4 =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch4, tlsContext4, tlsContextManager);
|
new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-4", filterChainMatch4, HTTP_CONNECTION_MANAGER, tlsContext4,
|
||||||
|
tlsContextManager);
|
||||||
|
|
||||||
// has prefix ranges with both matching and source type external and matching source port: this
|
// has prefix ranges with both matching and source type external and matching source port: this
|
||||||
// gets selected
|
// gets selected
|
||||||
|
|
@ -808,7 +829,9 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChain5 =
|
EnvoyServerProtoData.FilterChain filterChain5 =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch5, tlsContext5, tlsContextManager);
|
new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-5", filterChainMatch5, HTTP_CONNECTION_MANAGER, tlsContext5,
|
||||||
|
tlsContextManager);
|
||||||
|
|
||||||
// has prefix range with prefixLen of 29: gets eliminated in step 2
|
// has prefix range with prefixLen of 29: gets eliminated in step 2
|
||||||
EnvoyServerProtoData.FilterChainMatch filterChainMatch6 =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatch6 =
|
||||||
|
|
@ -822,10 +845,12 @@ public class FilterChainMatchTest {
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChain6 =
|
EnvoyServerProtoData.FilterChain filterChain6 =
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch6, tlsContext6, tlsContextManager);
|
new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-6", filterChainMatch6, HTTP_CONNECTION_MANAGER, tlsContext6,
|
||||||
|
tlsContextManager);
|
||||||
|
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
new EnvoyServerProtoData.FilterChain(null, null, tlsContextManager);
|
"filter-chain-7", null, HTTP_CONNECTION_MANAGER, null, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
"listener1",
|
"listener1",
|
||||||
|
|
@ -833,112 +858,77 @@ public class FilterChainMatchTest {
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
filterChain1, filterChain2, filterChain3, filterChain4, filterChain5, filterChain6),
|
filterChain1, filterChain2, filterChain3, filterChain4, filterChain5, filterChain6),
|
||||||
defaultFilterChain);
|
defaultFilterChain);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContextPicked = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextPicked = getDownstreamTlsContext();
|
||||||
assertThat(tlsContextPicked).isSameInstanceAs(tlsContext5);
|
assertThat(tlsContextPicked).isSameInstanceAs(tlsContext5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void filterChainMatch_unsupportedMatchers()
|
public void filterChainMatch_unsupportedMatchers()
|
||||||
throws InvalidProtocolBufferException, UnknownHostException {
|
throws UnknownHostException {
|
||||||
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
|
||||||
io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext tlsContext1 =
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext1 =
|
||||||
CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "ROOTCA");
|
||||||
"CERT1", "ROOTCA");
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext2 =
|
||||||
io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext tlsContext2 =
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "ROOTCA");
|
||||||
CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext3 =
|
||||||
"CERT2", "ROOTCA");
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT3", "ROOTCA");
|
||||||
io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext tlsContext3 =
|
|
||||||
CommonTlsContextTestsUtil.buildTestDownstreamTlsContext(
|
|
||||||
"CERT3", "ROOTCA");
|
|
||||||
|
|
||||||
FilterChainMatch filterChainMatch1 =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatch1 =
|
||||||
FilterChainMatch.newBuilder()
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
.addAllServerNames(Arrays.asList("server1", "server2"))
|
0 /* destinationPort */,
|
||||||
.setTransportProtocol("tls")
|
Collections.singletonList(
|
||||||
.addAllApplicationProtocols(Arrays.asList("managed-mtls", "h2"))
|
new EnvoyServerProtoData.CidrRange("10.1.0.0", 16)) /* prefixRange */,
|
||||||
.addPrefixRanges(CidrRange.newBuilder()
|
Arrays.asList("managed-mtls", "h2") /* applicationProtocol */,
|
||||||
.setAddressPrefix("10.1.0.0")
|
Collections.<EnvoyServerProtoData.CidrRange>emptyList() /* sourcePrefixRanges */,
|
||||||
.setPrefixLen(UInt32Value.of(16))
|
EnvoyServerProtoData.ConnectionSourceType.ANY /* sourceType */,
|
||||||
.build())
|
Collections.<Integer>emptyList() /* sourcePorts */,
|
||||||
.build();
|
Arrays.asList("server1", "server2") /* serverNames */,
|
||||||
|
"tls" /* transportProtocol */);
|
||||||
|
|
||||||
FilterChainMatch filterChainMatch2 =
|
EnvoyServerProtoData.FilterChainMatch filterChainMatch2 =
|
||||||
FilterChainMatch.newBuilder()
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
.addPrefixRanges(CidrRange.newBuilder()
|
0 /* destinationPort */,
|
||||||
.setAddressPrefix("10.0.0.0")
|
Collections.singletonList(
|
||||||
.setPrefixLen(UInt32Value.of(8))
|
new EnvoyServerProtoData.CidrRange("10.0.0.0", 8)) /* prefixRange */,
|
||||||
.build())
|
Collections.<String>emptyList() /* applicationProtocol */,
|
||||||
.build();
|
Collections.<EnvoyServerProtoData.CidrRange>emptyList() /* sourcePrefixRanges */,
|
||||||
|
EnvoyServerProtoData.ConnectionSourceType.ANY /* sourceType */,
|
||||||
|
Collections.<Integer>emptyList() /* sourcePorts */,
|
||||||
|
Collections.<String>emptyList() /* serverNames */,
|
||||||
|
"" /* transportProtocol */);
|
||||||
|
|
||||||
FilterChain filterChain1 =
|
EnvoyServerProtoData.FilterChainMatch defaultFilterChainMatch =
|
||||||
FilterChain.newBuilder()
|
new EnvoyServerProtoData.FilterChainMatch(
|
||||||
.setFilterChainMatch(filterChainMatch1)
|
0 /* destinationPort */,
|
||||||
.setTransportSocket(TransportSocket.newBuilder().setName("envoy.transport_sockets.tls")
|
Collections.<EnvoyServerProtoData.CidrRange>emptyList() /* prefixRange */,
|
||||||
.setTypedConfig(Any.pack(tlsContext1))
|
Collections.<String>emptyList() /* applicationProtocol */,
|
||||||
.build())
|
Collections.<EnvoyServerProtoData.CidrRange>emptyList() /* sourcePrefixRanges */,
|
||||||
.addFilters(Filter.newBuilder()
|
EnvoyServerProtoData.ConnectionSourceType.ANY /* sourceType */,
|
||||||
.setName("envoy.http_connection_manager")
|
Collections.<Integer>emptyList() /* sourcePorts */,
|
||||||
.setTypedConfig(Any.newBuilder()
|
Collections.<String>emptyList() /* serverNames */,
|
||||||
.setTypeUrl(
|
"" /* transportProtocol */);
|
||||||
"type.googleapis.com/"
|
|
||||||
+ "envoy.extensions.filters.network.http_connection_manager"
|
|
||||||
+ ".v3.HttpConnectionManager"))
|
|
||||||
.build())
|
|
||||||
.build();
|
|
||||||
FilterChain filterChain2 =
|
|
||||||
FilterChain.newBuilder()
|
|
||||||
.setFilterChainMatch(filterChainMatch2)
|
|
||||||
.setTransportSocket(TransportSocket.newBuilder().setName("envoy.transport_sockets.tls")
|
|
||||||
.setTypedConfig(Any.pack(tlsContext2))
|
|
||||||
.build())
|
|
||||||
.addFilters(Filter.newBuilder()
|
|
||||||
.setName("envoy.http_connection_manager")
|
|
||||||
.setTypedConfig(Any.newBuilder()
|
|
||||||
.setTypeUrl(
|
|
||||||
"type.googleapis.com/"
|
|
||||||
+ "envoy.extensions.filters.network.http_connection_manager"
|
|
||||||
+ ".v3.HttpConnectionManager"))
|
|
||||||
.build())
|
|
||||||
.build();
|
|
||||||
FilterChain defaultFilterChain =
|
|
||||||
FilterChain.newBuilder()
|
|
||||||
.setTransportSocket(TransportSocket.newBuilder().setName("envoy.transport_sockets.tls")
|
|
||||||
.setTypedConfig(Any.pack(tlsContext3))
|
|
||||||
.build())
|
|
||||||
.addFilters(Filter.newBuilder()
|
|
||||||
.setName("envoy.http_connection_manager")
|
|
||||||
.setTypedConfig(Any.newBuilder()
|
|
||||||
.setTypeUrl(
|
|
||||||
"type.googleapis.com/"
|
|
||||||
+ "envoy.extensions.filters.network.http_connection_manager"
|
|
||||||
+ ".v3.HttpConnectionManager"))
|
|
||||||
.build())
|
|
||||||
.build();
|
|
||||||
Address address =
|
|
||||||
Address.newBuilder()
|
|
||||||
.setSocketAddress(
|
|
||||||
SocketAddress.newBuilder().setPortValue(8000).setAddress("10.2.1.34").build())
|
|
||||||
.build();
|
|
||||||
io.envoyproxy.envoy.config.listener.v3.Listener listener =
|
|
||||||
io.envoyproxy.envoy.config.listener.v3.Listener.newBuilder()
|
|
||||||
.setName("8000")
|
|
||||||
.setAddress(address)
|
|
||||||
.addFilterChains(filterChain1)
|
|
||||||
.addFilterChains(filterChain2)
|
|
||||||
.setDefaultFilterChain(defaultFilterChain)
|
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
EnvoyServerProtoData.Listener xdsListener = EnvoyServerProtoData.Listener
|
EnvoyServerProtoData.FilterChain filterChain1 = new EnvoyServerProtoData.FilterChain(
|
||||||
.fromEnvoyProtoListener(listener, mock(TlsContextManager.class));
|
"filter-chain-foo", filterChainMatch1, HTTP_CONNECTION_MANAGER, tlsContext1,
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(xdsListener);
|
mock(TlsContextManager.class));
|
||||||
|
EnvoyServerProtoData.FilterChain filterChain2 = new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-bar", filterChainMatch2, HTTP_CONNECTION_MANAGER, tlsContext2,
|
||||||
|
mock(TlsContextManager.class));
|
||||||
|
|
||||||
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-baz", defaultFilterChainMatch, HTTP_CONNECTION_MANAGER, tlsContext3,
|
||||||
|
mock(TlsContextManager.class));
|
||||||
|
|
||||||
|
EnvoyServerProtoData.Listener listener = new EnvoyServerProtoData.Listener(
|
||||||
|
"", "10.2.1.34:8000", Arrays.asList(filterChain1, filterChain2), defaultFilterChain);
|
||||||
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContextPicked = getDownstreamTlsContext();
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextPicked = getDownstreamTlsContext();
|
||||||
// assert defaultFilterChain match
|
// assert defaultFilterChain match
|
||||||
assertThat(tlsContextPicked.getCommonTlsContext().getTlsCertificateSdsSecretConfigsList().get(0)
|
assertThat(tlsContextPicked.getCommonTlsContext().getTlsCertificateSdsSecretConfigsList()
|
||||||
.getName()).isEqualTo("CERT3");
|
.get(0).getName()).isEqualTo("CERT3");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupChannel(String localIp, String remoteIp, int remotePort)
|
private void setupChannel(String localIp, String remoteIp, int remotePort)
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import io.grpc.Status;
|
||||||
import io.grpc.StatusException;
|
import io.grpc.StatusException;
|
||||||
import io.grpc.inprocess.InProcessSocketAddress;
|
import io.grpc.inprocess.InProcessSocketAddress;
|
||||||
import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext;
|
import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext;
|
||||||
|
import io.grpc.xds.XdsClient.LdsUpdate;
|
||||||
import io.grpc.xds.internal.sds.CommonTlsContextTestsUtil;
|
import io.grpc.xds.internal.sds.CommonTlsContextTestsUtil;
|
||||||
import io.grpc.xds.internal.sds.SslContextProvider;
|
import io.grpc.xds.internal.sds.SslContextProvider;
|
||||||
import io.grpc.xds.internal.sds.SslContextProviderSupplier;
|
import io.grpc.xds.internal.sds.SslContextProviderSupplier;
|
||||||
|
|
@ -131,7 +132,7 @@ public class XdsClientWrapperForServerSdsTestMisc {
|
||||||
"10.1.2.3",
|
"10.1.2.3",
|
||||||
Collections.<EnvoyServerProtoData.FilterChain>emptyList(),
|
Collections.<EnvoyServerProtoData.FilterChain>emptyList(),
|
||||||
null);
|
null);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
DownstreamTlsContext tlsContext = getDownstreamTlsContext();
|
DownstreamTlsContext tlsContext = getDownstreamTlsContext();
|
||||||
assertThat(tlsContext).isNull();
|
assertThat(tlsContext).isNull();
|
||||||
|
|
|
||||||
|
|
@ -202,11 +202,11 @@ public class XdsNameResolverTest {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void resolving_ldsResourceUpdateRdsName() {
|
public void resolving_ldsResourceUpdateRdsName() {
|
||||||
Route route1 = Route.create(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
Route route1 = Route.forAction(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(
|
RouteAction.forCluster(
|
||||||
cluster1, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(15L)),
|
cluster1, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(15L)),
|
||||||
ImmutableMap.<String, FilterConfig>of());
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
Route route2 = Route.create(RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
Route route2 = Route.forAction(RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(
|
RouteAction.forCluster(
|
||||||
cluster2, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(20L)),
|
cluster2, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(20L)),
|
||||||
ImmutableMap.<String, FilterConfig>of());
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
|
|
@ -260,7 +260,7 @@ public class XdsNameResolverTest {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void resolving_ldsResourceRevokedAndAddedBack() {
|
public void resolving_ldsResourceRevokedAndAddedBack() {
|
||||||
Route route = Route.create(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
Route route = Route.forAction(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(
|
RouteAction.forCluster(
|
||||||
cluster1, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(15L)),
|
cluster1, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(15L)),
|
||||||
ImmutableMap.<String, FilterConfig>of());
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
|
|
@ -299,7 +299,7 @@ public class XdsNameResolverTest {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void resolving_rdsResourceRevokedAndAddedBack() {
|
public void resolving_rdsResourceRevokedAndAddedBack() {
|
||||||
Route route = Route.create(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
Route route = Route.forAction(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(
|
RouteAction.forCluster(
|
||||||
cluster1, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(15L)),
|
cluster1, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(15L)),
|
||||||
ImmutableMap.<String, FilterConfig>of());
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
|
|
@ -373,11 +373,11 @@ public class XdsNameResolverTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<VirtualHost> buildUnmatchedVirtualHosts() {
|
private List<VirtualHost> buildUnmatchedVirtualHosts() {
|
||||||
Route route1 = Route.create(RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
Route route1 = Route.forAction(RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(
|
RouteAction.forCluster(
|
||||||
cluster2, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(15L)),
|
cluster2, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(15L)),
|
||||||
ImmutableMap.<String, FilterConfig>of());
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
Route route2 = Route.create(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
Route route2 = Route.forAction(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(
|
RouteAction.forCluster(
|
||||||
cluster1, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(15L)),
|
cluster1, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(15L)),
|
||||||
ImmutableMap.<String, FilterConfig>of());
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
|
|
@ -394,7 +394,7 @@ public class XdsNameResolverTest {
|
||||||
public void resolved_noTimeout() {
|
public void resolved_noTimeout() {
|
||||||
resolver.start(mockListener);
|
resolver.start(mockListener);
|
||||||
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
Route route = Route.create(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
Route route = Route.forAction(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(
|
RouteAction.forCluster(
|
||||||
cluster1, Collections.<HashPolicy>emptyList(), null), // per-route timeout unset
|
cluster1, Collections.<HashPolicy>emptyList(), null), // per-route timeout unset
|
||||||
ImmutableMap.<String, FilterConfig>of());
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
|
|
@ -412,7 +412,7 @@ public class XdsNameResolverTest {
|
||||||
public void resolved_fallbackToHttpMaxStreamDurationAsTimeout() {
|
public void resolved_fallbackToHttpMaxStreamDurationAsTimeout() {
|
||||||
resolver.start(mockListener);
|
resolver.start(mockListener);
|
||||||
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
Route route = Route.create(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
Route route = Route.forAction(RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(
|
RouteAction.forCluster(
|
||||||
cluster1, Collections.<HashPolicy>emptyList(), null), // per-route timeout unset
|
cluster1, Collections.<HashPolicy>emptyList(), null), // per-route timeout unset
|
||||||
ImmutableMap.<String, FilterConfig>of());
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
|
|
@ -436,7 +436,7 @@ public class XdsNameResolverTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolved_simpleCallFailedToRoute() {
|
public void resolved_simpleCallFailedToRoute_noMatchingRoute() {
|
||||||
InternalConfigSelector configSelector = resolveToClusters();
|
InternalConfigSelector configSelector = resolveToClusters();
|
||||||
CallInfo call = new CallInfo("FooService", "barMethod");
|
CallInfo call = new CallInfo("FooService", "barMethod");
|
||||||
Result selectResult = configSelector.selectConfig(
|
Result selectResult = configSelector.selectConfig(
|
||||||
|
|
@ -448,13 +448,48 @@ public class XdsNameResolverTest {
|
||||||
verifyNoMoreInteractions(mockListener);
|
verifyNoMoreInteractions(mockListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test
|
||||||
|
public void resolved_simpleCallFailedToRoute_routeWithNonForwardingAction() {
|
||||||
|
resolver.start(mockListener);
|
||||||
|
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
|
xdsClient.deliverLdsUpdate(
|
||||||
|
Arrays.asList(
|
||||||
|
Route.forNonForwardingAction(
|
||||||
|
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
|
ImmutableMap.<String, FilterConfig>of()),
|
||||||
|
Route.forAction(
|
||||||
|
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||||
|
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
||||||
|
TimeUnit.SECONDS.toNanos(15L)),
|
||||||
|
ImmutableMap.<String, FilterConfig>of())));
|
||||||
|
verify(mockListener).onResult(resolutionResultCaptor.capture());
|
||||||
|
ResolutionResult result = resolutionResultCaptor.getValue();
|
||||||
|
assertThat(result.getAddresses()).isEmpty();
|
||||||
|
assertServiceConfigForLoadBalancingConfig(
|
||||||
|
Collections.singletonList(cluster2),
|
||||||
|
(Map<String, ?>) result.getServiceConfig().getConfig());
|
||||||
|
assertThat(result.getAttributes().get(InternalXdsAttributes.XDS_CLIENT_POOL)).isNotNull();
|
||||||
|
assertThat(result.getAttributes().get(InternalXdsAttributes.CALL_COUNTER_PROVIDER)).isNotNull();
|
||||||
|
InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY);
|
||||||
|
// Simulates making a call1 RPC.
|
||||||
|
Result selectResult = configSelector.selectConfig(
|
||||||
|
new PickSubchannelArgsImpl(call1.methodDescriptor, new Metadata(), CallOptions.DEFAULT));
|
||||||
|
Status status = selectResult.getStatus();
|
||||||
|
assertThat(status.isOk()).isFalse();
|
||||||
|
assertThat(status.getCode()).isEqualTo(Code.UNAVAILABLE);
|
||||||
|
assertThat(status.getDescription())
|
||||||
|
.isEqualTo("Could not route RPC to Route with non-forwarding action");
|
||||||
|
verifyNoMoreInteractions(mockListener);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolved_rpcHashingByHeader_withoutSubstitution() {
|
public void resolved_rpcHashingByHeader_withoutSubstitution() {
|
||||||
resolver.start(mockListener);
|
resolver.start(mockListener);
|
||||||
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
xdsClient.deliverLdsUpdate(
|
xdsClient.deliverLdsUpdate(
|
||||||
Collections.singletonList(
|
Collections.singletonList(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(
|
RouteMatch.withPathExactOnly(
|
||||||
"/" + TestMethodDescriptors.voidMethod().getFullMethodName()),
|
"/" + TestMethodDescriptors.voidMethod().getFullMethodName()),
|
||||||
RouteAction.forCluster(cluster1, Collections.singletonList(HashPolicy.forHeader(
|
RouteAction.forCluster(cluster1, Collections.singletonList(HashPolicy.forHeader(
|
||||||
|
|
@ -485,7 +520,7 @@ public class XdsNameResolverTest {
|
||||||
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
xdsClient.deliverLdsUpdate(
|
xdsClient.deliverLdsUpdate(
|
||||||
Collections.singletonList(
|
Collections.singletonList(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(
|
RouteMatch.withPathExactOnly(
|
||||||
"/" + TestMethodDescriptors.voidMethod().getFullMethodName()),
|
"/" + TestMethodDescriptors.voidMethod().getFullMethodName()),
|
||||||
RouteAction.forCluster(cluster1, Collections.singletonList(HashPolicy.forHeader(
|
RouteAction.forCluster(cluster1, Collections.singletonList(HashPolicy.forHeader(
|
||||||
|
|
@ -522,7 +557,7 @@ public class XdsNameResolverTest {
|
||||||
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
xdsClient.deliverLdsUpdate(
|
xdsClient.deliverLdsUpdate(
|
||||||
Collections.singletonList(
|
Collections.singletonList(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(
|
RouteMatch.withPathExactOnly(
|
||||||
"/" + TestMethodDescriptors.voidMethod().getFullMethodName()),
|
"/" + TestMethodDescriptors.voidMethod().getFullMethodName()),
|
||||||
RouteAction.forCluster(cluster1, Collections.singletonList(
|
RouteAction.forCluster(cluster1, Collections.singletonList(
|
||||||
|
|
@ -553,7 +588,7 @@ public class XdsNameResolverTest {
|
||||||
xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
xdsClient.deliverLdsUpdate(
|
xdsClient.deliverLdsUpdate(
|
||||||
Collections.singletonList(
|
Collections.singletonList(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(
|
RouteMatch.withPathExactOnly(
|
||||||
"/" + TestMethodDescriptors.voidMethod().getFullMethodName()),
|
"/" + TestMethodDescriptors.voidMethod().getFullMethodName()),
|
||||||
RouteAction.forCluster(cluster1, Collections.singletonList(
|
RouteAction.forCluster(cluster1, Collections.singletonList(
|
||||||
|
|
@ -584,13 +619,13 @@ public class XdsNameResolverTest {
|
||||||
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
xdsClient.deliverLdsUpdate(
|
xdsClient.deliverLdsUpdate(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(
|
RouteAction.forCluster(
|
||||||
"another-cluster", Collections.<HashPolicy>emptyList(),
|
"another-cluster", Collections.<HashPolicy>emptyList(),
|
||||||
TimeUnit.SECONDS.toNanos(20L)),
|
TimeUnit.SECONDS.toNanos(20L)),
|
||||||
ImmutableMap.<String, FilterConfig>of()),
|
ImmutableMap.<String, FilterConfig>of()),
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(
|
RouteAction.forCluster(
|
||||||
cluster2, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(15L)),
|
cluster2, Collections.<HashPolicy>emptyList(), TimeUnit.SECONDS.toNanos(15L)),
|
||||||
|
|
@ -623,13 +658,13 @@ public class XdsNameResolverTest {
|
||||||
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
xdsClient.deliverLdsUpdate(
|
xdsClient.deliverLdsUpdate(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(
|
RouteAction.forCluster(
|
||||||
"another-cluster", Collections.<HashPolicy>emptyList(),
|
"another-cluster", Collections.<HashPolicy>emptyList(),
|
||||||
TimeUnit.SECONDS.toNanos(20L)),
|
TimeUnit.SECONDS.toNanos(20L)),
|
||||||
ImmutableMap.<String, FilterConfig>of()),
|
ImmutableMap.<String, FilterConfig>of()),
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
||||||
TimeUnit.SECONDS.toNanos(15L)),
|
TimeUnit.SECONDS.toNanos(15L)),
|
||||||
|
|
@ -658,12 +693,12 @@ public class XdsNameResolverTest {
|
||||||
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
xdsClient.deliverLdsUpdate(
|
xdsClient.deliverLdsUpdate(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster("another-cluster", Collections.<HashPolicy>emptyList(),
|
RouteAction.forCluster("another-cluster", Collections.<HashPolicy>emptyList(),
|
||||||
TimeUnit.SECONDS.toNanos(20L)),
|
TimeUnit.SECONDS.toNanos(20L)),
|
||||||
ImmutableMap.<String, FilterConfig>of()),
|
ImmutableMap.<String, FilterConfig>of()),
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
||||||
TimeUnit.SECONDS.toNanos(15L)),
|
TimeUnit.SECONDS.toNanos(15L)),
|
||||||
|
|
@ -677,12 +712,12 @@ public class XdsNameResolverTest {
|
||||||
|
|
||||||
xdsClient.deliverLdsUpdate(
|
xdsClient.deliverLdsUpdate(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster("another-cluster", Collections.<HashPolicy>emptyList(),
|
RouteAction.forCluster("another-cluster", Collections.<HashPolicy>emptyList(),
|
||||||
TimeUnit.SECONDS.toNanos(15L)),
|
TimeUnit.SECONDS.toNanos(15L)),
|
||||||
ImmutableMap.<String, FilterConfig>of()),
|
ImmutableMap.<String, FilterConfig>of()),
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
||||||
TimeUnit.SECONDS.toNanos(15L)),
|
TimeUnit.SECONDS.toNanos(15L)),
|
||||||
|
|
@ -698,19 +733,19 @@ public class XdsNameResolverTest {
|
||||||
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
xdsClient.deliverLdsUpdate(
|
xdsClient.deliverLdsUpdate(
|
||||||
Collections.singletonList(
|
Collections.singletonList(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
||||||
TimeUnit.SECONDS.toNanos(15L)),
|
TimeUnit.SECONDS.toNanos(15L)),
|
||||||
ImmutableMap.<String, FilterConfig>of())));
|
ImmutableMap.<String, FilterConfig>of())));
|
||||||
xdsClient.deliverLdsUpdate(
|
xdsClient.deliverLdsUpdate(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(cluster1, Collections.<HashPolicy>emptyList(),
|
RouteAction.forCluster(cluster1, Collections.<HashPolicy>emptyList(),
|
||||||
TimeUnit.SECONDS.toNanos(15L)),
|
TimeUnit.SECONDS.toNanos(15L)),
|
||||||
ImmutableMap.<String, FilterConfig>of()),
|
ImmutableMap.<String, FilterConfig>of()),
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
||||||
TimeUnit.SECONDS.toNanos(15L)),
|
TimeUnit.SECONDS.toNanos(15L)),
|
||||||
|
|
@ -727,7 +762,7 @@ public class XdsNameResolverTest {
|
||||||
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
xdsClient.deliverLdsUpdate(
|
xdsClient.deliverLdsUpdate(
|
||||||
Collections.singletonList(
|
Collections.singletonList(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forWeightedClusters(
|
RouteAction.forWeightedClusters(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
|
|
@ -790,12 +825,12 @@ public class XdsNameResolverTest {
|
||||||
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
FakeXdsClient xdsClient = (FakeXdsClient) resolver.getXdsClient();
|
||||||
xdsClient.deliverLdsUpdate(
|
xdsClient.deliverLdsUpdate(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call1.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(cluster1, Collections.<HashPolicy>emptyList(),
|
RouteAction.forCluster(cluster1, Collections.<HashPolicy>emptyList(),
|
||||||
TimeUnit.SECONDS.toNanos(15L)),
|
TimeUnit.SECONDS.toNanos(15L)),
|
||||||
ImmutableMap.<String, FilterConfig>of()),
|
ImmutableMap.<String, FilterConfig>of()),
|
||||||
Route.create(
|
Route.forAction(
|
||||||
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
RouteMatch.withPathExactOnly(call2.getFullMethodNameForPath()),
|
||||||
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
RouteAction.forCluster(cluster2, Collections.<HashPolicy>emptyList(),
|
||||||
TimeUnit.SECONDS.toNanos(15L)),
|
TimeUnit.SECONDS.toNanos(15L)),
|
||||||
|
|
@ -1591,7 +1626,8 @@ public class XdsNameResolverTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
void deliverLdsUpdate(long httpMaxStreamDurationNano, List<VirtualHost> virtualHosts) {
|
void deliverLdsUpdate(long httpMaxStreamDurationNano, List<VirtualHost> virtualHosts) {
|
||||||
ldsWatcher.onChanged(new LdsUpdate(httpMaxStreamDurationNano, virtualHosts, null));
|
ldsWatcher.onChanged(LdsUpdate.forApiListener(HttpConnectionManager.forVirtualHosts(
|
||||||
|
httpMaxStreamDurationNano, virtualHosts, null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void deliverLdsUpdate(final List<Route> routes) {
|
void deliverLdsUpdate(final List<Route> routes) {
|
||||||
|
|
@ -1599,7 +1635,8 @@ public class XdsNameResolverTest {
|
||||||
VirtualHost.create(
|
VirtualHost.create(
|
||||||
"virtual-host", Collections.singletonList(AUTHORITY), routes,
|
"virtual-host", Collections.singletonList(AUTHORITY), routes,
|
||||||
ImmutableMap.<String, FilterConfig>of());
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
ldsWatcher.onChanged(new LdsUpdate(0L, Collections.singletonList(virtualHost), null));
|
ldsWatcher.onChanged(LdsUpdate.forApiListener(HttpConnectionManager.forVirtualHosts(
|
||||||
|
0L, Collections.singletonList(virtualHost), null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void deliverLdsUpdateWithFaultInjection(
|
void deliverLdsUpdateWithFaultInjection(
|
||||||
|
|
@ -1625,7 +1662,7 @@ public class XdsNameResolverTest {
|
||||||
overrideConfig = routeFaultConfig == null
|
overrideConfig = routeFaultConfig == null
|
||||||
? ImmutableMap.<String, FilterConfig>of()
|
? ImmutableMap.<String, FilterConfig>of()
|
||||||
: ImmutableMap.<String, FilterConfig>of(FAULT_FILTER_INSTANCE_NAME, routeFaultConfig);
|
: ImmutableMap.<String, FilterConfig>of(FAULT_FILTER_INSTANCE_NAME, routeFaultConfig);
|
||||||
Route route = Route.create(
|
Route route = Route.forAction(
|
||||||
RouteMatch.create(
|
RouteMatch.create(
|
||||||
PathMatcher.fromPrefix("/", false), Collections.<HeaderMatcher>emptyList(), null),
|
PathMatcher.fromPrefix("/", false), Collections.<HeaderMatcher>emptyList(), null),
|
||||||
RouteAction.forWeightedClusters(
|
RouteAction.forWeightedClusters(
|
||||||
|
|
@ -1642,7 +1679,8 @@ public class XdsNameResolverTest {
|
||||||
Collections.singletonList(AUTHORITY),
|
Collections.singletonList(AUTHORITY),
|
||||||
Collections.singletonList(route),
|
Collections.singletonList(route),
|
||||||
overrideConfig);
|
overrideConfig);
|
||||||
ldsWatcher.onChanged(new LdsUpdate(0L, Collections.singletonList(virtualHost), filterChain));
|
ldsWatcher.onChanged(LdsUpdate.forApiListener(HttpConnectionManager.forVirtualHosts(
|
||||||
|
0L, Collections.singletonList(virtualHost), filterChain)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void deliverLdsUpdateWithNoRouterFilter() {
|
void deliverLdsUpdateWithNoRouterFilter() {
|
||||||
|
|
@ -1651,8 +1689,8 @@ public class XdsNameResolverTest {
|
||||||
Collections.singletonList(AUTHORITY),
|
Collections.singletonList(AUTHORITY),
|
||||||
Collections.<Route>emptyList(),
|
Collections.<Route>emptyList(),
|
||||||
Collections.<String, FilterConfig>emptyMap());
|
Collections.<String, FilterConfig>emptyMap());
|
||||||
ldsWatcher.onChanged(new LdsUpdate(
|
ldsWatcher.onChanged(LdsUpdate.forApiListener(HttpConnectionManager.forVirtualHosts(
|
||||||
0L, Collections.singletonList(virtualHost), ImmutableList.<NamedFilterConfig>of()));
|
0L, Collections.singletonList(virtualHost), ImmutableList.<NamedFilterConfig>of())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void deliverLdsUpdateForRdsNameWithFaultInjection(
|
void deliverLdsUpdateForRdsNameWithFaultInjection(
|
||||||
|
|
@ -1664,11 +1702,13 @@ public class XdsNameResolverTest {
|
||||||
ImmutableList<NamedFilterConfig> filterChain = ImmutableList.of(
|
ImmutableList<NamedFilterConfig> filterChain = ImmutableList.of(
|
||||||
new NamedFilterConfig(FAULT_FILTER_INSTANCE_NAME, httpFilterFaultConfig),
|
new NamedFilterConfig(FAULT_FILTER_INSTANCE_NAME, httpFilterFaultConfig),
|
||||||
new NamedFilterConfig(ROUTER_FILTER_INSTANCE_NAME, RouterFilter.ROUTER_CONFIG));
|
new NamedFilterConfig(ROUTER_FILTER_INSTANCE_NAME, RouterFilter.ROUTER_CONFIG));
|
||||||
ldsWatcher.onChanged(new LdsUpdate(0L, rdsName, filterChain));
|
ldsWatcher.onChanged(LdsUpdate.forApiListener(HttpConnectionManager.forRdsName(
|
||||||
|
0L, rdsName, filterChain)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void deliverLdsUpdateForRdsName(String rdsName) {
|
void deliverLdsUpdateForRdsName(String rdsName) {
|
||||||
ldsWatcher.onChanged(new LdsUpdate(0, rdsName, null));
|
ldsWatcher.onChanged(LdsUpdate.forApiListener(HttpConnectionManager.forRdsName(
|
||||||
|
0, rdsName, null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void deliverLdsResourceNotFound() {
|
void deliverLdsResourceNotFound() {
|
||||||
|
|
@ -1690,7 +1730,7 @@ public class XdsNameResolverTest {
|
||||||
overrideConfig = routFaultConfig == null
|
overrideConfig = routFaultConfig == null
|
||||||
? ImmutableMap.<String, FilterConfig>of()
|
? ImmutableMap.<String, FilterConfig>of()
|
||||||
: ImmutableMap.<String, FilterConfig>of(FAULT_FILTER_INSTANCE_NAME, routFaultConfig);
|
: ImmutableMap.<String, FilterConfig>of(FAULT_FILTER_INSTANCE_NAME, routFaultConfig);
|
||||||
Route route = Route.create(
|
Route route = Route.forAction(
|
||||||
RouteMatch.create(
|
RouteMatch.create(
|
||||||
PathMatcher.fromPrefix("/", false), Collections.<HeaderMatcher>emptyList(), null),
|
PathMatcher.fromPrefix("/", false), Collections.<HeaderMatcher>emptyList(), null),
|
||||||
RouteAction.forWeightedClusters(
|
RouteAction.forWeightedClusters(
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ import io.grpc.testing.protobuf.SimpleResponse;
|
||||||
import io.grpc.testing.protobuf.SimpleServiceGrpc;
|
import io.grpc.testing.protobuf.SimpleServiceGrpc;
|
||||||
import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext;
|
import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext;
|
||||||
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
|
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
|
||||||
|
import io.grpc.xds.Filter.NamedFilterConfig;
|
||||||
|
import io.grpc.xds.XdsClient.LdsUpdate;
|
||||||
import io.grpc.xds.internal.sds.CommonTlsContextTestsUtil;
|
import io.grpc.xds.internal.sds.CommonTlsContextTestsUtil;
|
||||||
import io.grpc.xds.internal.sds.SslContextProviderSupplier;
|
import io.grpc.xds.internal.sds.SslContextProviderSupplier;
|
||||||
import io.grpc.xds.internal.sds.TlsContextManagerImpl;
|
import io.grpc.xds.internal.sds.TlsContextManagerImpl;
|
||||||
|
|
@ -59,6 +61,7 @@ import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
|
|
@ -336,7 +339,7 @@ public class XdsSdsClientServerTest {
|
||||||
TlsContextManager tlsContextManager) {
|
TlsContextManager tlsContextManager) {
|
||||||
EnvoyServerProtoData.Listener listener = buildListener("listener1", "0.0.0.0", tlsContext,
|
EnvoyServerProtoData.Listener listener = buildListener("listener1", "0.0.0.0", tlsContext,
|
||||||
tlsContextManager);
|
tlsContextManager);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -366,8 +369,12 @@ public class XdsSdsClientServerTest {
|
||||||
Arrays.<Integer>asList(),
|
Arrays.<Integer>asList(),
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
// HttpConnectionManager currently not used for server side.
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch, tlsContext, tlsContextManager);
|
HttpConnectionManager httpConnectionManager = HttpConnectionManager.forRdsName(
|
||||||
|
0L, "does not matter", Collections.<NamedFilterConfig>emptyList());
|
||||||
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-foo", filterChainMatch, httpConnectionManager, tlsContext,
|
||||||
|
tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(name, address, Arrays.asList(defaultFilterChain), null);
|
new EnvoyServerProtoData.Listener(name, address, Arrays.asList(defaultFilterChain), null);
|
||||||
return listener;
|
return listener;
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,12 @@ import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import io.grpc.InsecureChannelCredentials;
|
import io.grpc.InsecureChannelCredentials;
|
||||||
import io.grpc.internal.ObjectPool;
|
import io.grpc.internal.ObjectPool;
|
||||||
|
import io.grpc.xds.Filter.NamedFilterConfig;
|
||||||
|
import io.grpc.xds.XdsClient.LdsUpdate;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
@ -121,7 +124,7 @@ class XdsServerTestHelper {
|
||||||
EnvoyServerProtoData.DownstreamTlsContext tlsContext, TlsContextManager tlsContextManager) {
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext, TlsContextManager tlsContextManager) {
|
||||||
EnvoyServerProtoData.Listener listener = buildTestListener("listener1", "10.1.2.3",
|
EnvoyServerProtoData.Listener listener = buildTestListener("listener1", "10.1.2.3",
|
||||||
Arrays.<Integer>asList(), tlsContext, null, tlsContextManager);
|
Arrays.<Integer>asList(), tlsContext, null, tlsContextManager);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,7 +135,7 @@ class XdsServerTestHelper {
|
||||||
TlsContextManager tlsContextManager) {
|
TlsContextManager tlsContextManager) {
|
||||||
EnvoyServerProtoData.Listener listener = buildTestListener("listener1", "10.1.2.3", sourcePorts,
|
EnvoyServerProtoData.Listener listener = buildTestListener("listener1", "10.1.2.3", sourcePorts,
|
||||||
tlsContext, tlsContextForDefaultFilterChain, tlsContextManager);
|
tlsContext, tlsContextForDefaultFilterChain, tlsContextManager);
|
||||||
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
registeredWatcher.onChanged(listenerUpdate);
|
registeredWatcher.onChanged(listenerUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,10 +161,14 @@ class XdsServerTestHelper {
|
||||||
sourcePorts,
|
sourcePorts,
|
||||||
Arrays.<String>asList(),
|
Arrays.<String>asList(),
|
||||||
null);
|
null);
|
||||||
EnvoyServerProtoData.FilterChain filterChain1 =
|
// HttpConnectionManager currently not used for server side.
|
||||||
new EnvoyServerProtoData.FilterChain(filterChainMatch1, tlsContext, tlsContextManager);
|
HttpConnectionManager httpConnectionManager = HttpConnectionManager.forRdsName(
|
||||||
EnvoyServerProtoData.FilterChain defaultFilterChain =
|
0L, "does not matter", Collections.<NamedFilterConfig>emptyList());
|
||||||
new EnvoyServerProtoData.FilterChain(null, tlsContextForDefaultFilterChain,
|
EnvoyServerProtoData.FilterChain filterChain1 = new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-foo", filterChainMatch1, httpConnectionManager, tlsContext,
|
||||||
|
tlsContextManager);
|
||||||
|
EnvoyServerProtoData.FilterChain defaultFilterChain = new EnvoyServerProtoData.FilterChain(
|
||||||
|
"filter-chain-bar", null, httpConnectionManager, tlsContextForDefaultFilterChain,
|
||||||
tlsContextManager);
|
tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
new EnvoyServerProtoData.Listener(
|
new EnvoyServerProtoData.Listener(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue