[TEST] added ExternalTestCluster that allows to run tests against an external cluster

All the ordinary test operations happen based on the ImmutableTestCluster base class and are executed via transport client. Will be used especially for the REST tests once migrated to the standard randomized runner.

Added new httpAddresses method to ImmutableTestCluster to be able to retrieve the http addresses to connect to for the REST tests. Both versions will look inside the cluster to figure out which nodes are available for http calls and their addresses.

The external cluster is used as global cluster if the tests.cluster system property is available. The property needs to contain a comma separated list of available elasticsearch nodes that will be used to connect to the cluster (e.g. localhost:9300,localhost:9301).

Only a subset of the integration tests can currently be run successfully against the external cluster, for more precision the ones that don't modify the cluster layout (don't require cluster() functionalities but rely only on immutableCluster()). Also at least two data nodes are required otherwise the ensureGreen calls cannot succeed.

Closes #5630
This commit is contained in:
javanna 2014-03-31 19:41:24 +02:00 committed by Luca Cavanna
parent 70c089de0a
commit 38dd501ab5
5 changed files with 145 additions and 6 deletions

View File

@ -469,6 +469,7 @@
<tests.rest.suite>${tests.rest.suite}</tests.rest.suite>
<tests.rest.spec>${tests.rest.spec}</tests.rest.spec>
<tests.network>${tests.network}</tests.network>
<tests.cluster>${tests.cluster}</tests.cluster>
<es.node.local>${env.ES_TEST_LOCAL}</es.node.local>
<es.node.mode>${es.node.mode}</es.node.mode>
<es.logger.level>${es.logger.level}</es.logger.level>

View File

@ -48,9 +48,12 @@ import org.elasticsearch.client.internal.InternalClient;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.Priority;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.discovery.zen.elect.ElectMasterService;
@ -137,7 +140,7 @@ import static org.hamcrest.Matchers.equalTo;
@Ignore
@AbstractRandomizedTest.IntegrationTests
public abstract class ElasticsearchIntegrationTest extends ElasticsearchTestCase {
private static TestCluster GLOBAL_CLUSTER;
private static ImmutableTestCluster GLOBAL_CLUSTER;
/**
* Key used to set the transport client ratio via the commandline -D{@value #TESTS_CLIENT_RATIO}
@ -177,8 +180,27 @@ public abstract class ElasticsearchIntegrationTest extends ElasticsearchTestCase
// Initialize lazily. No need for volatiles/ CASs since each JVM runs at most one test
// suite at any given moment.
if (GLOBAL_CLUSTER == null) {
long masterSeed = SeedUtils.parseSeed(RandomizedContext.current().getRunnerSeedAsString());
GLOBAL_CLUSTER = new TestCluster(masterSeed, clusterName("shared", ElasticsearchTestCase.CHILD_VM_ID, masterSeed));
String cluster = System.getProperty("tests.cluster");
if (Strings.hasLength(cluster)) {
String[] stringAddresses = cluster.split(",");
TransportAddress[] transportAddresses = new TransportAddress[stringAddresses.length];
int i = 0;
for (String stringAddress : stringAddresses) {
String[] split = stringAddress.split(":");
if (split.length < 2) {
throw new IllegalArgumentException("address [" + cluster + "] not valid");
}
try {
transportAddresses[i++] = new InetSocketTransportAddress(split[0], Integer.valueOf(split[1]));
} catch(NumberFormatException e) {
throw new IllegalArgumentException("port is not valid, expected number but was [" + split[1] + "]");
}
}
GLOBAL_CLUSTER = new ExternalTestCluster(transportAddresses);
} else {
long masterSeed = SeedUtils.parseSeed(RandomizedContext.current().getRunnerSeedAsString());
GLOBAL_CLUSTER = new TestCluster(masterSeed, clusterName("shared", ElasticsearchTestCase.CHILD_VM_ID, masterSeed));
}
}
}

View File

@ -0,0 +1,98 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.test;
import com.google.common.collect.Lists;
import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import java.net.InetSocketAddress;
import java.util.Iterator;
/**
* External cluster to run the tests against.
* It is a pure immutable test cluster that allows to send requests to a pre-existing cluster
* and supports by nature all the needed test operations like wipeIndices etc.
*/
public final class ExternalTestCluster extends ImmutableTestCluster {
private final Client client;
private final InetSocketAddress[] httpAddresses;
private final int dataNodes;
public ExternalTestCluster(TransportAddress... transportAddresses) {
this.client = new TransportClient(ImmutableSettings.settingsBuilder().put("client.transport.ignore_cluster_name", true))
.addTransportAddresses(transportAddresses);
NodesInfoResponse nodeInfos = this.client.admin().cluster().prepareNodesInfo().clear().setSettings(true).setHttp(true).get();
httpAddresses = new InetSocketAddress[nodeInfos.getNodes().length];
int dataNodes = 0;
for (int i = 0; i < nodeInfos.getNodes().length; i++) {
NodeInfo nodeInfo = nodeInfos.getNodes()[i];
httpAddresses[i] = ((InetSocketTransportAddress) nodeInfo.getHttp().address().publishAddress()).address();
if (nodeInfo.getSettings().getAsBoolean("node.data", true)) {
dataNodes++;
}
}
this.dataNodes = dataNodes;
}
@Override
public void afterTest() {
}
@Override
public Client client() {
return client;
}
@Override
public int size() {
return httpAddresses.length;
}
@Override
public int dataNodes() {
return dataNodes;
}
@Override
public InetSocketAddress[] httpAddresses() {
return httpAddresses;
}
@Override
public void close() {
client.close();
}
@Override
public Iterator<Client> iterator() {
return Lists.newArrayList(client).iterator();
}
}

View File

@ -42,14 +42,13 @@ import org.elasticsearch.indices.IndexTemplateMissingException;
import org.elasticsearch.repositories.RepositoryMissingException;
import org.elasticsearch.search.SearchService;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Random;
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS;
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAllFilesClosed;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAllSearchersClosed;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.*;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
@ -123,6 +122,12 @@ public abstract class ImmutableTestCluster implements Iterable<Client> {
*/
public abstract int dataNodes();
/**
* Returns the http addresses of the nodes within the cluster.
* Can be used to run REST tests against the test cluster.
*/
public abstract InetSocketAddress[] httpAddresses();
/**
* Closes the current cluster
*/

View File

@ -24,6 +24,7 @@ import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.lucene.util.IOUtils;
import org.elasticsearch.ElasticsearchIllegalStateException;
@ -46,10 +47,12 @@ import org.elasticsearch.common.network.NetworkUtils;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.ImmutableSettings.Builder;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.BigArraysModule;
import org.elasticsearch.env.NodeEnvironment;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.index.engine.IndexEngineModule;
import org.elasticsearch.node.Node;
import org.elasticsearch.node.internal.InternalNode;
@ -68,6 +71,7 @@ import org.junit.Assert;
import java.io.Closeable;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@ -802,6 +806,15 @@ public final class TestCluster extends ImmutableTestCluster {
return this.nodes.size();
}
@Override
public InetSocketAddress[] httpAddresses() {
List<InetSocketAddress> addresses = Lists.newArrayList();
for (HttpServerTransport httpServerTransport : getInstances(HttpServerTransport.class)) {
addresses.add(((InetSocketTransportAddress) httpServerTransport.boundAddress().publishAddress()).address());
}
return addresses.toArray(new InetSocketAddress[addresses.size()]);
}
/**
* Stops a random node in the cluster.
*/