parent
b34a311d02
commit
c789592e26
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012-2020 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure.elasticsearch;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.searchbox.client.JestClient;
|
|
||||||
|
|
||||||
import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration;
|
|
||||||
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
|
|
||||||
import org.springframework.boot.actuate.elasticsearch.ElasticsearchHealthIndicator;
|
|
||||||
import org.springframework.boot.actuate.elasticsearch.ElasticsearchJestHealthIndicator;
|
|
||||||
import org.springframework.boot.actuate.health.HealthContributor;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
|
||||||
import org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link EnableAutoConfiguration Auto-configuration} for
|
|
||||||
* {@link ElasticsearchHealthIndicator} using the {@link JestClient}.
|
|
||||||
*
|
|
||||||
* @author Stephane Nicoll
|
|
||||||
* @since 2.1.0
|
|
||||||
*/
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@ConditionalOnClass(JestClient.class)
|
|
||||||
@ConditionalOnBean(JestClient.class)
|
|
||||||
@ConditionalOnEnabledHealthIndicator("elasticsearch")
|
|
||||||
@AutoConfigureAfter(JestAutoConfiguration.class)
|
|
||||||
@Deprecated
|
|
||||||
public class ElasticSearchJestHealthContributorAutoConfiguration
|
|
||||||
extends CompositeHealthContributorConfiguration<ElasticsearchJestHealthIndicator, JestClient> {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean(name = { "elasticsearchHealthIndicator", "elasticsearchHealthContributor" })
|
|
||||||
public HealthContributor elasticsearchHealthContributor(Map<String, JestClient> clients) {
|
|
||||||
return createContributor(clients);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012-2020 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.actuate.autoconfigure.elasticsearch;
|
|
||||||
|
|
||||||
import io.searchbox.client.JestClient;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration;
|
|
||||||
import org.springframework.boot.actuate.elasticsearch.ElasticsearchHealthIndicator;
|
|
||||||
import org.springframework.boot.actuate.elasticsearch.ElasticsearchJestHealthIndicator;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
|
||||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link ElasticSearchJestHealthContributorAutoConfiguration}.
|
|
||||||
*
|
|
||||||
* @author Phillip Webb
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
class ElasticsearchHealthContributorAutoConfigurationTests {
|
|
||||||
|
|
||||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(AutoConfigurations
|
|
||||||
.of(ElasticSearchJestHealthContributorAutoConfiguration.class, HealthContributorAutoConfiguration.class));
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void runWhenUsingJestClientShouldCreateIndicator() {
|
|
||||||
this.contextRunner.withBean(JestClient.class, () -> mock(JestClient.class))
|
|
||||||
.withSystemProperties("es.set.netty.runtime.available.processors=false")
|
|
||||||
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchJestHealthIndicator.class)
|
|
||||||
.doesNotHaveBean(ElasticsearchHealthIndicator.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void runWhenDisabledShouldNotCreateIndicator() {
|
|
||||||
this.contextRunner.withPropertyValues("management.health.elasticsearch.enabled:false")
|
|
||||||
.run((context) -> assertThat(context).doesNotHaveBean(ElasticsearchHealthIndicator.class)
|
|
||||||
.doesNotHaveBean(ElasticsearchJestHealthIndicator.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012-2019 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.actuate.elasticsearch;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import io.searchbox.client.JestClient;
|
|
||||||
import io.searchbox.client.JestResult;
|
|
||||||
|
|
||||||
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
|
|
||||||
import org.springframework.boot.actuate.health.Health;
|
|
||||||
import org.springframework.boot.actuate.health.HealthIndicator;
|
|
||||||
import org.springframework.boot.json.JsonParser;
|
|
||||||
import org.springframework.boot.json.JsonParserFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link HealthIndicator} for Elasticsearch using a {@link JestClient}.
|
|
||||||
*
|
|
||||||
* @author Stephane Nicoll
|
|
||||||
* @author Julian Devia Serna
|
|
||||||
* @author Brian Clozel
|
|
||||||
* @since 2.0.0
|
|
||||||
*/
|
|
||||||
public class ElasticsearchJestHealthIndicator extends AbstractHealthIndicator {
|
|
||||||
|
|
||||||
private final JestClient jestClient;
|
|
||||||
|
|
||||||
private final JsonParser jsonParser = JsonParserFactory.getJsonParser();
|
|
||||||
|
|
||||||
public ElasticsearchJestHealthIndicator(JestClient jestClient) {
|
|
||||||
super("Elasticsearch health check failed");
|
|
||||||
this.jestClient = jestClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
|
||||||
JestResult healthResult = this.jestClient.execute(new io.searchbox.cluster.Health.Builder().build());
|
|
||||||
if (healthResult.getResponseCode() != 200 || !healthResult.isSucceeded()) {
|
|
||||||
builder.down();
|
|
||||||
builder.withDetail("statusCode", healthResult.getResponseCode());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Map<String, Object> response = this.jsonParser.parseMap(healthResult.getJsonString());
|
|
||||||
String status = (String) response.get("status");
|
|
||||||
if (status.equals(io.searchbox.cluster.Health.Status.RED.getKey())) {
|
|
||||||
builder.outOfService();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
builder.up();
|
|
||||||
}
|
|
||||||
builder.withDetails(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,141 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012-2019 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.actuate.elasticsearch;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
import io.searchbox.action.Action;
|
|
||||||
import io.searchbox.client.JestClient;
|
|
||||||
import io.searchbox.client.JestResult;
|
|
||||||
import io.searchbox.client.config.exception.CouldNotConnectException;
|
|
||||||
import io.searchbox.core.SearchResult;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import org.springframework.boot.actuate.health.Health;
|
|
||||||
import org.springframework.boot.actuate.health.Status;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.assertj.core.api.Assertions.entry;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.BDDMockito.given;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link ElasticsearchJestHealthIndicator}.
|
|
||||||
*
|
|
||||||
* @author Stephane Nicoll
|
|
||||||
* @author Julian Devia Serna
|
|
||||||
* @author Brian Clozel
|
|
||||||
*/
|
|
||||||
class ElasticsearchJestHealthIndicatorTests {
|
|
||||||
|
|
||||||
private final JestClient jestClient = mock(JestClient.class);
|
|
||||||
|
|
||||||
private final ElasticsearchJestHealthIndicator healthIndicator = new ElasticsearchJestHealthIndicator(
|
|
||||||
this.jestClient);
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Test
|
|
||||||
void elasticsearchIsUp() throws IOException {
|
|
||||||
given(this.jestClient.execute(any(Action.class))).willReturn(createJestResult(200, true, "green"));
|
|
||||||
Health health = this.healthIndicator.health();
|
|
||||||
assertThat(health.getStatus()).isEqualTo(Status.UP);
|
|
||||||
assertHealthDetailsWithStatus(health.getDetails(), "green");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
void elasticsearchWithYellowStatusIsUp() throws IOException {
|
|
||||||
given(this.jestClient.execute(any(Action.class))).willReturn(createJestResult(200, true, "yellow"));
|
|
||||||
Health health = this.healthIndicator.health();
|
|
||||||
assertThat(health.getStatus()).isEqualTo(Status.UP);
|
|
||||||
assertHealthDetailsWithStatus(health.getDetails(), "yellow");
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Test
|
|
||||||
void elasticsearchIsDown() throws IOException {
|
|
||||||
given(this.jestClient.execute(any(Action.class)))
|
|
||||||
.willThrow(new CouldNotConnectException("http://localhost:9200", new IOException()));
|
|
||||||
Health health = this.healthIndicator.health();
|
|
||||||
assertThat(health.getStatus()).isEqualTo(Status.DOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Test
|
|
||||||
void elasticsearchIsDownWhenQueryDidNotSucceed() throws IOException {
|
|
||||||
given(this.jestClient.execute(any(Action.class))).willReturn(createJestResult(200, false, ""));
|
|
||||||
Health health = this.healthIndicator.health();
|
|
||||||
assertThat(health.getStatus()).isEqualTo(Status.DOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Test
|
|
||||||
void elasticsearchIsDownByResponseCode() throws IOException {
|
|
||||||
given(this.jestClient.execute(any(Action.class))).willReturn(createJestResult(500, false, ""));
|
|
||||||
Health health = this.healthIndicator.health();
|
|
||||||
assertThat(health.getStatus()).isEqualTo(Status.DOWN);
|
|
||||||
assertThat(health.getDetails()).contains(entry("statusCode", 500));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Test
|
|
||||||
void elasticsearchIsOutOfServiceByStatus() throws IOException {
|
|
||||||
given(this.jestClient.execute(any(Action.class))).willReturn(createJestResult(200, true, "red"));
|
|
||||||
Health health = this.healthIndicator.health();
|
|
||||||
assertThat(health.getStatus()).isEqualTo(Status.OUT_OF_SERVICE);
|
|
||||||
assertHealthDetailsWithStatus(health.getDetails(), "red");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertHealthDetailsWithStatus(Map<String, Object> details, String status) {
|
|
||||||
assertThat(details).contains(entry("cluster_name", "elasticsearch"), entry("status", status),
|
|
||||||
entry("timed_out", false), entry("number_of_nodes", 1), entry("number_of_data_nodes", 1),
|
|
||||||
entry("active_primary_shards", 0), entry("active_shards", 0), entry("relocating_shards", 0),
|
|
||||||
entry("initializing_shards", 0), entry("unassigned_shards", 0), entry("delayed_unassigned_shards", 0),
|
|
||||||
entry("number_of_pending_tasks", 0), entry("number_of_in_flight_fetch", 0),
|
|
||||||
entry("task_max_waiting_in_queue_millis", 0), entry("active_shards_percent_as_number", 100.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JestResult createJestResult(int responseCode, boolean succeeded, String status) {
|
|
||||||
|
|
||||||
SearchResult searchResult = new SearchResult(new Gson());
|
|
||||||
String json;
|
|
||||||
if (responseCode == 200) {
|
|
||||||
json = String.format(
|
|
||||||
"{\"cluster_name\":\"elasticsearch\","
|
|
||||||
+ "\"status\":\"%s\",\"timed_out\":false,\"number_of_nodes\":1,"
|
|
||||||
+ "\"number_of_data_nodes\":1,\"active_primary_shards\":0,"
|
|
||||||
+ "\"active_shards\":0,\"relocating_shards\":0,\"initializing_shards\":0,"
|
|
||||||
+ "\"unassigned_shards\":0,\"delayed_unassigned_shards\":0,"
|
|
||||||
+ "\"number_of_pending_tasks\":0,\"number_of_in_flight_fetch\":0,"
|
|
||||||
+ "\"task_max_waiting_in_queue_millis\":0,\"active_shards_percent_as_number\":100.0}",
|
|
||||||
status);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
json = "{\n \"error\": \"Server Error\",\n \"status\": \"" + status + "\"\n}";
|
|
||||||
}
|
|
||||||
searchResult.setJsonString(json);
|
|
||||||
searchResult.setJsonObject(JsonParser.parseString(json).getAsJsonObject());
|
|
||||||
searchResult.setResponseCode(responseCode);
|
|
||||||
searchResult.setSucceeded(succeeded);
|
|
||||||
return searchResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012-2019 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.elasticsearch.jest;
|
|
||||||
|
|
||||||
import io.searchbox.client.config.HttpClientConfig;
|
|
||||||
import io.searchbox.client.config.HttpClientConfig.Builder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback interface that can be implemented by beans wishing to further customize the
|
|
||||||
* {@link HttpClientConfig} via a {@link Builder HttpClientConfig.Builder} whilst
|
|
||||||
* retaining default auto-configuration.
|
|
||||||
*
|
|
||||||
* @author Stephane Nicoll
|
|
||||||
* @since 1.5.0
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface HttpClientConfigBuilderCustomizer {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Customize the {@link Builder}.
|
|
||||||
* @param builder the builder to customize
|
|
||||||
*/
|
|
||||||
void customize(Builder builder);
|
|
||||||
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012-2019 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.elasticsearch.jest;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import io.searchbox.client.JestClient;
|
|
||||||
import io.searchbox.client.JestClientFactory;
|
|
||||||
import io.searchbox.client.config.HttpClientConfig;
|
|
||||||
import org.apache.http.HttpHost;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
|
||||||
import org.springframework.boot.autoconfigure.elasticsearch.jest.JestProperties.Proxy;
|
|
||||||
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
|
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
||||||
import org.springframework.boot.context.properties.PropertyMapper;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link EnableAutoConfiguration Auto-configuration} for Jest.
|
|
||||||
*
|
|
||||||
* @author Stephane Nicoll
|
|
||||||
* @since 1.4.0
|
|
||||||
* @deprecated since 2.2.0 in favor of other auto-configured Elasticsearch clients
|
|
||||||
*/
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@ConditionalOnClass(JestClient.class)
|
|
||||||
@EnableConfigurationProperties(JestProperties.class)
|
|
||||||
@AutoConfigureAfter(GsonAutoConfiguration.class)
|
|
||||||
@Deprecated
|
|
||||||
public class JestAutoConfiguration {
|
|
||||||
|
|
||||||
@Bean(destroyMethod = "shutdownClient")
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
public JestClient jestClient(JestProperties properties, ObjectProvider<Gson> gson,
|
|
||||||
ObjectProvider<HttpClientConfigBuilderCustomizer> builderCustomizers) {
|
|
||||||
JestClientFactory factory = new JestClientFactory();
|
|
||||||
factory.setHttpClientConfig(createHttpClientConfig(properties, gson, builderCustomizers));
|
|
||||||
return factory.getObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected HttpClientConfig createHttpClientConfig(JestProperties properties, ObjectProvider<Gson> gson,
|
|
||||||
ObjectProvider<HttpClientConfigBuilderCustomizer> builderCustomizers) {
|
|
||||||
HttpClientConfig.Builder builder = new HttpClientConfig.Builder(properties.getUris());
|
|
||||||
PropertyMapper map = PropertyMapper.get();
|
|
||||||
map.from(properties::getUsername).whenHasText()
|
|
||||||
.to((username) -> builder.defaultCredentials(username, properties.getPassword()));
|
|
||||||
Proxy proxy = properties.getProxy();
|
|
||||||
map.from(proxy::getHost).whenHasText().to((host) -> {
|
|
||||||
Assert.notNull(proxy.getPort(), "Proxy port must not be null");
|
|
||||||
builder.proxy(new HttpHost(host, proxy.getPort()));
|
|
||||||
});
|
|
||||||
map.from(gson::getIfUnique).whenNonNull().to(builder::gson);
|
|
||||||
map.from(properties::isMultiThreaded).to(builder::multiThreaded);
|
|
||||||
map.from(properties::getConnectionTimeout).whenNonNull().asInt(Duration::toMillis).to(builder::connTimeout);
|
|
||||||
map.from(properties::getReadTimeout).whenNonNull().asInt(Duration::toMillis).to(builder::readTimeout);
|
|
||||||
builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,152 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012-2019 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.elasticsearch.jest;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration properties for Jest.
|
|
||||||
*
|
|
||||||
* @author Stephane Nicoll
|
|
||||||
* @since 1.4.0
|
|
||||||
*/
|
|
||||||
@ConfigurationProperties(prefix = "spring.elasticsearch.jest")
|
|
||||||
public class JestProperties {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Comma-separated list of the Elasticsearch instances to use.
|
|
||||||
*/
|
|
||||||
private List<String> uris = new ArrayList<>(Collections.singletonList("http://localhost:9200"));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Login username.
|
|
||||||
*/
|
|
||||||
private String username;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Login password.
|
|
||||||
*/
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether to enable connection requests from multiple execution threads.
|
|
||||||
*/
|
|
||||||
private boolean multiThreaded = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connection timeout.
|
|
||||||
*/
|
|
||||||
private Duration connectionTimeout = Duration.ofSeconds(3);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read timeout.
|
|
||||||
*/
|
|
||||||
private Duration readTimeout = Duration.ofSeconds(3);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy settings.
|
|
||||||
*/
|
|
||||||
private final Proxy proxy = new Proxy();
|
|
||||||
|
|
||||||
public List<String> getUris() {
|
|
||||||
return this.uris;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUris(List<String> uris) {
|
|
||||||
this.uris = uris;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUsername() {
|
|
||||||
return this.username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUsername(String username) {
|
|
||||||
this.username = username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
|
||||||
return this.password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMultiThreaded() {
|
|
||||||
return this.multiThreaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMultiThreaded(boolean multiThreaded) {
|
|
||||||
this.multiThreaded = multiThreaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Duration getConnectionTimeout() {
|
|
||||||
return this.connectionTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setConnectionTimeout(Duration connectionTimeout) {
|
|
||||||
this.connectionTimeout = connectionTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Duration getReadTimeout() {
|
|
||||||
return this.readTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReadTimeout(Duration readTimeout) {
|
|
||||||
this.readTimeout = readTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Proxy getProxy() {
|
|
||||||
return this.proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Proxy {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy host the HTTP client should use.
|
|
||||||
*/
|
|
||||||
private String host;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy port the HTTP client should use.
|
|
||||||
*/
|
|
||||||
private Integer port;
|
|
||||||
|
|
||||||
public String getHost() {
|
|
||||||
return this.host;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHost(String host) {
|
|
||||||
this.host = host;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getPort() {
|
|
||||||
return this.port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPort(Integer port) {
|
|
||||||
this.port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012-2019 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Auto-configuration for Jest.
|
|
||||||
*/
|
|
||||||
package org.springframework.boot.autoconfigure.elasticsearch.jest;
|
|
@ -1,173 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012-2019 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.elasticsearch.jest;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import io.searchbox.action.Action;
|
|
||||||
import io.searchbox.client.JestClient;
|
|
||||||
import io.searchbox.client.JestResult;
|
|
||||||
import io.searchbox.client.http.JestHttpClient;
|
|
||||||
import io.searchbox.core.Get;
|
|
||||||
import io.searchbox.core.Index;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.testcontainers.elasticsearch.ElasticsearchContainer;
|
|
||||||
import org.testcontainers.junit.jupiter.Container;
|
|
||||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanCreationException;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
|
||||||
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
|
|
||||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link JestAutoConfiguration}.
|
|
||||||
*
|
|
||||||
* @author Stephane Nicoll
|
|
||||||
* @author Andy Wilkinson
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@Testcontainers(disabledWithoutDocker = true)
|
|
||||||
class JestAutoConfigurationTests {
|
|
||||||
|
|
||||||
@Container
|
|
||||||
static final ElasticsearchContainer elasticsearch = new ElasticsearchContainer().withStartupAttempts(5)
|
|
||||||
.withStartupTimeout(Duration.ofMinutes(10));
|
|
||||||
|
|
||||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
|
||||||
.withConfiguration(AutoConfigurations.of(GsonAutoConfiguration.class, JestAutoConfiguration.class));
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void jestClientOnLocalhostByDefault() {
|
|
||||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(JestClient.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void customJestClient() {
|
|
||||||
this.contextRunner.withUserConfiguration(CustomJestClient.class)
|
|
||||||
.withPropertyValues("spring.elasticsearch.jest.uris[0]=http://localhost:9200")
|
|
||||||
.run((context) -> assertThat(context).hasSingleBean(JestClient.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void customGson() {
|
|
||||||
this.contextRunner.withUserConfiguration(CustomGson.class)
|
|
||||||
.withPropertyValues("spring.elasticsearch.jest.uris=http://localhost:9200").run((context) -> {
|
|
||||||
JestHttpClient client = (JestHttpClient) context.getBean(JestClient.class);
|
|
||||||
assertThat(client.getGson()).isSameAs(context.getBean("customGson"));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void customizerOverridesAutoConfig() {
|
|
||||||
this.contextRunner.withUserConfiguration(BuilderCustomizer.class)
|
|
||||||
.withPropertyValues("spring.elasticsearch.jest.uris=http://localhost:9200").run((context) -> {
|
|
||||||
JestHttpClient client = (JestHttpClient) context.getBean(JestClient.class);
|
|
||||||
assertThat(client.getGson()).isSameAs(context.getBean(BuilderCustomizer.class).getGson());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void proxyHostWithoutPort() {
|
|
||||||
this.contextRunner
|
|
||||||
.withPropertyValues("spring.elasticsearch.jest.uris=http://localhost:9200",
|
|
||||||
"spring.elasticsearch.jest.proxy.host=proxy.example.com")
|
|
||||||
.run((context) -> assertThat(context.getStartupFailure()).isInstanceOf(BeanCreationException.class)
|
|
||||||
.hasMessageContaining("Proxy port must not be null"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void jestCanCommunicateWithElasticsearchInstance() {
|
|
||||||
this.contextRunner
|
|
||||||
.withPropertyValues("spring.elasticsearch.jest.uris=http://" + elasticsearch.getHttpHostAddress())
|
|
||||||
.run((context) -> {
|
|
||||||
JestClient client = context.getBean(JestClient.class);
|
|
||||||
Map<String, String> source = new HashMap<>();
|
|
||||||
source.put("a", "alpha");
|
|
||||||
source.put("b", "bravo");
|
|
||||||
Index index = new Index.Builder(source).index("foo").type("bar").id("1").build();
|
|
||||||
execute(client, index);
|
|
||||||
Get getRequest = new Get.Builder("foo", "1").build();
|
|
||||||
assertThat(execute(client, getRequest).getResponseCode()).isEqualTo(200);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private JestResult execute(JestClient client, Action<? extends JestResult> action) {
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
try {
|
|
||||||
return client.execute(action);
|
|
||||||
}
|
|
||||||
catch (IOException ex) {
|
|
||||||
// Continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return client.execute(action);
|
|
||||||
}
|
|
||||||
catch (IOException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
static class CustomJestClient {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
JestClient customJestClient() {
|
|
||||||
return mock(JestClient.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
static class CustomGson {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
Gson customGson() {
|
|
||||||
return new Gson();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
|
||||||
@Import(CustomGson.class)
|
|
||||||
static class BuilderCustomizer {
|
|
||||||
|
|
||||||
private final Gson gson = new Gson();
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
HttpClientConfigBuilderCustomizer customizer() {
|
|
||||||
return (builder) -> builder.gson(BuilderCustomizer.this.gson);
|
|
||||||
}
|
|
||||||
|
|
||||||
Gson getGson() {
|
|
||||||
return this.gson;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012-2019 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.docs.elasticsearch.jest;
|
|
||||||
|
|
||||||
import io.searchbox.client.config.HttpClientConfig;
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.elasticsearch.jest.HttpClientConfigBuilderCustomizer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example configuration for using a {@link HttpClientConfigBuilderCustomizer} to
|
|
||||||
* configure additional HTTP settings.
|
|
||||||
*
|
|
||||||
* @author Stephane Nicoll
|
|
||||||
*/
|
|
||||||
public class JestClientCustomizationExample {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link HttpClientConfigBuilderCustomizer} that applies additional HTTP settings
|
|
||||||
* to the auto-configured jest client.
|
|
||||||
*/
|
|
||||||
// tag::customizer[]
|
|
||||||
static class HttpSettingsCustomizer implements HttpClientConfigBuilderCustomizer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void customize(HttpClientConfig.Builder builder) {
|
|
||||||
builder.maxTotalConnection(100).defaultMaxTotalConnectionPerRoute(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// end::customizer[]
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue