Skip to content

Commit 8513fd1

Browse files
author
Luca Di Grazia
committed
Reuse Elasticsearch container between test runs for integration tests (#6843)
Added the new `withReuse(true)` flag from this new testcontainers feature: testcontainers/testcontainers-java#1781 This allows not only reusing a container between different tests in the same run, but also keeping the container alive for subsequent runs to decrease container startup time.
1 parent e259a50 commit 8513fd1

File tree

1 file changed

+94
-43
lines changed
  • dataset/GitHub_Java/Graylog2.graylog2-server/graylog2-server/src/test/java/org/graylog/testing/elasticsearch

1 file changed

+94
-43
lines changed

dataset/GitHub_Java/Graylog2.graylog2-server/graylog2-server/src/test/java/org/graylog/testing/elasticsearch/ElasticsearchInstance.java

+94-43
Original file line numberDiff line numberDiff line change
@@ -16,39 +16,68 @@
1616
*/
1717
package org.graylog.testing.elasticsearch;
1818

19+
import com.fasterxml.jackson.databind.JsonNode;
20+
import com.github.joschi.jadconfig.util.Duration;
1921
import com.github.zafarkhaja.semver.Version;
20-
import com.google.common.io.Resources;
22+
import com.google.common.base.Stopwatch;
23+
import com.google.common.collect.ImmutableList;
24+
import io.searchbox.client.JestClient;
25+
import io.searchbox.cluster.State;
26+
import org.graylog.testing.PropertyLoader;
27+
import org.graylog2.bindings.providers.JestClientProvider;
28+
import org.graylog2.indexer.cluster.jest.JestUtils;
29+
import org.graylog2.shared.bindings.providers.ObjectMapperProvider;
2130
import org.junit.rules.ExternalResource;
22-
import org.testcontainers.containers.Network;
31+
import org.slf4j.Logger;
32+
import org.slf4j.LoggerFactory;
2333
import org.testcontainers.containers.wait.strategy.Wait;
2434
import org.testcontainers.elasticsearch.ElasticsearchContainer;
25-
import org.testcontainers.utility.DockerImageName;
2635

27-
import java.net.URL;
28-
import java.nio.file.Paths;
36+
import java.net.URI;
2937
import java.util.HashMap;
30-
import java.util.Locale;
3138
import java.util.Map;
39+
import java.util.Properties;
40+
import java.util.concurrent.TimeUnit;
41+
42+
import static com.google.common.collect.Iterators.toArray;
3243

3344
/**
34-
* This rule starts an Elasticsearch instance and provides a configured {@link Client}.
45+
* This rule starts an Elasticsearch instance and provides a configured {@link JestClient}.
3546
*/
36-
public abstract class ElasticsearchInstance extends ExternalResource {
47+
public class ElasticsearchInstance extends ExternalResource {
48+
49+
private static final Logger LOG = LoggerFactory.getLogger(ElasticsearchInstance.class);
50+
3751
private static final Map<Version, ElasticsearchContainer> containersByVersion = new HashMap<>();
3852

53+
private static final String PROPERTIES_RESOURCE_NAME = "elasticsearch.properties";
54+
3955
private static final String DEFAULT_IMAGE_OSS = "docker.elastic.co/elasticsearch/elasticsearch-oss";
4056
private static final String DEFAULT_IMAGE = "elasticsearch";
57+
private static final String DEFAULT_VERSION = "6.8.4";
4158

42-
private static final int ES_PORT = 9200;
43-
private static final String NETWORK_ALIAS = "elasticsearch";
44-
59+
private final ElasticsearchContainer container;
60+
private JestClient jestClient;
61+
private Client client;
62+
private FixtureImporter fixtureImporter = new FixtureImporter();
4563
private final Version version;
46-
protected final ElasticsearchContainer container;
4764

48-
protected abstract Client client();
49-
protected abstract FixtureImporter fixtureImporter();
65+
public static ElasticsearchInstance create() {
66+
final Properties properties = PropertyLoader.loadProperties(PROPERTIES_RESOURCE_NAME);
67+
68+
return create(properties.getProperty("version", DEFAULT_VERSION));
69+
}
70+
71+
public static ElasticsearchInstance create(String versionString) {
72+
final Version version = Version.valueOf(versionString);
73+
final String image = imageNameFrom(version);
74+
75+
LOG.debug("Creating instance {}", image);
76+
77+
return new ElasticsearchInstance(image, version);
78+
}
5079

51-
protected static String imageNameFrom(Version version) {
80+
private static String imageNameFrom(Version version) {
5281
final String defaultImage = version.satisfies("^6.0.0")
5382
// The OSS image only exists for 6.0.0 and later
5483
? DEFAULT_IMAGE_OSS
@@ -57,60 +86,82 @@ protected static String imageNameFrom(Version version) {
5786
return defaultImage + ":" + version.toString();
5887
}
5988

60-
protected ElasticsearchInstance(String image, Version version, Network network) {
89+
private ElasticsearchInstance(String image, Version version) {
6190
this.version = version;
62-
63-
this.container = createContainer(image, version, network);
91+
this.container = createContainer(image, version);
6492
}
6593

66-
private ElasticsearchContainer createContainer(String image, Version version, Network network) {
94+
private static ElasticsearchContainer createContainer(String image, Version version) {
6795
if (!containersByVersion.containsKey(version)) {
68-
ElasticsearchContainer container = buildContainer(image, network);
69-
container.start();
70-
containersByVersion.put(version, container);
96+
containersByVersion.put(version, startNewContainerInstance(image));
7197
}
7298
return containersByVersion.get(version);
7399
}
74100

75-
private ElasticsearchContainer buildContainer(String image, Network network) {
76-
return new ElasticsearchContainer(DockerImageName.parse(image).asCompatibleSubstituteFor("docker.elastic.co/elasticsearch/elasticsearch"))
101+
private static ElasticsearchContainer startNewContainerInstance(String image) {
102+
final Stopwatch sw = Stopwatch.createStarted();
103+
104+
final ElasticsearchContainer container = new ElasticsearchContainer(image)
77105
.withReuse(true)
78-
.withEnv("ES_JAVA_OPTS", "-Xms2g -Xmx2g")
106+
.withEnv("ES_JAVA_OPTS", "-Xms512m -Xmx512m")
79107
.withEnv("discovery.type", "single-node")
80-
.withEnv("action.auto_create_index", ".watches,.triggered_watches,.watcher-history-*")
81-
.withEnv("cluster.info.update.interval", "10s")
82-
.withNetwork(network)
83-
.withNetworkAliases(NETWORK_ALIAS)
84-
.waitingFor(Wait.forHttp("/").forPort(ES_PORT));
108+
.withEnv("action.auto_create_index", "false")
109+
.waitingFor(Wait.forHttp("/").forPort(9200));
110+
container.start();
111+
LOG.debug("Started container {} in {}ms", container.getContainerInfo().getName(), sw.elapsed(TimeUnit.MILLISECONDS));
112+
return container;
113+
}
114+
115+
@Override
116+
protected void before() {
117+
jestClient = new JestClientProvider(
118+
ImmutableList.of(URI.create("http://" + container.getHttpHostAddress())),
119+
Duration.seconds(60),
120+
Duration.seconds(60),
121+
Duration.seconds(60),
122+
1,
123+
1,
124+
1,
125+
false,
126+
null,
127+
Duration.seconds(60),
128+
false,
129+
new ObjectMapperProvider().get()
130+
).get();
131+
132+
client = new Client(jestClient);
85133
}
86134

87135
@Override
88136
protected void after() {
89137
cleanUp();
90138
}
91139

92-
public void cleanUp() {
93-
client().cleanUp();
140+
private void cleanUp() {
141+
final State request = new State.Builder().withMetadata().build();
142+
final JsonNode result = JestUtils.execute(jestClient, request, () -> "failed to read state").getJsonObject();
143+
144+
client.deleteTemplates(metadataFieldNamesFor(result, "templates"));
145+
client.deleteIndices(metadataFieldNamesFor(result, "indices"));
94146
}
95147

96-
public static String internalUri() {
97-
return String.format(Locale.US, "http://%s:%d", NETWORK_ALIAS, ES_PORT);
148+
private String[] metadataFieldNamesFor(JsonNode result, String templates) {
149+
return toArray(result.get("metadata").get(templates).fieldNames(), String.class);
98150
}
99151

100152
public Version version() {
101153
return version;
102154
}
103155

104-
public void importFixtureResource(String resourcePath, Class<?> testClass) {
105-
boolean isFullResourcePath = Paths.get(resourcePath).getNameCount() > 1;
106-
107-
@SuppressWarnings("UnstableApiUsage") final URL fixtureResource = isFullResourcePath
108-
? Resources.getResource(resourcePath)
109-
: Resources.getResource(testClass, resourcePath);
156+
public JestClient jestClient() {
157+
return jestClient;
158+
}
110159

111-
fixtureImporter().importResource(fixtureResource);
160+
public Client client() {
161+
return client;
162+
}
112163

113-
// Make sure the data we just imported is visible
114-
client().refreshNode();
164+
FixtureImporter fixtureImporter() {
165+
return fixtureImporter;
115166
}
116167
}

0 commit comments

Comments
 (0)