/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.elasticsearch.test;
import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import static org.fest.assertions.Assertions.assertThat;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.eclipse.jetty.http.HttpHeader;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.hibernate.search.elasticsearch.cfg.ElasticsearchEnvironment;
import org.hibernate.search.elasticsearch.client.impl.DefaultElasticsearchClientFactory;
import org.hibernate.search.elasticsearch.client.impl.ElasticsearchClient;
import org.hibernate.search.elasticsearch.client.impl.ElasticsearchRequest;
import org.hibernate.search.elasticsearch.client.impl.ElasticsearchRequest.Builder;
import org.hibernate.search.elasticsearch.client.impl.URLEncodedString;
import org.hibernate.search.elasticsearch.impl.JsonBuilder;
import org.hibernate.search.test.util.impl.ExpectedLog4jLog;
import org.hibernate.search.testsupport.BytemanHelper;
import org.hibernate.search.testsupport.BytemanHelper.BytemanAccessor;
import org.hibernate.search.testsupport.TestForIssue;
import org.hibernate.search.testsupport.concurrency.Poller;
import org.hibernate.search.testsupport.setup.SearchConfigurationForTest;
import org.jboss.byteman.contrib.bmunit.BMRule;
import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.http.Fault;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import com.github.tomakehurst.wiremock.matching.UrlPathPattern;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* @author Yoann Rodiere
*/
@RunWith(BMUnitRunner.class)
public class DefaultElasticsearchClientFactoryTest {
private static final Poller POLLER = Poller.milliseconds( 10_000, 500 );
private static final JsonParser JSON_PARSER = new JsonParser();
private static final String CLIENT_SCOPE_NAME = "default";
private static final String CLIENT_PROPERTY_PREFIX = "hibernate.search.default.";
@Rule
public ExpectedException thrown = ExpectedException.none();
@Rule
public ExpectedLog4jLog logged = ExpectedLog4jLog.create();
@Rule
public BytemanAccessor byteman = BytemanHelper.createAccessor();
@Rule
public WireMockRule wireMockRule1 = new WireMockRule( wireMockConfig().port( 0 ).httpsPort( 0 ) /* Automatic port selection */ );
@Rule
public WireMockRule wireMockRule2 = new WireMockRule( wireMockConfig().port( 0 ).httpsPort( 0 ) /* Automatic port selection */ );
private DefaultElasticsearchClientFactory clientFactory = new DefaultElasticsearchClientFactory();
@Test
@TestForIssue(jiraKey = "HSEARCH-2274")
public void simple() throws Exception {
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI, httpUrlFor( wireMockRule1 ) );
String payload = "{ \"foo\": \"bar\" }";
wireMockRule1.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 200 ) ) );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
Response result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
wireMockRule1.verify( postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
}
}
@Test
public void error() throws Exception {
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI, httpUrlFor( wireMockRule1 ) );
String payload = "{ \"foo\": \"bar\" }";
String errorMessage = "ErrorMessageExplainingTheError";
wireMockRule1.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn(
elasticsearchResponse().withStatus( 500 )
.withBody( "{ \"error\": \"" + errorMessage + "\" }" )
) );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
Response result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 500 );
assertThat( IOUtils.toString( result.getEntity().getContent() ) ).as( "response body" ).contains( errorMessage );
}
}
@Test
public void timeout_read() throws Exception {
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI, httpUrlFor( wireMockRule1 ) )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_READ_TIMEOUT, "1000" )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_REQUEST_TIMEOUT, "99999" );
String payload = "{ \"foo\": \"bar\" }";
wireMockRule1.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn(
elasticsearchResponse()
.withFixedDelay( 2000 )
) );
thrown.expect( IOException.class );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
doPost( client, "/myIndex/myType", payload );
}
}
@Test
public void timeout_request() throws Exception {
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI, httpUrlFor( wireMockRule1 ) )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_READ_TIMEOUT, "99999" )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_REQUEST_TIMEOUT, "1000" );
String payload = "{ \"foo\": \"bar\" }";
wireMockRule1.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn(
elasticsearchResponse()
.withFixedDelay( 2000 )
) );
thrown.expect( IOException.class );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
doPost( client, "/myIndex/myType", payload );
}
}
@Test
@TestForIssue(jiraKey = "HSEARCH-2235")
public void multipleHosts() throws Exception {
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI,
httpUrlFor( wireMockRule1 ) + " " + httpUrlFor( wireMockRule2 ) );
String payload = "{ \"foo\": \"bar\" }";
wireMockRule1.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 200 ) ) );
wireMockRule2.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 200 ) ) );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
Response result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
wireMockRule1.verify( postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
wireMockRule2.verify( postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
}
}
@Test
@TestForIssue(jiraKey = "HSEARCH-2469")
public void multipleHosts_failover_serverError() throws Exception {
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI,
httpUrlFor( wireMockRule1 ) + " " + httpUrlFor( wireMockRule2 ) );
String payload = "{ \"foo\": \"bar\" }";
wireMockRule1.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 200 ) ) );
wireMockRule2.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 503 ) ) );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
Response result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
wireMockRule1.verify( 2, postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
wireMockRule2.verify( 1, postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
wireMockRule1.resetRequests();
wireMockRule2.resetRequests();
result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
// Must not use the failing node anymore
wireMockRule1.verify( 2, postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
wireMockRule2.verify( 0, postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
}
}
@Test
@TestForIssue(jiraKey = "HSEARCH-2469")
public void multipleHosts_failover_timeout() throws Exception {
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI,
httpUrlFor( wireMockRule1 ) + " " + httpUrlFor( wireMockRule2 ) )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_READ_TIMEOUT, "1000" /* 1s */ );
String payload = "{ \"foo\": \"bar\" }";
wireMockRule1.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 200 ) ) );
wireMockRule2.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 200 ).withFixedDelay( 10_000 /* 10s => will time out */ ) ) );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
Response result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
wireMockRule1.verify( 2, postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
/*
* Wiremock introduces the delay *before* registering the request to the journal,
* so we should have no request in the journal if we time out.
*/
wireMockRule2.verify( 0, postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
wireMockRule1.resetRequests();
wireMockRule2.resetRequests();
/*
* Remove the failure in the previously failing node,
* so that we can detect if requests are sent to this node.
*/
wireMockRule2.resetMappings();
wireMockRule2.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 200 ) ) );
result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
// Must not use the failing node anymore
wireMockRule1.verify( 2, postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
wireMockRule2.verify( 0, postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
}
}
@Test
@TestForIssue(jiraKey = "HSEARCH-2469")
public void multipleHosts_failover_fault() throws Exception {
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI,
httpUrlFor( wireMockRule1 ) + " " + httpUrlFor( wireMockRule2 ) )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_READ_TIMEOUT, "1000" /* 1s */ );
String payload = "{ \"foo\": \"bar\" }";
wireMockRule1.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 200 ) ) );
wireMockRule2.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 200 ).withFault( Fault.MALFORMED_RESPONSE_CHUNK ) ) );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
Response result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
wireMockRule1.verify( 2, postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
wireMockRule2.verify( 1, postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
wireMockRule1.resetRequests();
wireMockRule2.resetRequests();
result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
// Must not use the failing node anymore
wireMockRule1.verify( 2, postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
wireMockRule2.verify( 0, postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
}
}
@Test
@TestForIssue(jiraKey = "HSEARCH-2449")
public void discovery() throws Exception {
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI, httpUrlFor( wireMockRule1 ) )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.DISCOVERY_ENABLED, "true" )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.DISCOVERY_REFRESH_INTERVAL, "1" );
String nodesInfoResult = dummyNodeInfoResponse( wireMockRule1.port(), wireMockRule2.port() );
wireMockRule1.stubFor( get( WireMock.urlMatching( "/_nodes.*" ) )
.willReturn( elasticsearchResponse().withStatus( 200 ).withBody( nodesInfoResult ) ) );
wireMockRule2.stubFor( get( WireMock.urlMatching( "/_nodes.*" ) )
.willReturn( elasticsearchResponse().withStatus( 200 ).withBody( nodesInfoResult ) ) );
String payload = "{ \"foo\": \"bar\" }";
wireMockRule1.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 200 ) ) );
wireMockRule2.stubFor( post( urlPathLike( "/myIndex/myType" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 200 ) ) );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
Response result = doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
/*
* Send requests repeatedly until both hosts have been targeted.
* This should happen pretty early (as soon as we sent two requests, actually),
* but there is always the risk that the sniffer would send a request
* between our own requests, effectively making our own requests target the same host
* (since the hosts are each targeted in turn).
*/
POLLER.pollAssertion( () -> {
doPost( client, "/myIndex/myType", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
wireMockRule1.verify( postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
wireMockRule2.verify( postRequestedFor( urlPathLike( "/myIndex/myType" ) ) );
} );
}
}
@Test
@TestForIssue(jiraKey = "HSEARCH-2736")
@BMRule(
name = "trackHttpsHostsDiscovery",
targetClass = "org.elasticsearch.client.RestClient",
targetMethod = "setHosts(HttpHost[])",
helper = "org.hibernate.search.testsupport.BytemanHelper",
binding = "host0 : HttpHost = $1.length >= 1 ? $1[0] : null, host1 : HttpHost = $1.length >= 2 ? $1[1] : null;",
condition = "host0 != null && host0.getSchemeName().equals( \"https\" )"
+ " || host1 != null && host1.getSchemeName().equals( \"https\" )",
action = "pushEvent( \"https\" )"
)
@Ignore // HSEARCH-2481 Byteman-based tests executed in the Elasticsearch module won't work
public void discoveryScheme() throws Exception {
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
// Need to use HTTP here, so that the sniffer can at least retrieve the host list
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI, httpUrlFor( wireMockRule1 ) )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.DISCOVERY_ENABLED, "true" )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.DISCOVERY_REFRESH_INTERVAL, "1" )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.DISCOVERY_SCHEME, "https" );
String nodesInfoResult = dummyNodeInfoResponse(
wireMockRule1.httpsPort(),
wireMockRule2.httpsPort()
);
wireMockRule1.stubFor( get( WireMock.urlMatching( "/_nodes.*" ) )
.willReturn( elasticsearchResponse().withStatus( 200 ).withBody( nodesInfoResult ) ) );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
/*
* We can't use a valid SSL/TLS certificate, so we just check, using Byteman,
* that the sniffer found some HTTPS hosts at some point.
*/
POLLER.pollAssertion( () -> {
assertThat( byteman.isEventStackEmpty() ? null : byteman.consumeNextRecordedEvent() )
.as( "An event confirming that HTTPS was used" ).isEqualTo( "https" );
} );
}
}
@Test
@TestForIssue(jiraKey = "HSEARCH-2453")
public void authentication() throws Exception {
String username = "ironman";
String password = "j@rV1s";
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI, httpUrlFor( wireMockRule1 ) )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_USERNAME, username )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_PASSWORD, password );
String payload = "{ \"foo\": \"bar\" }";
/*
* Jest (actually, the Apache HTTP client) always tries an unauthenticated request first,
* and only provides an authentication token if it gets a 401 status.
* Thus we must stub the response for unauthenticated requests too.
*/
wireMockRule1.stubFor( post( urlPathLike( "/myIndex/myType/_search" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn(
elasticsearchResponse().withStatus( 401 )
.withHeader( HttpHeader.WWW_AUTHENTICATE.asString(), "Basic" ) )
);
wireMockRule1.stubFor( post( urlPathLike( "/myIndex/myType/_search" ) )
.withBasicAuth( username, password )
.withRequestBody( equalToJson( payload ) )
.willReturn( elasticsearchResponse().withStatus( 200 ) ) );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
Response result = doPost( client, "/myIndex/myType/_search", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 200 );
wireMockRule1.verify( postRequestedFor( urlPathLike( "/myIndex/myType/_search" ) ) );
}
}
@Test
@TestForIssue(jiraKey = "HSEARCH-2453")
public void authentication_error() throws Exception {
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI, httpUrlFor( wireMockRule1 ) );
String payload = "{ \"foo\": \"bar\" }";
String statusMessage = "StatusMessageUnauthorized";
wireMockRule1.stubFor( post( urlPathLike( "/myIndex/myType/_search" ) )
.withRequestBody( equalToJson( payload ) )
.willReturn(
elasticsearchResponse().withStatus( 401 /* Unauthorized */ )
.withStatusMessage( statusMessage )
) );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
Response result = doPost( client, "/myIndex/myType/_search", payload );
assertThat( result.getStatusLine().getStatusCode() ).as( "status code" ).isEqualTo( 401 );
assertThat( result.getStatusLine().getReasonPhrase() ).as( "reason phrase" ).contains( statusMessage );
}
}
@Test
@TestForIssue(jiraKey = "HSEARCH-2453")
public void authentication_http_password() throws Exception {
String username = "ironman";
String password = "j@rV1s";
String httpUri = "http://foo.com/";
SearchConfigurationForTest configuration = new SearchConfigurationForTest()
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_URI, httpUri )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_USERNAME, username )
.addProperty( CLIENT_PROPERTY_PREFIX + ElasticsearchEnvironment.SERVER_PASSWORD, password );
logged.expectMessage( "HSEARCH400073", httpUri );
try ( ElasticsearchClient client = clientFactory.create( CLIENT_SCOPE_NAME, configuration.getProperties() ) ) {
// Nothing to do here
}
}
private Response doPost(ElasticsearchClient client, String path, String payload) throws IOException, ResponseException {
return client.execute( buildRequest( ElasticsearchRequest.post(), path, payload ) );
}
private ElasticsearchRequest buildRequest(Builder builder, String path, String payload) {
for ( String pathComponent : path.split( "/" ) ) {
if ( !pathComponent.isEmpty() ) {
URLEncodedString fromString = URLEncodedString.fromString( pathComponent );
builder = builder.pathComponent( fromString );
}
}
if ( payload != null ) {
builder = builder.body( JSON_PARSER.parse( payload ).getAsJsonObject() );
}
return builder.build();
}
private static String httpUrlFor(WireMockRule rule) {
return "http://localhost:" + rule.port();
}
private static UrlPathPattern urlPathLike(String path) {
return urlPathMatching( path + "/?" );
}
private static ResponseDefinitionBuilder elasticsearchResponse() {
return ResponseDefinitionBuilder.okForEmptyJson();
}
private String dummyNodeInfoResponse(int... ports) {
JsonBuilder.Object nodesBuilder = JsonBuilder.object();
int index = 1;
for ( int port : ports ) {
nodesBuilder.add( "hJLXmY_NTrCytiIMbX4_" + index + "g", dummyNodeInfo( port ) );
++index;
}
return JsonBuilder.object()
.addProperty( "cluster_name", "foo-cluster.local" )
.add( "nodes", nodesBuilder.build() )
.build()
.toString();
}
private JsonObject dummyNodeInfo(int port) {
return JsonBuilder.object()
.addProperty( "name", "nodeForPort" + port )
.add( "http", JsonBuilder.object()
.addProperty( "publish_address", "localhost:" + port )
)
.add( "plugins", JsonBuilder.array().build() )
.build();
}
}