@Nullable @Override public NameResolver newNameResolver(URI targetUri, Attributes params) { if (SCHEME.equals(targetUri.getScheme())) { String targetPath = Preconditions.checkNotNull(targetUri.getPath(), "targetPath"); Preconditions.checkArgument(targetPath.startsWith("/"), "the path component (%s) of the target (%s) must start with '/'", targetPath, targetUri); String[] parts = targetPath.split("/"); if (parts.length != 4) { throw new IllegalArgumentException("Must be formatted like kubernetes:///{namespace}/{service}/{port}"); } try { int port = Integer.valueOf(parts[3]); return new KubernetesNameResolver(parts[1], parts[2], port, params, GrpcUtil.TIMER_SERVICE, GrpcUtil.SHARED_CHANNEL_EXECUTOR); } catch (NumberFormatException e) { throw new IllegalArgumentException("Unable to parse port number", e); } } else { return null; } }
@Nullable @Override public NameResolver newNameResolver(URI targetUri, Attributes params) { final String scheme = targetUri.getScheme(); if (!SCHEME_DISCOVER.equals(scheme) && !SCHEME_DIRECT.equals(scheme)) { return null; } final String authority = targetUri.getAuthority(); final List<InetSocketAddress> addresses = Splitter.on(',').splitToList(authority).stream().map(host -> { final String[] strings = host.split(":"); Preconditions.checkArgument(strings.length == 2, "URI should have both address and port"); return InetSocketAddress.createUnresolved(strings[0], Integer.valueOf(strings[1])); }).collect(Collectors.toList()); return new ControllerNameResolver(authority, addresses, SCHEME_DISCOVER.equals(scheme)); }
@Before public void setUp() throws Throwable { List<String> grpcServers = new ArrayList<String>(); grpcServers.add("127.0.0.1:2181"); RemoteDownstreamConfig.Collector.GRPC_SERVERS = grpcServers; Config.Collector.GRPC_CHANNEL_CHECK_INTERVAL = 1; mockStatic(NettyChannelBuilder.class); when(NettyChannelBuilder.forAddress(anyString(), anyInt())).thenReturn(mock); when(mock.nameResolverFactory(any(NameResolver.Factory.class))).thenReturn(mock); when(mock.maxInboundMessageSize(anyInt())).thenReturn(mock); when(mock.usePlaintext(true)).thenReturn(mock); when(mock.build()).thenReturn(grpcServerRule.getChannel()); grpcChannelManager.addChannelListener(listener); }
@Override protected Attributes getNameResolverParams() { int defaultPort; switch (negotiationType) { case PLAINTEXT: defaultPort = GrpcUtil.DEFAULT_PORT_PLAINTEXT; break; case TLS: defaultPort = GrpcUtil.DEFAULT_PORT_SSL; break; default: throw new AssertionError(negotiationType + " not handled"); } return Attributes.newBuilder() .set(NameResolver.Factory.PARAMS_DEFAULT_PORT, defaultPort).build(); }
@Override @CheckReturnValue protected Attributes getNameResolverParams() { int defaultPort; switch (negotiationType) { case PLAINTEXT: case PLAINTEXT_UPGRADE: defaultPort = GrpcUtil.DEFAULT_PORT_PLAINTEXT; break; case TLS: defaultPort = GrpcUtil.DEFAULT_PORT_SSL; break; default: throw new AssertionError(negotiationType + " not handled"); } return Attributes.newBuilder() .set(NameResolver.Factory.PARAMS_DEFAULT_PORT, defaultPort).build(); }
@Override public NameResolver newNameResolver(URI notUsedUri, Attributes params) { return new NameResolver() { @Override public String getServiceAuthority() { return authority; } @Override public void start(final Listener listener) { listener.onAddresses( Collections.singletonList(new EquivalentAddressGroup(address)), Attributes.EMPTY); } @Override public void shutdown() {} }; }
@Test public void forwardsNonOverridenCalls() { NameResolver.Factory wrappedFactory = mock(NameResolver.Factory.class); NameResolver mockResolver = mock(NameResolver.class); when(wrappedFactory.newNameResolver(any(URI.class), any(Attributes.class))) .thenReturn(mockResolver); NameResolver.Factory factory = new OverrideAuthorityNameResolverFactory(wrappedFactory, "override:5678"); NameResolver overrideResolver = factory.newNameResolver(URI.create("dns:///localhost:443"), Attributes.EMPTY); assertNotNull(overrideResolver); NameResolver.Listener listener = mock(NameResolver.Listener.class); overrideResolver.start(listener); verify(mockResolver).start(listener); overrideResolver.shutdown(); verify(mockResolver).shutdown(); overrideResolver.refresh(); verify(mockResolver).refresh(); }
@Test public void validTargetNoResovler() { Factory nameResolverFactory = new NameResolver.Factory() { @Override public NameResolver newNameResolver(URI targetUri, Attributes params) { return null; } @Override public String getDefaultScheme() { return "defaultscheme"; } }; try { ManagedChannelImpl.getNameResolver( "foo.googleapis.com:8080", nameResolverFactory, NAME_RESOLVER_PARAMS); fail("Should fail"); } catch (IllegalArgumentException e) { // expected } }
@Test public void firstShouldFind() throws Exception { NameResolver fakeResolver = new FakeResolver(); FakeResolverProvider canResolve = new FakeResolverProvider("aaa://", fakeResolver); FakeResolverProvider cannotResolve = new FakeResolverProvider("bbb://", null); NameResolver.Factory factory = FallbackResolver.startWith(canResolve).thenCheck(cannotResolve); assertEquals(fakeResolver, factory.newNameResolver(new URI("aaa://foo"), Attributes.EMPTY)); }
@Test public void secondShouldFind() throws Exception { NameResolver fakeResolver = new FakeResolver(); FakeResolverProvider canResolve = new FakeResolverProvider("aaa://", fakeResolver); FakeResolverProvider cannotResolve = new FakeResolverProvider("bbb://", null); NameResolver.Factory factory = FallbackResolver.startWith(cannotResolve).thenCheck(canResolve); assertEquals(fakeResolver, factory.newNameResolver(new URI("bbb://foo"), Attributes.EMPTY)); }
@Test public void neitherShouldFind() throws Exception { FakeResolverProvider cannotResolve = new FakeResolverProvider("bbb://", null); NameResolver.Factory factory = FallbackResolver.startWith(cannotResolve).thenCheck(cannotResolve); assertNull(factory.newNameResolver(new URI("bbb://foo"), Attributes.EMPTY)); }
@Test public void firstSchemeIsDefaultScheme() { NameResolver fakeResolver = new FakeResolver(); FakeResolverProvider canResolve = new FakeResolverProvider("aaa://", fakeResolver); FakeResolverProvider cannotResolve = new FakeResolverProvider("bbb://", null); NameResolver.Factory factory = FallbackResolver.startWith(canResolve).thenCheck(cannotResolve); assertEquals("aaa://", factory.getDefaultScheme()); }
@Nullable @Override public NameResolver newNameResolver(URI targetUri, Attributes params) { if ("etcd".equals(targetUri.getScheme())) { return new SmartNameResolver(this.authority , this.uris, this.loader); } else { return null; } }
public static NameResolver.Factory forEndpoints( String authority, Collection<String> endpoints, URIResolverLoader loader) { List<URI> uris = endpoints.stream().map(endpoint -> { try { return new URI(endpoint); } catch (URISyntaxException e) { throw new IllegalArgumentException(e); } }).collect(Collectors.toList()); return new SmartNameResolverFactory(authority, uris, loader); }
@Override public NameResolver newNameResolver(URI targetUri, Attributes params) { if (SCHEME.equals(targetUri.getScheme())) { params = Attributes.newBuilder(params) .set(GrpclbConstants.ATTR_LB_POLICY, GrpclbConstants.LbPolicy.ROUND_ROBIN).build(); return new ZkNameResolver(targetUri, params, getCallOptions()); } else { return null; } }
@Test public void changeStatusToDisConnectedWithReportError() throws Throwable { doThrow(new RuntimeException()).when(mock).nameResolverFactory(any(NameResolver.Factory.class)); grpcChannelManager.run(); verify(listener, times(1)).statusChanged(GRPCChannelStatus.DISCONNECT); assertThat(listener.status, is(GRPCChannelStatus.DISCONNECT)); }
@Override public final T nameResolverFactory(NameResolver.Factory resolverFactory) { Preconditions.checkState(directServerAddress == null, "directServerAddress is set (%s), which forbids the use of NameResolverFactory", directServerAddress); if (resolverFactory != null) { this.nameResolverFactory = resolverFactory; } else { this.nameResolverFactory = DEFAULT_NAME_RESOLVER_FACTORY; } return thisT(); }
/** * Returns a {@link NameResolver.Factory} for the channel. */ NameResolver.Factory getNameResolverFactory() { if (authorityOverride == null) { return nameResolverFactory; } else { return new OverrideAuthorityNameResolverFactory(nameResolverFactory, authorityOverride); } }
@Nullable @Override public NameResolver newNameResolver(URI targetUri, Attributes params) { final NameResolver resolver = delegate.newNameResolver(targetUri, params); // 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; } }; }
DnsNameResolver(@Nullable String nsAuthority, String name, Attributes params, Resource<ScheduledExecutorService> timerServiceResource, Resource<ExecutorService> executorResource, ProxyDetector proxyDetector) { // TODO: if a DNS server is provided as nsAuthority, use it. // https://www.captechconsulting.com/blogs/accessing-the-dusty-corners-of-dns-with-java this.timerServiceResource = timerServiceResource; this.executorResource = executorResource; // Must prepend a "//" to the name when constructing a URI, otherwise it will be treated as an // opaque URI, thus the authority and host of the resulted URI would be null. URI nameUri = URI.create("//" + name); authority = Preconditions.checkNotNull(nameUri.getAuthority(), "nameUri (%s) doesn't have an authority", nameUri); host = Preconditions.checkNotNull(nameUri.getHost(), "host"); if (nameUri.getPort() == -1) { Integer defaultPort = params.get(NameResolver.Factory.PARAMS_DEFAULT_PORT); if (defaultPort != null) { port = defaultPort; } else { throw new IllegalArgumentException( "name '" + name + "' doesn't contain a port, and default port is not set in params"); } } else { port = nameUri.getPort(); } this.proxyDetector = proxyDetector; }
@Override public NameResolver newNameResolver(final URI targetUri, Attributes params) { if (!expectedUri.equals(targetUri)) { return null; } assertSame(NAME_RESOLVER_PARAMS, params); FakeNameResolver resolver = new FakeNameResolver(); resolvers.add(resolver); return resolver; }
@Override public NameResolver newNameResolver(URI notUsedUri, Attributes params) { return new NameResolver() { @Override public String getServiceAuthority() { return "irrelevant-authority"; } @Override public void start(final Listener listener) { listener.onError(error); } @Override public void shutdown() {} }; }
@Test public void overridesAuthority() { NameResolver nameResolverMock = mock(NameResolver.class); NameResolver.Factory wrappedFactory = mock(NameResolver.Factory.class); when(wrappedFactory.newNameResolver(any(URI.class), any(Attributes.class))) .thenReturn(nameResolverMock); String override = "override:5678"; NameResolver.Factory factory = new OverrideAuthorityNameResolverFactory(wrappedFactory, override); NameResolver nameResolver = factory.newNameResolver(URI.create("dns:///localhost:443"), Attributes.EMPTY); assertNotNull(nameResolver); assertEquals(override, nameResolver.getServiceAuthority()); }
@Test public void wontWrapNull() { NameResolver.Factory wrappedFactory = mock(NameResolver.Factory.class); when(wrappedFactory.newNameResolver(any(URI.class), any(Attributes.class))).thenReturn(null); NameResolver.Factory factory = new OverrideAuthorityNameResolverFactory(wrappedFactory, "override:5678"); assertEquals(null, factory.newNameResolver(URI.create("dns:///localhost:443"), Attributes.EMPTY)); }
@Override public NameResolver newNameResolver(URI targetUri, Attributes params) { if (expectedScheme.equals(targetUri.getScheme())) { return new FakeNameResolver(targetUri); } return null; }
private DnsNameResolver newResolver( String name, int port, DelegateResolver delegateResolver, ProxyDetector proxyDetector) { DnsNameResolver dnsResolver = new DnsNameResolver( null, name, Attributes.newBuilder().set(NameResolver.Factory.PARAMS_DEFAULT_PORT, port).build(), fakeTimerServiceResource, fakeExecutorResource, proxyDetector); dnsResolver.setDelegateResolver(delegateResolver); return dnsResolver; }
@Test public void nameResolverFactory_null() { NameResolver.Factory defaultValue = builder.getNameResolverFactory(); builder.nameResolverFactory(mock(NameResolver.Factory.class)); assertEquals(builder, builder.nameResolverFactory(null)); assertEquals(defaultValue, builder.getNameResolverFactory()); }
@Override public NameResolver newNameResolver(URI targetUri, Attributes params) { return new GrpcNameResolver(targetUri, params, subscribeUrl); }
public FakeResolverProvider(String scheme, NameResolver resolver) { this.scheme = scheme; this.resolver = resolver; }
@Override public NameResolver newNameResolver(URI targetUri, Attributes params) { return resolver; }
@Nullable @Override public NameResolver newNameResolver(URI targetUri, Attributes params) { return new DiscoveryClientNameResolver(targetUri.toString(), client, params); }
@Override public NameResolver newNameResolver(URI targetUri, Attributes params) { return new SimpleNameResolver(collectorAddresses, collectorAuthority); }
@Override protected Attributes getNameResolverParams() { return Attributes.newBuilder() .set(NameResolver.Factory.PARAMS_DEFAULT_PORT, GrpcUtil.DEFAULT_PORT_SSL).build(); }
@Test public void usePlaintextDefaultPort() { OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("host", 1234).usePlaintext(true); assertEquals(GrpcUtil.DEFAULT_PORT_PLAINTEXT, builder.getNameResolverParams().get(NameResolver.Factory.PARAMS_DEFAULT_PORT).intValue()); }
LbHelperImpl(NameResolver nr) { this.nr = checkNotNull(nr, "NameResolver"); }
@Override public NameResolver.Factory getNameResolverFactory() { return nameResolverFactory; }
ForwardingNameResolver(NameResolver delegate) { checkNotNull(delegate, "delegate can not be null"); this.delegate = delegate; }
private void createChannel( NameResolver.Factory nameResolverFactory, List<ClientInterceptor> interceptors) { createChannel( nameResolverFactory, interceptors, true /* requestConnection */, ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE); }
private void createChannel( NameResolver.Factory nameResolverFactory, List<ClientInterceptor> interceptors, boolean requestConnection, long idleTimeoutMillis) { class Builder extends AbstractManagedChannelImplBuilder<Builder> { Builder(String target) { super(target); } @Override protected ClientTransportFactory buildTransportFactory() { throw new UnsupportedOperationException(); } @Override protected Attributes getNameResolverParams() { return NAME_RESOLVER_PARAMS; } @Override public Builder usePlaintext(boolean b) { throw new UnsupportedOperationException(); } } Builder builder = new Builder(target) .nameResolverFactory(nameResolverFactory) .loadBalancerFactory(mockLoadBalancerFactory) .userAgent(userAgent); builder.executorPool = executorPool; builder.idleTimeoutMillis = idleTimeoutMillis; builder.binlogProvider = binlogProvider; checkState(channel == null); channel = new ManagedChannelImpl( builder, mockTransportFactory, new FakeBackoffPolicyProvider(), oobExecutorPool, timer.getStopwatchSupplier(), interceptors, GrpcUtil.NOOP_PROXY_DETECTOR, channelStatsFactory); if (requestConnection) { // Force-exit the initial idle-mode channel.exitIdleMode(); assertEquals( idleTimeoutMillis == ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE ? 0 : 1, timer.numPendingTasks()); ArgumentCaptor<Helper> helperCaptor = ArgumentCaptor.forClass(null); verify(mockLoadBalancerFactory).newLoadBalancer(helperCaptor.capture()); helper = helperCaptor.getValue(); } }
@Before public void setUp() { MockitoAnnotations.initMocks(this); when(mockLoadBalancerFactory.newLoadBalancer(any(Helper.class))).thenReturn(mockLoadBalancer); when(mockNameResolver.getServiceAuthority()).thenReturn(AUTHORITY); when(mockNameResolverFactory .newNameResolver(any(URI.class), any(Attributes.class))) .thenReturn(mockNameResolver); when(mockTransportFactory.getScheduledExecutorService()) .thenReturn(timer.getScheduledExecutorService()); class Builder extends AbstractManagedChannelImplBuilder<Builder> { Builder(String target) { super(target); } @Override protected ClientTransportFactory buildTransportFactory() { throw new UnsupportedOperationException(); } @Override public Builder usePlaintext(boolean b) { throw new UnsupportedOperationException(); } } Builder builder = new Builder("fake://target") .nameResolverFactory(mockNameResolverFactory) .loadBalancerFactory(mockLoadBalancerFactory) .idleTimeout(IDLE_TIMEOUT_SECONDS, TimeUnit.SECONDS) .userAgent(USER_AGENT); builder.executorPool = executorPool; channel = new ManagedChannelImpl( builder, mockTransportFactory, new FakeBackoffPolicyProvider(), oobExecutorPool, timer.getStopwatchSupplier(), Collections.<ClientInterceptor>emptyList(), GrpcUtil.NOOP_PROXY_DETECTOR, CallTracer.getDefaultFactory()); newTransports = TestUtils.captureTransports(mockTransportFactory); for (int i = 0; i < 2; i++) { ArrayList<SocketAddress> addrs = Lists.newArrayList(); for (int j = 0; j < 2; j++) { addrs.add(new FakeSocketAddress("servergroup" + i + "server" + j)); } servers.add(new EquivalentAddressGroup(addrs)); } verify(mockNameResolverFactory).newNameResolver(any(URI.class), any(Attributes.class)); // Verify the initial idleness verify(mockLoadBalancerFactory, never()).newLoadBalancer(any(Helper.class)); verify(mockTransportFactory, never()).newClientTransport( any(SocketAddress.class), anyString(), anyString(), any(ProxyParameters.class)); verify(mockNameResolver, never()).start(any(NameResolver.Listener.class)); }