diff --git a/README.md b/README.md
index 7270e7c..610d5e6 100644
--- a/README.md
+++ b/README.md
@@ -5,15 +5,15 @@ Dropwizard Elasticsearch
[](https://coveralls.io/r/dropwizard/dropwizard-elasticsearch)
[](http://mvnrepository.com/artifact/io.dropwizard.modules/dropwizard-elasticsearch)
-A set of classes for using [Elasticsearch][1] (version 2.3.0 and higher) in a [Dropwizard][2] application.
+A set of classes for using [Elasticsearch][1] (version 7.1.0 and higher) in a [Dropwizard][2] application.
The package provides a [lifecycle-managed][3] client class (`ManagedEsClient`), a configuration class with the most
common options (`EsConfiguration`), and some [health checks][4] which can instantly be used in any Dropwizard application.
[1]: http://www.elasticsearch.org/
-[2]: http://dropwizard.io/1.2.0/docs
-[3]: http://dropwizard.io/1.2.0/docs/manual/core.html#managed-objects
-[4]: http://dropwizard.io/1.2.0/docs/manual/core.html#health-checks
+[2]: http://dropwizard.io/1.3.0/docs
+[3]: http://dropwizard.io/1.3.0/docs/manual/core.html#managed-objects
+[4]: http://dropwizard.io/1.3.0/docs/manual/core.html#health-checks
Usage
@@ -43,33 +43,14 @@ Configuration
The following configuration settings are supported by `EsConfiguration`:
-* `nodeClient`: When `true`, `ManagedEsClient` will create a `NodeClient`, otherwise a `TransportClient`; default: `true`
* `servers`: A list of servers for usage with the created TransportClient if `nodeClient` is `false`
-* `clusterName`: The name of the Elasticsearch cluster; default: "elasticsearch"
-* `settings`: Any additional settings for Elasticsearch, see [Configuration](https://www.elastic.co/guide/en/elasticsearch/reference/2.4/setup-configuration.html)
-* `settingsFile`: Any additional settings file for Elasticsearch, see [Configuration](https://www.elastic.co/guide/en/elasticsearch/reference/2.4/setup-configuration.html)
-An example configuration file for creating a Node Client could like this:
+An example configuration file for creating a High Level Rest Client could like this:
- clusterName: MyClusterName
- settings:
- node.name: MyCustomNodeName
-
-The order of precedence is: `nodeClient`/`servers`/`clusterName` > `settings` > `settingsFile`, meaning that
-any setting in `settingsFile` can be overwritten with `settings` which in turn get overwritten by the specific settings
-like `clusterName`.
-
-Maven Artifacts
----------------
-
-This project is available on Maven Central. To add it to your project simply add the following dependencies to your
-`pom.xml`:
-
-
- io.dropwizard.modules
- dropwizard-elasticsearch
- 1.2.0-1
-
+ servers:
+ - http://127.0.0.1:9200
+ - http://127.0.0.1:9201
+ - http://127.0.0.1:9202
Support
diff --git a/pom.xml b/pom.xml
index fd0738f..1bebedb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
io.dropwizard.modules
dropwizard-elasticsearch
- 1.2.0-2-SNAPSHOT
+ 1.3.0-1-SNAPSHOT
jar
Dropwizard Elasticsearch Bundle
@@ -69,7 +69,7 @@
1.8
1.8
1.3.12
- 2.4.6
+ 7.1.0
@@ -90,8 +90,13 @@
dropwizard-core
- org.elasticsearch
- elasticsearch
+ org.elasticsearch.client
+ elasticsearch-rest-high-level-client
+ ${elasticsearch.version}
+
+
+ org.elasticsearch.client
+ elasticsearch-rest-client-sniffer
${elasticsearch.version}
diff --git a/src/main/java/io/dropwizard/elasticsearch/config/BasicAuthenticationConfiguration.java b/src/main/java/io/dropwizard/elasticsearch/config/BasicAuthenticationConfiguration.java
new file mode 100644
index 0000000..87a7c78
--- /dev/null
+++ b/src/main/java/io/dropwizard/elasticsearch/config/BasicAuthenticationConfiguration.java
@@ -0,0 +1,23 @@
+package io.dropwizard.elasticsearch.config;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import javax.validation.constraints.NotNull;
+
+public class BasicAuthenticationConfiguration {
+ @JsonProperty
+ @NotNull
+ private String user="";
+
+ @JsonProperty
+ @NotNull
+ private String password="";
+
+ public String getUser() {
+ return user;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+}
diff --git a/src/main/java/io/dropwizard/elasticsearch/config/EsConfiguration.java b/src/main/java/io/dropwizard/elasticsearch/config/EsConfiguration.java
index cdf0a3d..e269a27 100644
--- a/src/main/java/io/dropwizard/elasticsearch/config/EsConfiguration.java
+++ b/src/main/java/io/dropwizard/elasticsearch/config/EsConfiguration.java
@@ -1,61 +1,111 @@
package io.dropwizard.elasticsearch.config;
-import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.net.HostAndPort;
-import io.dropwizard.validation.ValidationMethod;
-import org.hibernate.validator.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
+import org.apache.http.HttpHost;
+import org.apache.http.message.BasicHeader;
+
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import javax.validation.constraints.NotNull;
+
/**
* Configuration class for Elasticsearch related settings.
*/
public class EsConfiguration {
@JsonProperty
@NotNull
- private List servers = Collections.emptyList();
+ private List servers = Collections.emptyList();
@JsonProperty
- @NotEmpty
- private String clusterName = "elasticsearch";
+ @NotNull
+ private int connectTimeOut = 1000;
@JsonProperty
- private boolean nodeClient = true;
+ @NotNull
+ private int socketTimeOut = 30000;
+
+ @JsonProperty
+ private int numberOfThreads = 0;
+
+ @JsonProperty
+ private String node = "";
+
+ @JsonProperty
+ private BasicAuthenticationConfiguration basicAuthentication = null;
+
+ @JsonProperty
+ private KeyStoreConfiguration keystore = null;
+
+ @JsonProperty
+ private SnifferConfiguration sniffer = null;
@JsonProperty
- @NotNull
private Map settings = Collections.emptyMap();
@JsonProperty
- private String settingsFile = null;
+ private Map headers = Collections.emptyMap();
- public List getServers() {
+ public List getServers() {
return servers;
}
- public String getClusterName() {
- return clusterName;
+ public List getServersAsHttpHosts() {
+ ArrayList httpHosts=new ArrayList<>();
+ getServers().forEach(hostAndPort -> {
+ HttpHost httpHost = HttpHost.create(hostAndPort);
+ if (httpHost.getPort() < 0) {
+ httpHost = new HttpHost(httpHost.getHostName(), 9200);
+ }
+ httpHosts.add(httpHost);
+ });
+ return httpHosts;
}
- public boolean isNodeClient() {
- return nodeClient;
+ public Map getHeaders() {
+ return headers;
}
- public Map getSettings() {
- return settings;
+ public List getHeadersAsHeaders() {
+ ArrayList basicHeaders = new ArrayList<>();
+ for (Map.Entry entry: getHeaders().entrySet()) {
+ basicHeaders.add(new BasicHeader(entry.getKey(), entry.getValue()));
+ }
+ return basicHeaders;
+ }
+
+ public int getConnectTimeOut() {
+ return connectTimeOut;
+ }
+
+ public int getSocketTimeOut() {
+ return socketTimeOut;
+ }
+
+ public int getNumberOfThreads() {
+ return numberOfThreads;
}
- public String getSettingsFile() {
- return settingsFile;
+ public String getNode() {
+ return node;
}
- @ValidationMethod
- @JsonIgnore
- public boolean isValidConfig() {
- return nodeClient || !servers.isEmpty();
+ public BasicAuthenticationConfiguration getBasicAuthentication() {
+ return basicAuthentication;
+ }
+
+ public KeyStoreConfiguration getKeystore() {
+ return keystore;
+ }
+
+ public SnifferConfiguration getSniffer() {
+ return sniffer;
+ }
+
+ public Map getSettings() {
+ return settings;
}
}
diff --git a/src/main/java/io/dropwizard/elasticsearch/config/KeyStoreConfiguration.java b/src/main/java/io/dropwizard/elasticsearch/config/KeyStoreConfiguration.java
new file mode 100644
index 0000000..e1581e2
--- /dev/null
+++ b/src/main/java/io/dropwizard/elasticsearch/config/KeyStoreConfiguration.java
@@ -0,0 +1,33 @@
+package io.dropwizard.elasticsearch.config;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import javax.validation.constraints.NotNull;
+
+public class KeyStoreConfiguration {
+ @JsonProperty
+ private String type = "jks";
+
+ @JsonProperty
+ @NotNull
+ private String keyStorePath="";
+
+ @JsonProperty
+ @NotNull
+ private String keyStorePass="";
+
+ public String getType() {
+ return type;
+ }
+
+ public Path getKeyStorePath() {
+ return Paths.get(keyStorePath);
+ }
+
+ public String getKeyStorePass() {
+ return keyStorePass;
+ }
+}
diff --git a/src/main/java/io/dropwizard/elasticsearch/config/SnifferConfiguration.java b/src/main/java/io/dropwizard/elasticsearch/config/SnifferConfiguration.java
new file mode 100644
index 0000000..55d47a2
--- /dev/null
+++ b/src/main/java/io/dropwizard/elasticsearch/config/SnifferConfiguration.java
@@ -0,0 +1,27 @@
+package io.dropwizard.elasticsearch.config;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class SnifferConfiguration {
+
+ @JsonProperty
+ private Boolean sniffOnFailure = true;
+
+ @JsonProperty
+ private int sniffIntervalMillis = 5000;
+
+ @JsonProperty
+ private int sniffAfterFailureDelayMillis = 30000;
+
+ public Boolean getSniffOnFailure() {
+ return sniffOnFailure;
+ }
+
+ public int getSniffIntervalMillis() {
+ return sniffIntervalMillis;
+ }
+
+ public int getSniffAfterFailureDelayMillis() {
+ return sniffAfterFailureDelayMillis;
+ }
+}
diff --git a/src/main/java/io/dropwizard/elasticsearch/health/EsClusterHealthCheck.java b/src/main/java/io/dropwizard/elasticsearch/health/EsClusterHealthCheck.java
index dbdcad3..7764400 100644
--- a/src/main/java/io/dropwizard/elasticsearch/health/EsClusterHealthCheck.java
+++ b/src/main/java/io/dropwizard/elasticsearch/health/EsClusterHealthCheck.java
@@ -1,7 +1,12 @@
package io.dropwizard.elasticsearch.health;
import com.codahale.metrics.health.HealthCheck;
+
+import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
+import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.client.Client;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.health.ClusterHealthStatus;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -12,7 +17,7 @@
* @see Admin Cluster Health
*/
public class EsClusterHealthCheck extends HealthCheck {
- private final Client client;
+ private final RestHighLevelClient client;
private final boolean failOnYellow;
/**
@@ -21,7 +26,7 @@ public class EsClusterHealthCheck extends HealthCheck {
* @param client an Elasticsearch {@link Client} instance connected to the cluster
* @param failOnYellow whether the health check should fail if the cluster health state is yellow
*/
- public EsClusterHealthCheck(Client client, boolean failOnYellow) {
+ public EsClusterHealthCheck(RestHighLevelClient client, boolean failOnYellow) {
this.client = checkNotNull(client);
this.failOnYellow = failOnYellow;
}
@@ -30,9 +35,9 @@ public EsClusterHealthCheck(Client client, boolean failOnYellow) {
* Construct a new Elasticsearch cluster health check which will fail if the cluster health state is
* {@link ClusterHealthStatus#RED}.
*
- * @param client an Elasticsearch {@link Client} instance connected to the cluster
+ * @param client an Elasticsearch {@link RestHighLevelClient} instance connected to the cluster
*/
- public EsClusterHealthCheck(Client client) {
+ public EsClusterHealthCheck(RestHighLevelClient client) {
this(client, false);
}
@@ -47,7 +52,9 @@ public EsClusterHealthCheck(Client client) {
*/
@Override
protected Result check() throws Exception {
- final ClusterHealthStatus status = client.admin().cluster().prepareHealth().get().getStatus();
+ ClusterHealthRequest request = new ClusterHealthRequest();
+ ClusterHealthResponse response = client.cluster().health(request, RequestOptions.DEFAULT);
+ final ClusterHealthStatus status = response.getStatus();
if (status == ClusterHealthStatus.RED || (failOnYellow && status == ClusterHealthStatus.YELLOW)) {
return Result.unhealthy("Last status: %s", status.name());
diff --git a/src/main/java/io/dropwizard/elasticsearch/health/EsIndexDocsHealthCheck.java b/src/main/java/io/dropwizard/elasticsearch/health/EsIndexDocsHealthCheck.java
index dc561a7..3977a9f 100644
--- a/src/main/java/io/dropwizard/elasticsearch/health/EsIndexDocsHealthCheck.java
+++ b/src/main/java/io/dropwizard/elasticsearch/health/EsIndexDocsHealthCheck.java
@@ -1,10 +1,16 @@
package io.dropwizard.elasticsearch.health;
-import com.codahale.metrics.health.HealthCheck;
import com.google.common.collect.ImmutableList;
-import org.elasticsearch.action.admin.indices.stats.IndexStats;
-import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
+
+import com.codahale.metrics.health.HealthCheck;
+
import org.elasticsearch.client.Client;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.core.CountRequest;
+import org.elasticsearch.client.core.CountResponse;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.util.ArrayList;
import java.util.List;
@@ -21,7 +27,7 @@
public class EsIndexDocsHealthCheck extends HealthCheck {
private static final String HEALTH_CHECK_NAME = "elasticsearch-index-documents";
private static final long DEFAULT_DOCUMENT_THRESHOLD = 1L;
- private final Client client;
+ private final RestHighLevelClient client;
private final String[] indices;
private final long documentThreshold;
@@ -34,7 +40,7 @@ public class EsIndexDocsHealthCheck extends HealthCheck {
* @throws IllegalArgumentException if {@code indices} was {@literal null} or empty,
* or {@code documentThreshold} was less than 1
*/
- public EsIndexDocsHealthCheck(Client client, List indices, long documentThreshold) {
+ public EsIndexDocsHealthCheck(RestHighLevelClient client, List indices, long documentThreshold) {
checkArgument(!indices.isEmpty(), "At least one index must be given");
checkArgument(documentThreshold > 0L, "The document threshold must at least be 1");
@@ -50,7 +56,7 @@ public EsIndexDocsHealthCheck(Client client, List indices, long document
* @param client an Elasticsearch {@link Client} instance connected to the cluster
* @param indices a {@link List} of indices in Elasticsearch which should be checked
*/
- public EsIndexDocsHealthCheck(Client client, List indices) {
+ public EsIndexDocsHealthCheck(RestHighLevelClient client, List indices) {
this(client, indices, DEFAULT_DOCUMENT_THRESHOLD);
}
@@ -61,7 +67,7 @@ public EsIndexDocsHealthCheck(Client client, List indices) {
* @param indexName the index in Elasticsearch which should be checked
* @param documentThreshold the minimal number of documents in an index
*/
- public EsIndexDocsHealthCheck(Client client, String indexName, long documentThreshold) {
+ public EsIndexDocsHealthCheck(RestHighLevelClient client, String indexName, long documentThreshold) {
this(client, ImmutableList.of(indexName), documentThreshold);
}
@@ -71,7 +77,7 @@ public EsIndexDocsHealthCheck(Client client, String indexName, long documentThre
* @param client an Elasticsearch {@link Client} instance connected to the cluster
* @param indexName the index in Elasticsearch which should be checked
*/
- public EsIndexDocsHealthCheck(Client client, String indexName) {
+ public EsIndexDocsHealthCheck(RestHighLevelClient client, String indexName) {
this(client, indexName, DEFAULT_DOCUMENT_THRESHOLD);
}
@@ -86,28 +92,30 @@ public EsIndexDocsHealthCheck(Client client, String indexName) {
*/
@Override
protected Result check() throws Exception {
- final IndicesStatsResponse indicesStatsResponse = client.admin().indices().prepareStats(indices).get();
-
final List indexDetails = new ArrayList(indices.length);
boolean healthy = true;
- for (IndexStats indexStats : indicesStatsResponse.getIndices().values()) {
- long documentCount = indexStats.getPrimaries().getDocs().getCount();
-
+ for (String index: indices) {
+ long documentCount = count(index);
if (documentCount < documentThreshold) {
healthy = false;
- indexDetails.add(String.format("%s (%d)", indexStats.getIndex(), documentCount));
+ indexDetails.add(String.format("%s (%d)", index, documentCount));
} else {
- indexDetails.add(String.format("%s (%d!)", indexStats.getIndex(), documentCount));
+ indexDetails.add(String.format("%s (%d!)", index, documentCount));
}
}
-
final String resultDetails = String.format("Last stats: %s", indexDetails);
-
if (healthy) {
return Result.healthy(resultDetails);
} else {
return Result.unhealthy(resultDetails);
}
}
-}
\ No newline at end of file
+
+ private long count(String index) throws Exception {
+ SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
+ CountRequest countRequest = new CountRequest().source(searchSourceBuilder);
+ CountResponse countResponse = client.count(countRequest, RequestOptions.DEFAULT);
+ return countResponse.getCount();
+ }
+}
diff --git a/src/main/java/io/dropwizard/elasticsearch/health/EsIndexExistsHealthCheck.java b/src/main/java/io/dropwizard/elasticsearch/health/EsIndexExistsHealthCheck.java
index 56b2f0c..1dbd79c 100644
--- a/src/main/java/io/dropwizard/elasticsearch/health/EsIndexExistsHealthCheck.java
+++ b/src/main/java/io/dropwizard/elasticsearch/health/EsIndexExistsHealthCheck.java
@@ -1,9 +1,12 @@
package io.dropwizard.elasticsearch.health;
-import com.codahale.metrics.health.HealthCheck;
import com.google.common.collect.ImmutableList;
-import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
-import org.elasticsearch.client.Client;
+
+import com.codahale.metrics.health.HealthCheck;
+
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.indices.GetIndexRequest;
import java.util.List;
@@ -16,17 +19,17 @@
* @see Admin Indices Indices Exists
*/
public class EsIndexExistsHealthCheck extends HealthCheck {
- private final Client client;
+ private final RestHighLevelClient client;
private final String[] indices;
/**
* Construct a new Elasticsearch index exists health check.
*
- * @param client an Elasticsearch {@link Client} instance connected to the cluster
+ * @param client an Elasticsearch {@link RestHighLevelClient} instance connected to the cluster
* @param indices a {@link List} of indices in Elasticsearch which should be checked
* @throws IllegalArgumentException if {@code indices} was {@literal null} or empty
*/
- public EsIndexExistsHealthCheck(Client client, List indices) {
+ public EsIndexExistsHealthCheck(RestHighLevelClient client, List indices) {
checkArgument(!indices.isEmpty(), "At least one index must be given");
this.client = checkNotNull(client);
@@ -39,7 +42,7 @@ public EsIndexExistsHealthCheck(Client client, List indices) {
* @param client an Elasticsearch {@link org.elasticsearch.client.Client} instance connected to the cluster
* @param indexName the index in Elasticsearch which should be checked
*/
- public EsIndexExistsHealthCheck(Client client, String indexName) {
+ public EsIndexExistsHealthCheck(RestHighLevelClient client, String indexName) {
this(client, ImmutableList.of(indexName));
}
@@ -54,12 +57,12 @@ public EsIndexExistsHealthCheck(Client client, String indexName) {
*/
@Override
protected Result check() throws Exception {
- final IndicesExistsResponse indicesExistsResponse = client.admin().indices().prepareExists(indices).get();
-
- if (indicesExistsResponse.isExists()) {
+ GetIndexRequest request = new GetIndexRequest(indices);
+ boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
+ if (exists) {
return Result.healthy();
} else {
return Result.unhealthy("One or more indices do not exist.");
}
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/io/dropwizard/elasticsearch/managed/ManagedEsClient.java b/src/main/java/io/dropwizard/elasticsearch/managed/ManagedEsClient.java
index a91c039..877d857 100644
--- a/src/main/java/io/dropwizard/elasticsearch/managed/ManagedEsClient.java
+++ b/src/main/java/io/dropwizard/elasticsearch/managed/ManagedEsClient.java
@@ -1,96 +1,113 @@
package io.dropwizard.elasticsearch.managed;
-import com.google.common.io.Resources;
-import io.dropwizard.elasticsearch.config.EsConfiguration;
-import io.dropwizard.elasticsearch.util.TransportAddressHelper;
-import io.dropwizard.lifecycle.Managed;
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
+import org.apache.http.impl.nio.reactor.IOReactorConfig;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.ssl.SSLContexts;
import org.elasticsearch.client.Client;
-import org.elasticsearch.client.transport.TransportClient;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.transport.TransportAddress;
-import org.elasticsearch.node.Node;
+import org.elasticsearch.client.Node;
+import org.elasticsearch.client.NodeSelector;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestClientBuilder;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.sniff.SniffOnFailureListener;
+import org.elasticsearch.client.sniff.Sniffer;
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.security.KeyStore;
+import java.util.Iterator;
-import java.io.File;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import javax.net.ssl.SSLContext;
+
+import io.dropwizard.elasticsearch.config.EsConfiguration;
+import io.dropwizard.lifecycle.Managed;
import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Strings.isNullOrEmpty;
-import static org.elasticsearch.node.NodeBuilder.nodeBuilder;
+
/**
- * A Dropwizard managed Elasticsearch {@link Client}. Depending on the {@link EsConfiguration} a Node Client or
- * a {@link TransportClient} a is being created and its lifecycle is managed by Dropwizard.
+ * A Dropwizard managed Elasticsearch {@link RestHighLevelClient}.
+ * Depending on the {@link EsConfiguration} a High Level Rest Client
+ * a {@link RestHighLevelClient} a is being created and its lifecycle is managed by Dropwizard.
*
- * @see Node Client
- * @see Transport Client
*/
public class ManagedEsClient implements Managed {
- private Node node = null;
- private Client client = null;
-
- /**
- * Create a new managed Elasticsearch {@link Client}. If {@link EsConfiguration#nodeClient} is {@literal true}, a
- * Node Client is being created, otherwise a {@link TransportClient} is being created with {@link EsConfiguration#servers}
- * as transport addresses.
- *
- * @param config a valid {@link EsConfiguration} instance
- */
- public ManagedEsClient(final EsConfiguration config) {
+ private RestHighLevelClient client = null;
+ private Sniffer sniffer = null;
+ public ManagedEsClient(final EsConfiguration config) throws Exception {
checkNotNull(config, "EsConfiguration must not be null");
- final Settings.Builder settingsBuilder = Settings.builder();
- if (!isNullOrEmpty(config.getSettingsFile())) {
- Path path = Paths.get(config.getSettingsFile());
- if (!path.toFile().exists()) {
- try {
- final URL url = Resources.getResource(config.getSettingsFile());
- path = new File(url.toURI()).toPath();
- } catch (URISyntaxException | NullPointerException e) {
- throw new IllegalArgumentException("settings file cannot be found", e);
- }
- }
- settingsBuilder.loadFromPath(path);
+ RestClientBuilder restClientBuilder = RestClient.builder(config.getServersAsHttpHosts().toArray(new HttpHost[0]));
+ setRequest(restClientBuilder, config);
+
+ if (!config.getHeadersAsHeaders().isEmpty()) {
+ restClientBuilder.setDefaultHeaders(config.getHeadersAsHeaders().toArray(new Header[0]));
+ }
+
+ if (config.getNumberOfThreads()>0) {
+ setThreads(restClientBuilder, config);
+ }
+
+ if (config.getNode()!= null && !config.getNode().isEmpty()) {
+ setNodeSelector(restClientBuilder, config);
+ }
+
+ if (config.getBasicAuthentication() != null) {
+ setCredential(restClientBuilder, config);
+ }
+
+ if (config.getKeystore()!= null) {
+ setKeyStore(restClientBuilder, config);
}
- final Settings settings = settingsBuilder
- .put(config.getSettings())
- .put("cluster.name", config.getClusterName())
- .build();
-
- if (config.isNodeClient()) {
- this.node = nodeBuilder()
- .client(true)
- .data(false)
- .settings(settings)
- .build();
- this.client = this.node.client();
+ if (config.getSniffer()!=null) {
+ if (config.getSniffer().getSniffOnFailure()) {
+ SniffOnFailureListener sniffOnFailureListener =
+ new SniffOnFailureListener();
+ restClientBuilder.setFailureListener(sniffOnFailureListener);
+ this.client = new RestHighLevelClient(restClientBuilder);
+ this.sniffer = Sniffer.builder(this.client.getLowLevelClient())
+ .setSniffAfterFailureDelayMillis(config.getSniffer().getSniffAfterFailureDelayMillis())
+ .build();
+ sniffOnFailureListener.setSniffer(this.sniffer);
+
+ } else {
+ this.client = new RestHighLevelClient(restClientBuilder);
+ this.sniffer = Sniffer.builder(this.client.getLowLevelClient())
+ .setSniffIntervalMillis(config.getSniffer().getSniffIntervalMillis())
+ .build();
+ }
+
} else {
- final TransportAddress[] addresses = TransportAddressHelper.fromHostAndPorts(config.getServers());
- this.client = TransportClient.builder().settings(settings).build().addTransportAddresses(addresses);
+ this.client = new RestHighLevelClient(restClientBuilder);
}
}
/**
- * Create a new managed Elasticsearch {@link Client} from the provided {@link Node}.
+ * Create a new managed Elasticsearch {@link Client} from the provided {@link Client}.
*
- * @param node a valid {@link Node} instance
+ * @param client an initialized {@link Client} instance
*/
- public ManagedEsClient(final Node node) {
- this.node = checkNotNull(node, "Elasticsearch node must not be null");
- this.client = node.client();
+ public ManagedEsClient(RestHighLevelClient client) {
+ this.client = checkNotNull(client, "Elasticsearch client must not be null");
}
-
/**
* Create a new managed Elasticsearch {@link Client} from the provided {@link Client}.
*
* @param client an initialized {@link Client} instance
*/
- public ManagedEsClient(Client client) {
+ public ManagedEsClient(RestHighLevelClient client, Sniffer sniffer) {
this.client = checkNotNull(client, "Elasticsearch client must not be null");
+ this.sniffer = checkNotNull(sniffer, "Sniffer must not be null");
}
/**
@@ -100,7 +117,6 @@ public ManagedEsClient(Client client) {
*/
@Override
public void start() throws Exception {
- startNode();
}
/**
@@ -112,7 +128,6 @@ public void start() throws Exception {
@Override
public void stop() throws Exception {
closeClient();
- closeNode();
}
/**
@@ -120,27 +135,109 @@ public void stop() throws Exception {
*
* @return a valid Elasticsearch {@link Client} instance
*/
- public Client getClient() {
+ public RestHighLevelClient getClient() {
return client;
}
- private Node startNode() {
- if (null != node) {
- return node.start();
+
+ private void closeClient() throws Exception {
+ if (null != client) {
+ client.close();
}
+ if (null != sniffer) {
+ sniffer.close();
+ }
+ }
- return null;
+ private void setRequest(RestClientBuilder restClientBuilder, EsConfiguration config) {
+ restClientBuilder.setRequestConfigCallback(
+ new RestClientBuilder.RequestConfigCallback() {
+ @Override
+ public RequestConfig.Builder customizeRequestConfig(
+ RequestConfig.Builder requestConfigBuilder) {
+ return requestConfigBuilder
+ .setConnectTimeout(config.getConnectTimeOut())
+ .setSocketTimeout(config.getSocketTimeOut());
+ }
+ });
}
- private void closeNode() {
- if (null != node && !node.isClosed()) {
- node.close();
- }
+ private void setThreads(RestClientBuilder restClientBuilder, EsConfiguration config) {
+ restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
+ @Override
+ public HttpAsyncClientBuilder customizeHttpClient(
+ HttpAsyncClientBuilder httpClientBuilder) {
+ return httpClientBuilder.setDefaultIOReactorConfig(
+ IOReactorConfig.custom()
+ .setIoThreadCount(config.getNumberOfThreads())
+ .build());
+ }
+ });
}
- private void closeClient() {
- if (null != client) {
- client.close();
+ private void setCredential(RestClientBuilder restClientBuilder, EsConfiguration config) {
+ final CredentialsProvider credentialsProvider =
+ new BasicCredentialsProvider();
+ credentialsProvider.setCredentials(AuthScope.ANY,
+ new UsernamePasswordCredentials(config.getBasicAuthentication().getUser(), config.getBasicAuthentication().getPassword()));
+ restClientBuilder
+ .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
+ @Override
+ public HttpAsyncClientBuilder customizeHttpClient(
+ HttpAsyncClientBuilder httpClientBuilder) {
+ httpClientBuilder.disableAuthCaching();
+ return httpClientBuilder
+ .setDefaultCredentialsProvider(credentialsProvider);
+ }
+ });
+ }
+
+ private void setKeyStore(RestClientBuilder restClientBuilder, EsConfiguration config) throws Exception {
+ KeyStore truststore = KeyStore.getInstance(config.getKeystore().getType());
+ try (InputStream is = Files.newInputStream(config.getKeystore().getKeyStorePath())) {
+ truststore.load(is, config.getKeystore().getKeyStorePass().toCharArray());
}
+ SSLContextBuilder sslBuilder = SSLContexts.custom()
+ .loadTrustMaterial(truststore, null);
+ final SSLContext sslContext = sslBuilder.build();
+ restClientBuilder
+ .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
+ @Override
+ public HttpAsyncClientBuilder customizeHttpClient(
+ HttpAsyncClientBuilder httpClientBuilder) {
+ return httpClientBuilder.setSSLContext(sslContext);
+ }
+ });
+ }
+
+ private void setNodeSelector(RestClientBuilder restClientBuilder, EsConfiguration config) {
+ restClientBuilder.setNodeSelector(new NodeSelector() {
+ @Override
+ public void select(Iterable nodes) {
+ /*
+ * Prefer any node that belongs to rack_one. If none is around
+ * we will go to another rack till it's time to try and revive
+ * some of the nodes that belong to rack_one.
+ */
+ boolean foundOne = false;
+ for (Node node : nodes) {
+ String rackId = node.getAttributes().get("rack_id").get(0);
+ if (config.getNode().equals(rackId)) {
+ foundOne = true;
+ break;
+ }
+ }
+ if (foundOne) {
+ Iterator nodesIt = nodes.iterator();
+ while (nodesIt.hasNext()) {
+ Node node = nodesIt.next();
+ String rackId = node.getAttributes().get("rack_id").get(0);
+ if (config.getNode().equals(rackId) == false) {
+ nodesIt.remove();
+ }
+ }
+ }
+ }
+ });
}
}
diff --git a/src/main/java/io/dropwizard/elasticsearch/util/TransportAddressHelper.java b/src/main/java/io/dropwizard/elasticsearch/util/TransportAddressHelper.java
deleted file mode 100644
index 615d30a..0000000
--- a/src/main/java/io/dropwizard/elasticsearch/util/TransportAddressHelper.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package io.dropwizard.elasticsearch.util;
-
-import com.google.common.net.HostAndPort;
-import org.elasticsearch.common.transport.InetSocketTransportAddress;
-import org.elasticsearch.common.transport.TransportAddress;
-
-import java.net.InetSocketAddress;
-import java.util.List;
-
-/**
- * Helper class for converting Guava {@link HostAndPort} objects to Elasticsearch {@link TransportAddress}.
- */
-public class TransportAddressHelper {
- private static final int DEFAULT_PORT = 9300;
-
- /**
- * Convert a {@link HostAndPort} instance to {@link TransportAddress}. If the {@link HostAndPort} instance doesn't
- * contain a port the resulting {@link TransportAddress} will have {@link #DEFAULT_PORT} as port.
- *
- * @param hostAndPort a valid {@link HostAndPort} instance
- * @return a {@link TransportAddress} equivalent to the provided {@link HostAndPort} instance
- */
- public static TransportAddress fromHostAndPort(final HostAndPort hostAndPort) {
- InetSocketAddress address = new InetSocketAddress(hostAndPort.getHost(), hostAndPort.getPortOrDefault(DEFAULT_PORT));
- return new InetSocketTransportAddress(address);
- }
-
- /**
- * Convert a list of {@link HostAndPort} instances to an array of {@link TransportAddress} instances.
- *
- * @param hostAndPorts a {@link List} of valid {@link HostAndPort} instances
- * @return an array of {@link TransportAddress} instances
- * @see #fromHostAndPort(com.google.common.net.HostAndPort)
- */
- public static TransportAddress[] fromHostAndPorts(final List hostAndPorts) {
- if (hostAndPorts == null) {
- return new TransportAddress[0];
- } else {
- TransportAddress[] transportAddresses = new TransportAddress[hostAndPorts.size()];
-
- for (int i = 0; i < hostAndPorts.size(); i++) {
- transportAddresses[i] = fromHostAndPort(hostAndPorts.get(i));
- }
-
- return transportAddresses;
- }
- }
-}
diff --git a/src/test/java/io/dropwizard/elasticsearch/config/CredentialConfigurationTest.java b/src/test/java/io/dropwizard/elasticsearch/config/CredentialConfigurationTest.java
new file mode 100644
index 0000000..636c7ff
--- /dev/null
+++ b/src/test/java/io/dropwizard/elasticsearch/config/CredentialConfigurationTest.java
@@ -0,0 +1,39 @@
+package io.dropwizard.elasticsearch.config;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import javax.validation.Validation;
+import javax.validation.Validator;
+
+import io.dropwizard.configuration.ConfigurationException;
+import io.dropwizard.configuration.ConfigurationFactory;
+import io.dropwizard.configuration.DefaultConfigurationFactoryFactory;
+import io.dropwizard.jackson.Jackson;
+
+
+/**
+ * Unit tests for {@link BasicAuthenticationConfiguration}.
+ */
+public class CredentialConfigurationTest {
+ private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
+ private final ConfigurationFactory configFactory =
+ new DefaultConfigurationFactoryFactory()
+ .create(BasicAuthenticationConfiguration.class, validator, Jackson.newObjectMapper(), "dw");
+
+ @Test
+ public void defaultConfigShouldBeValid() throws IOException, ConfigurationException {
+ configFactory.build();
+ }
+
+ @Test(expected = ConfigurationException.class)
+ public void userAndPasswordMustBeSet() throws IOException, ConfigurationException, URISyntaxException {
+ URL configFileUrl = this.getClass().getResource("/invalid.yml");
+ File configFile = new File(configFileUrl.toURI());
+ configFactory.build(configFile);
+ }
+}
diff --git a/src/test/java/io/dropwizard/elasticsearch/config/EsConfigurationTest.java b/src/test/java/io/dropwizard/elasticsearch/config/EsConfigurationTest.java
index 7e607ba..841c9ef 100644
--- a/src/test/java/io/dropwizard/elasticsearch/config/EsConfigurationTest.java
+++ b/src/test/java/io/dropwizard/elasticsearch/config/EsConfigurationTest.java
@@ -28,7 +28,7 @@ public void defaultConfigShouldBeValid() throws IOException, ConfigurationExcept
}
@Test(expected = ConfigurationException.class)
- public void eitherNodeClientOrServerListMustBeSet() throws IOException, ConfigurationException, URISyntaxException {
+ public void serverListMustBeSet() throws IOException, ConfigurationException, URISyntaxException {
URL configFileUrl = this.getClass().getResource("/invalid.yml");
File configFile = new File(configFileUrl.toURI());
configFactory.build(configFile);
diff --git a/src/test/java/io/dropwizard/elasticsearch/config/KeyStoreConfigurationTest.java b/src/test/java/io/dropwizard/elasticsearch/config/KeyStoreConfigurationTest.java
new file mode 100644
index 0000000..0463532
--- /dev/null
+++ b/src/test/java/io/dropwizard/elasticsearch/config/KeyStoreConfigurationTest.java
@@ -0,0 +1,38 @@
+package io.dropwizard.elasticsearch.config;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import javax.validation.Validation;
+import javax.validation.Validator;
+
+import io.dropwizard.configuration.ConfigurationException;
+import io.dropwizard.configuration.ConfigurationFactory;
+import io.dropwizard.configuration.DefaultConfigurationFactoryFactory;
+import io.dropwizard.jackson.Jackson;
+
+/**
+ * Unit tests for {@link KeyStoreConfiguration}.
+ */
+public class KeyStoreConfigurationTest {
+ private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
+ private final ConfigurationFactory configFactory =
+ new DefaultConfigurationFactoryFactory()
+ .create(KeyStoreConfiguration.class, validator, Jackson.newObjectMapper(), "dw");
+
+ @Test
+ public void defaultConfigShouldBeValid() throws IOException, ConfigurationException {
+ configFactory.build();
+ }
+
+ @Test(expected = ConfigurationException.class)
+ public void keyStorePathAndPassMustBeSet() throws IOException, ConfigurationException, URISyntaxException {
+ URL configFileUrl = this.getClass().getResource("/invalid.yml");
+ File configFile = new File(configFileUrl.toURI());
+ configFactory.build(configFile);
+ }
+}
diff --git a/src/test/java/io/dropwizard/elasticsearch/config/SnifferConfigurationTest.java b/src/test/java/io/dropwizard/elasticsearch/config/SnifferConfigurationTest.java
new file mode 100644
index 0000000..9a35195
--- /dev/null
+++ b/src/test/java/io/dropwizard/elasticsearch/config/SnifferConfigurationTest.java
@@ -0,0 +1,29 @@
+package io.dropwizard.elasticsearch.config;
+
+
+import org.junit.Test;
+
+import java.io.IOException;
+
+import javax.validation.Validation;
+import javax.validation.Validator;
+
+import io.dropwizard.configuration.ConfigurationException;
+import io.dropwizard.configuration.ConfigurationFactory;
+import io.dropwizard.configuration.DefaultConfigurationFactoryFactory;
+import io.dropwizard.jackson.Jackson;
+
+/**
+ * Unit tests for {@link SnifferConfiguration}.
+ */
+public class SnifferConfigurationTest {
+ private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
+ private final ConfigurationFactory configFactory =
+ new DefaultConfigurationFactoryFactory()
+ .create(SnifferConfiguration.class, validator, Jackson.newObjectMapper(), "dw");
+
+ @Test
+ public void defaultConfigShouldBeValid() throws IOException, ConfigurationException {
+ configFactory.build();
+ }
+}
diff --git a/src/test/java/io/dropwizard/elasticsearch/health/EsClusterHealthCheckTest.java b/src/test/java/io/dropwizard/elasticsearch/health/EsClusterHealthCheckTest.java
index b70b03b..f1eebaf 100644
--- a/src/test/java/io/dropwizard/elasticsearch/health/EsClusterHealthCheckTest.java
+++ b/src/test/java/io/dropwizard/elasticsearch/health/EsClusterHealthCheckTest.java
@@ -1,9 +1,21 @@
package io.dropwizard.elasticsearch.health;
-import org.elasticsearch.client.Client;
+import com.codahale.metrics.health.HealthCheck;
+
+import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
+import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
+import org.elasticsearch.client.ClusterClient;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
/**
* Unit tests for {@link EsClusterHealthCheck}
@@ -16,6 +28,54 @@ public void initializationWithNullClientShouldFail() {
@Test
public void initializationWithClientShouldSucceed() {
- new EsClusterHealthCheck(mock(Client.class));
+ new EsClusterHealthCheck(mock(RestHighLevelClient.class));
+ }
+
+ @Test
+ public void canHaveHealthyResultsWithFormattedMessage() throws Exception {
+ RestHighLevelClient client = mock(RestHighLevelClient.class);
+ ClusterClient clusterClient = mock(ClusterClient.class);
+ EsClusterHealthCheck healthCheck = new EsClusterHealthCheck(client);
+ ClusterHealthResponse response = mock(ClusterHealthResponse.class);
+
+ when(client.cluster()).thenReturn(clusterClient);
+ when(clusterClient.health(any(ClusterHealthRequest.class), any(RequestOptions.class))).thenReturn(response);
+ when(response.getStatus()).thenReturn(ClusterHealthStatus.GREEN);
+ HealthCheck.Result result = healthCheck.check();
+
+ assertTrue(result.isHealthy());
+ assertEquals(result.getMessage(), "Last status: GREEN");
+ }
+
+ @Test
+ public void canHaveUnHealthyResultsWithFormattedMessage() throws Exception {
+ RestHighLevelClient client = mock(RestHighLevelClient.class);
+ ClusterClient clusterClient = mock(ClusterClient.class);
+ EsClusterHealthCheck healthCheck = new EsClusterHealthCheck(client);
+ ClusterHealthResponse response = mock(ClusterHealthResponse.class);
+
+ when(client.cluster()).thenReturn(clusterClient);
+ when(clusterClient.health(any(ClusterHealthRequest.class), any(RequestOptions.class))).thenReturn(response);
+ when(response.getStatus()).thenReturn(ClusterHealthStatus.RED);
+ HealthCheck.Result result = healthCheck.check();
+
+ assertFalse(result.isHealthy());
+ assertEquals(result.getMessage(), "Last status: RED");
+ }
+
+ @Test
+ public void canHaveUnHealthyResultsOnYellowWithFormattedMessage() throws Exception {
+ RestHighLevelClient client = mock(RestHighLevelClient.class);
+ ClusterClient clusterClient = mock(ClusterClient.class);
+ EsClusterHealthCheck healthCheck = new EsClusterHealthCheck(client, true);
+ ClusterHealthResponse response = mock(ClusterHealthResponse.class);
+
+ when(client.cluster()).thenReturn(clusterClient);
+ when(clusterClient.health(any(ClusterHealthRequest.class), any(RequestOptions.class))).thenReturn(response);
+ when(response.getStatus()).thenReturn(ClusterHealthStatus.YELLOW);
+ HealthCheck.Result result = healthCheck.check();
+
+ assertFalse(result.isHealthy());
+ assertEquals(result.getMessage(), "Last status: YELLOW");
}
}
diff --git a/src/test/java/io/dropwizard/elasticsearch/health/EsIndexDocsHealthCheckTest.java b/src/test/java/io/dropwizard/elasticsearch/health/EsIndexDocsHealthCheckTest.java
index a3c0882..d2faa72 100644
--- a/src/test/java/io/dropwizard/elasticsearch/health/EsIndexDocsHealthCheckTest.java
+++ b/src/test/java/io/dropwizard/elasticsearch/health/EsIndexDocsHealthCheckTest.java
@@ -1,12 +1,23 @@
package io.dropwizard.elasticsearch.health;
import com.google.common.collect.ImmutableList;
-import org.elasticsearch.client.Client;
+
+import com.codahale.metrics.health.HealthCheck;
+
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.core.CountRequest;
+import org.elasticsearch.client.core.CountResponse;
import org.junit.Test;
import java.util.Collections;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
/**
* Unit tests for {@link EsIndexDocsHealthCheck}.
@@ -19,31 +30,56 @@ public void initializationWithNullClientShouldFail() {
@Test(expected = IllegalArgumentException.class)
public void initializationWithoutIndicesShouldFail() {
- new EsIndexDocsHealthCheck(mock(Client.class), Collections.emptyList());
+ new EsIndexDocsHealthCheck(mock(RestHighLevelClient.class), Collections.emptyList());
}
@Test(expected = NullPointerException.class)
public void initializationWithoutIndexShouldFail() {
- new EsIndexDocsHealthCheck(mock(Client.class), (String) null);
+ new EsIndexDocsHealthCheck(mock(RestHighLevelClient.class), (String) null);
}
@Test
public void initializationWithClientAndIndicesShouldSucceed() {
- new EsIndexDocsHealthCheck(mock(Client.class), ImmutableList.of("index", "foobar"));
+ new EsIndexDocsHealthCheck(mock(RestHighLevelClient.class), ImmutableList.of("index", "foobar"));
}
@Test
public void initializationWithClientAndIndexShouldSucceed() {
- new EsIndexDocsHealthCheck(mock(Client.class), "index");
+ new EsIndexDocsHealthCheck(mock(RestHighLevelClient.class), "index");
}
@Test(expected = IllegalArgumentException.class)
public void initializationWithDocumentThresholdTooLowShouldFail() {
- new EsIndexDocsHealthCheck(mock(Client.class), "index", 0L);
+ new EsIndexDocsHealthCheck(mock(RestHighLevelClient.class), "index", 0L);
}
@Test
public void initializationWithValidParametersShouldSucceedl() {
- new EsIndexDocsHealthCheck(mock(Client.class), "index", 10L);
+ new EsIndexDocsHealthCheck(mock(RestHighLevelClient.class), "index", 10L);
+ }
+
+
+ @Test
+ public void canHaveHealthyResultsWithFormattedMessage() throws Exception {
+ RestHighLevelClient client = mock(RestHighLevelClient.class);
+ EsIndexDocsHealthCheck healthCheck = new EsIndexDocsHealthCheck(client, "index");
+ CountResponse countResponse = mock(CountResponse.class);
+ when(client.count(any(CountRequest.class), any(RequestOptions.class))).thenReturn(countResponse);
+ when(countResponse.getCount()).thenReturn(10L);
+ HealthCheck.Result result = healthCheck.check();
+ assertTrue(result.isHealthy());
+ assertEquals(result.getMessage(), "Last stats: [index (10!)]");
+ }
+
+ @Test
+ public void canHaveUnhealthyResultsWithFormattedMessage() throws Exception {
+ RestHighLevelClient client = mock(RestHighLevelClient.class);
+ EsIndexDocsHealthCheck healthCheck = new EsIndexDocsHealthCheck(client, "index");
+ CountResponse countResponse = mock(CountResponse.class);
+ when(client.count(any(CountRequest.class), any(RequestOptions.class))).thenReturn(countResponse);
+ when(countResponse.getCount()).thenReturn(0L);
+ HealthCheck.Result result = healthCheck.check();
+ assertFalse(result.isHealthy());
+ assertEquals(result.getMessage(), "Last stats: [index (0)]");
}
}
diff --git a/src/test/java/io/dropwizard/elasticsearch/health/EsIndexExistsHealthCheckTest.java b/src/test/java/io/dropwizard/elasticsearch/health/EsIndexExistsHealthCheckTest.java
index 32191df..65cd8f1 100644
--- a/src/test/java/io/dropwizard/elasticsearch/health/EsIndexExistsHealthCheckTest.java
+++ b/src/test/java/io/dropwizard/elasticsearch/health/EsIndexExistsHealthCheckTest.java
@@ -1,16 +1,30 @@
package io.dropwizard.elasticsearch.health;
import com.google.common.collect.ImmutableList;
-import org.elasticsearch.client.Client;
+
+import com.codahale.metrics.health.HealthCheck;
+
+import org.elasticsearch.client.IndicesClient;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.indices.GetIndexRequest;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
import java.util.Collections;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
/**
* Unit tests for {@link EsIndexExistsHealthCheck}.
*/
+@RunWith(MockitoJUnitRunner.class)
public class EsIndexExistsHealthCheckTest {
@Test(expected = NullPointerException.class)
public void initializationWithNullClientShouldFail() {
@@ -19,21 +33,46 @@ public void initializationWithNullClientShouldFail() {
@Test(expected = IllegalArgumentException.class)
public void initializationWithoutIndicesShouldFail() {
- new EsIndexExistsHealthCheck(mock(Client.class), Collections.emptyList());
+ new EsIndexExistsHealthCheck(mock(RestHighLevelClient.class), Collections.emptyList());
}
@Test(expected = NullPointerException.class)
public void initializationWithoutIndexShouldFail() {
- new EsIndexExistsHealthCheck(mock(Client.class), (String) null);
+ new EsIndexExistsHealthCheck(mock(RestHighLevelClient.class), (String) null);
}
@Test
public void initializationWithClientAndIndexShouldSucceed() {
- new EsIndexExistsHealthCheck(mock(Client.class), "index");
+ new EsIndexExistsHealthCheck(mock(RestHighLevelClient.class), "index");
}
@Test
public void initializationWithClientAndIndicesShouldSucceed() {
- new EsIndexExistsHealthCheck(mock(Client.class), ImmutableList.of("index", "foobar"));
+ new EsIndexExistsHealthCheck(mock(RestHighLevelClient.class), ImmutableList.of("index", "foobar"));
+ }
+
+ @Test
+ public void canHaveHealthyResults() throws Exception {
+ RestHighLevelClient client = mock(RestHighLevelClient.class);
+ IndicesClient indicesClient = mock(IndicesClient.class);
+ EsIndexExistsHealthCheck healthCheck = new EsIndexExistsHealthCheck(client, "index");
+
+ when(client.indices()).thenReturn(indicesClient);
+ when(indicesClient.exists(any(GetIndexRequest.class), any(RequestOptions.class))).thenReturn(true);
+ HealthCheck.Result result = healthCheck.check();
+ assertTrue(result.isHealthy());
+ }
+
+ @Test
+ public void canHaveUnhealthyResultsWithFormattedMessage() throws Exception {
+ RestHighLevelClient client = mock(RestHighLevelClient.class);
+ IndicesClient indicesClient = mock(IndicesClient.class);
+ EsIndexExistsHealthCheck healthCheck = new EsIndexExistsHealthCheck(client, "index");
+
+ when(client.indices()).thenReturn(indicesClient);
+ when(indicesClient.exists(any(GetIndexRequest.class), any(RequestOptions.class))).thenReturn(false);
+ HealthCheck.Result result = healthCheck.check();
+ assertFalse(result.isHealthy());
+ assertEquals(result.getMessage(), "One or more indices do not exist.");
}
}
diff --git a/src/test/java/io/dropwizard/elasticsearch/managed/ManagedEsClientTest.java b/src/test/java/io/dropwizard/elasticsearch/managed/ManagedEsClientTest.java
index af5becb..a04cf36 100644
--- a/src/test/java/io/dropwizard/elasticsearch/managed/ManagedEsClientTest.java
+++ b/src/test/java/io/dropwizard/elasticsearch/managed/ManagedEsClientTest.java
@@ -1,37 +1,36 @@
package io.dropwizard.elasticsearch.managed;
-import com.google.common.net.HostAndPort;
-import io.dropwizard.configuration.ConfigurationException;
-import io.dropwizard.configuration.ConfigurationFactory;
-import io.dropwizard.configuration.DefaultConfigurationFactoryFactory;
-import io.dropwizard.elasticsearch.config.EsConfiguration;
-import io.dropwizard.elasticsearch.util.TransportAddressHelper;
-import io.dropwizard.jackson.Jackson;
-import io.dropwizard.lifecycle.Managed;
-import org.elasticsearch.client.Client;
-import org.elasticsearch.client.node.NodeClient;
-import org.elasticsearch.client.transport.TransportClient;
-import org.elasticsearch.node.Node;
+import org.elasticsearch.client.RestHighLevelClient;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
-import javax.validation.Validation;
-import javax.validation.Validator;
+import org.elasticsearch.client.sniff.Sniffer;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
+import javax.validation.Validation;
+import javax.validation.Validator;
+
+import io.dropwizard.configuration.ConfigurationException;
+import io.dropwizard.configuration.ConfigurationFactory;
+import io.dropwizard.configuration.DefaultConfigurationFactoryFactory;
+import io.dropwizard.elasticsearch.config.EsConfiguration;
+import io.dropwizard.jackson.Jackson;
+import io.dropwizard.lifecycle.Managed;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
/**
* Unit tests for {@link ManagedEsClient}.
*/
+@RunWith(MockitoJUnitRunner.class)
public class ManagedEsClientTest {
private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
private final ConfigurationFactory configFactory =
@@ -39,130 +38,115 @@ public class ManagedEsClientTest {
.create(EsConfiguration.class, validator, Jackson.newObjectMapper(), "dw");
@Test(expected = NullPointerException.class)
- public void ensureEsConfigurationIsNotNull() {
+ public void ensureEsConfigurationIsNotNull() throws Exception {
new ManagedEsClient((EsConfiguration) null);
}
- @Test(expected = NullPointerException.class)
- public void ensureNodeIsNotNull() {
- new ManagedEsClient((Node) null);
- }
-
@Test(expected = NullPointerException.class)
public void ensureClientIsNotNull() {
- new ManagedEsClient((Client) null);
+ new ManagedEsClient((RestHighLevelClient) null);
}
@Test
public void stopShouldCloseTheClient() throws Exception {
- Client client = mock(Client.class);
+ RestHighLevelClient client =
+ mock(RestHighLevelClient.class);
Managed managed = new ManagedEsClient(client);
-
+ // to stub a final method it is necessary to have the
+ // /src/test/resources/mockito-extensions/org.mockiot.plugins.MockMaker file
+ // with `mock-maker-inline` as context
+ doNothing().when(client).close();
+ assertNotNull(client);
managed.start();
managed.stop();
-
verify(client).close();
+ assertNotNull(client);
}
@Test
- public void lifecycleMethodsShouldStartAndCloseTheNode() throws Exception {
- Node node = mock(Node.class);
- when(node.isClosed()).thenReturn(false);
- Managed managed = new ManagedEsClient(node);
-
+ public void stopShouldCloseTheClientWithSniffer() throws Exception {
+ RestHighLevelClient client =
+ mock(RestHighLevelClient.class);
+ Sniffer sniffer = mock(Sniffer.class);
+ Managed managed = new ManagedEsClient(client, sniffer);
+ // to stub a final method it is necessary to have the
+ // /src/test/resources/mockito-extensions/org.mockiot.plugins.MockMaker file
+ // with `mock-maker-inline` as context
+ doNothing().when(client).close();
+ doNothing().when(sniffer).close();
+ assertNotNull(client);
managed.start();
- verify(node).start();
-
managed.stop();
- verify(node).close();
- }
-
- @Test
- public void managedEsClientWithNodeShouldReturnClient() throws Exception {
- Client client = mock(Client.class);
- Node node = mock(Node.class);
- when(node.client()).thenReturn(client);
-
- ManagedEsClient managed = new ManagedEsClient(node);
-
- assertSame(client, managed.getClient());
+ verify(client).close();
+ verify(sniffer).close();
}
@Test
- public void nodeClientShouldBeCreatedFromConfig() throws URISyntaxException, IOException, ConfigurationException {
- URL configFileUrl = this.getClass().getResource("/node_client.yml");
+ public void highLevelRestClientShouldBeCreatedFromConfig() throws Exception {
+ URL configFileUrl = this.getClass().getResource("/rest_client.yml");
File configFile = new File(configFileUrl.toURI());
EsConfiguration config = configFactory.build(configFile);
ManagedEsClient managedEsClient = new ManagedEsClient(config);
- Client client = managedEsClient.getClient();
-
- assertNotNull(client);
- assertTrue(client instanceof NodeClient);
+ RestHighLevelClient restHighLevelClient = managedEsClient.getClient();
- NodeClient nodeClient = (NodeClient) client;
- assertEquals(config.getClusterName(), nodeClient.settings().get("cluster.name"));
- assertEquals("true", nodeClient.settings().get("node.client"));
- assertEquals("false", nodeClient.settings().get("node.data"));
- }
+ assertNotNull(restHighLevelClient);
- @Test
- public void transportClientShouldBeCreatedFromConfig() throws URISyntaxException, IOException, ConfigurationException {
- URL configFileUrl = this.getClass().getResource("/transport_client.yml");
- File configFile = new File(configFileUrl.toURI());
- EsConfiguration config = configFactory.build(configFile);
-
- ManagedEsClient managedEsClient = new ManagedEsClient(config);
- Client client = managedEsClient.getClient();
+ assertEquals(3, restHighLevelClient.getLowLevelClient().getNodes().size());
+ assertEquals(
+ "127.0.0.1",
+ restHighLevelClient.getLowLevelClient().getNodes().get(0).getHost().getHostName());
- assertNotNull(client);
- assertTrue(client instanceof TransportClient);
+ assertEquals(
+ 9200,
+ restHighLevelClient.getLowLevelClient().getNodes().get(0).getHost().getPort());
+ assertEquals(
+ "127.0.0.1",
+ restHighLevelClient.getLowLevelClient().getNodes().get(1).getHost().getHostName());
- final TransportClient transportClient = (TransportClient) client;
- assertEquals(3, transportClient.transportAddresses().size());
assertEquals(
- TransportAddressHelper.fromHostAndPort(HostAndPort.fromParts("127.0.0.1", 9300)),
- transportClient.transportAddresses().get(0));
+ 9201,
+ restHighLevelClient.getLowLevelClient().getNodes().get(1).getHost().getPort());
assertEquals(
- TransportAddressHelper.fromHostAndPort(HostAndPort.fromParts("127.0.0.1", 9301)),
- transportClient.transportAddresses().get(1));
+ "127.0.0.1",
+ restHighLevelClient.getLowLevelClient().getNodes().get(2).getHost().getHostName());
+
assertEquals(
- TransportAddressHelper.fromHostAndPort(HostAndPort.fromParts("127.0.0.1", 9302)),
- transportClient.transportAddresses().get(2));
+ 9202,
+ restHighLevelClient.getLowLevelClient().getNodes().get(2).getHost().getPort());
}
@Test
- public void managedClientShouldUseCustomElasticsearchConfig() throws URISyntaxException, IOException, ConfigurationException {
- URL configFileUrl = this.getClass().getResource("/custom_settings_file.yml");
+ public void highLevelRestClientShouldBeCreatedFromConfigWithExtendedFields() throws Exception {
+ URL configFileUrl = this.getClass().getResource("/rest_client_with_sniffer_on_failure.yml");
File configFile = new File(configFileUrl.toURI());
EsConfiguration config = configFactory.build(configFile);
ManagedEsClient managedEsClient = new ManagedEsClient(config);
- Client client = managedEsClient.getClient();
+ RestHighLevelClient restHighLevelClient = managedEsClient.getClient();
- assertNotNull(client);
- assertTrue(client instanceof NodeClient);
+ assertNotNull(restHighLevelClient);
- NodeClient nodeClient = (NodeClient) client;
- assertEquals(config.getClusterName(), nodeClient.settings().get("cluster.name"));
- assertEquals("19300-19400", nodeClient.settings().get("transport.tcp.port"));
+ assertEquals(1, restHighLevelClient.getLowLevelClient().getNodes().size());
+ assertEquals(
+ "127.0.0.1",
+ restHighLevelClient.getLowLevelClient().getNodes().get(0).getHost().getHostName());
}
@Test
- public void managedClientObeysPrecedenceOfSettings() throws URISyntaxException, IOException, ConfigurationException {
- URL configFileUrl = this.getClass().getResource("/custom_settings_precedence.yml");
+ public void highLevelRestClientShouldBeCreatedWithSniffer() throws Exception {
+ URL configFileUrl = this.getClass().getResource("/rest_client_sniffer.yml");
File configFile = new File(configFileUrl.toURI());
EsConfiguration config = configFactory.build(configFile);
ManagedEsClient managedEsClient = new ManagedEsClient(config);
- Client client = managedEsClient.getClient();
+ RestHighLevelClient restHighLevelClient = managedEsClient.getClient();
- assertNotNull(client);
- assertTrue(client instanceof NodeClient);
+ assertNotNull(restHighLevelClient);
- NodeClient nodeClient = (NodeClient) client;
- assertEquals(config.getClusterName(), nodeClient.settings().get("cluster.name"));
- assertEquals("29300-29400", nodeClient.settings().get("transport.tcp.port"));
- assertEquals("target/data/yaml", nodeClient.settings().get("path.home"));
+ assertEquals(1, restHighLevelClient.getLowLevelClient().getNodes().size());
+ assertEquals(
+ "127.0.0.1",
+ restHighLevelClient.getLowLevelClient().getNodes().get(0).getHost().getHostName());
}
}
diff --git a/src/test/java/io/dropwizard/elasticsearch/util/TransportAddressHelperTest.java b/src/test/java/io/dropwizard/elasticsearch/util/TransportAddressHelperTest.java
deleted file mode 100644
index d9699c5..0000000
--- a/src/test/java/io/dropwizard/elasticsearch/util/TransportAddressHelperTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package io.dropwizard.elasticsearch.util;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.net.HostAndPort;
-import org.elasticsearch.common.transport.InetSocketTransportAddress;
-import org.elasticsearch.common.transport.TransportAddress;
-import org.junit.Test;
-
-import java.util.Collections;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Unit tests for {@link TransportAddressHelper}.
- */
-public class TransportAddressHelperTest {
-
- private static final int ES_DEFAULT_PORT = 9300;
-
- @Test(expected = NullPointerException.class)
- public void fromHostAndPortWithNullShouldFail() {
- TransportAddressHelper.fromHostAndPort(null);
- }
-
- @Test
- public void fromHostAndPortsWithNullShouldReturnEmptyArray() {
- TransportAddress[] result = TransportAddressHelper.fromHostAndPorts(null);
-
- assertEquals(0, result.length);
- }
-
- @Test
- public void fromHostAndPortsWithEmptyListShouldReturnEmptyArray() {
- TransportAddress[] result = TransportAddressHelper.fromHostAndPorts(Collections.emptyList());
-
- assertEquals(0, result.length);
- }
-
- @Test
- public void fromHostAndPortWithoutPortShouldUseDefaultPort() {
- InetSocketTransportAddress result = (InetSocketTransportAddress) TransportAddressHelper
- .fromHostAndPort(HostAndPort.fromString("localhost"));
-
- assertEquals("localhost", result.address().getHostName());
- assertEquals(ES_DEFAULT_PORT, result.address().getPort());
- }
-
- @Test
- public void fromHostAndPortWithCorrectDataShouldSucceed() {
- InetSocketTransportAddress result = (InetSocketTransportAddress) TransportAddressHelper
- .fromHostAndPort(HostAndPort.fromParts("localhost", 1234));
-
- assertEquals("localhost", result.address().getHostName());
- assertEquals(1234, result.address().getPort());
- }
-
- @Test
- public void fromHostAndPostWithCorrectDataShouldSucceed() {
- final List hostAndPorts = ImmutableList.of(
- HostAndPort.fromParts("example.net", 1234),
- HostAndPort.fromParts("example.com", 5678),
- HostAndPort.fromString("example.org")
- );
- final TransportAddress[] result = TransportAddressHelper.fromHostAndPorts(hostAndPorts);
-
- assertEquals(3, result.length);
-
- for (int i = 0; i < result.length; i++) {
- final InetSocketTransportAddress transportAddress = (InetSocketTransportAddress) result[i];
- assertEquals(hostAndPorts.get(i).getHost(), transportAddress.address().getHostName());
- assertEquals(hostAndPorts.get(i).getPortOrDefault(ES_DEFAULT_PORT), transportAddress.address().getPort());
- }
- }
-}
diff --git a/src/test/resources/custom_settings_file.yml b/src/test/resources/custom_settings_file.yml
deleted file mode 100644
index 8d8a34e..0000000
--- a/src/test/resources/custom_settings_file.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-clusterName: dropwizard_elasticsearch_test
-settingsFile: elasticsearch.yml
\ No newline at end of file
diff --git a/src/test/resources/custom_settings_precedence.yml b/src/test/resources/custom_settings_precedence.yml
deleted file mode 100644
index 7939520..0000000
--- a/src/test/resources/custom_settings_precedence.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-clusterName: dropwizard_elasticsearch_test
-settingsFile: elasticsearch_precedence.yml
-settings:
- cluster.name: settingsYaml
- transport.tcp.port: 29300-29400
- path.home: "target/data/yaml"
\ No newline at end of file
diff --git a/src/test/resources/elasticsearch.yml b/src/test/resources/elasticsearch.yml
deleted file mode 100644
index ce8c5a2..0000000
--- a/src/test/resources/elasticsearch.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-transport.tcp.port: 19300-19400
-path.home: "target/data"
\ No newline at end of file
diff --git a/src/test/resources/elasticsearch_precedence.yml b/src/test/resources/elasticsearch_precedence.yml
deleted file mode 100644
index 467e0f3..0000000
--- a/src/test/resources/elasticsearch_precedence.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-cluster.name: settingsFile
-transport.tcp.port: 19300-19400
-path.home: "target/data/settings"
\ No newline at end of file
diff --git a/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000..1f0955d
--- /dev/null
+++ b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+mock-maker-inline
diff --git a/src/test/resources/node_client.yml b/src/test/resources/node_client.yml
deleted file mode 100644
index 7d0395d..0000000
--- a/src/test/resources/node_client.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-clusterName: dropwizard_elasticsearch_test
-settings:
- path.home: "target/data"
\ No newline at end of file
diff --git a/src/test/resources/rest_client.yml b/src/test/resources/rest_client.yml
new file mode 100644
index 0000000..8f8f061
--- /dev/null
+++ b/src/test/resources/rest_client.yml
@@ -0,0 +1,4 @@
+servers:
+ - http://127.0.0.1
+ - http://127.0.0.1:9201
+ - http://127.0.0.1:9202
diff --git a/src/test/resources/rest_client_sniffer.yml b/src/test/resources/rest_client_sniffer.yml
new file mode 100644
index 0000000..69d6d99
--- /dev/null
+++ b/src/test/resources/rest_client_sniffer.yml
@@ -0,0 +1,15 @@
+servers:
+ - http://127.0.0.1
+connectTimeOut: 5000
+socketTimeOut: 60000
+numberOfThreads: 1
+node: "node_one"
+headers:
+ header_one: value
+basicAuthentication:
+ user: one_user
+ password: mYsEcReT
+sniffer:
+ sniffOnFailure: false
+ sniffIntervalMillis: 6000
+ sniffAfterFailureDelayMillis: 60000
diff --git a/src/test/resources/rest_client_with_sniffer_on_failure.yml b/src/test/resources/rest_client_with_sniffer_on_failure.yml
new file mode 100644
index 0000000..b351891
--- /dev/null
+++ b/src/test/resources/rest_client_with_sniffer_on_failure.yml
@@ -0,0 +1,10 @@
+servers:
+ - http://127.0.0.1
+connectTimeOut: 5000
+socketTimeOut: 60000
+numberOfThreads: 1
+node: "node_one"
+sniffer:
+ sniffOnFailure: true
+ sniffIntervalMillis: 6000
+ sniffAfterFailureDelayMillis: 60000
diff --git a/src/test/resources/transport_client.yml b/src/test/resources/transport_client.yml
deleted file mode 100644
index 1e65b03..0000000
--- a/src/test/resources/transport_client.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-nodeClient: false
-clusterName: dropwizard_elasticsearch_test
-servers:
- - 127.0.0.1
- - 127.0.0.1:9301
- - 127.0.0.1:9302
\ No newline at end of file
diff --git a/src/test/resources/transport_client_with_empty_server_list.yml b/src/test/resources/transport_client_with_empty_server_list.yml
deleted file mode 100644
index ef0398c..0000000
--- a/src/test/resources/transport_client_with_empty_server_list.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-nodeClient: false
-clusterName: dropwizard_elasticsearch_test
\ No newline at end of file