mirror of https://github.com/grpc/grpc-java.git
xds: listener type validation (#11933)
This commit is contained in:
parent
84c7713b2f
commit
c8d1e6e39c
|
@ -22,6 +22,7 @@ import com.google.auto.value.AutoValue;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.protobuf.util.Durations;
|
import com.google.protobuf.util.Durations;
|
||||||
|
import io.envoyproxy.envoy.config.core.v3.SocketAddress.Protocol;
|
||||||
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.client.EnvoyProtoData;
|
import io.grpc.xds.client.EnvoyProtoData;
|
||||||
|
@ -248,13 +249,17 @@ public final class EnvoyServerProtoData {
|
||||||
@Nullable
|
@Nullable
|
||||||
abstract FilterChain defaultFilterChain();
|
abstract FilterChain defaultFilterChain();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
abstract Protocol protocol();
|
||||||
|
|
||||||
static Listener create(
|
static Listener create(
|
||||||
String name,
|
String name,
|
||||||
@Nullable String address,
|
@Nullable String address,
|
||||||
ImmutableList<FilterChain> filterChains,
|
ImmutableList<FilterChain> filterChains,
|
||||||
@Nullable FilterChain defaultFilterChain) {
|
@Nullable FilterChain defaultFilterChain,
|
||||||
|
@Nullable Protocol protocol) {
|
||||||
return new AutoValue_EnvoyServerProtoData_Listener(name, address, filterChains,
|
return new AutoValue_EnvoyServerProtoData_Listener(name, address, filterChains,
|
||||||
defaultFilterChain);
|
defaultFilterChain, protocol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,13 +162,16 @@ class XdsListenerResource extends XdsResourceType<LdsUpdate> {
|
||||||
}
|
}
|
||||||
|
|
||||||
String address = null;
|
String address = null;
|
||||||
|
SocketAddress socketAddress = null;
|
||||||
if (proto.getAddress().hasSocketAddress()) {
|
if (proto.getAddress().hasSocketAddress()) {
|
||||||
SocketAddress socketAddress = proto.getAddress().getSocketAddress();
|
socketAddress = proto.getAddress().getSocketAddress();
|
||||||
address = socketAddress.getAddress();
|
address = socketAddress.getAddress();
|
||||||
|
if (address.isEmpty()) {
|
||||||
|
throw new ResourceInvalidException("Invalid address: Empty address is not allowed.");
|
||||||
|
}
|
||||||
switch (socketAddress.getPortSpecifierCase()) {
|
switch (socketAddress.getPortSpecifierCase()) {
|
||||||
case NAMED_PORT:
|
case NAMED_PORT:
|
||||||
address = address + ":" + socketAddress.getNamedPort();
|
throw new ResourceInvalidException("NAMED_PORT is not supported in gRPC.");
|
||||||
break;
|
|
||||||
case PORT_VALUE:
|
case PORT_VALUE:
|
||||||
address = address + ":" + socketAddress.getPortValue();
|
address = address + ":" + socketAddress.getPortValue();
|
||||||
break;
|
break;
|
||||||
|
@ -209,8 +212,8 @@ class XdsListenerResource extends XdsResourceType<LdsUpdate> {
|
||||||
null, certProviderInstances, args);
|
null, certProviderInstances, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EnvoyServerProtoData.Listener.create(
|
return EnvoyServerProtoData.Listener.create(proto.getName(), address, filterChains.build(),
|
||||||
proto.getName(), address, filterChains.build(), defaultFilterChain);
|
defaultFilterChain, socketAddress == null ? null : socketAddress.getProtocol());
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
|
|
@ -684,6 +684,13 @@ final class XdsNameResolver extends NameResolver {
|
||||||
// Process Route
|
// Process Route
|
||||||
XdsConfig update = updateOrStatus.getValue();
|
XdsConfig update = updateOrStatus.getValue();
|
||||||
HttpConnectionManager httpConnectionManager = update.getListener().httpConnectionManager();
|
HttpConnectionManager httpConnectionManager = update.getListener().httpConnectionManager();
|
||||||
|
if (httpConnectionManager == null) {
|
||||||
|
logger.log(XdsLogLevel.INFO, "API Listener: httpConnectionManager does not exist.");
|
||||||
|
updateActiveFilters(null);
|
||||||
|
cleanUpRoutes(updateOrStatus.getStatus());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VirtualHost virtualHost = update.getVirtualHost();
|
VirtualHost virtualHost = update.getVirtualHost();
|
||||||
ImmutableList<NamedFilterConfig> filterConfigs = httpConnectionManager.httpFilterConfigs();
|
ImmutableList<NamedFilterConfig> filterConfigs = httpConnectionManager.httpFilterConfigs();
|
||||||
long streamDurationNano = httpConnectionManager.httpMaxStreamDurationNano();
|
long streamDurationNano = httpConnectionManager.httpMaxStreamDurationNano();
|
||||||
|
|
|
@ -24,7 +24,10 @@ import com.google.auto.value.AutoValue;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.net.HostAndPort;
|
||||||
|
import com.google.common.net.InetAddresses;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
|
import io.envoyproxy.envoy.config.core.v3.SocketAddress.Protocol;
|
||||||
import io.grpc.Attributes;
|
import io.grpc.Attributes;
|
||||||
import io.grpc.InternalServerInterceptors;
|
import io.grpc.InternalServerInterceptors;
|
||||||
import io.grpc.Metadata;
|
import io.grpc.Metadata;
|
||||||
|
@ -57,6 +60,7 @@ import io.grpc.xds.client.XdsClient;
|
||||||
import io.grpc.xds.client.XdsClient.ResourceWatcher;
|
import io.grpc.xds.client.XdsClient.ResourceWatcher;
|
||||||
import io.grpc.xds.internal.security.SslContextProviderSupplier;
|
import io.grpc.xds.internal.security.SslContextProviderSupplier;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -383,7 +387,21 @@ final class XdsServerWrapper extends Server {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.log(Level.FINEST, "Received Lds update {0}", update);
|
logger.log(Level.FINEST, "Received Lds update {0}", update);
|
||||||
checkNotNull(update.listener(), "update");
|
if (update.listener() == null) {
|
||||||
|
onResourceDoesNotExist("Non-API");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String ldsAddress = update.listener().address();
|
||||||
|
if (ldsAddress == null || update.listener().protocol() != Protocol.TCP
|
||||||
|
|| !ipAddressesMatch(ldsAddress)) {
|
||||||
|
handleConfigNotFoundOrMismatch(
|
||||||
|
Status.UNKNOWN.withDescription(
|
||||||
|
String.format(
|
||||||
|
"Listener address mismatch: expected %s, but got %s.",
|
||||||
|
listenerAddress, ldsAddress)).asException());
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!pendingRds.isEmpty()) {
|
if (!pendingRds.isEmpty()) {
|
||||||
// filter chain state has not yet been applied to filterChainSelectorManager and there
|
// filter chain state has not yet been applied to filterChainSelectorManager and there
|
||||||
// are two sets of sslContextProviderSuppliers, so we release the old ones.
|
// are two sets of sslContextProviderSuppliers, so we release the old ones.
|
||||||
|
@ -432,6 +450,18 @@ final class XdsServerWrapper extends Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean ipAddressesMatch(String ldsAddress) {
|
||||||
|
HostAndPort ldsAddressHnP = HostAndPort.fromString(ldsAddress);
|
||||||
|
HostAndPort listenerAddressHnP = HostAndPort.fromString(listenerAddress);
|
||||||
|
if (!ldsAddressHnP.hasPort() || !listenerAddressHnP.hasPort()
|
||||||
|
|| ldsAddressHnP.getPort() != listenerAddressHnP.getPort()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
InetAddress listenerIp = InetAddresses.forString(listenerAddressHnP.getHost());
|
||||||
|
InetAddress ldsIp = InetAddresses.forString(ldsAddressHnP.getHost());
|
||||||
|
return listenerIp.equals(ldsIp);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResourceDoesNotExist(final String resourceName) {
|
public void onResourceDoesNotExist(final String resourceName) {
|
||||||
if (stopped) {
|
if (stopped) {
|
||||||
|
@ -440,7 +470,7 @@ final class XdsServerWrapper extends Server {
|
||||||
StatusException statusException = Status.UNAVAILABLE.withDescription(
|
StatusException statusException = Status.UNAVAILABLE.withDescription(
|
||||||
String.format("Listener %s unavailable, xDS node ID: %s", resourceName,
|
String.format("Listener %s unavailable, xDS node ID: %s", resourceName,
|
||||||
xdsClient.getBootstrapInfo().node().getId())).asException();
|
xdsClient.getBootstrapInfo().node().getId())).asException();
|
||||||
handleConfigNotFound(statusException);
|
handleConfigNotFoundOrMismatch(statusException);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -674,7 +704,7 @@ final class XdsServerWrapper extends Server {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleConfigNotFound(StatusException exception) {
|
private void handleConfigNotFoundOrMismatch(StatusException exception) {
|
||||||
cleanUpRouteDiscoveryStates();
|
cleanUpRouteDiscoveryStates();
|
||||||
shutdownActiveFilters();
|
shutdownActiveFilters();
|
||||||
List<SslContextProviderSupplier> toRelease = getSuppliersInUse();
|
List<SslContextProviderSupplier> toRelease = getSuppliersInUse();
|
||||||
|
|
|
@ -366,10 +366,14 @@ public class ControlPlaneRule extends TestWatcher {
|
||||||
.setFilterChainMatch(filterChainMatch)
|
.setFilterChainMatch(filterChainMatch)
|
||||||
.addFilters(filter)
|
.addFilters(filter)
|
||||||
.build();
|
.build();
|
||||||
|
Address address = Address.newBuilder()
|
||||||
|
.setSocketAddress(SocketAddress.newBuilder().setAddress("0.0.0.0").setPortValue(0))
|
||||||
|
.build();
|
||||||
return Listener.newBuilder()
|
return Listener.newBuilder()
|
||||||
.setName(SERVER_LISTENER_TEMPLATE_NO_REPLACEMENT)
|
.setName(SERVER_LISTENER_TEMPLATE_NO_REPLACEMENT)
|
||||||
.setTrafficDirection(TrafficDirection.INBOUND)
|
.setTrafficDirection(TrafficDirection.INBOUND)
|
||||||
.addFilterChains(filterChain)
|
.addFilterChains(filterChain)
|
||||||
|
.setAddress(address)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2661,6 +2661,41 @@ public class GrpcXdsClientImplDataTest {
|
||||||
listener,null, filterRegistry, null, getXdsResourceTypeArgs(true));
|
listener,null, filterRegistry, null, getXdsResourceTypeArgs(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseServerSideListener_emptyAddress() throws ResourceInvalidException {
|
||||||
|
Listener listener =
|
||||||
|
Listener.newBuilder()
|
||||||
|
.setName("listener1")
|
||||||
|
.setTrafficDirection(TrafficDirection.INBOUND)
|
||||||
|
.setAddress(Address.newBuilder()
|
||||||
|
.setSocketAddress(
|
||||||
|
SocketAddress.newBuilder()))
|
||||||
|
.build();
|
||||||
|
thrown.expect(ResourceInvalidException.class);
|
||||||
|
thrown.expectMessage("Invalid address: Empty address is not allowed.");
|
||||||
|
|
||||||
|
XdsListenerResource.parseServerSideListener(
|
||||||
|
listener,null, filterRegistry, null, getXdsResourceTypeArgs(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseServerSideListener_namedPort() throws ResourceInvalidException {
|
||||||
|
Listener listener =
|
||||||
|
Listener.newBuilder()
|
||||||
|
.setName("listener1")
|
||||||
|
.setTrafficDirection(TrafficDirection.INBOUND)
|
||||||
|
.setAddress(Address.newBuilder()
|
||||||
|
.setSocketAddress(
|
||||||
|
SocketAddress.newBuilder()
|
||||||
|
.setAddress("172.14.14.5").setNamedPort("")))
|
||||||
|
.build();
|
||||||
|
thrown.expect(ResourceInvalidException.class);
|
||||||
|
thrown.expectMessage("NAMED_PORT is not supported in gRPC.");
|
||||||
|
|
||||||
|
XdsListenerResource.parseServerSideListener(
|
||||||
|
listener,null, filterRegistry, null, getXdsResourceTypeArgs(true));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseServerSideListener_nonUniqueFilterChainMatch() throws ResourceInvalidException {
|
public void parseServerSideListener_nonUniqueFilterChainMatch() throws ResourceInvalidException {
|
||||||
Filter filter1 = buildHttpConnectionManagerFilter(
|
Filter filter1 = buildHttpConnectionManagerFilter(
|
||||||
|
|
|
@ -32,6 +32,7 @@ import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
|
import io.envoyproxy.envoy.config.core.v3.SocketAddress.Protocol;
|
||||||
import io.grpc.Server;
|
import io.grpc.Server;
|
||||||
import io.grpc.ServerBuilder;
|
import io.grpc.ServerBuilder;
|
||||||
import io.grpc.Status;
|
import io.grpc.Status;
|
||||||
|
@ -165,9 +166,10 @@ public class XdsClientWrapperForServerSdsTestMisc {
|
||||||
EnvoyServerProtoData.Listener tcpListener =
|
EnvoyServerProtoData.Listener tcpListener =
|
||||||
EnvoyServerProtoData.Listener.create(
|
EnvoyServerProtoData.Listener.create(
|
||||||
"listener1",
|
"listener1",
|
||||||
"10.1.2.3",
|
"0.0.0.0:7000",
|
||||||
ImmutableList.of(),
|
ImmutableList.of(),
|
||||||
null);
|
null,
|
||||||
|
Protocol.TCP);
|
||||||
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(tcpListener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(tcpListener);
|
||||||
xdsClient.ldsWatcher.onChanged(listenerUpdate);
|
xdsClient.ldsWatcher.onChanged(listenerUpdate);
|
||||||
verify(listener, timeout(5000)).onServing();
|
verify(listener, timeout(5000)).onServing();
|
||||||
|
|
|
@ -35,6 +35,7 @@ import static org.junit.Assert.fail;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
|
import io.envoyproxy.envoy.config.core.v3.SocketAddress.Protocol;
|
||||||
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CertificateValidationContext;
|
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CertificateValidationContext;
|
||||||
import io.grpc.Attributes;
|
import io.grpc.Attributes;
|
||||||
import io.grpc.EquivalentAddressGroup;
|
import io.grpc.EquivalentAddressGroup;
|
||||||
|
@ -497,7 +498,7 @@ public class XdsSecurityClientServerTest {
|
||||||
DownstreamTlsContext downstreamTlsContext =
|
DownstreamTlsContext downstreamTlsContext =
|
||||||
CommonTlsContextTestsUtil.buildDownstreamTlsContext(
|
CommonTlsContextTestsUtil.buildDownstreamTlsContext(
|
||||||
"cert-instance-name2", true, true);
|
"cert-instance-name2", true, true);
|
||||||
EnvoyServerProtoData.Listener listener = buildListener("listener1", "0.0.0.0",
|
EnvoyServerProtoData.Listener listener = buildListener("listener1", "0.0.0.0:0",
|
||||||
downstreamTlsContext,
|
downstreamTlsContext,
|
||||||
tlsContextManagerForServer);
|
tlsContextManagerForServer);
|
||||||
xdsClient.deliverLdsUpdate(LdsUpdate.forTcpListener(listener));
|
xdsClient.deliverLdsUpdate(LdsUpdate.forTcpListener(listener));
|
||||||
|
@ -601,7 +602,7 @@ public class XdsSecurityClientServerTest {
|
||||||
tlsContextManagerForServer = new TlsContextManagerImpl(bootstrapInfoForServer);
|
tlsContextManagerForServer = new TlsContextManagerImpl(bootstrapInfoForServer);
|
||||||
XdsServerWrapper xdsServer = (XdsServerWrapper) builder.build();
|
XdsServerWrapper xdsServer = (XdsServerWrapper) builder.build();
|
||||||
SettableFuture<Throwable> startFuture = startServerAsync(xdsServer);
|
SettableFuture<Throwable> startFuture = startServerAsync(xdsServer);
|
||||||
EnvoyServerProtoData.Listener listener = buildListener("listener1", "10.1.2.3",
|
EnvoyServerProtoData.Listener listener = buildListener("listener1", "0.0.0.0:0",
|
||||||
downstreamTlsContext, tlsContextManagerForServer);
|
downstreamTlsContext, tlsContextManagerForServer);
|
||||||
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
xdsClient.deliverLdsUpdate(listenerUpdate);
|
xdsClient.deliverLdsUpdate(listenerUpdate);
|
||||||
|
@ -642,7 +643,7 @@ public class XdsSecurityClientServerTest {
|
||||||
"filter-chain-foo", filterChainMatch, httpConnectionManager, tlsContext,
|
"filter-chain-foo", filterChainMatch, httpConnectionManager, tlsContext,
|
||||||
tlsContextManager);
|
tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener = EnvoyServerProtoData.Listener.create(
|
EnvoyServerProtoData.Listener listener = EnvoyServerProtoData.Listener.create(
|
||||||
name, address, ImmutableList.of(defaultFilterChain), null);
|
name, address, ImmutableList.of(defaultFilterChain), null, Protocol.TCP);
|
||||||
return listener;
|
return listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package io.grpc.xds;
|
package io.grpc.xds;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static io.grpc.xds.XdsServerTestHelper.buildTestListener;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import static org.mockito.Mockito.any;
|
import static org.mockito.Mockito.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
@ -26,6 +27,7 @@ import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
import io.grpc.BindableService;
|
import io.grpc.BindableService;
|
||||||
import io.grpc.InsecureServerCredentials;
|
import io.grpc.InsecureServerCredentials;
|
||||||
|
@ -33,6 +35,7 @@ import io.grpc.ServerServiceDefinition;
|
||||||
import io.grpc.Status;
|
import io.grpc.Status;
|
||||||
import io.grpc.StatusException;
|
import io.grpc.StatusException;
|
||||||
import io.grpc.testing.GrpcCleanupRule;
|
import io.grpc.testing.GrpcCleanupRule;
|
||||||
|
import io.grpc.xds.XdsListenerResource.LdsUpdate;
|
||||||
import io.grpc.xds.XdsServerTestHelper.FakeXdsClient;
|
import io.grpc.xds.XdsServerTestHelper.FakeXdsClient;
|
||||||
import io.grpc.xds.XdsServerTestHelper.FakeXdsClientPoolFactory;
|
import io.grpc.xds.XdsServerTestHelper.FakeXdsClientPoolFactory;
|
||||||
import io.grpc.xds.internal.security.CommonTlsContextTestsUtil;
|
import io.grpc.xds.internal.security.CommonTlsContextTestsUtil;
|
||||||
|
@ -221,10 +224,13 @@ public class XdsServerBuilderTest {
|
||||||
buildServer(mockXdsServingStatusListener);
|
buildServer(mockXdsServingStatusListener);
|
||||||
Future<Throwable> future = startServerAsync();
|
Future<Throwable> future = startServerAsync();
|
||||||
// create port conflict for start to fail
|
// create port conflict for start to fail
|
||||||
XdsServerTestHelper.generateListenerUpdate(
|
EnvoyServerProtoData.Listener listener = buildTestListener(
|
||||||
xdsClient,
|
"listener1", "0.0.0.0:" + port, ImmutableList.of(),
|
||||||
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"),
|
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"),
|
||||||
tlsContextManager);
|
null, tlsContextManager);
|
||||||
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
|
xdsClient.deliverLdsUpdate(listenerUpdate);
|
||||||
|
|
||||||
Throwable exception = future.get(5, TimeUnit.SECONDS);
|
Throwable exception = future.get(5, TimeUnit.SECONDS);
|
||||||
assertThat(exception).isInstanceOf(IOException.class);
|
assertThat(exception).isInstanceOf(IOException.class);
|
||||||
assertThat(exception).hasMessageThat().contains("Failed to bind");
|
assertThat(exception).hasMessageThat().contains("Failed to bind");
|
||||||
|
|
|
@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
|
import io.envoyproxy.envoy.config.core.v3.SocketAddress.Protocol;
|
||||||
import io.grpc.InsecureChannelCredentials;
|
import io.grpc.InsecureChannelCredentials;
|
||||||
import io.grpc.MetricRecorder;
|
import io.grpc.MetricRecorder;
|
||||||
import io.grpc.internal.ObjectPool;
|
import io.grpc.internal.ObjectPool;
|
||||||
|
@ -74,7 +75,7 @@ public class XdsServerTestHelper {
|
||||||
static void generateListenerUpdate(FakeXdsClient xdsClient,
|
static void generateListenerUpdate(FakeXdsClient xdsClient,
|
||||||
EnvoyServerProtoData.DownstreamTlsContext tlsContext,
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext,
|
||||||
TlsContextManager tlsContextManager) {
|
TlsContextManager tlsContextManager) {
|
||||||
EnvoyServerProtoData.Listener listener = buildTestListener("listener1", "10.1.2.3",
|
EnvoyServerProtoData.Listener listener = buildTestListener("listener1", "0.0.0.0:0",
|
||||||
ImmutableList.of(), tlsContext, null, tlsContextManager);
|
ImmutableList.of(), tlsContext, null, tlsContextManager);
|
||||||
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
xdsClient.deliverLdsUpdate(listenerUpdate);
|
xdsClient.deliverLdsUpdate(listenerUpdate);
|
||||||
|
@ -85,7 +86,8 @@ public class XdsServerTestHelper {
|
||||||
EnvoyServerProtoData.DownstreamTlsContext tlsContext,
|
EnvoyServerProtoData.DownstreamTlsContext tlsContext,
|
||||||
EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain,
|
EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain,
|
||||||
TlsContextManager tlsContextManager) {
|
TlsContextManager tlsContextManager) {
|
||||||
EnvoyServerProtoData.Listener listener = buildTestListener("listener1", "10.1.2.3", sourcePorts,
|
EnvoyServerProtoData.Listener listener = buildTestListener(
|
||||||
|
"listener1", "0.0.0.0:7000", sourcePorts,
|
||||||
tlsContext, tlsContextForDefaultFilterChain, tlsContextManager);
|
tlsContext, tlsContextForDefaultFilterChain, tlsContextManager);
|
||||||
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(listener);
|
||||||
xdsClient.deliverLdsUpdate(listenerUpdate);
|
xdsClient.deliverLdsUpdate(listenerUpdate);
|
||||||
|
@ -130,7 +132,7 @@ public class XdsServerTestHelper {
|
||||||
tlsContextForDefaultFilterChain, tlsContextManager);
|
tlsContextForDefaultFilterChain, tlsContextManager);
|
||||||
EnvoyServerProtoData.Listener listener =
|
EnvoyServerProtoData.Listener listener =
|
||||||
EnvoyServerProtoData.Listener.create(
|
EnvoyServerProtoData.Listener.create(
|
||||||
name, address, ImmutableList.of(filterChain1), defaultFilterChain);
|
name, address, ImmutableList.of(filterChain1), defaultFilterChain, Protocol.TCP);
|
||||||
return listener;
|
return listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +292,14 @@ public class XdsServerTestHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void deliverLdsUpdateWithApiListener(long httpMaxStreamDurationNano,
|
||||||
|
List<VirtualHost> virtualHosts) {
|
||||||
|
execute(() -> {
|
||||||
|
ldsWatcher.onChanged(LdsUpdate.forApiListener(HttpConnectionManager.forVirtualHosts(
|
||||||
|
httpMaxStreamDurationNano, virtualHosts, null)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void deliverLdsUpdate(LdsUpdate ldsUpdate) {
|
void deliverLdsUpdate(LdsUpdate ldsUpdate) {
|
||||||
execute(() -> ldsWatcher.onChanged(ldsUpdate));
|
execute(() -> ldsWatcher.onChanged(ldsUpdate));
|
||||||
}
|
}
|
||||||
|
@ -297,8 +307,8 @@ public class XdsServerTestHelper {
|
||||||
void deliverLdsUpdate(
|
void deliverLdsUpdate(
|
||||||
List<FilterChain> filterChains,
|
List<FilterChain> filterChains,
|
||||||
@Nullable FilterChain defaultFilterChain) {
|
@Nullable FilterChain defaultFilterChain) {
|
||||||
deliverLdsUpdate(LdsUpdate.forTcpListener(Listener.create(
|
deliverLdsUpdate(LdsUpdate.forTcpListener(Listener.create("listener", "0.0.0.0:1",
|
||||||
"listener", "0.0.0.0:1", ImmutableList.copyOf(filterChains), defaultFilterChain)));
|
ImmutableList.copyOf(filterChains), defaultFilterChain, Protocol.TCP)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void deliverLdsUpdate(FilterChain filterChain, @Nullable FilterChain defaultFilterChain) {
|
void deliverLdsUpdate(FilterChain filterChain, @Nullable FilterChain defaultFilterChain) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.net.InetAddresses;
|
import com.google.common.net.InetAddresses;
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
|
import io.envoyproxy.envoy.config.core.v3.SocketAddress.Protocol;
|
||||||
import io.grpc.Attributes;
|
import io.grpc.Attributes;
|
||||||
import io.grpc.InsecureChannelCredentials;
|
import io.grpc.InsecureChannelCredentials;
|
||||||
import io.grpc.Metadata;
|
import io.grpc.Metadata;
|
||||||
|
@ -54,6 +55,7 @@ import io.grpc.testing.TestMethodDescriptors;
|
||||||
import io.grpc.xds.EnvoyServerProtoData.CidrRange;
|
import io.grpc.xds.EnvoyServerProtoData.CidrRange;
|
||||||
import io.grpc.xds.EnvoyServerProtoData.FilterChain;
|
import io.grpc.xds.EnvoyServerProtoData.FilterChain;
|
||||||
import io.grpc.xds.EnvoyServerProtoData.FilterChainMatch;
|
import io.grpc.xds.EnvoyServerProtoData.FilterChainMatch;
|
||||||
|
import io.grpc.xds.EnvoyServerProtoData.Listener;
|
||||||
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.FilterChainMatchingProtocolNegotiators.FilterChainMatchingHandler.FilterChainSelector;
|
import io.grpc.xds.FilterChainMatchingProtocolNegotiators.FilterChainMatchingHandler.FilterChainSelector;
|
||||||
|
@ -61,6 +63,7 @@ import io.grpc.xds.StatefulFilter.Config;
|
||||||
import io.grpc.xds.VirtualHost.Route;
|
import io.grpc.xds.VirtualHost.Route;
|
||||||
import io.grpc.xds.VirtualHost.Route.RouteMatch;
|
import io.grpc.xds.VirtualHost.Route.RouteMatch;
|
||||||
import io.grpc.xds.VirtualHost.Route.RouteMatch.PathMatcher;
|
import io.grpc.xds.VirtualHost.Route.RouteMatch.PathMatcher;
|
||||||
|
import io.grpc.xds.XdsListenerResource.LdsUpdate;
|
||||||
import io.grpc.xds.XdsRouteConfigureResource.RdsUpdate;
|
import io.grpc.xds.XdsRouteConfigureResource.RdsUpdate;
|
||||||
import io.grpc.xds.XdsServerBuilder.XdsServingStatusListener;
|
import io.grpc.xds.XdsServerBuilder.XdsServingStatusListener;
|
||||||
import io.grpc.xds.XdsServerTestHelper.FakeXdsClient;
|
import io.grpc.xds.XdsServerTestHelper.FakeXdsClient;
|
||||||
|
@ -538,6 +541,146 @@ public class XdsServerWrapperTest {
|
||||||
verify(mockServer).start();
|
verify(mockServer).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onChanged_listenerIsNull()
|
||||||
|
throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
|
xdsServerWrapper = new XdsServerWrapper("10.1.2.3:1", mockBuilder, listener,
|
||||||
|
selectorManager, new FakeXdsClientPoolFactory(xdsClient),
|
||||||
|
filterRegistry, executor.getScheduledExecutorService());
|
||||||
|
final SettableFuture<Server> start = SettableFuture.create();
|
||||||
|
Executors.newSingleThreadExecutor().execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
start.set(xdsServerWrapper.start());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
start.setException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
String ldsResource = xdsClient.ldsResource.get(5, TimeUnit.SECONDS);
|
||||||
|
assertThat(ldsResource).isEqualTo("grpc/server?udpa.resource.listening_address=10.1.2.3:1");
|
||||||
|
VirtualHost virtualHost =
|
||||||
|
VirtualHost.create(
|
||||||
|
"virtual-host", Collections.singletonList("auth"), new ArrayList<Route>(),
|
||||||
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
|
|
||||||
|
xdsClient.deliverLdsUpdateWithApiListener(0L, Arrays.asList(virtualHost));
|
||||||
|
|
||||||
|
verify(listener, timeout(10000)).onNotServing(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onChanged_listenerAddressMissingPort()
|
||||||
|
throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
|
xdsServerWrapper = new XdsServerWrapper("10.1.2.3:1", mockBuilder, listener,
|
||||||
|
selectorManager, new FakeXdsClientPoolFactory(xdsClient),
|
||||||
|
filterRegistry, executor.getScheduledExecutorService());
|
||||||
|
final SettableFuture<Server> start = SettableFuture.create();
|
||||||
|
Executors.newSingleThreadExecutor().execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
start.set(xdsServerWrapper.start());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
start.setException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
String ldsResource = xdsClient.ldsResource.get(5, TimeUnit.SECONDS);
|
||||||
|
assertThat(ldsResource).isEqualTo("grpc/server?udpa.resource.listening_address=10.1.2.3:1");
|
||||||
|
VirtualHost virtualHost =
|
||||||
|
VirtualHost.create(
|
||||||
|
"virtual-host", Collections.singletonList("auth"), new ArrayList<Route>(),
|
||||||
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
|
HttpConnectionManager httpConnectionManager = HttpConnectionManager.forVirtualHosts(
|
||||||
|
0L, Collections.singletonList(virtualHost), new ArrayList<NamedFilterConfig>());
|
||||||
|
EnvoyServerProtoData.FilterChain filterChain = EnvoyServerProtoData.FilterChain.create(
|
||||||
|
"filter-chain-foo", createMatch(), httpConnectionManager, createTls(),
|
||||||
|
mock(TlsContextManager.class));
|
||||||
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(
|
||||||
|
Listener.create("listener", "20.3.4.5:",
|
||||||
|
ImmutableList.copyOf(Collections.singletonList(filterChain)), null, Protocol.TCP));
|
||||||
|
|
||||||
|
xdsClient.deliverLdsUpdate(listenerUpdate);
|
||||||
|
|
||||||
|
verify(listener, timeout(10000)).onNotServing(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onChanged_listenerAddressMismatch()
|
||||||
|
throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
|
xdsServerWrapper = new XdsServerWrapper("10.1.2.3:1", mockBuilder, listener,
|
||||||
|
selectorManager, new FakeXdsClientPoolFactory(xdsClient),
|
||||||
|
filterRegistry, executor.getScheduledExecutorService());
|
||||||
|
final SettableFuture<Server> start = SettableFuture.create();
|
||||||
|
Executors.newSingleThreadExecutor().execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
start.set(xdsServerWrapper.start());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
start.setException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
String ldsResource = xdsClient.ldsResource.get(5, TimeUnit.SECONDS);
|
||||||
|
assertThat(ldsResource).isEqualTo("grpc/server?udpa.resource.listening_address=10.1.2.3:1");
|
||||||
|
VirtualHost virtualHost =
|
||||||
|
VirtualHost.create(
|
||||||
|
"virtual-host", Collections.singletonList("auth"), new ArrayList<Route>(),
|
||||||
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
|
HttpConnectionManager httpConnectionManager = HttpConnectionManager.forVirtualHosts(
|
||||||
|
0L, Collections.singletonList(virtualHost), new ArrayList<NamedFilterConfig>());
|
||||||
|
EnvoyServerProtoData.FilterChain filterChain = EnvoyServerProtoData.FilterChain.create(
|
||||||
|
"filter-chain-foo", createMatch(), httpConnectionManager, createTls(),
|
||||||
|
mock(TlsContextManager.class));
|
||||||
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(
|
||||||
|
Listener.create("listener", "20.3.4.5:1",
|
||||||
|
ImmutableList.copyOf(Collections.singletonList(filterChain)), null, Protocol.TCP));
|
||||||
|
|
||||||
|
xdsClient.deliverLdsUpdate(listenerUpdate);
|
||||||
|
|
||||||
|
verify(listener, timeout(10000)).onNotServing(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onChanged_listenerAddressPortMismatch()
|
||||||
|
throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
|
xdsServerWrapper = new XdsServerWrapper("10.1.2.3:1", mockBuilder, listener,
|
||||||
|
selectorManager, new FakeXdsClientPoolFactory(xdsClient),
|
||||||
|
filterRegistry, executor.getScheduledExecutorService());
|
||||||
|
final SettableFuture<Server> start = SettableFuture.create();
|
||||||
|
Executors.newSingleThreadExecutor().execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
start.set(xdsServerWrapper.start());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
start.setException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
String ldsResource = xdsClient.ldsResource.get(5, TimeUnit.SECONDS);
|
||||||
|
assertThat(ldsResource).isEqualTo("grpc/server?udpa.resource.listening_address=10.1.2.3:1");
|
||||||
|
VirtualHost virtualHost =
|
||||||
|
VirtualHost.create(
|
||||||
|
"virtual-host", Collections.singletonList("auth"), new ArrayList<Route>(),
|
||||||
|
ImmutableMap.<String, FilterConfig>of());
|
||||||
|
HttpConnectionManager httpConnectionManager = HttpConnectionManager.forVirtualHosts(
|
||||||
|
0L, Collections.singletonList(virtualHost), new ArrayList<NamedFilterConfig>());
|
||||||
|
EnvoyServerProtoData.FilterChain filterChain = EnvoyServerProtoData.FilterChain.create(
|
||||||
|
"filter-chain-foo", createMatch(), httpConnectionManager, createTls(),
|
||||||
|
mock(TlsContextManager.class));
|
||||||
|
LdsUpdate listenerUpdate = LdsUpdate.forTcpListener(
|
||||||
|
Listener.create("listener", "10.1.2.3:2",
|
||||||
|
ImmutableList.copyOf(Collections.singletonList(filterChain)), null, Protocol.TCP));
|
||||||
|
|
||||||
|
xdsClient.deliverLdsUpdate(listenerUpdate);
|
||||||
|
|
||||||
|
verify(listener, timeout(10000)).onNotServing(any());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void discoverState_rds() throws Exception {
|
public void discoverState_rds() throws Exception {
|
||||||
final SettableFuture<Server> start = SettableFuture.create();
|
final SettableFuture<Server> start = SettableFuture.create();
|
||||||
|
@ -1811,7 +1954,7 @@ public class XdsServerWrapperTest {
|
||||||
/**
|
/**
|
||||||
* Returns the least-specific match-all Filter Chain Match.
|
* Returns the least-specific match-all Filter Chain Match.
|
||||||
*/
|
*/
|
||||||
private static FilterChainMatch createMatch() {
|
static FilterChainMatch createMatch() {
|
||||||
return FilterChainMatch.create(
|
return FilterChainMatch.create(
|
||||||
0,
|
0,
|
||||||
ImmutableList.of(),
|
ImmutableList.of(),
|
||||||
|
@ -1867,7 +2010,7 @@ public class XdsServerWrapperTest {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EnvoyServerProtoData.DownstreamTlsContext createTls() {
|
static EnvoyServerProtoData.DownstreamTlsContext createTls() {
|
||||||
return CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
return CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue