|
18 | 18 | */ |
19 | 19 | package org.elasticsearch.transport; |
20 | 20 |
|
| 21 | +import org.apache.lucene.util.IOUtils; |
21 | 22 | import org.elasticsearch.Version; |
22 | 23 | import org.elasticsearch.action.ActionListener; |
23 | 24 | import org.elasticsearch.cluster.node.DiscoveryNode; |
|
34 | 35 | import java.net.InetSocketAddress; |
35 | 36 | import java.util.Arrays; |
36 | 37 | import java.util.Collections; |
| 38 | +import java.util.HashSet; |
37 | 39 | import java.util.List; |
38 | 40 | import java.util.Map; |
39 | 41 | import java.util.concurrent.CopyOnWriteArrayList; |
40 | 42 | import java.util.concurrent.CountDownLatch; |
41 | 43 | import java.util.concurrent.TimeUnit; |
| 44 | +import java.util.concurrent.atomic.AtomicReference; |
| 45 | +import java.util.function.BiFunction; |
42 | 46 |
|
43 | 47 | public class RemoteClusterServiceTests extends ESTestCase { |
44 | 48 |
|
@@ -303,4 +307,151 @@ private ActionListener<Void> connectionListener(final CountDownLatch latch) { |
303 | 307 | return ActionListener.wrap(x -> latch.countDown(), x -> fail()); |
304 | 308 | } |
305 | 309 |
|
| 310 | + |
| 311 | + public void testCollectNodes() throws InterruptedException, IOException { |
| 312 | + final Settings settings = Settings.EMPTY; |
| 313 | + final List<DiscoveryNode> knownNodes_c1 = new CopyOnWriteArrayList<>(); |
| 314 | + final List<DiscoveryNode> knownNodes_c2 = new CopyOnWriteArrayList<>(); |
| 315 | + |
| 316 | + try (MockTransportService c1N1 = |
| 317 | + startTransport("cluster_1_node_1", knownNodes_c1, Version.CURRENT); |
| 318 | + MockTransportService c1N2 = |
| 319 | + startTransport("cluster_1_node_2", knownNodes_c1, Version.CURRENT); |
| 320 | + MockTransportService c2N1 = |
| 321 | + startTransport("cluster_2_node_1", knownNodes_c2, Version.CURRENT); |
| 322 | + MockTransportService c2N2 = |
| 323 | + startTransport("cluster_2_node_2", knownNodes_c2, Version.CURRENT)) { |
| 324 | + final DiscoveryNode c1N1Node = c1N1.getLocalDiscoNode(); |
| 325 | + final DiscoveryNode c1N2Node = c1N2.getLocalDiscoNode(); |
| 326 | + final DiscoveryNode c2N1Node = c2N1.getLocalDiscoNode(); |
| 327 | + final DiscoveryNode c2N2Node = c2N2.getLocalDiscoNode(); |
| 328 | + knownNodes_c1.add(c1N1Node); |
| 329 | + knownNodes_c1.add(c1N2Node); |
| 330 | + knownNodes_c2.add(c2N1Node); |
| 331 | + knownNodes_c2.add(c2N2Node); |
| 332 | + Collections.shuffle(knownNodes_c1, random()); |
| 333 | + Collections.shuffle(knownNodes_c2, random()); |
| 334 | + |
| 335 | + try (MockTransportService transportService = MockTransportService.createNewService( |
| 336 | + settings, |
| 337 | + Version.CURRENT, |
| 338 | + threadPool, |
| 339 | + null)) { |
| 340 | + transportService.start(); |
| 341 | + transportService.acceptIncomingRequests(); |
| 342 | + final Settings.Builder builder = Settings.builder(); |
| 343 | + builder.putArray( |
| 344 | + "search.remote.cluster_1.seeds", c1N1Node.getAddress().toString()); |
| 345 | + builder.putArray( |
| 346 | + "search.remote.cluster_2.seeds", c2N1Node.getAddress().toString()); |
| 347 | + try (RemoteClusterService service = |
| 348 | + new RemoteClusterService(settings, transportService)) { |
| 349 | + assertFalse(service.isCrossClusterSearchEnabled()); |
| 350 | + service.initializeRemoteClusters(); |
| 351 | + assertFalse(service.isCrossClusterSearchEnabled()); |
| 352 | + |
| 353 | + final InetSocketAddress c1N1Address = ((InetSocketTransportAddress)c1N1Node.getAddress()).address(); |
| 354 | + final InetSocketAddress c1N2Address = ((InetSocketTransportAddress)c1N2Node.getAddress()).address(); |
| 355 | + final InetSocketAddress c2N1Address = ((InetSocketTransportAddress)c2N1Node.getAddress()).address(); |
| 356 | + final InetSocketAddress c2N2Address = ((InetSocketTransportAddress)c2N2Node.getAddress()).address(); |
| 357 | + |
| 358 | + final CountDownLatch firstLatch = new CountDownLatch(1); |
| 359 | + service.updateRemoteCluster( |
| 360 | + "cluster_1", |
| 361 | + Arrays.asList(c1N1Address, c1N2Address), |
| 362 | + connectionListener(firstLatch)); |
| 363 | + firstLatch.await(); |
| 364 | + |
| 365 | + final CountDownLatch secondLatch = new CountDownLatch(1); |
| 366 | + service.updateRemoteCluster( |
| 367 | + "cluster_2", |
| 368 | + Arrays.asList(c2N1Address, c2N2Address), |
| 369 | + connectionListener(secondLatch)); |
| 370 | + secondLatch.await(); |
| 371 | + CountDownLatch latch = new CountDownLatch(1); |
| 372 | + service.collectNodes(new HashSet<>(Arrays.asList("cluster_1", "cluster_2")), |
| 373 | + new ActionListener<BiFunction<String, String, DiscoveryNode>>() { |
| 374 | + @Override |
| 375 | + public void onResponse(BiFunction<String, String, DiscoveryNode> func) { |
| 376 | + try { |
| 377 | + assertEquals(c1N1Node, func.apply("cluster_1", c1N1Node.getId())); |
| 378 | + assertEquals(c1N2Node, func.apply("cluster_1", c1N2Node.getId())); |
| 379 | + assertEquals(c2N1Node, func.apply("cluster_2", c2N1Node.getId())); |
| 380 | + assertEquals(c2N2Node, func.apply("cluster_2", c2N2Node.getId())); |
| 381 | + } finally { |
| 382 | + latch.countDown(); |
| 383 | + } |
| 384 | + } |
| 385 | + |
| 386 | + @Override |
| 387 | + public void onFailure(Exception e) { |
| 388 | + try { |
| 389 | + throw new AssertionError(e); |
| 390 | + } finally { |
| 391 | + latch.countDown(); |
| 392 | + } |
| 393 | + } |
| 394 | + }); |
| 395 | + latch.await(); |
| 396 | + { |
| 397 | + CountDownLatch failLatch = new CountDownLatch(1); |
| 398 | + AtomicReference<Exception> ex = new AtomicReference<>(); |
| 399 | + service.collectNodes(new HashSet<>(Arrays.asList("cluster_1", "cluster_2", "no such cluster")), |
| 400 | + new ActionListener<BiFunction<String, String, DiscoveryNode>>() { |
| 401 | + @Override |
| 402 | + public void onResponse(BiFunction<String, String, DiscoveryNode> stringStringDiscoveryNodeBiFunction) { |
| 403 | + try { |
| 404 | + fail("should not be called"); |
| 405 | + } finally { |
| 406 | + failLatch.countDown(); |
| 407 | + } |
| 408 | + } |
| 409 | + |
| 410 | + @Override |
| 411 | + public void onFailure(Exception e) { |
| 412 | + try { |
| 413 | + ex.set(e); |
| 414 | + } finally { |
| 415 | + failLatch.countDown(); |
| 416 | + } |
| 417 | + } |
| 418 | + }); |
| 419 | + failLatch.await(); |
| 420 | + assertNotNull(ex.get()); |
| 421 | + assertTrue(ex.get() instanceof IllegalArgumentException); |
| 422 | + assertEquals("no such remote cluster: [no such cluster]", ex.get().getMessage()); |
| 423 | + } |
| 424 | + { |
| 425 | + // close all targets and check for the transport level failure path |
| 426 | + IOUtils.close(c1N1, c1N2, c2N1, c2N2); |
| 427 | + CountDownLatch failLatch = new CountDownLatch(1); |
| 428 | + AtomicReference<Exception> ex = new AtomicReference<>(); |
| 429 | + service.collectNodes(new HashSet<>(Arrays.asList("cluster_1", "cluster_2")), |
| 430 | + new ActionListener<BiFunction<String, String, DiscoveryNode>>() { |
| 431 | + @Override |
| 432 | + public void onResponse(BiFunction<String, String, DiscoveryNode> stringStringDiscoveryNodeBiFunction) { |
| 433 | + try { |
| 434 | + fail("should not be called"); |
| 435 | + } finally { |
| 436 | + failLatch.countDown(); |
| 437 | + } |
| 438 | + } |
| 439 | + |
| 440 | + @Override |
| 441 | + public void onFailure(Exception e) { |
| 442 | + try { |
| 443 | + ex.set(e); |
| 444 | + } finally { |
| 445 | + failLatch.countDown(); |
| 446 | + } |
| 447 | + } |
| 448 | + }); |
| 449 | + failLatch.await(); |
| 450 | + assertNotNull(ex.get()); |
| 451 | + assertTrue(ex.get().getClass().toString(), ex.get() instanceof TransportException); |
| 452 | + } |
| 453 | + } |
| 454 | + } |
| 455 | + } |
| 456 | + } |
306 | 457 | } |
0 commit comments