mirror of https://github.com/grpc/grpc-java.git
core: enhance ManagedChannelBuilder.overrideAuthority()
Enhance `ManagedChannelBuilder.overrideAuthority()` to make it impossible to use a different authority to a backend by wrapping ClientTransportFactory.newClientTransport() and setting ClientTransportOptions’ authority. To avoid confusing the LB policy, it would need to keep the original addresses to return during `Subchannel.getAddresses()` The class `OverrideAuthorityNameResolverFactory` is deleted and its logic is moved into `ManagedChannelImpl`.
This commit is contained in:
parent
64676198c5
commit
9437783838
|
|
@ -37,6 +37,9 @@ public final class EquivalentAddressGroup {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The authority to be used when constructing Subchannels for this EquivalentAddressGroup.
|
* The authority to be used when constructing Subchannels for this EquivalentAddressGroup.
|
||||||
|
* However, if the channel has overridden authority via
|
||||||
|
* {@link ManagedChannelBuilder#overrideAuthority(String)}, the transport will use the channel's
|
||||||
|
* authority override.
|
||||||
*/
|
*/
|
||||||
@Attr
|
@Attr
|
||||||
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/6138")
|
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/6138")
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,9 @@ public abstract class ManagedChannelBuilder<T extends ManagedChannelBuilder<T>>
|
||||||
* Overrides the authority used with TLS and HTTP virtual hosting. It does not change what host is
|
* Overrides the authority used with TLS and HTTP virtual hosting. It does not change what host is
|
||||||
* actually connected to. Is commonly in the form {@code host:port}.
|
* actually connected to. Is commonly in the form {@code host:port}.
|
||||||
*
|
*
|
||||||
|
* <p>If the channel builder overrides authority, any authority override from name resolution
|
||||||
|
* result (via {@link EquivalentAddressGroup#ATTR_AUTHORITY_OVERRIDE}) will be discarded.
|
||||||
|
*
|
||||||
* <p>This method is intended for testing, but may safely be used outside of tests as an
|
* <p>This method is intended for testing, but may safely be used outside of tests as an
|
||||||
* alternative to DNS overrides.
|
* alternative to DNS overrides.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkState;
|
||||||
import static io.grpc.ConnectivityState.IDLE;
|
import static io.grpc.ConnectivityState.IDLE;
|
||||||
import static io.grpc.ConnectivityState.SHUTDOWN;
|
import static io.grpc.ConnectivityState.SHUTDOWN;
|
||||||
import static io.grpc.ConnectivityState.TRANSIENT_FAILURE;
|
import static io.grpc.ConnectivityState.TRANSIENT_FAILURE;
|
||||||
|
import static io.grpc.EquivalentAddressGroup.ATTR_AUTHORITY_OVERRIDE;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
|
|
@ -152,6 +153,8 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
||||||
|
|
||||||
private final InternalLogId logId;
|
private final InternalLogId logId;
|
||||||
private final String target;
|
private final String target;
|
||||||
|
@Nullable
|
||||||
|
private final String authorityOverride;
|
||||||
private final NameResolverRegistry nameResolverRegistry;
|
private final NameResolverRegistry nameResolverRegistry;
|
||||||
private final NameResolver.Factory nameResolverFactory;
|
private final NameResolver.Factory nameResolverFactory;
|
||||||
private final NameResolver.Args nameResolverArgs;
|
private final NameResolver.Args nameResolverArgs;
|
||||||
|
|
@ -361,7 +364,8 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
||||||
nameResolver.shutdown();
|
nameResolver.shutdown();
|
||||||
nameResolverStarted = false;
|
nameResolverStarted = false;
|
||||||
if (channelIsActive) {
|
if (channelIsActive) {
|
||||||
nameResolver = getNameResolver(target, nameResolverFactory, nameResolverArgs);
|
nameResolver = getNameResolver(
|
||||||
|
target, authorityOverride, nameResolverFactory, nameResolverArgs);
|
||||||
} else {
|
} else {
|
||||||
nameResolver = null;
|
nameResolver = null;
|
||||||
}
|
}
|
||||||
|
|
@ -612,7 +616,6 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
||||||
logId, builder.maxTraceEvents, timeProvider.currentTimeNanos(),
|
logId, builder.maxTraceEvents, timeProvider.currentTimeNanos(),
|
||||||
"Channel for '" + target + "'");
|
"Channel for '" + target + "'");
|
||||||
channelLogger = new ChannelLoggerImpl(channelTracer, timeProvider);
|
channelLogger = new ChannelLoggerImpl(channelTracer, timeProvider);
|
||||||
this.nameResolverFactory = builder.getNameResolverFactory();
|
|
||||||
ProxyDetector proxyDetector =
|
ProxyDetector proxyDetector =
|
||||||
builder.proxyDetector != null ? builder.proxyDetector : GrpcUtil.DEFAULT_PROXY_DETECTOR;
|
builder.proxyDetector != null ? builder.proxyDetector : GrpcUtil.DEFAULT_PROXY_DETECTOR;
|
||||||
this.retryEnabled = builder.retryEnabled && !builder.temporarilyDisableRetry;
|
this.retryEnabled = builder.retryEnabled && !builder.temporarilyDisableRetry;
|
||||||
|
|
@ -644,7 +647,10 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
this.nameResolver = getNameResolver(target, nameResolverFactory, nameResolverArgs);
|
this.authorityOverride = builder.authorityOverride;
|
||||||
|
this.nameResolverFactory = builder.nameResolverFactory;
|
||||||
|
this.nameResolver = getNameResolver(
|
||||||
|
target, authorityOverride, nameResolverFactory, nameResolverArgs);
|
||||||
this.balancerRpcExecutorPool = checkNotNull(balancerRpcExecutorPool, "balancerRpcExecutorPool");
|
this.balancerRpcExecutorPool = checkNotNull(balancerRpcExecutorPool, "balancerRpcExecutorPool");
|
||||||
this.balancerRpcExecutorHolder = new ExecutorHolder(balancerRpcExecutorPool);
|
this.balancerRpcExecutorHolder = new ExecutorHolder(balancerRpcExecutorPool);
|
||||||
this.delayedTransport = new DelayedClientTransport(this.executor, this.syncContext);
|
this.delayedTransport = new DelayedClientTransport(this.executor, this.syncContext);
|
||||||
|
|
@ -715,9 +721,8 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
private static NameResolver getNameResolver(
|
||||||
static NameResolver getNameResolver(String target, NameResolver.Factory nameResolverFactory,
|
String target, NameResolver.Factory nameResolverFactory, NameResolver.Args nameResolverArgs) {
|
||||||
NameResolver.Args nameResolverArgs) {
|
|
||||||
// Finding a NameResolver. Try using the target string as the URI. If that fails, try prepending
|
// Finding a NameResolver. Try using the target string as the URI. If that fails, try prepending
|
||||||
// "dns:///".
|
// "dns:///".
|
||||||
URI targetUri = null;
|
URI targetUri = null;
|
||||||
|
|
@ -760,6 +765,22 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
||||||
target, uriSyntaxErrors.length() > 0 ? " (" + uriSyntaxErrors + ")" : ""));
|
target, uriSyntaxErrors.length() > 0 ? " (" + uriSyntaxErrors + ")" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static NameResolver getNameResolver(
|
||||||
|
String target, @Nullable final String overrideAuthority,
|
||||||
|
NameResolver.Factory nameResolverFactory, NameResolver.Args nameResolverArgs) {
|
||||||
|
NameResolver resolver = getNameResolver(target, nameResolverFactory, nameResolverArgs);
|
||||||
|
if (overrideAuthority == null) {
|
||||||
|
return resolver;
|
||||||
|
}
|
||||||
|
return new ForwardingNameResolver(resolver) {
|
||||||
|
@Override
|
||||||
|
public String getServiceAuthority() {
|
||||||
|
return overrideAuthority;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
InternalConfigSelector getConfigSelector() {
|
InternalConfigSelector getConfigSelector() {
|
||||||
return realChannel.configSelector.get();
|
return realChannel.configSelector.get();
|
||||||
|
|
@ -1850,12 +1871,19 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
||||||
final InternalLogId subchannelLogId;
|
final InternalLogId subchannelLogId;
|
||||||
final ChannelLoggerImpl subchannelLogger;
|
final ChannelLoggerImpl subchannelLogger;
|
||||||
final ChannelTracer subchannelTracer;
|
final ChannelTracer subchannelTracer;
|
||||||
|
List<EquivalentAddressGroup> addressGroups;
|
||||||
InternalSubchannel subchannel;
|
InternalSubchannel subchannel;
|
||||||
boolean started;
|
boolean started;
|
||||||
boolean shutdown;
|
boolean shutdown;
|
||||||
ScheduledHandle delayedShutdownTask;
|
ScheduledHandle delayedShutdownTask;
|
||||||
|
|
||||||
SubchannelImpl(CreateSubchannelArgs args, LbHelperImpl helper) {
|
SubchannelImpl(CreateSubchannelArgs args, LbHelperImpl helper) {
|
||||||
|
addressGroups = args.getAddresses();
|
||||||
|
if (authorityOverride != null) {
|
||||||
|
List<EquivalentAddressGroup> eagsWithoutOverrideAttr =
|
||||||
|
stripOverrideAuthorityAttributes(args.getAddresses());
|
||||||
|
args = args.toBuilder().setAddresses(eagsWithoutOverrideAttr).build();
|
||||||
|
}
|
||||||
this.args = checkNotNull(args, "args");
|
this.args = checkNotNull(args, "args");
|
||||||
this.helper = checkNotNull(helper, "helper");
|
this.helper = checkNotNull(helper, "helper");
|
||||||
subchannelLogId = InternalLogId.allocate("Subchannel", /*details=*/ authority());
|
subchannelLogId = InternalLogId.allocate("Subchannel", /*details=*/ authority());
|
||||||
|
|
@ -1992,7 +2020,7 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
||||||
public List<EquivalentAddressGroup> getAllAddresses() {
|
public List<EquivalentAddressGroup> getAllAddresses() {
|
||||||
syncContext.throwIfNotInThisSynchronizationContext();
|
syncContext.throwIfNotInThisSynchronizationContext();
|
||||||
checkState(started, "not started");
|
checkState(started, "not started");
|
||||||
return subchannel.getAddressGroups();
|
return addressGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -2029,8 +2057,24 @@ final class ManagedChannelImpl extends ManagedChannel implements
|
||||||
@Override
|
@Override
|
||||||
public void updateAddresses(List<EquivalentAddressGroup> addrs) {
|
public void updateAddresses(List<EquivalentAddressGroup> addrs) {
|
||||||
syncContext.throwIfNotInThisSynchronizationContext();
|
syncContext.throwIfNotInThisSynchronizationContext();
|
||||||
|
addressGroups = addrs;
|
||||||
|
if (authorityOverride != null) {
|
||||||
|
addrs = stripOverrideAuthorityAttributes(addrs);
|
||||||
|
}
|
||||||
subchannel.updateAddresses(addrs);
|
subchannel.updateAddresses(addrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<EquivalentAddressGroup> stripOverrideAuthorityAttributes(
|
||||||
|
List<EquivalentAddressGroup> eags) {
|
||||||
|
List<EquivalentAddressGroup> eagsWithoutOverrideAttr = new ArrayList<>();
|
||||||
|
for (EquivalentAddressGroup eag : eags) {
|
||||||
|
EquivalentAddressGroup eagWithoutOverrideAttr = new EquivalentAddressGroup(
|
||||||
|
eag.getAddresses(),
|
||||||
|
eag.getAttributes().toBuilder().discard(ATTR_AUTHORITY_OVERRIDE).build());
|
||||||
|
eagsWithoutOverrideAttr.add(eagWithoutOverrideAttr);
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(eagsWithoutOverrideAttr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ public final class ManagedChannelImplBuilder
|
||||||
final NameResolverRegistry nameResolverRegistry = NameResolverRegistry.getDefaultRegistry();
|
final NameResolverRegistry nameResolverRegistry = NameResolverRegistry.getDefaultRegistry();
|
||||||
|
|
||||||
// Access via getter, which may perform authority override as needed
|
// Access via getter, which may perform authority override as needed
|
||||||
private NameResolver.Factory nameResolverFactory = nameResolverRegistry.asFactory();
|
NameResolver.Factory nameResolverFactory = nameResolverRegistry.asFactory();
|
||||||
|
|
||||||
final String target;
|
final String target;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
@ -123,7 +123,7 @@ public final class ManagedChannelImplBuilder
|
||||||
String userAgent;
|
String userAgent;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private String authorityOverride;
|
String authorityOverride;
|
||||||
|
|
||||||
String defaultLbPolicy = GrpcUtil.DEFAULT_LB_POLICY;
|
String defaultLbPolicy = GrpcUtil.DEFAULT_LB_POLICY;
|
||||||
|
|
||||||
|
|
@ -393,12 +393,6 @@ public final class ManagedChannelImplBuilder
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@VisibleForTesting
|
|
||||||
String getOverrideAuthority() {
|
|
||||||
return authorityOverride;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ManagedChannelImplBuilder idleTimeout(long value, TimeUnit unit) {
|
public ManagedChannelImplBuilder idleTimeout(long value, TimeUnit unit) {
|
||||||
checkArgument(value > 0, "idle timeout is %s, but must be positive", value);
|
checkArgument(value > 0, "idle timeout is %s, but must be positive", value);
|
||||||
|
|
@ -699,17 +693,6 @@ public final class ManagedChannelImplBuilder
|
||||||
return channelBuilderDefaultPortProvider.getDefaultPort();
|
return channelBuilderDefaultPortProvider.getDefaultPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a {@link NameResolver.Factory} for the channel.
|
|
||||||
*/
|
|
||||||
NameResolver.Factory getNameResolverFactory() {
|
|
||||||
if (authorityOverride == null) {
|
|
||||||
return nameResolverFactory;
|
|
||||||
} else {
|
|
||||||
return new OverrideAuthorityNameResolverFactory(nameResolverFactory, authorityOverride);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class DirectAddressNameResolverFactory extends NameResolver.Factory {
|
private static class DirectAddressNameResolverFactory extends NameResolver.Factory {
|
||||||
final SocketAddress address;
|
final SocketAddress address;
|
||||||
final String authority;
|
final String authority;
|
||||||
|
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2017 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.internal;
|
|
||||||
|
|
||||||
import io.grpc.NameResolver;
|
|
||||||
import java.net.URI;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper class that overrides the authority of a NameResolver, while preserving all other
|
|
||||||
* functionality.
|
|
||||||
*/
|
|
||||||
final class OverrideAuthorityNameResolverFactory extends NameResolver.Factory {
|
|
||||||
private final NameResolver.Factory delegate;
|
|
||||||
private final String authorityOverride;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for the {@link NameResolver.Factory}
|
|
||||||
*
|
|
||||||
* @param delegate The actual underlying factory that will produce the a {@link NameResolver}
|
|
||||||
* @param authorityOverride The authority that will be returned by {@link
|
|
||||||
* NameResolver#getServiceAuthority()}
|
|
||||||
*/
|
|
||||||
OverrideAuthorityNameResolverFactory(NameResolver.Factory delegate, String authorityOverride) {
|
|
||||||
this.delegate = delegate;
|
|
||||||
this.authorityOverride = authorityOverride;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
|
|
||||||
final NameResolver resolver = delegate.newNameResolver(targetUri, args);
|
|
||||||
// Do not wrap null values. We do not want to impede error signaling.
|
|
||||||
if (resolver == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new ForwardingNameResolver(resolver) {
|
|
||||||
@Override
|
|
||||||
public String getServiceAuthority() {
|
|
||||||
return authorityOverride;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDefaultScheme() {
|
|
||||||
return delegate.getDefaultScheme();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -180,7 +180,7 @@ public class ManagedChannelImplBuilderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nameResolverFactory_default() {
|
public void nameResolverFactory_default() {
|
||||||
assertNotNull(builder.getNameResolverFactory());
|
assertNotNull(builder.nameResolverFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -188,16 +188,16 @@ public class ManagedChannelImplBuilderTest {
|
||||||
public void nameResolverFactory_normal() {
|
public void nameResolverFactory_normal() {
|
||||||
NameResolver.Factory nameResolverFactory = mock(NameResolver.Factory.class);
|
NameResolver.Factory nameResolverFactory = mock(NameResolver.Factory.class);
|
||||||
assertEquals(builder, builder.nameResolverFactory(nameResolverFactory));
|
assertEquals(builder, builder.nameResolverFactory(nameResolverFactory));
|
||||||
assertEquals(nameResolverFactory, builder.getNameResolverFactory());
|
assertEquals(nameResolverFactory, builder.nameResolverFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public void nameResolverFactory_null() {
|
public void nameResolverFactory_null() {
|
||||||
NameResolver.Factory defaultValue = builder.getNameResolverFactory();
|
NameResolver.Factory defaultValue = builder.nameResolverFactory;
|
||||||
builder.nameResolverFactory(mock(NameResolver.Factory.class));
|
builder.nameResolverFactory(mock(NameResolver.Factory.class));
|
||||||
assertEquals(builder, builder.nameResolverFactory(null));
|
assertEquals(builder, builder.nameResolverFactory(null));
|
||||||
assertEquals(defaultValue, builder.getNameResolverFactory());
|
assertEquals(defaultValue, builder.nameResolverFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
|
|
@ -334,14 +334,14 @@ public class ManagedChannelImplBuilderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void overrideAuthority_default() {
|
public void overrideAuthority_default() {
|
||||||
assertNull(builder.getOverrideAuthority());
|
assertNull(builder.authorityOverride);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void overrideAuthority_normal() {
|
public void overrideAuthority_normal() {
|
||||||
String overrideAuthority = "best-authority";
|
String overrideAuthority = "best-authority";
|
||||||
assertEquals(builder, builder.overrideAuthority(overrideAuthority));
|
assertEquals(builder, builder.overrideAuthority(overrideAuthority));
|
||||||
assertEquals(overrideAuthority, builder.getOverrideAuthority());
|
assertEquals(overrideAuthority, builder.authorityOverride);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
@Test(expected = NullPointerException.class)
|
||||||
|
|
@ -354,14 +354,6 @@ public class ManagedChannelImplBuilderTest {
|
||||||
builder.overrideAuthority("not_allowed");
|
builder.overrideAuthority("not_allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void overrideAuthority_getNameResolverFactory() {
|
|
||||||
assertNull(builder.getOverrideAuthority());
|
|
||||||
assertFalse(builder.getNameResolverFactory() instanceof OverrideAuthorityNameResolverFactory);
|
|
||||||
builder.overrideAuthority("google.com");
|
|
||||||
assertTrue(builder.getNameResolverFactory() instanceof OverrideAuthorityNameResolverFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void checkAuthority_validAuthorityAllowed() {
|
public void checkAuthority_validAuthorityAllowed() {
|
||||||
assertEquals(DUMMY_AUTHORITY_VALID, builder.checkAuthority(DUMMY_AUTHORITY_VALID));
|
assertEquals(DUMMY_AUTHORITY_VALID, builder.checkAuthority(DUMMY_AUTHORITY_VALID));
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package io.grpc.internal;
|
package io.grpc.internal;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
@ -32,7 +33,8 @@ import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.JUnit4;
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
/** Unit tests for {@link ManagedChannelImpl#getNameResolver}. */
|
/** Unit tests for {@link ManagedChannelImpl#getNameResolver(
|
||||||
|
* String, String,NameResolver.Factory, NameResolver.Args)}. */
|
||||||
@RunWith(JUnit4.class)
|
@RunWith(JUnit4.class)
|
||||||
public class ManagedChannelImplGetNameResolverTest {
|
public class ManagedChannelImplGetNameResolverTest {
|
||||||
private static final NameResolver.Args NAMERESOLVER_ARGS = NameResolver.Args.newBuilder()
|
private static final NameResolver.Args NAMERESOLVER_ARGS = NameResolver.Args.newBuilder()
|
||||||
|
|
@ -60,6 +62,17 @@ public class ManagedChannelImplGetNameResolverTest {
|
||||||
new URI("defaultscheme", "", "/foo.googleapis.com:8080", null));
|
new URI("defaultscheme", "", "/foo.googleapis.com:8080", null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void validAuthorityTarget_overrideAuthority() throws Exception {
|
||||||
|
String target = "foo.googleapis.com:8080";
|
||||||
|
String overrideAuthority = "override.authority";
|
||||||
|
URI expectedUri = new URI("defaultscheme", "", "/foo.googleapis.com:8080", null);
|
||||||
|
NameResolver.Factory nameResolverFactory = new FakeNameResolverFactory(expectedUri.getScheme());
|
||||||
|
NameResolver nameResolver = ManagedChannelImpl.getNameResolver(
|
||||||
|
target, overrideAuthority, nameResolverFactory, NAMERESOLVER_ARGS);
|
||||||
|
assertThat(nameResolver.getServiceAuthority()).isEqualTo(overrideAuthority);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validUriTarget() throws Exception {
|
public void validUriTarget() throws Exception {
|
||||||
testValidTarget("scheme:///foo.googleapis.com:8080", "scheme:///foo.googleapis.com:8080",
|
testValidTarget("scheme:///foo.googleapis.com:8080", "scheme:///foo.googleapis.com:8080",
|
||||||
|
|
@ -116,7 +129,7 @@ public class ManagedChannelImplGetNameResolverTest {
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
ManagedChannelImpl.getNameResolver(
|
ManagedChannelImpl.getNameResolver(
|
||||||
"foo.googleapis.com:8080", nameResolverFactory, NAMERESOLVER_ARGS);
|
"foo.googleapis.com:8080", null, nameResolverFactory, NAMERESOLVER_ARGS);
|
||||||
fail("Should fail");
|
fail("Should fail");
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// expected
|
// expected
|
||||||
|
|
@ -126,7 +139,7 @@ public class ManagedChannelImplGetNameResolverTest {
|
||||||
private void testValidTarget(String target, String expectedUriString, URI expectedUri) {
|
private void testValidTarget(String target, String expectedUriString, URI expectedUri) {
|
||||||
NameResolver.Factory nameResolverFactory = new FakeNameResolverFactory(expectedUri.getScheme());
|
NameResolver.Factory nameResolverFactory = new FakeNameResolverFactory(expectedUri.getScheme());
|
||||||
FakeNameResolver nameResolver = (FakeNameResolver) ManagedChannelImpl.getNameResolver(
|
FakeNameResolver nameResolver = (FakeNameResolver) ManagedChannelImpl.getNameResolver(
|
||||||
target, nameResolverFactory, NAMERESOLVER_ARGS);
|
target, null, nameResolverFactory, NAMERESOLVER_ARGS);
|
||||||
assertNotNull(nameResolver);
|
assertNotNull(nameResolver);
|
||||||
assertEquals(expectedUri, nameResolver.uri);
|
assertEquals(expectedUri, nameResolver.uri);
|
||||||
assertEquals(expectedUriString, nameResolver.uri.toString());
|
assertEquals(expectedUriString, nameResolver.uri.toString());
|
||||||
|
|
@ -137,7 +150,7 @@ public class ManagedChannelImplGetNameResolverTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FakeNameResolver nameResolver = (FakeNameResolver) ManagedChannelImpl.getNameResolver(
|
FakeNameResolver nameResolver = (FakeNameResolver) ManagedChannelImpl.getNameResolver(
|
||||||
target, nameResolverFactory, NAMERESOLVER_ARGS);
|
target, null, nameResolverFactory, NAMERESOLVER_ARGS);
|
||||||
fail("Should have failed, but got resolver with " + nameResolver.uri);
|
fail("Should have failed, but got resolver with " + nameResolver.uri);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// expected
|
// expected
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import static io.grpc.ConnectivityState.IDLE;
|
||||||
import static io.grpc.ConnectivityState.READY;
|
import static io.grpc.ConnectivityState.READY;
|
||||||
import static io.grpc.ConnectivityState.SHUTDOWN;
|
import static io.grpc.ConnectivityState.SHUTDOWN;
|
||||||
import static io.grpc.ConnectivityState.TRANSIENT_FAILURE;
|
import static io.grpc.ConnectivityState.TRANSIENT_FAILURE;
|
||||||
|
import static io.grpc.EquivalentAddressGroup.ATTR_AUTHORITY_OVERRIDE;
|
||||||
import static junit.framework.TestCase.assertNotSame;
|
import static junit.framework.TestCase.assertNotSame;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
|
@ -380,6 +381,64 @@ public class ManagedChannelImplTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createSubchannel_resolverOverrideAuthority() {
|
||||||
|
EquivalentAddressGroup addressGroup = new EquivalentAddressGroup(
|
||||||
|
socketAddress,
|
||||||
|
Attributes.newBuilder()
|
||||||
|
.set(ATTR_AUTHORITY_OVERRIDE, "resolver.override.authority")
|
||||||
|
.build());
|
||||||
|
channelBuilder.nameResolverFactory(
|
||||||
|
new FakeNameResolverFactory.Builder(expectedUri)
|
||||||
|
.setServers(Collections.singletonList(addressGroup))
|
||||||
|
.build());
|
||||||
|
createChannel();
|
||||||
|
|
||||||
|
Subchannel subchannel =
|
||||||
|
createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, subchannelStateListener);
|
||||||
|
requestConnectionSafely(helper, subchannel);
|
||||||
|
ArgumentCaptor<ClientTransportOptions> transportOptionCaptor = ArgumentCaptor.forClass(null);
|
||||||
|
verify(mockTransportFactory)
|
||||||
|
.newClientTransport(
|
||||||
|
any(SocketAddress.class), transportOptionCaptor.capture(), any(ChannelLogger.class));
|
||||||
|
assertThat(transportOptionCaptor.getValue().getAuthority())
|
||||||
|
.isEqualTo("resolver.override.authority");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createSubchannel_channelBuilderOverrideAuthority() {
|
||||||
|
channelBuilder.overrideAuthority("channel-builder.override.authority");
|
||||||
|
EquivalentAddressGroup addressGroup = new EquivalentAddressGroup(
|
||||||
|
socketAddress,
|
||||||
|
Attributes.newBuilder()
|
||||||
|
.set(ATTR_AUTHORITY_OVERRIDE, "resolver.override.authority")
|
||||||
|
.build());
|
||||||
|
channelBuilder.nameResolverFactory(
|
||||||
|
new FakeNameResolverFactory.Builder(expectedUri)
|
||||||
|
.setServers(Collections.singletonList(addressGroup))
|
||||||
|
.build());
|
||||||
|
createChannel();
|
||||||
|
|
||||||
|
final Subchannel subchannel =
|
||||||
|
createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, subchannelStateListener);
|
||||||
|
requestConnectionSafely(helper, subchannel);
|
||||||
|
ArgumentCaptor<ClientTransportOptions> transportOptionCaptor = ArgumentCaptor.forClass(null);
|
||||||
|
verify(mockTransportFactory)
|
||||||
|
.newClientTransport(
|
||||||
|
any(SocketAddress.class), transportOptionCaptor.capture(), any(ChannelLogger.class));
|
||||||
|
assertThat(transportOptionCaptor.getValue().getAuthority())
|
||||||
|
.isEqualTo("channel-builder.override.authority");
|
||||||
|
final List<EquivalentAddressGroup> subchannelEags = new ArrayList<>();
|
||||||
|
helper.getSynchronizationContext().execute(
|
||||||
|
new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
subchannelEags.addAll(subchannel.getAllAddresses());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertThat(subchannelEags).isEqualTo(ImmutableList.of(addressGroup));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void idleModeDisabled() {
|
public void idleModeDisabled() {
|
||||||
channelBuilder.nameResolverFactory(
|
channelBuilder.nameResolverFactory(
|
||||||
|
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2017 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.internal;
|
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import io.grpc.ChannelLogger;
|
|
||||||
import io.grpc.NameResolver;
|
|
||||||
import io.grpc.NameResolver.ServiceConfigParser;
|
|
||||||
import io.grpc.ProxyDetector;
|
|
||||||
import io.grpc.SynchronizationContext;
|
|
||||||
import java.lang.Thread.UncaughtExceptionHandler;
|
|
||||||
import java.net.URI;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.JUnit4;
|
|
||||||
|
|
||||||
/** Unit tests for {@link OverrideAuthorityNameResolverFactory}. */
|
|
||||||
@RunWith(JUnit4.class)
|
|
||||||
public class OverrideAuthorityNameResolverTest {
|
|
||||||
private static final NameResolver.Args ARGS = NameResolver.Args.newBuilder()
|
|
||||||
.setDefaultPort(8080)
|
|
||||||
.setProxyDetector(mock(ProxyDetector.class))
|
|
||||||
.setSynchronizationContext(new SynchronizationContext(mock(UncaughtExceptionHandler.class)))
|
|
||||||
.setServiceConfigParser(mock(ServiceConfigParser.class))
|
|
||||||
.setChannelLogger(mock(ChannelLogger.class))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void overridesAuthority() {
|
|
||||||
NameResolver nameResolverMock = mock(NameResolver.class);
|
|
||||||
NameResolver.Factory wrappedFactory = mock(NameResolver.Factory.class);
|
|
||||||
when(wrappedFactory.newNameResolver(any(URI.class), any(NameResolver.Args.class)))
|
|
||||||
.thenReturn(nameResolverMock);
|
|
||||||
String override = "override:5678";
|
|
||||||
NameResolver.Factory factory =
|
|
||||||
new OverrideAuthorityNameResolverFactory(wrappedFactory, override);
|
|
||||||
NameResolver nameResolver = factory.newNameResolver(URI.create("dns:///localhost:443"), ARGS);
|
|
||||||
assertNotNull(nameResolver);
|
|
||||||
assertEquals(override, nameResolver.getServiceAuthority());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void wontWrapNull() {
|
|
||||||
NameResolver.Factory wrappedFactory = mock(NameResolver.Factory.class);
|
|
||||||
when(wrappedFactory.newNameResolver(any(URI.class), any(NameResolver.Args.class)))
|
|
||||||
.thenReturn(null);
|
|
||||||
NameResolver.Factory factory =
|
|
||||||
new OverrideAuthorityNameResolverFactory(wrappedFactory, "override:5678");
|
|
||||||
assertEquals(null,
|
|
||||||
factory.newNameResolver(URI.create("dns:///localhost:443"), ARGS));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void forwardsNonOverridenCalls() {
|
|
||||||
NameResolver.Factory wrappedFactory = mock(NameResolver.Factory.class);
|
|
||||||
NameResolver mockResolver = mock(NameResolver.class);
|
|
||||||
when(wrappedFactory.newNameResolver(any(URI.class), any(NameResolver.Args.class)))
|
|
||||||
.thenReturn(mockResolver);
|
|
||||||
NameResolver.Factory factory =
|
|
||||||
new OverrideAuthorityNameResolverFactory(wrappedFactory, "override:5678");
|
|
||||||
NameResolver overrideResolver =
|
|
||||||
factory.newNameResolver(URI.create("dns:///localhost:443"), ARGS);
|
|
||||||
assertNotNull(overrideResolver);
|
|
||||||
NameResolver.Listener2 listener = mock(NameResolver.Listener2.class);
|
|
||||||
|
|
||||||
overrideResolver.start(listener);
|
|
||||||
verify(mockResolver).start(listener);
|
|
||||||
|
|
||||||
overrideResolver.shutdown();
|
|
||||||
verify(mockResolver).shutdown();
|
|
||||||
|
|
||||||
overrideResolver.refresh();
|
|
||||||
verify(mockResolver).refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue