Reject port ranges in `discovery.seed_hosts` (#41905)

Today Elasticsearch accepts, but silently ignores, port ranges in the
`discovery.seed_hosts` setting:

```
discovery.seed_hosts: 10.1.2.3:9300-9400
```

Silently ignoring part of a setting like this is trappy. With this change we
reject seed host addresses of this form.

Closes #40786
Backport of #41404
This commit is contained in:
David Turner 2019-05-08 08:34:32 +01:00 committed by GitHub
parent e04953a2bf
commit 4c909e93bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 193 additions and 187 deletions

View File

@ -17,3 +17,15 @@ coming[7.2.0]
//tag::notable-breaking-changes[] //tag::notable-breaking-changes[]
// end::notable-breaking-changes[] // end::notable-breaking-changes[]
[[breaking_72_discovery_changes]]
=== Discovery changes
[float]
==== Only a single port may be given for each seed host.
In earlier versions you could include a range of ports in entries in the
`discovery.seed_hosts` list, but {es} used only the first port in the range and
unexpectedly ignored the rest. For instance if you set `discovery.seed_hosts:
"10.11.12.13:9300-9310"` then {es} would only use `10.11.12.13:9300` for
discovery. Seed host addresses containing port ranges are now rejected.

View File

@ -208,8 +208,7 @@ public class AzureSeedHostsProvider implements SeedHostsProvider {
} }
try { try {
// we only limit to 1 port per address, makes no sense to ping 100 ports TransportAddress[] addresses = transportService.addressesFromString(networkAddress);
TransportAddress[] addresses = transportService.addressesFromString(networkAddress, 1);
for (TransportAddress address : addresses) { for (TransportAddress address : addresses) {
logger.trace("adding {}, transport_address {}", networkAddress, address); logger.trace("adding {}, transport_address {}", networkAddress, address);
dynamicHosts.add(address); dynamicHosts.add(address);

View File

@ -174,8 +174,7 @@ class AwsEc2SeedHostsProvider implements SeedHostsProvider {
} }
if (address != null) { if (address != null) {
try { try {
// we only limit to 1 port per address, makes no sense to ping 100 ports final TransportAddress[] addresses = transportService.addressesFromString(address);
final TransportAddress[] addresses = transportService.addressesFromString(address, 1);
for (int i = 0; i < addresses.length; i++) { for (int i = 0; i < addresses.length; i++) {
logger.trace("adding {}, address {}, transport_address {}", instance.getInstanceId(), address, addresses[i]); logger.trace("adding {}, address {}, transport_address {}", instance.getInstanceId(), address, addresses[i]);
dynamicHosts.add(addresses[i]); dynamicHosts.add(addresses[i]);

View File

@ -77,7 +77,7 @@ public class Ec2DiscoveryTests extends ESTestCase {
new NetworkService(Collections.emptyList()), PageCacheRecycler.NON_RECYCLING_INSTANCE, namedWriteableRegistry, new NetworkService(Collections.emptyList()), PageCacheRecycler.NON_RECYCLING_INSTANCE, namedWriteableRegistry,
new NoneCircuitBreakerService()) { new NoneCircuitBreakerService()) {
@Override @Override
public TransportAddress[] addressesFromString(String address, int perAddressLimit) throws UnknownHostException { public TransportAddress[] addressesFromString(String address) throws UnknownHostException {
// we just need to ensure we don't resolve DNS here // we just need to ensure we don't resolve DNS here
return new TransportAddress[] {poorMansDNS.getOrDefault(address, buildNewFakeTransportAddress())}; return new TransportAddress[] {poorMansDNS.getOrDefault(address, buildNewFakeTransportAddress())};
} }

View File

@ -233,8 +233,7 @@ public class GceSeedHostsProvider implements SeedHostsProvider {
// ip_private is a single IP Address. We need to build a TransportAddress from it // ip_private is a single IP Address. We need to build a TransportAddress from it
// If user has set `es_port` metadata, we don't need to ping all ports // If user has set `es_port` metadata, we don't need to ping all ports
// we only limit to 1 addresses, makes no sense to ping 100 ports TransportAddress[] addresses = transportService.addressesFromString(address);
TransportAddress[] addresses = transportService.addressesFromString(address, 1);
for (TransportAddress transportAddress : addresses) { for (TransportAddress transportAddress : addresses) {
logger.trace("adding {}, type {}, address {}, transport_address {}, status {}", name, type, logger.trace("adding {}, type {}, address {}, transport_address {}, status {}", name, type,

View File

@ -75,7 +75,7 @@ public class FileBasedSeedHostsProvider implements SeedHostsProvider {
@Override @Override
public List<TransportAddress> getSeedAddresses(HostsResolver hostsResolver) { public List<TransportAddress> getSeedAddresses(HostsResolver hostsResolver) {
final List<TransportAddress> transportAddresses = hostsResolver.resolveHosts(getHostsList(), 1); final List<TransportAddress> transportAddresses = hostsResolver.resolveHosts(getHostsList());
logger.debug("seed addresses: {}", transportAddresses); logger.debug("seed addresses: {}", transportAddresses);
return transportAddresses; return transportAddresses;
} }

View File

@ -36,10 +36,9 @@ public interface SeedHostsProvider {
/** /**
* Helper object that allows to resolve a list of hosts to a list of transport addresses. * Helper object that allows to resolve a list of hosts to a list of transport addresses.
* Each host is resolved into a transport address (or a collection of addresses if the * Each host is resolved into a transport address
* number of ports is greater than one)
*/ */
interface HostsResolver { interface HostsResolver {
List<TransportAddress> resolveHosts(List<String> hosts, int limitPortCounts); List<TransportAddress> resolveHosts(List<String> hosts);
} }
} }

View File

@ -116,7 +116,6 @@ public class SeedHostsResolver extends AbstractLifecycleComponent implements Con
* @param executorService the executor service used to parallelize hostname lookups * @param executorService the executor service used to parallelize hostname lookups
* @param logger logger used for logging messages regarding hostname lookups * @param logger logger used for logging messages regarding hostname lookups
* @param hosts the hosts to resolve * @param hosts the hosts to resolve
* @param limitPortCounts the number of ports to resolve (should be 1 for non-local transport)
* @param transportService the transport service * @param transportService the transport service
* @param resolveTimeout the timeout before returning from hostname lookups * @param resolveTimeout the timeout before returning from hostname lookups
* @return a list of resolved transport addresses * @return a list of resolved transport addresses
@ -125,7 +124,6 @@ public class SeedHostsResolver extends AbstractLifecycleComponent implements Con
final ExecutorService executorService, final ExecutorService executorService,
final Logger logger, final Logger logger,
final List<String> hosts, final List<String> hosts,
final int limitPortCounts,
final TransportService transportService, final TransportService transportService,
final TimeValue resolveTimeout) { final TimeValue resolveTimeout) {
Objects.requireNonNull(executorService); Objects.requireNonNull(executorService);
@ -140,7 +138,7 @@ public class SeedHostsResolver extends AbstractLifecycleComponent implements Con
final List<Callable<TransportAddress[]>> callables = final List<Callable<TransportAddress[]>> callables =
hosts hosts
.stream() .stream()
.map(hn -> (Callable<TransportAddress[]>) () -> transportService.addressesFromString(hn, limitPortCounts)) .map(hn -> (Callable<TransportAddress[]>) () -> transportService.addressesFromString(hn))
.collect(Collectors.toList()); .collect(Collectors.toList());
final List<Future<TransportAddress[]>> futures; final List<Future<TransportAddress[]>> futures;
try { try {
@ -224,9 +222,8 @@ public class SeedHostsResolver extends AbstractLifecycleComponent implements Con
} }
List<TransportAddress> providedAddresses List<TransportAddress> providedAddresses
= hostsProvider.getSeedAddresses((hosts, limitPortCounts) = hostsProvider.getSeedAddresses(hosts ->
-> resolveHostsLists(executorService.get(), logger, hosts, limitPortCounts, resolveHostsLists(executorService.get(), logger, hosts, transportService, resolveTimeout));
transportService, resolveTimeout));
consumer.accept(providedAddresses); consumer.accept(providedAddresses);
} }

View File

@ -50,12 +50,7 @@ public class SettingsBasedSeedHostsProvider implements SeedHostsProvider {
public static final Setting<List<String>> DISCOVERY_SEED_HOSTS_SETTING = public static final Setting<List<String>> DISCOVERY_SEED_HOSTS_SETTING =
Setting.listSetting("discovery.seed_hosts", emptyList(), Function.identity(), Property.NodeScope); Setting.listSetting("discovery.seed_hosts", emptyList(), Function.identity(), Property.NodeScope);
// these limits are per-address
private static final int LIMIT_FOREIGN_PORTS_COUNT = 1;
private static final int LIMIT_LOCAL_PORTS_COUNT = 5;
private final List<String> configuredHosts; private final List<String> configuredHosts;
private final int limitPortCounts;
public SettingsBasedSeedHostsProvider(Settings settings, TransportService transportService) { public SettingsBasedSeedHostsProvider(Settings settings, TransportService transportService) {
if (LEGACY_DISCOVERY_ZEN_PING_UNICAST_HOSTS_SETTING.exists(settings)) { if (LEGACY_DISCOVERY_ZEN_PING_UNICAST_HOSTS_SETTING.exists(settings)) {
@ -66,15 +61,11 @@ public class SettingsBasedSeedHostsProvider implements SeedHostsProvider {
} }
configuredHosts = LEGACY_DISCOVERY_ZEN_PING_UNICAST_HOSTS_SETTING.get(settings); configuredHosts = LEGACY_DISCOVERY_ZEN_PING_UNICAST_HOSTS_SETTING.get(settings);
// we only limit to 1 address, makes no sense to ping 100 ports // we only limit to 1 address, makes no sense to ping 100 ports
limitPortCounts = LIMIT_FOREIGN_PORTS_COUNT;
} else if (DISCOVERY_SEED_HOSTS_SETTING.exists(settings)) { } else if (DISCOVERY_SEED_HOSTS_SETTING.exists(settings)) {
configuredHosts = DISCOVERY_SEED_HOSTS_SETTING.get(settings); configuredHosts = DISCOVERY_SEED_HOSTS_SETTING.get(settings);
// we only limit to 1 address, makes no sense to ping 100 ports
limitPortCounts = LIMIT_FOREIGN_PORTS_COUNT;
} else { } else {
// if unicast hosts are not specified, fill with simple defaults on the local machine // if unicast hosts are not specified, fill with simple defaults on the local machine
configuredHosts = transportService.getLocalAddresses(); configuredHosts = transportService.getDefaultSeedAddresses();
limitPortCounts = LIMIT_LOCAL_PORTS_COUNT;
} }
logger.debug("using initial hosts {}", configuredHosts); logger.debug("using initial hosts {}", configuredHosts);
@ -82,6 +73,6 @@ public class SettingsBasedSeedHostsProvider implements SeedHostsProvider {
@Override @Override
public List<TransportAddress> getSeedAddresses(HostsResolver hostsResolver) { public List<TransportAddress> getSeedAddresses(HostsResolver hostsResolver) {
return hostsResolver.resolveHosts(configuredHosts, limitPortCounts); return hostsResolver.resolveHosts(configuredHosts);
} }
} }

View File

@ -144,8 +144,7 @@ public class UnicastZenPing implements ZenPing {
} }
private SeedHostsProvider.HostsResolver createHostsResolver() { private SeedHostsProvider.HostsResolver createHostsResolver() {
return (hosts, limitPortCounts) -> SeedHostsResolver.resolveHostsLists(unicastZenPingExecutorService, logger, hosts, return hosts -> SeedHostsResolver.resolveHostsLists(unicastZenPingExecutorService, logger, hosts, transportService, resolveTimeout);
limitPortCounts, transportService, resolveTimeout);
} }
@Override @Override

View File

@ -86,6 +86,7 @@ import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableMap;
import static org.elasticsearch.common.transport.NetworkExceptionHelper.isCloseConnectionException; import static org.elasticsearch.common.transport.NetworkExceptionHelper.isCloseConnectionException;
@ -102,6 +103,9 @@ public abstract class TcpTransport extends AbstractLifecycleComponent implements
private static final long NINETY_PER_HEAP_SIZE = (long) (JvmInfo.jvmInfo().getMem().getHeapMax().getBytes() * 0.9); private static final long NINETY_PER_HEAP_SIZE = (long) (JvmInfo.jvmInfo().getMem().getHeapMax().getBytes() * 0.9);
private static final BytesReference EMPTY_BYTES_REFERENCE = new BytesArray(new byte[0]); private static final BytesReference EMPTY_BYTES_REFERENCE = new BytesArray(new byte[0]);
// this limit is per-address
private static final int LIMIT_LOCAL_PORTS_COUNT = 6;
protected final Settings settings; protected final Settings settings;
protected final ThreadPool threadPool; protected final ThreadPool threadPool;
protected final PageCacheRecycler pageCacheRecycler; protected final PageCacheRecycler pageCacheRecycler;
@ -311,14 +315,20 @@ public abstract class TcpTransport extends AbstractLifecycleComponent implements
} }
@Override @Override
public List<String> getLocalAddresses() { public List<String> getDefaultSeedAddresses() {
List<String> local = new ArrayList<>(); List<String> local = new ArrayList<>();
local.add("127.0.0.1"); local.add("127.0.0.1");
// check if v6 is supported, if so, v4 will also work via mapped addresses. // check if v6 is supported, if so, v4 will also work via mapped addresses.
if (NetworkUtils.SUPPORTS_V6) { if (NetworkUtils.SUPPORTS_V6) {
local.add("[::1]"); // may get ports appended! local.add("[::1]"); // may get ports appended!
} }
return local; return local.stream()
.flatMap(
address -> Arrays.stream(defaultPortRange())
.limit(LIMIT_LOCAL_PORTS_COUNT)
.mapToObj(port -> address + ":" + port)
)
.collect(Collectors.toList());
} }
protected void bindServer(ProfileSettings profileSettings) { protected void bindServer(ProfileSettings profileSettings) {
@ -456,8 +466,17 @@ public abstract class TcpTransport extends AbstractLifecycleComponent implements
} }
@Override @Override
public TransportAddress[] addressesFromString(String address, int perAddressLimit) throws UnknownHostException { public TransportAddress[] addressesFromString(String address) throws UnknownHostException {
return parse(address, settings.get("transport.profiles.default.port", TransportSettings.PORT.get(settings)), perAddressLimit); return parse(address, defaultPortRange()[0]);
}
private int[] defaultPortRange() {
return new PortsRange(
settings.get(
TransportSettings.PORT_PROFILE.getConcreteSettingForNamespace(TransportSettings.DEFAULT_PROFILE).getKey(),
TransportSettings.PORT.get(settings)
)
).ports();
} }
// this code is a take on guava's HostAndPort, like a HostAndPortRange // this code is a take on guava's HostAndPort, like a HostAndPortRange
@ -467,9 +486,9 @@ public abstract class TcpTransport extends AbstractLifecycleComponent implements
private static final Pattern BRACKET_PATTERN = Pattern.compile("^\\[(.*:.*)\\](?::([\\d\\-]*))?$"); private static final Pattern BRACKET_PATTERN = Pattern.compile("^\\[(.*:.*)\\](?::([\\d\\-]*))?$");
/** /**
* parse a hostname+port range spec into its equivalent addresses * parse a hostname+port spec into its equivalent addresses
*/ */
static TransportAddress[] parse(String hostPortString, String defaultPortRange, int perAddressLimit) throws UnknownHostException { static TransportAddress[] parse(String hostPortString, int defaultPort) throws UnknownHostException {
Objects.requireNonNull(hostPortString); Objects.requireNonNull(hostPortString);
String host; String host;
String portString = null; String portString = null;
@ -498,22 +517,18 @@ public abstract class TcpTransport extends AbstractLifecycleComponent implements
} }
} }
int port;
// if port isn't specified, fill with the default // if port isn't specified, fill with the default
if (portString == null || portString.isEmpty()) { if (portString == null || portString.isEmpty()) {
portString = defaultPortRange; port = defaultPort;
} else {
port = Integer.parseInt(portString);
} }
// generate address for each port in the range return Arrays.stream(InetAddress.getAllByName(host))
Set<InetAddress> addresses = new HashSet<>(Arrays.asList(InetAddress.getAllByName(host))); .distinct()
List<TransportAddress> transportAddresses = new ArrayList<>(); .map(address -> new TransportAddress(address, port))
int[] ports = new PortsRange(portString).ports(); .toArray(TransportAddress[]::new);
int limit = Math.min(ports.length, perAddressLimit);
for (int i = 0; i < limit; i++) {
for (InetAddress address : addresses) {
transportAddresses.add(new TransportAddress(address, ports[i]));
}
}
return transportAddresses.toArray(new TransportAddress[transportAddresses.size()]);
} }
@Override @Override

View File

@ -68,12 +68,12 @@ public interface Transport extends LifecycleComponent {
/** /**
* Returns an address from its string representation. * Returns an address from its string representation.
*/ */
TransportAddress[] addressesFromString(String address, int perAddressLimit) throws UnknownHostException; TransportAddress[] addressesFromString(String address) throws UnknownHostException;
/** /**
* Returns a list of all local adresses for this transport * Returns a list of all local addresses for this transport
*/ */
List<String> getLocalAddresses(); List<String> getDefaultSeedAddresses();
default CircuitBreaker getInFlightRequestBreaker() { default CircuitBreaker getInFlightRequestBreaker() {
return new NoopCircuitBreaker("in-flight-noop"); return new NoopCircuitBreaker("in-flight-noop");

View File

@ -313,8 +313,8 @@ public class TransportService extends AbstractLifecycleComponent implements Tran
return transport.boundAddress(); return transport.boundAddress();
} }
public List<String> getLocalAddresses() { public List<String> getDefaultSeedAddresses() {
return transport.getLocalAddresses(); return transport.getDefaultSeedAddresses();
} }
/** /**
@ -750,8 +750,8 @@ public class TransportService extends AbstractLifecycleComponent implements Tran
return true; return true;
} }
public TransportAddress[] addressesFromString(String address, int perAddressLimit) throws UnknownHostException { public TransportAddress[] addressesFromString(String address) throws UnknownHostException {
return transport.addressesFromString(address, perAddressLimit); return transport.addressesFromString(address);
} }
/** /**

View File

@ -170,7 +170,7 @@ abstract class FailAndRetryMockTransport<Response extends TransportResponse> imp
} }
@Override @Override
public TransportAddress[] addressesFromString(String address, int perAddressLimit) throws UnknownHostException { public TransportAddress[] addressesFromString(String address) throws UnknownHostException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -128,7 +128,7 @@ public class TransportClientNodesServiceTests extends ESTestCase {
threadPool = new TestThreadPool("transport-client-nodes-service-tests"); threadPool = new TestThreadPool("transport-client-nodes-service-tests");
transport = new FailAndRetryMockTransport<TestResponse>(random(), clusterName) { transport = new FailAndRetryMockTransport<TestResponse>(random(), clusterName) {
@Override @Override
public List<String> getLocalAddresses() { public List<String> getDefaultSeedAddresses() {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -401,7 +401,7 @@ public class NodeConnectionsServiceTests extends ESTestCase {
} }
@Override @Override
public TransportAddress[] addressesFromString(String address, int perAddressLimit) { public TransportAddress[] addressesFromString(String address) {
return new TransportAddress[0]; return new TransportAddress[0];
} }
@ -440,7 +440,7 @@ public class NodeConnectionsServiceTests extends ESTestCase {
} }
@Override @Override
public List<String> getLocalAddresses() { public List<String> getDefaultSeedAddresses() {
return null; return null;
} }

View File

@ -115,9 +115,8 @@ public class FileBasedSeedHostsProviderTests extends ESTestCase {
public void testUnicastHostsDoesNotExist() { public void testUnicastHostsDoesNotExist() {
final FileBasedSeedHostsProvider provider = new FileBasedSeedHostsProvider(createTempDir().toAbsolutePath()); final FileBasedSeedHostsProvider provider = new FileBasedSeedHostsProvider(createTempDir().toAbsolutePath());
final List<TransportAddress> addresses = provider.getSeedAddresses((hosts, limitPortCounts) -> final List<TransportAddress> addresses = provider.getSeedAddresses(hosts ->
SeedHostsResolver.resolveHostsLists(executorService, logger, hosts, limitPortCounts, transportService, SeedHostsResolver.resolveHostsLists(executorService, logger, hosts, transportService, TimeValue.timeValueSeconds(10)));
TimeValue.timeValueSeconds(10)));
assertEquals(0, addresses.size()); assertEquals(0, addresses.size());
} }
@ -145,8 +144,7 @@ public class FileBasedSeedHostsProviderTests extends ESTestCase {
writer.write(String.join("\n", hostEntries)); writer.write(String.join("\n", hostEntries));
} }
return new FileBasedSeedHostsProvider(configPath).getSeedAddresses((hosts, limitPortCounts) -> return new FileBasedSeedHostsProvider(configPath).getSeedAddresses(hosts ->
SeedHostsResolver.resolveHostsLists(executorService, logger, hosts, limitPortCounts, transportService, SeedHostsResolver.resolveHostsLists(executorService, logger, hosts, transportService, TimeValue.timeValueSeconds(10)));
TimeValue.timeValueSeconds(10)));
} }
} }

View File

@ -147,47 +147,6 @@ public class SeedHostsResolverTests extends ESTestCase {
assertThat(resolvedAddressesRef.get(), equalTo(transportAddresses)); assertThat(resolvedAddressesRef.get(), equalTo(transportAddresses));
} }
public void testPortLimit() {
final NetworkService networkService = new NetworkService(Collections.emptyList());
final Transport transport = new MockNioTransport(
Settings.EMPTY,
Version.CURRENT,
threadPool,
networkService,
PageCacheRecycler.NON_RECYCLING_INSTANCE,
new NamedWriteableRegistry(Collections.emptyList()),
new NoneCircuitBreakerService()) {
@Override
public BoundTransportAddress boundAddress() {
return new BoundTransportAddress(
new TransportAddress[]{new TransportAddress(InetAddress.getLoopbackAddress(), 9500)},
new TransportAddress(InetAddress.getLoopbackAddress(), 9500)
);
}
};
closeables.push(transport);
final TransportService transportService =
new TransportService(Settings.EMPTY, transport, threadPool, TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null,
Collections.emptySet());
closeables.push(transportService);
final int limitPortCounts = randomIntBetween(1, 10);
final List<TransportAddress> transportAddresses = SeedHostsResolver.resolveHostsLists(
executorService,
logger,
Collections.singletonList("127.0.0.1"),
limitPortCounts,
transportService,
TimeValue.timeValueSeconds(30));
assertThat(transportAddresses, hasSize(limitPortCounts));
final Set<Integer> ports = new HashSet<>();
for (final TransportAddress address : transportAddresses) {
assertTrue(address.address().getAddress().isLoopbackAddress());
ports.add(address.getPort());
}
assertThat(ports, equalTo(IntStream.range(9300, 9300 + limitPortCounts).mapToObj(m -> m).collect(Collectors.toSet())));
}
public void testRemovingLocalAddresses() { public void testRemovingLocalAddresses() {
final NetworkService networkService = new NetworkService(Collections.emptyList()); final NetworkService networkService = new NetworkService(Collections.emptyList());
final InetAddress loopbackAddress = InetAddress.getLoopbackAddress(); final InetAddress loopbackAddress = InetAddress.getLoopbackAddress();
@ -219,8 +178,9 @@ public class SeedHostsResolverTests extends ESTestCase {
final List<TransportAddress> transportAddresses = SeedHostsResolver.resolveHostsLists( final List<TransportAddress> transportAddresses = SeedHostsResolver.resolveHostsLists(
executorService, executorService,
logger, logger,
Collections.singletonList(NetworkAddress.format(loopbackAddress)), IntStream.range(9300, 9310)
10, .mapToObj(port -> NetworkAddress.format(loopbackAddress) + ":" + port)
.collect(Collectors.toList()),
transportService, transportService,
TimeValue.timeValueSeconds(30)); TimeValue.timeValueSeconds(30));
assertThat(transportAddresses, hasSize(7)); assertThat(transportAddresses, hasSize(7));
@ -255,7 +215,7 @@ public class SeedHostsResolverTests extends ESTestCase {
} }
@Override @Override
public TransportAddress[] addressesFromString(String address, int perAddressLimit) throws UnknownHostException { public TransportAddress[] addressesFromString(String address) throws UnknownHostException {
throw unknownHostException; throw unknownHostException;
} }
@ -271,7 +231,6 @@ public class SeedHostsResolverTests extends ESTestCase {
executorService, executorService,
logger, logger,
Arrays.asList(hostname), Arrays.asList(hostname),
1,
transportService, transportService,
TimeValue.timeValueSeconds(30) TimeValue.timeValueSeconds(30)
); );
@ -302,7 +261,7 @@ public class SeedHostsResolverTests extends ESTestCase {
} }
@Override @Override
public TransportAddress[] addressesFromString(String address, int perAddressLimit) throws UnknownHostException { public TransportAddress[] addressesFromString(String address) throws UnknownHostException {
if ("hostname1".equals(address)) { if ("hostname1".equals(address)) {
return new TransportAddress[]{new TransportAddress(TransportAddress.META_ADDRESS, 9300)}; return new TransportAddress[]{new TransportAddress(TransportAddress.META_ADDRESS, 9300)};
} else if ("hostname2".equals(address)) { } else if ("hostname2".equals(address)) {
@ -330,7 +289,6 @@ public class SeedHostsResolverTests extends ESTestCase {
executorService, executorService,
logger, logger,
Arrays.asList("hostname1", "hostname2"), Arrays.asList("hostname1", "hostname2"),
1,
transportService, transportService,
resolveTimeout); resolveTimeout);
@ -373,7 +331,6 @@ public class SeedHostsResolverTests extends ESTestCase {
executorService, executorService,
logger, logger,
Arrays.asList("127.0.0.1:9300:9300", "127.0.0.1:9301"), Arrays.asList("127.0.0.1:9300:9300", "127.0.0.1:9301"),
1,
transportService, transportService,
TimeValue.timeValueSeconds(30)); TimeValue.timeValueSeconds(30));
assertThat(transportAddresses, hasSize(1)); // only one of the two is valid and will be used assertThat(transportAddresses, hasSize(1)); // only one of the two is valid and will be used

View File

@ -22,7 +22,6 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.discovery.SeedHostsProvider.HostsResolver; import org.elasticsearch.discovery.SeedHostsProvider.HostsResolver;
import org.elasticsearch.discovery.SettingsBasedSeedHostsProvider;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
@ -38,18 +37,15 @@ public class SettingsBasedSeedHostsProviderTests extends ESTestCase {
private class AssertingHostsResolver implements HostsResolver { private class AssertingHostsResolver implements HostsResolver {
private final Set<String> expectedHosts; private final Set<String> expectedHosts;
private final int expectedPortCount;
private boolean resolvedHosts; private boolean resolvedHosts;
AssertingHostsResolver(int expectedPortCount, String... expectedHosts) { AssertingHostsResolver(String... expectedHosts) {
this.expectedPortCount = expectedPortCount;
this.expectedHosts = Sets.newHashSet(expectedHosts); this.expectedHosts = Sets.newHashSet(expectedHosts);
} }
@Override @Override
public List<TransportAddress> resolveHosts(List<String> hosts, int limitPortCounts) { public List<TransportAddress> resolveHosts(List<String> hosts) {
assertEquals(expectedPortCount, limitPortCounts);
assertEquals(expectedHosts, Sets.newHashSet(hosts)); assertEquals(expectedHosts, Sets.newHashSet(hosts));
resolvedHosts = true; resolvedHosts = true;
return emptyList(); return emptyList();
@ -61,15 +57,19 @@ public class SettingsBasedSeedHostsProviderTests extends ESTestCase {
} }
public void testScansPortsByDefault() { public void testScansPortsByDefault() {
final AssertingHostsResolver hostsResolver = new AssertingHostsResolver(5, "::1", "127.0.0.1"); final AssertingHostsResolver hostsResolver = new AssertingHostsResolver(
"[::1]:9300", "[::1]:9301", "127.0.0.1:9300", "127.0.0.1:9301"
);
final TransportService transportService = mock(TransportService.class); final TransportService transportService = mock(TransportService.class);
when(transportService.getLocalAddresses()).thenReturn(Arrays.asList("::1", "127.0.0.1")); when(transportService.getDefaultSeedAddresses()).thenReturn(
Arrays.asList("[::1]:9300", "[::1]:9301", "127.0.0.1:9300", "127.0.0.1:9301")
);
new SettingsBasedSeedHostsProvider(Settings.EMPTY, transportService).getSeedAddresses(hostsResolver); new SettingsBasedSeedHostsProvider(Settings.EMPTY, transportService).getSeedAddresses(hostsResolver);
assertTrue(hostsResolver.getResolvedHosts()); assertTrue(hostsResolver.getResolvedHosts());
} }
public void testGetsHostsFromSetting() { public void testGetsHostsFromSetting() {
final AssertingHostsResolver hostsResolver = new AssertingHostsResolver(1, "bar", "foo"); final AssertingHostsResolver hostsResolver = new AssertingHostsResolver("bar", "foo");
new SettingsBasedSeedHostsProvider(Settings.builder() new SettingsBasedSeedHostsProvider(Settings.builder()
.putList(SettingsBasedSeedHostsProvider.DISCOVERY_SEED_HOSTS_SETTING.getKey(), "foo", "bar") .putList(SettingsBasedSeedHostsProvider.DISCOVERY_SEED_HOSTS_SETTING.getKey(), "foo", "bar")
.build(), null).getSeedAddresses(hostsResolver); .build(), null).getSeedAddresses(hostsResolver);
@ -77,7 +77,7 @@ public class SettingsBasedSeedHostsProviderTests extends ESTestCase {
} }
public void testGetsHostsFromLegacySetting() { public void testGetsHostsFromLegacySetting() {
final AssertingHostsResolver hostsResolver = new AssertingHostsResolver(1, "bar", "foo"); final AssertingHostsResolver hostsResolver = new AssertingHostsResolver("bar", "foo");
new SettingsBasedSeedHostsProvider(Settings.builder() new SettingsBasedSeedHostsProvider(Settings.builder()
.putList(SettingsBasedSeedHostsProvider.LEGACY_DISCOVERY_ZEN_PING_UNICAST_HOSTS_SETTING.getKey(), "foo", "bar") .putList(SettingsBasedSeedHostsProvider.LEGACY_DISCOVERY_ZEN_PING_UNICAST_HOSTS_SETTING.getKey(), "foo", "bar")
.build(), null).getSeedAddresses(hostsResolver); .build(), null).getSeedAddresses(hostsResolver);

View File

@ -19,14 +19,25 @@
package org.elasticsearch.transport; package org.elasticsearch.transport;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.util.MockPageCacheRecycler;
import org.elasticsearch.indices.breaker.NoneCircuitBreakerService;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.TestThreadPool;
import org.hamcrest.Matcher;
import java.io.IOException; import java.io.IOException;
import java.io.StreamCorruptedException; import java.io.StreamCorruptedException;
import java.net.InetSocketAddress;
import java.util.Collections;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.hamcrest.core.IsInstanceOf.instanceOf;
/** Unit tests for {@link TcpTransport} */ /** Unit tests for {@link TcpTransport} */
@ -34,50 +45,26 @@ public class TcpTransportTests extends ESTestCase {
/** Test ipv4 host with a default port works */ /** Test ipv4 host with a default port works */
public void testParseV4DefaultPort() throws Exception { public void testParseV4DefaultPort() throws Exception {
TransportAddress[] addresses = TcpTransport.parse("127.0.0.1", "1234", Integer.MAX_VALUE); TransportAddress[] addresses = TcpTransport.parse("127.0.0.1", 1234);
assertEquals(1, addresses.length); assertEquals(1, addresses.length);
assertEquals("127.0.0.1", addresses[0].getAddress()); assertEquals("127.0.0.1", addresses[0].getAddress());
assertEquals(1234, addresses[0].getPort()); assertEquals(1234, addresses[0].getPort());
} }
/** Test ipv4 host with a default port range works */
public void testParseV4DefaultRange() throws Exception {
TransportAddress[] addresses = TcpTransport.parse("127.0.0.1", "1234-1235", Integer.MAX_VALUE);
assertEquals(2, addresses.length);
assertEquals("127.0.0.1", addresses[0].getAddress());
assertEquals(1234, addresses[0].getPort());
assertEquals("127.0.0.1", addresses[1].getAddress());
assertEquals(1235, addresses[1].getPort());
}
/** Test ipv4 host with port works */ /** Test ipv4 host with port works */
public void testParseV4WithPort() throws Exception { public void testParseV4WithPort() throws Exception {
TransportAddress[] addresses = TcpTransport.parse("127.0.0.1:2345", "1234", Integer.MAX_VALUE); TransportAddress[] addresses = TcpTransport.parse("127.0.0.1:2345", 1234);
assertEquals(1, addresses.length); assertEquals(1, addresses.length);
assertEquals("127.0.0.1", addresses[0].getAddress()); assertEquals("127.0.0.1", addresses[0].getAddress());
assertEquals(2345, addresses[0].getPort()); assertEquals(2345, addresses[0].getPort());
} }
/** Test ipv4 host with port range works */
public void testParseV4WithPortRange() throws Exception {
TransportAddress[] addresses = TcpTransport.parse("127.0.0.1:2345-2346", "1234", Integer.MAX_VALUE);
assertEquals(2, addresses.length);
assertEquals("127.0.0.1", addresses[0].getAddress());
assertEquals(2345, addresses[0].getPort());
assertEquals("127.0.0.1", addresses[1].getAddress());
assertEquals(2346, addresses[1].getPort());
}
/** Test unbracketed ipv6 hosts in configuration fail. Leave no ambiguity */ /** Test unbracketed ipv6 hosts in configuration fail. Leave no ambiguity */
public void testParseV6UnBracketed() throws Exception { public void testParseV6UnBracketed() throws Exception {
try { try {
TcpTransport.parse("::1", "1234", Integer.MAX_VALUE); TcpTransport.parse("::1", 1234);
fail("should have gotten exception"); fail("should have gotten exception");
} catch (IllegalArgumentException expected) { } catch (IllegalArgumentException expected) {
assertTrue(expected.getMessage().contains("must be bracketed")); assertTrue(expected.getMessage().contains("must be bracketed"));
@ -86,53 +73,107 @@ public class TcpTransportTests extends ESTestCase {
/** Test ipv6 host with a default port works */ /** Test ipv6 host with a default port works */
public void testParseV6DefaultPort() throws Exception { public void testParseV6DefaultPort() throws Exception {
TransportAddress[] addresses = TcpTransport.parse("[::1]", "1234", Integer.MAX_VALUE); TransportAddress[] addresses = TcpTransport.parse("[::1]", 1234);
assertEquals(1, addresses.length); assertEquals(1, addresses.length);
assertEquals("::1", addresses[0].getAddress()); assertEquals("::1", addresses[0].getAddress());
assertEquals(1234, addresses[0].getPort()); assertEquals(1234, addresses[0].getPort());
} }
/** Test ipv6 host with a default port range works */
public void testParseV6DefaultRange() throws Exception {
TransportAddress[] addresses = TcpTransport.parse("[::1]", "1234-1235", Integer.MAX_VALUE);
assertEquals(2, addresses.length);
assertEquals("::1", addresses[0].getAddress());
assertEquals(1234, addresses[0].getPort());
assertEquals("::1", addresses[1].getAddress());
assertEquals(1235, addresses[1].getPort());
}
/** Test ipv6 host with port works */ /** Test ipv6 host with port works */
public void testParseV6WithPort() throws Exception { public void testParseV6WithPort() throws Exception {
TransportAddress[] addresses = TcpTransport.parse("[::1]:2345", "1234", Integer.MAX_VALUE); TransportAddress[] addresses = TcpTransport.parse("[::1]:2345", 1234);
assertEquals(1, addresses.length); assertEquals(1, addresses.length);
assertEquals("::1", addresses[0].getAddress()); assertEquals("::1", addresses[0].getAddress());
assertEquals(2345, addresses[0].getPort()); assertEquals(2345, addresses[0].getPort());
} }
/** Test ipv6 host with port range works */ public void testRejectsPortRanges() {
public void testParseV6WithPortRange() throws Exception { expectThrows(
TransportAddress[] addresses = TcpTransport.parse("[::1]:2345-2346", "1234", Integer.MAX_VALUE); NumberFormatException.class,
assertEquals(2, addresses.length); () -> TcpTransport.parse("[::1]:100-200", 1000)
);
assertEquals("::1", addresses[0].getAddress());
assertEquals(2345, addresses[0].getPort());
assertEquals("::1", addresses[1].getAddress());
assertEquals(2346, addresses[1].getPort());
} }
/** Test per-address limit */ public void testDefaultSeedAddressesWithDefaultPort() {
public void testAddressLimit() throws Exception { testDefaultSeedAddresses(Settings.EMPTY, containsInAnyOrder(
TransportAddress[] addresses = TcpTransport.parse("[::1]:100-200", "1000", 3); "[::1]:9300", "[::1]:9301", "[::1]:9302", "[::1]:9303", "[::1]:9304", "[::1]:9305",
assertEquals(3, addresses.length); "127.0.0.1:9300", "127.0.0.1:9301", "127.0.0.1:9302", "127.0.0.1:9303", "127.0.0.1:9304", "127.0.0.1:9305"));
assertEquals(100, addresses[0].getPort()); }
assertEquals(101, addresses[1].getPort());
assertEquals(102, addresses[2].getPort()); public void testDefaultSeedAddressesWithNonstandardGlobalPortRange() {
testDefaultSeedAddresses(Settings.builder().put(TransportSettings.PORT.getKey(), "9500-9600").build(), containsInAnyOrder(
"[::1]:9500", "[::1]:9501", "[::1]:9502", "[::1]:9503", "[::1]:9504", "[::1]:9505",
"127.0.0.1:9500", "127.0.0.1:9501", "127.0.0.1:9502", "127.0.0.1:9503", "127.0.0.1:9504", "127.0.0.1:9505"));
}
public void testDefaultSeedAddressesWithSmallGlobalPortRange() {
testDefaultSeedAddresses(Settings.builder().put(TransportSettings.PORT.getKey(), "9300-9302").build(), containsInAnyOrder(
"[::1]:9300", "[::1]:9301", "[::1]:9302",
"127.0.0.1:9300", "127.0.0.1:9301", "127.0.0.1:9302"));
}
public void testDefaultSeedAddressesWithNonstandardProfilePortRange() {
testDefaultSeedAddresses(Settings.builder()
.put(TransportSettings.PORT_PROFILE.getConcreteSettingForNamespace(TransportSettings.DEFAULT_PROFILE).getKey(), "9500-9600")
.build(),
containsInAnyOrder(
"[::1]:9500", "[::1]:9501", "[::1]:9502", "[::1]:9503", "[::1]:9504", "[::1]:9505",
"127.0.0.1:9500", "127.0.0.1:9501", "127.0.0.1:9502", "127.0.0.1:9503", "127.0.0.1:9504", "127.0.0.1:9505"));
}
public void testDefaultSeedAddressesWithSmallProfilePortRange() {
testDefaultSeedAddresses(Settings.builder()
.put(TransportSettings.PORT_PROFILE.getConcreteSettingForNamespace(TransportSettings.DEFAULT_PROFILE).getKey(), "9300-9302")
.build(),
containsInAnyOrder(
"[::1]:9300", "[::1]:9301", "[::1]:9302",
"127.0.0.1:9300", "127.0.0.1:9301", "127.0.0.1:9302"));
}
public void testDefaultSeedAddressesPrefersProfileSettingToGlobalSetting() {
testDefaultSeedAddresses(Settings.builder()
.put(TransportSettings.PORT_PROFILE.getConcreteSettingForNamespace(TransportSettings.DEFAULT_PROFILE).getKey(), "9300-9302")
.put(TransportSettings.PORT.getKey(), "9500-9600")
.build(),
containsInAnyOrder(
"[::1]:9300", "[::1]:9301", "[::1]:9302",
"127.0.0.1:9300", "127.0.0.1:9301", "127.0.0.1:9302"));
}
public void testDefaultSeedAddressesWithNonstandardSinglePort() {
testDefaultSeedAddresses(Settings.builder().put(TransportSettings.PORT.getKey(), "9500").build(),
containsInAnyOrder("[::1]:9500", "127.0.0.1:9500"));
}
private void testDefaultSeedAddresses(final Settings settings, Matcher<Iterable<? extends String>> seedAddressesMatcher) {
final TestThreadPool testThreadPool = new TestThreadPool("test");
try {
final TcpTransport tcpTransport = new TcpTransport(settings, Version.CURRENT, testThreadPool,
new MockPageCacheRecycler(settings),
new NoneCircuitBreakerService(), writableRegistry(), new NetworkService(Collections.emptyList())) {
@Override
protected TcpServerChannel bind(String name, InetSocketAddress address) {
throw new UnsupportedOperationException();
}
@Override
protected TcpChannel initiateChannel(DiscoveryNode node) {
throw new UnsupportedOperationException();
}
@Override
protected void stopInternal() {
throw new UnsupportedOperationException();
}
};
assertThat(tcpTransport.getDefaultSeedAddresses(), seedAddressesMatcher);
} finally {
testThreadPool.shutdown();
}
} }
public void testDecodeWithIncompleteHeader() throws IOException { public void testDecodeWithIncompleteHeader() throws IOException {

View File

@ -208,7 +208,7 @@ public class MockTransport implements Transport, LifecycleComponent {
} }
@Override @Override
public TransportAddress[] addressesFromString(String address, int perAddressLimit) { public TransportAddress[] addressesFromString(String address) {
return new TransportAddress[0]; return new TransportAddress[0];
} }
@ -238,7 +238,7 @@ public class MockTransport implements Transport, LifecycleComponent {
} }
@Override @Override
public List<String> getLocalAddresses() { public List<String> getDefaultSeedAddresses() {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -118,13 +118,13 @@ public final class StubbableTransport implements Transport {
} }
@Override @Override
public TransportAddress[] addressesFromString(String address, int perAddressLimit) throws UnknownHostException { public TransportAddress[] addressesFromString(String address) throws UnknownHostException {
return delegate.addressesFromString(address, perAddressLimit); return delegate.addressesFromString(address);
} }
@Override @Override
public List<String> getLocalAddresses() { public List<String> getDefaultSeedAddresses() {
return delegate.getLocalAddresses(); return delegate.getDefaultSeedAddresses();
} }
@Override @Override