Elastic Search: Split reusable code to utility classes
As a preparatory step before adding the implementation of the account index in Elastic Search, split out code that can be reused into utility classes. Change-Id: I46e0fe4e4e2ef969565cd2f481ab45c46397016e Signed-off-by: Dariusz Luksza <dluksza@collab.net> Signed-off-by: David Pursehouse <dpursehouse@collab.net>
This commit is contained in:
		 Dariusz Luksza
					Dariusz Luksza
				
			
				
					committed by
					
						 David Pursehouse
						David Pursehouse
					
				
			
			
				
	
			
			
			 David Pursehouse
						David Pursehouse
					
				
			
						parent
						
							91ff74efc8
						
					
				
				
					commit
					1d71d309a4
				
			| @@ -14,123 +14,60 @@ | ||||
|  | ||||
| package com.google.gerrit.elasticsearch; | ||||
|  | ||||
| import static com.google.common.base.Preconditions.checkState; | ||||
| import static com.google.common.truth.Truth.assertThat; | ||||
| import static com.google.gerrit.elasticsearch.ElasticChangeIndex.CHANGES_PREFIX; | ||||
| import static com.google.gerrit.elasticsearch.ElasticChangeIndex.CLOSED_CHANGES; | ||||
| import static com.google.gerrit.elasticsearch.ElasticChangeIndex.OPEN_CHANGES; | ||||
|  | ||||
| import com.google.common.base.Strings; | ||||
| import com.google.common.io.Files; | ||||
| import com.google.gerrit.elasticsearch.ElasticChangeIndex.ChangeMapping; | ||||
| import com.google.gerrit.server.index.IndexModule.IndexType; | ||||
| import com.google.gerrit.elasticsearch.ElasticTestUtils.ElasticNodeInfo; | ||||
| import com.google.gerrit.server.index.change.ChangeSchemaDefinitions; | ||||
| import com.google.gerrit.server.query.change.AbstractQueryChangesTest; | ||||
| import com.google.gerrit.testutil.InMemoryModule; | ||||
| import com.google.gerrit.testutil.InMemoryRepositoryManager.Repo; | ||||
| import com.google.gson.FieldNamingPolicy; | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
| import com.google.inject.Guice; | ||||
| import com.google.inject.Injector; | ||||
|  | ||||
| import org.eclipse.jgit.junit.TestRepository; | ||||
| import org.eclipse.jgit.lib.Config; | ||||
| import org.elasticsearch.action.admin.cluster.node.info.NodesInfoRequest; | ||||
| import org.elasticsearch.common.settings.Settings; | ||||
| import org.elasticsearch.node.Node; | ||||
| import org.elasticsearch.node.NodeBuilder; | ||||
| import org.junit.After; | ||||
| import org.junit.AfterClass; | ||||
| import org.junit.BeforeClass; | ||||
| import org.junit.Test; | ||||
|  | ||||
| import java.io.File; | ||||
| import java.nio.file.Path; | ||||
| import java.util.Iterator; | ||||
| import java.util.Map; | ||||
| import java.util.concurrent.ExecutionException; | ||||
|  | ||||
| public class ElasticQueryChangesTest extends AbstractQueryChangesTest { | ||||
|   private static final Gson gson = new GsonBuilder() | ||||
|       .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) | ||||
|       .create(); | ||||
|   private static final String INDEX_NAME = | ||||
|       String.format("%s%04d", CHANGES_PREFIX, | ||||
|           ChangeSchemaDefinitions.INSTANCE.getLatest().getVersion()); | ||||
|   private static Node node; | ||||
|   private static String port; | ||||
|   private static File elasticDir; | ||||
|  | ||||
|   static class NodeInfo { | ||||
|     String httpAddress; | ||||
|   } | ||||
|  | ||||
|   static class Info { | ||||
|     Map<String, NodeInfo> nodes; | ||||
|   } | ||||
|   private static ElasticNodeInfo nodeInfo; | ||||
|  | ||||
|   @BeforeClass | ||||
|   public static void startIndexService() | ||||
|       throws InterruptedException, ExecutionException { | ||||
|     if (node != null) { | ||||
|     if (nodeInfo != null) { | ||||
|       // do not start Elasticsearch twice | ||||
|       return; | ||||
|     } | ||||
|     elasticDir = Files.createTempDir(); | ||||
|     Path elasticDirPath = elasticDir.toPath(); | ||||
|     Settings settings = Settings.settingsBuilder() | ||||
|         .put("cluster.name", "gerrit") | ||||
|         .put("node.name", "Gerrit Elasticsearch Test Node") | ||||
|         .put("node.local", true) | ||||
|         .put("discovery.zen.ping.multicast.enabled", false) | ||||
|         .put("index.store.fs.memory.enabled", true) | ||||
|         .put("index.gateway.type", "none") | ||||
|         .put("index.max_result_window", Integer.MAX_VALUE) | ||||
|         .put("gateway.type", "default") | ||||
|         .put("http.port", 0) | ||||
|         .put("discovery.zen.ping.unicast.hosts", "[\"localhost\"]") | ||||
|         .put("path.home", elasticDirPath.toAbsolutePath()) | ||||
|         .put("path.data", elasticDirPath.resolve("data").toAbsolutePath()) | ||||
|         .put("path.work", elasticDirPath.resolve("work").toAbsolutePath()) | ||||
|         .put("path.logs", elasticDirPath.resolve("logs").toAbsolutePath()) | ||||
|         .put("transport.tcp.connect_timeout", "60s") | ||||
|         .build(); | ||||
|  | ||||
|     // Start the node | ||||
|     node = NodeBuilder.nodeBuilder() | ||||
|         .settings(settings) | ||||
|         .node(); | ||||
|  | ||||
|     // Wait for it to be ready | ||||
|     node.client() | ||||
|         .admin() | ||||
|         .cluster() | ||||
|         .prepareHealth() | ||||
|         .setWaitForYellowStatus() | ||||
|         .execute() | ||||
|         .actionGet(); | ||||
|     nodeInfo = ElasticTestUtils.startElasticsearchNode(); | ||||
|  | ||||
|     createIndexes(); | ||||
|  | ||||
|     assertThat(node.isClosed()).isFalse(); | ||||
|     port = getHttpPort(); | ||||
|   } | ||||
|  | ||||
|   @After | ||||
|   public void cleanupIndex() { | ||||
|     node.client().admin().indices().prepareDelete(INDEX_NAME).execute(); | ||||
|     createIndexes(); | ||||
|     if (nodeInfo != null) { | ||||
|       ElasticTestUtils.deleteIndexes(nodeInfo.node, INDEX_NAME); | ||||
|       createIndexes(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @AfterClass | ||||
|   public static void stopElasticsearchServer() { | ||||
|     if (node != null) { | ||||
|       node.close(); | ||||
|       node = null; | ||||
|     } | ||||
|     if (elasticDir != null && elasticDir.delete()) { | ||||
|       elasticDir = null; | ||||
|     if (nodeInfo != null) { | ||||
|       nodeInfo.node.close(); | ||||
|       nodeInfo.elasticDir.delete(); | ||||
|       nodeInfo = null; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -138,11 +75,7 @@ public class ElasticQueryChangesTest extends AbstractQueryChangesTest { | ||||
|   protected Injector createInjector() { | ||||
|     Config elasticsearchConfig = new Config(config); | ||||
|     InMemoryModule.setDefaults(elasticsearchConfig); | ||||
|     elasticsearchConfig.setEnum("index", null, "type", IndexType.ELASTICSEARCH); | ||||
|     elasticsearchConfig.setString("index", null, "protocol", "http"); | ||||
|     elasticsearchConfig.setString("index", null, "hostname", "localhost"); | ||||
|     elasticsearchConfig.setString("index", null, "port", port); | ||||
|     elasticsearchConfig.setBoolean("index", "elasticsearch", "test", true); | ||||
|     ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port); | ||||
|     return Guice.createInjector( | ||||
|         new InMemoryModule(elasticsearchConfig, notesMigration)); | ||||
|   } | ||||
| @@ -154,35 +87,19 @@ public class ElasticQueryChangesTest extends AbstractQueryChangesTest { | ||||
|         new ChangeMapping(ChangeSchemaDefinitions.INSTANCE.getLatest()); | ||||
|     openChangesMapping.closedChanges = null; | ||||
|     closedChangesMapping.openChanges = null; | ||||
|     node.client() | ||||
|     nodeInfo.node | ||||
|         .client() | ||||
|         .admin() | ||||
|         .indices() | ||||
|         .prepareCreate(INDEX_NAME) | ||||
|         .addMapping(OPEN_CHANGES, gson.toJson(openChangesMapping)) | ||||
|         .addMapping(CLOSED_CHANGES, gson.toJson(closedChangesMapping)) | ||||
|         .addMapping(OPEN_CHANGES, | ||||
|             ElasticTestUtils.gson.toJson(openChangesMapping)) | ||||
|         .addMapping(CLOSED_CHANGES, | ||||
|             ElasticTestUtils.gson.toJson(closedChangesMapping)) | ||||
|         .execute() | ||||
|         .actionGet(); | ||||
|   } | ||||
|  | ||||
|   private static String getHttpPort() | ||||
|       throws InterruptedException, ExecutionException { | ||||
|     String nodes = node.client().admin().cluster() | ||||
|         .nodesInfo(new NodesInfoRequest("*")).get().toString(); | ||||
|     Gson gson = new GsonBuilder() | ||||
|         .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) | ||||
|         .create(); | ||||
|     Info info = gson.fromJson(nodes, Info.class); | ||||
|  | ||||
|     checkState(info.nodes != null && info.nodes.size() == 1); | ||||
|     Iterator<NodeInfo> values = info.nodes.values().iterator(); | ||||
|     String httpAddress = values.next().httpAddress; | ||||
|  | ||||
|     checkState( | ||||
|         !Strings.isNullOrEmpty(httpAddress) && httpAddress.indexOf(':') > 0); | ||||
|     return httpAddress.substring(httpAddress.indexOf(':') + 1, | ||||
|         httpAddress.length()); | ||||
|   } | ||||
|  | ||||
|   @Test | ||||
|   public void byOwnerInvalidQuery() throws Exception { | ||||
|     TestRepository<Repo> repo = createProject("repo"); | ||||
|   | ||||
| @@ -0,0 +1,144 @@ | ||||
| // Copyright (C) 2016 The Android Open Source Project | ||||
| // | ||||
| // 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 | ||||
| // | ||||
| // http://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 com.google.gerrit.elasticsearch; | ||||
|  | ||||
| import static com.google.common.truth.Truth.assertThat; | ||||
|  | ||||
| import com.google.common.base.Strings; | ||||
| import com.google.common.io.Files; | ||||
| import com.google.gerrit.server.index.IndexModule.IndexType; | ||||
| import com.google.gson.FieldNamingPolicy; | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
|  | ||||
| import org.eclipse.jgit.lib.Config; | ||||
| import org.elasticsearch.action.admin.cluster.node.info.NodesInfoRequest; | ||||
| import org.elasticsearch.common.settings.Settings; | ||||
| import org.elasticsearch.node.Node; | ||||
| import org.elasticsearch.node.NodeBuilder; | ||||
|  | ||||
| import java.io.File; | ||||
| import java.nio.file.Path; | ||||
| import java.util.Iterator; | ||||
| import java.util.Map; | ||||
| import java.util.concurrent.ExecutionException; | ||||
|  | ||||
| final class ElasticTestUtils { | ||||
|   static final Gson gson = new GsonBuilder() | ||||
|       .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) | ||||
|       .create(); | ||||
|  | ||||
|   static class ElasticNodeInfo { | ||||
|     final Node node; | ||||
|     final String port; | ||||
|     final File elasticDir; | ||||
|  | ||||
|     private ElasticNodeInfo(Node node, File rootDir, String port) { | ||||
|       this.node = node; | ||||
|       this.port = port; | ||||
|       this.elasticDir = rootDir; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   static void configure(Config config, String port) { | ||||
|     config.setEnum("index", null, "type", IndexType.ELASTICSEARCH); | ||||
|     config.setString("index", null, "protocol", "http"); | ||||
|     config.setString("index", null, "hostname", "localhost"); | ||||
|     config.setString("index", null, "port", port); | ||||
|     config.setBoolean("index", "elasticsearch", "test", true); | ||||
|   } | ||||
|  | ||||
|   static ElasticNodeInfo startElasticsearchNode() | ||||
|       throws InterruptedException, ExecutionException { | ||||
|     File elasticDir = Files.createTempDir(); | ||||
|     Path elasticDirPath = elasticDir.toPath(); | ||||
|     Settings settings = Settings.settingsBuilder() | ||||
|         .put("cluster.name", "gerrit") | ||||
|         .put("node.name", "Gerrit Elasticsearch Test Node") | ||||
|         .put("node.local", true) | ||||
|         .put("discovery.zen.ping.multicast.enabled", false) | ||||
|         .put("index.store.fs.memory.enabled", true) | ||||
|         .put("index.gateway.type", "none") | ||||
|         .put("index.max_result_window", Integer.MAX_VALUE) | ||||
|         .put("gateway.type", "default") | ||||
|         .put("http.port", 0) | ||||
|         .put("discovery.zen.ping.unicast.hosts", "[\"localhost\"]") | ||||
|         .put("path.home", elasticDirPath.toAbsolutePath()) | ||||
|         .put("path.data", elasticDirPath.resolve("data").toAbsolutePath()) | ||||
|         .put("path.work", elasticDirPath.resolve("work").toAbsolutePath()) | ||||
|         .put("path.logs", elasticDirPath.resolve("logs").toAbsolutePath()) | ||||
|         .put("transport.tcp.connect_timeout", "60s") | ||||
|         .build(); | ||||
|  | ||||
|     // Start the node | ||||
|     Node node = NodeBuilder.nodeBuilder() | ||||
|         .settings(settings) | ||||
|         .node(); | ||||
|  | ||||
|     // Wait for it to be ready | ||||
|     node.client() | ||||
|         .admin() | ||||
|         .cluster() | ||||
|         .prepareHealth() | ||||
|         .setWaitForYellowStatus() | ||||
|         .execute() | ||||
|         .actionGet(); | ||||
|  | ||||
|     assertThat(node.isClosed()).isFalse(); | ||||
|     return new ElasticNodeInfo(node, elasticDir, getHttpPort(node)); | ||||
|   } | ||||
|  | ||||
|   static void deleteIndexes(Node node, String index) { | ||||
|     node.client().admin().indices().prepareDelete(index).execute(); | ||||
|   } | ||||
|  | ||||
|   static class NodeInfo { | ||||
|     String httpAddress; | ||||
|   } | ||||
|  | ||||
|   static class Info { | ||||
|     Map<String, NodeInfo> nodes; | ||||
|   } | ||||
|  | ||||
|   private static String getHttpPort(Node node) | ||||
|       throws InterruptedException, ExecutionException { | ||||
|     String nodes = node.client().admin().cluster() | ||||
|         .nodesInfo(new NodesInfoRequest("*")).get().toString(); | ||||
|     Gson gson = new GsonBuilder() | ||||
|         .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) | ||||
|         .create(); | ||||
|     Info info = gson.fromJson(nodes, Info.class); | ||||
|     if (info.nodes == null || info.nodes.size() != 1) { | ||||
|       throw new RuntimeException( | ||||
|           "Cannot extract local Elasticsearch http port"); | ||||
|     } | ||||
|     Iterator<NodeInfo> values = info.nodes.values().iterator(); | ||||
|     String httpAddress = values.next().httpAddress; | ||||
|     if (Strings.isNullOrEmpty(httpAddress)) { | ||||
|       throw new RuntimeException( | ||||
|           "Cannot extract local Elasticsearch http port"); | ||||
|     } | ||||
|     if (httpAddress.indexOf(':') < 0) { | ||||
|       throw new RuntimeException( | ||||
|           "Seems that port is not included in Elasticsearch http_address"); | ||||
|     } | ||||
|     return httpAddress.substring(httpAddress.indexOf(':') + 1, | ||||
|         httpAddress.length()); | ||||
|   } | ||||
|  | ||||
|   private ElasticTestUtils() { | ||||
|     // hide default constructor | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user