/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.search.elasticsearch.internal.connection; import com.liferay.portal.kernel.util.Props; import com.liferay.portal.kernel.util.PropsKeys; import com.liferay.portal.search.elasticsearch.configuration.ElasticsearchConfiguration; import com.liferay.portal.search.elasticsearch.internal.cluster.ClusterSettingsContext; import com.liferay.portal.search.elasticsearch.internal.cluster.UnicastSettingsContributor; import com.liferay.portal.search.elasticsearch.settings.BaseSettingsContributor; import com.liferay.portal.search.elasticsearch.settings.ClientSettingsHelper; import java.io.File; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import org.apache.commons.io.FileUtils; import org.elasticsearch.action.ActionFuture; import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest; import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequestBuilder; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.action.admin.indices.get.GetIndexRequestBuilder; import org.elasticsearch.action.admin.indices.get.GetIndexResponse; import org.elasticsearch.client.AdminClient; import org.elasticsearch.client.Client; import org.elasticsearch.client.ClusterAdminClient; import org.elasticsearch.client.IndicesAdminClient; import org.elasticsearch.common.unit.TimeValue; import org.mockito.Mockito; /** * @author André de Oliveira */ public class ElasticsearchFixture implements IndicesAdminClientSupplier { public ElasticsearchFixture(String subdirName) { this(subdirName, Collections.<String, Object>emptyMap()); } public ElasticsearchFixture( String subdirName, Map<String, Object> elasticsearchConfigurationProperties) { _elasticsearchConfigurationProperties = createElasticsearchConfigurationProperties( elasticsearchConfigurationProperties); _tmpDirName = "tmp/" + subdirName; } public void createNode() throws Exception { deleteTmpDir(); _embeddedElasticsearchConnection = createElasticsearchConnection(); } public void destroyNode() throws Exception { if (_embeddedElasticsearchConnection != null) { _embeddedElasticsearchConnection.close(); } deleteTmpDir(); } public AdminClient getAdminClient() { Client client = getClient(); return client.admin(); } public Client getClient() { return _embeddedElasticsearchConnection.getClient(); } public ClusterHealthResponse getClusterHealthResponse( HealthExpectations healthExpectations) { AdminClient adminClient = getAdminClient(); ClusterAdminClient clusterAdminClient = adminClient.cluster(); ClusterHealthRequestBuilder clusterHealthRequestBuilder = clusterAdminClient.prepareHealth(); ClusterHealthRequest clusterHealthRequest = clusterHealthRequestBuilder.request(); clusterHealthRequest.timeout(new TimeValue(10, TimeUnit.MINUTES)); clusterHealthRequest.waitForActiveShards( healthExpectations.activeShards); clusterHealthRequest.waitForNodes( String.valueOf(healthExpectations.numberOfNodes)); clusterHealthRequest.waitForRelocatingShards(0); clusterHealthRequest.waitForStatus(healthExpectations.status); ActionFuture<ClusterHealthResponse> health = clusterAdminClient.health( clusterHealthRequest); return health.actionGet(); } public Map<String, Object> getElasticsearchConfigurationProperties() { return _elasticsearchConfigurationProperties; } public EmbeddedElasticsearchConnection getEmbeddedElasticsearchConnection() { return _embeddedElasticsearchConnection; } public GetIndexResponse getIndex(String... indices) { IndicesAdminClient indicesAdminClient = getIndicesAdminClient(); GetIndexRequestBuilder getIndexRequestBuilder = indicesAdminClient.prepareGetIndex(); getIndexRequestBuilder.addIndices(indices); return getIndexRequestBuilder.get(); } @Override public IndicesAdminClient getIndicesAdminClient() { AdminClient adminClient = getAdminClient(); return adminClient.indices(); } public void setClusterSettingsContext( ClusterSettingsContext clusterSettingsContext) { _clusterSettingsContext = clusterSettingsContext; } public void setUp() throws Exception { createNode(); } public void tearDown() throws Exception { destroyNode(); } protected void addClusterLoggingThresholdContributor( EmbeddedElasticsearchConnection embeddedElasticsearchConnection) { embeddedElasticsearchConnection.addSettingsContributor( new BaseSettingsContributor(0) { @Override public void populate( ClientSettingsHelper clientSettingsHelper) { clientSettingsHelper.put( "cluster.service.slow_task_logging_threshold", "600s"); } }); } protected void addDiskThresholdSettingsContributor( EmbeddedElasticsearchConnection embeddedElasticsearchConnection) { embeddedElasticsearchConnection.addSettingsContributor( new BaseSettingsContributor(0) { @Override public void populate( ClientSettingsHelper clientSettingsHelper) { clientSettingsHelper.put( "cluster.routing.allocation.disk.threshold_enabled", "false"); } }); } protected void addUnicastSettingsContributor( EmbeddedElasticsearchConnection embeddedElasticsearchConnection) { if (_clusterSettingsContext == null) { return; } UnicastSettingsContributor unicastSettingsContributor = new UnicastSettingsContributor() { { setClusterSettingsContext(_clusterSettingsContext); activate(_elasticsearchConfigurationProperties); } }; embeddedElasticsearchConnection.addSettingsContributor( unicastSettingsContributor); } protected Map<String, Object> createElasticsearchConfigurationProperties( Map<String, Object> elasticsearchConfigurationProperties) { Map<String, Object> map = new HashMap<>( elasticsearchConfigurationProperties); map.put("configurationPid", ElasticsearchConfiguration.class.getName()); map.put("logExceptionsOnly", false); return map; } protected EmbeddedElasticsearchConnection createElasticsearchConnection() { EmbeddedElasticsearchConnection embeddedElasticsearchConnection = new EmbeddedElasticsearchConnection(); addClusterLoggingThresholdContributor(embeddedElasticsearchConnection); addDiskThresholdSettingsContributor(embeddedElasticsearchConnection); addUnicastSettingsContributor(embeddedElasticsearchConnection); Props props = Mockito.mock(Props.class); Mockito.when( props.get(PropsKeys.LIFERAY_HOME) ).thenReturn( _tmpDirName ); ClusterSettingsContext clusterSettingsContext = _clusterSettingsContext; if (clusterSettingsContext == null) { clusterSettingsContext = Mockito.mock(ClusterSettingsContext.class); } embeddedElasticsearchConnection.clusterSettingsContext = clusterSettingsContext; embeddedElasticsearchConnection.props = props; embeddedElasticsearchConnection.activate( _elasticsearchConfigurationProperties); embeddedElasticsearchConnection.connect(); return embeddedElasticsearchConnection; } protected void deleteTmpDir() throws Exception { FileUtils.deleteDirectory(new File(_tmpDirName)); } private ClusterSettingsContext _clusterSettingsContext; private final Map<String, Object> _elasticsearchConfigurationProperties; private EmbeddedElasticsearchConnection _embeddedElasticsearchConnection; private final String _tmpDirName; }