001/*
002 * Copyright 2012-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.autoconfigure.elasticsearch.rest;
018
019import org.apache.http.HttpHost;
020import org.apache.http.auth.AuthScope;
021import org.apache.http.auth.Credentials;
022import org.apache.http.auth.UsernamePasswordCredentials;
023import org.apache.http.client.CredentialsProvider;
024import org.apache.http.impl.client.BasicCredentialsProvider;
025import org.elasticsearch.client.RestClient;
026import org.elasticsearch.client.RestClientBuilder;
027import org.elasticsearch.client.RestHighLevelClient;
028
029import org.springframework.beans.factory.ObjectProvider;
030import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
031import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
032import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
033import org.springframework.boot.context.properties.EnableConfigurationProperties;
034import org.springframework.boot.context.properties.PropertyMapper;
035import org.springframework.context.annotation.Bean;
036import org.springframework.context.annotation.Configuration;
037
038/**
039 * {@link EnableAutoConfiguration Auto-configuration} for Elasticsearch REST clients.
040 *
041 * @author Brian Clozel
042 * @since 2.1.0
043 */
044@Configuration
045@ConditionalOnClass(RestClient.class)
046@EnableConfigurationProperties(RestClientProperties.class)
047public class RestClientAutoConfiguration {
048
049        private final RestClientProperties properties;
050
051        private final ObjectProvider<RestClientBuilderCustomizer> builderCustomizers;
052
053        public RestClientAutoConfiguration(RestClientProperties properties,
054                        ObjectProvider<RestClientBuilderCustomizer> builderCustomizers) {
055                this.properties = properties;
056                this.builderCustomizers = builderCustomizers;
057        }
058
059        @Bean
060        @ConditionalOnMissingBean
061        public RestClient restClient(RestClientBuilder builder) {
062                return builder.build();
063        }
064
065        @Bean
066        @ConditionalOnMissingBean
067        public RestClientBuilder restClientBuilder() {
068                HttpHost[] hosts = this.properties.getUris().stream().map(HttpHost::create)
069                                .toArray(HttpHost[]::new);
070                RestClientBuilder builder = RestClient.builder(hosts);
071                PropertyMapper map = PropertyMapper.get();
072                map.from(this.properties::getUsername).whenHasText().to((username) -> {
073                        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
074                        Credentials credentials = new UsernamePasswordCredentials(
075                                        this.properties.getUsername(), this.properties.getPassword());
076                        credentialsProvider.setCredentials(AuthScope.ANY, credentials);
077                        builder.setHttpClientConfigCallback((httpClientBuilder) -> httpClientBuilder
078                                        .setDefaultCredentialsProvider(credentialsProvider));
079                });
080                this.builderCustomizers.orderedStream()
081                                .forEach((customizer) -> customizer.customize(builder));
082                return builder;
083        }
084
085        @Configuration
086        @ConditionalOnClass(RestHighLevelClient.class)
087        public static class RestHighLevelClientConfiguration {
088
089                @Bean
090                @ConditionalOnMissingBean
091                public RestHighLevelClient restHighLevelClient(
092                                RestClientBuilder restClientBuilder) {
093                        return new RestHighLevelClient(restClientBuilder);
094                }
095
096        }
097
098}