Elasticsearch container
This module helps running elasticsearch using Testcontainers.
Note that it's based on the official Docker image provided by elastic.
Usage example
You can start an elasticsearch container instance from any Java application by using:
// Create the elasticsearch container.
try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE)) {
// Start the container. This step might take some time...
container.start();
// Do whatever you want with the rest client ...
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials(ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD)
);
client =
RestClient
.builder(HttpHost.create(container.getHttpHostAddress()))
.setHttpClientConfigCallback(httpClientBuilder -> {
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
})
.build();
Response response = client.performRequest(new Request("GET", "/_cluster/health"));
⋯
}
// Create the elasticsearch container.
try (
ElasticsearchContainer container = new ElasticsearchContainer(
"docker.elastic.co/elasticsearch/elasticsearch:8.1.2"
)
) {
// Start the container. This step might take some time...
container.start();
// Do whatever you want with the rest client ...
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials(ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD)
);
client =
RestClient
// use HTTPS for Elasticsearch 8
.builder(HttpHost.create("https://" + container.getHttpHostAddress()))
.setHttpClientConfigCallback(httpClientBuilder -> {
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
// SSL is activated by default in Elasticsearch 8
httpClientBuilder.setSSLContext(container.createSslContextFromCa());
return httpClientBuilder;
})
.build();
Response response = client.performRequest(new Request("GET", "/_cluster/health"));
⋯
}
// Create the elasticsearch container.
try (
ElasticsearchContainer container = new ElasticsearchContainer(
"docker.elastic.co/elasticsearch/elasticsearch:8.1.2"
)
// disable SSL
.withEnv("xpack.security.transport.ssl.enabled", "false")
.withEnv("xpack.security.http.ssl.enabled", "false")
) {
// Start the container. This step might take some time...
container.start();
// Do whatever you want with the rest client ...
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials(ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD)
);
client =
RestClient
.builder(HttpHost.create(container.getHttpHostAddress()))
.setHttpClientConfigCallback(httpClientBuilder -> {
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
})
.build();
Response response = client.performRequest(new Request("GET", "/_cluster/health"));
⋯
}
// Create the elasticsearch container.
try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE)) {
// Start the container. This step might take some time...
container.start();
// Do whatever you want with the transport client
TransportAddress transportAddress = new TransportAddress(container.getTcpHost());
String expectedClusterName = "docker-cluster";
Settings settings = Settings.builder().put("cluster.name", expectedClusterName).build();
try (
TransportClient transportClient = new PreBuiltTransportClient(settings)
.addTransportAddress(transportAddress)
) {
ClusterHealthResponse healths = transportClient.admin().cluster().prepareHealth().get();
String clusterName = healths.getClusterName();
⋯
}
}
Note that if you are still using the TransportClient
(not recommended as it is deprecated), the default cluster name is set to docker-cluster so you need to change cluster.name setting
or set client.transport.ignore_cluster_name to true.
Secure your Elasticsearch cluster
The default distribution of Elasticsearch comes with the basic license which contains security feature. You can turn on security by providing a password:
// Create the elasticsearch container.
try (
ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE)
// With a password
.withPassword(ELASTICSEARCH_PASSWORD)
) {
// Start the container. This step might take some time...
container.start();
// Create the secured client.
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials(ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD)
);
client =
RestClient
.builder(HttpHost.create(container.getHttpHostAddress()))
.setHttpClientConfigCallback(httpClientBuilder -> {
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
})
.build();
Response response = client.performRequest(new Request("GET", "/_cluster/health"));
⋯
}
Kibana container
This module also provides a KibanaContainer for testing with Kibana.
Kibana requires a connection to Elasticsearch and KibanaContainer supports two modes: managed and external.
Managed mode
In managed mode, KibanaContainer automatically connects to an ElasticsearchContainer:
// managedModeCanStartAndReachElasticsearchInSameExplicitNetwork {
try (
Network network = Network.newNetwork();
ElasticsearchContainer es = new ElasticsearchContainer(ES_IMAGE).withNetwork(network);
KibanaContainer kibana = new KibanaContainer(es).withNetwork(network)
) {
es.start();
kibana.start();
String status = getKibanaStatus(kibana);
Assertions.assertThat(status).isEqualTo("available");
}
// }
When using managed mode with explicit networks, both containers must share the same Network instance.
Alternatively, you can omit the network configuration entirely, and KibanaContainer will do its best effort to create a shared, ad-hoc network automatically.
External mode
In external mode, KibanaContainer connects to an external Elasticsearch instance via URL and using provided credentials:
final String esHostname = "elasticsearch";
// externalModeCanWorkWithUsernamePassword {
try (
Network network = Network.newNetwork();
ElasticsearchContainer es = new ElasticsearchContainer(ES_IMAGE)
.withNetwork(network)
.withNetworkAliases(esHostname)
.withEnv("xpack.security.http.ssl.enabled", "false")
) {
es.start();
String kibanaSystemPassword = setKibanaSystemPassword(es);
try (
KibanaContainer kibana = new KibanaContainer("docker.elastic.co/kibana/kibana:9.2.2") //this minor version is intentionally below ES version
.withNetwork(network)
.withElasticsearchUrl("http://" + esHostname + ":9200")
.withKibanaSystemPassword(kibanaSystemPassword)
) {
kibana.start();
String status = getKibanaStatus(kibana);
Assertions.assertThat(status).isEqualTo("available");
}
}
// }
For external mode with HTTPS, use withElasticsearchCaCertificate() to provide the CA certificate.
You can authenticate using either username/password (withElasticsearchCredentials()) or service account tokens (withElasticsearchServiceAccountToken()).
Adding this module to your project dependencies
Add the following dependency to your pom.xml/build.gradle file:
testImplementation "org.testcontainers:testcontainers-elasticsearch:2.0.5"
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-elasticsearch</artifactId>
<version>2.0.5</version>
<scope>test</scope>
</dependency>