Skip to content

Commit

Permalink
Change latest version to 7.9.2
Browse files Browse the repository at this point in the history
Add a test for secured cluster
This can be now activated for free with the default basic license.
  • Loading branch information
dadoonet committed Oct 15, 2020
1 parent ae5010a commit c5be8dd
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 16 deletions.
13 changes: 11 additions & 2 deletions docs/modules/elasticsearch.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
This module helps running [elasticsearch](https://www.elastic.co/products/elasticsearch) using
Testcontainers.

Note that it's based on the [official Docker image](https://www.elastic.co/guide/en/elasticsearch/reference/6.3/docker.html) provided by elastic.
Note that it's based on the [official Docker image](https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html) provided by elastic.

## Usage example

Expand All @@ -15,10 +15,19 @@ You can start an elasticsearch container instance from any Java application by u
<!--/codeinclude-->


Note that if you are still using the [TransportClient](https://www.elastic.co/guide/en/elasticsearch/client/java-api/6.3/transport-client.html)
Note that if you are still using the [TransportClient](https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html)
(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 some extra environment settings:

<!--codeinclude-->
[HttpClient](../../modules/elasticsearch/src/test/java/org/testcontainers/elasticsearch/ElasticsearchContainerTest.java) inside_block:httpClientSecuredContainer
<!--/codeinclude-->

## Choose your Elasticsearch license

If you prefer to start a Docker image with the pure OSS version (which means with no security in older versions or
Expand Down
2 changes: 1 addition & 1 deletion modules/elasticsearch/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ description = "TestContainers :: elasticsearch"
dependencies {
compile project(':testcontainers')
testCompile "org.elasticsearch.client:elasticsearch-rest-client:7.9.2"
testCompile "org.elasticsearch.client:transport:6.7.1"
testCompile "org.elasticsearch.client:transport:7.9.2"
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,16 @@ public class ElasticsearchContainer extends GenericContainer<ElasticsearchContai
/**
* Elasticsearch Docker base image
*/
@Deprecated
private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch");
@Deprecated
private static final DockerImageName DEFAULT_OSS_IMAGE_NAME = DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch-oss");

/**
* Elasticsearch Default version
*/
protected static final String DEFAULT_TAG = "6.4.1";
@Deprecated
protected static final String DEFAULT_TAG = "7.9.2";

/**
* @deprecated use {@link ElasticsearchContainer(DockerImageName)} instead
Expand All @@ -47,7 +50,7 @@ public ElasticsearchContainer() {

/**
* Create an Elasticsearch Container by passing the full docker image name
* @param dockerImageName Full docker image name as a {@link String}, like: docker.elastic.co/elasticsearch/elasticsearch:6.4.1
* @param dockerImageName Full docker image name as a {@link String}, like: docker.elastic.co/elasticsearch/elasticsearch:7.8.0
*/
public ElasticsearchContainer(String dockerImageName) {
this(DockerImageName.parse(dockerImageName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.Version;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
Expand All @@ -32,35 +31,41 @@ public class ElasticsearchContainerTest {
/**
* Elasticsearch version which should be used for the Tests
*/
private static final String ELASTICSEARCH_VERSION = Version.CURRENT.toString();
private static final String ELASTICSEARCH_VERSION = "7.9.2";
private static final DockerImageName ELASTICSEARCH_IMAGE =
DockerImageName
.parse("docker.elastic.co/elasticsearch/elasticsearch")
.withTag(ELASTICSEARCH_VERSION);

/**
* Elasticsearch default username, when secured with a license > basic
* Elasticsearch default username, when secured
*/
private static final String ELASTICSEARCH_USERNAME = "elastic";

/**
* Elasticsearch 5.x default password. In 6.x images, there's no security by default as shipped with a basic license.
* From 6.8, we can optionally activate security with a default password.
*/
private static final String ELASTICSEARCH_PASSWORD = "changeme";

private RestClient client = null;
private RestClient anonymousClient = null;

@After
public void stopRestClient() throws IOException {
if (client != null) {
client.close();
client = null;
}
if (anonymousClient != null) {
anonymousClient.close();
anonymousClient = null;
}
}

@SuppressWarnings("deprecation") // Using deprecated constructor for verification of backwards compatibility
@Test
public void elasticsearchDefaultTest() throws IOException {
@Deprecated // We will remove this test in the future
public void elasticsearchDeprecatedCtorTest() throws IOException {
// Create the elasticsearch container.
try (ElasticsearchContainer container = new ElasticsearchContainer()
.withEnv("foo", "bar") // dummy env for compiler checking correct generics usage
Expand All @@ -81,6 +86,48 @@ public void elasticsearchDefaultTest() throws IOException {
}
}

@Test
public void elasticsearchDefaultTest() throws IOException {
// Create the elasticsearch container.
try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE)
.withEnv("foo", "bar") // dummy env for compiler checking correct generics usage
) {
// Start the container. This step might take some time...
container.start();

// Do whatever you want with the rest client ...
Response response = getClient(container).performRequest(new Request("GET", "/"));
assertThat(response.getStatusLine().getStatusCode(), is(200));
assertThat(EntityUtils.toString(response.getEntity()), containsString(ELASTICSEARCH_VERSION));

// The default image is running with the features under Elastic License
response = getClient(container).performRequest(new Request("GET", "/_xpack/"));
assertThat(response.getStatusLine().getStatusCode(), is(200));
// For now we test that we have the monitoring feature available
assertThat(EntityUtils.toString(response.getEntity()), containsString("monitoring"));
}
}

@Test
public void elasticsearchSecuredTest() throws IOException {
try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE)
.withEnv("ELASTIC_PASSWORD", ELASTICSEARCH_PASSWORD)
.withEnv("xpack.security.enabled", "true")
) {
container.start();

// The cluster should be secured so it must fail when we try to access / without credentials
assertThrows("We should not be able to access / URI with an anonymous client.",
ResponseException.class,
() -> getAnonymousClient(container).performRequest(new Request("GET", "/")));

// But it should work when we try to access / with the proper login and password
Response response = getClient(container).performRequest(new Request("GET", "/"));
assertThat(response.getStatusLine().getStatusCode(), is(200));
assertThat(EntityUtils.toString(response.getEntity()), containsString(ELASTICSEARCH_VERSION));
}
}

@Test
public void elasticsearchVersion() throws IOException {
try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE)) {
Expand Down Expand Up @@ -118,7 +165,7 @@ public void elasticsearchOssImage() throws IOException {
public void restClientClusterHealth() throws IOException {
// httpClientContainer {
// Create the elasticsearch container.
try (ElasticsearchContainer container = new ElasticsearchContainer()) {
try (ElasticsearchContainer container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:" + ELASTICSEARCH_VERSION)) {
// Start the container. This step might take some time...
container.start();

Expand All @@ -140,15 +187,39 @@ public void restClientClusterHealth() throws IOException {
// }
}

@Test
public void restClientSecuredClusterHealth() throws IOException {
// httpClientSecuredContainer {
// Create the elasticsearch container.
try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE)
// With a password
.withEnv("ELASTIC_PASSWORD", ELASTICSEARCH_PASSWORD)
.withEnv("xpack.security.enabled", "true")) {
// 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 -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider))
.build();

Response response = client.performRequest(new Request("GET", "/_cluster/health"));
assertThat(response.getStatusLine().getStatusCode(), is(200));
assertThat(EntityUtils.toString(response.getEntity()), containsString("cluster_name"));
// httpClientSecuredContainer {{
}
// }
}

@Test
public void transportClientClusterHealth() {
// transportClientContainer {
// Create the elasticsearch container.
try (ElasticsearchContainer container = new ElasticsearchContainer(
DockerImageName
.parse("docker.elastic.co/elasticsearch/elasticsearch")
.withTag("6.4.1")
)){
try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE)){
// Start the container. This step might take some time...
container.start();

Expand Down Expand Up @@ -182,4 +253,11 @@ private RestClient getClient(ElasticsearchContainer container) {
return client;
}

private RestClient getAnonymousClient(ElasticsearchContainer container) {
if (anonymousClient == null) {
anonymousClient = RestClient.builder(HttpHost.create(container.getHttpHostAddress())).build();
}

return anonymousClient;
}
}

0 comments on commit c5be8dd

Please sign in to comment.