| // 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 static com.google.gerrit.elasticsearch.ElasticAccountIndex.ACCOUNTS_PREFIX; |
| 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 static com.google.gerrit.elasticsearch.ElasticGroupIndex.GROUPS_PREFIX; |
| |
| import com.google.common.base.Strings; |
| import com.google.common.io.Files; |
| import com.google.gerrit.elasticsearch.ElasticAccountIndex.AccountMapping; |
| import com.google.gerrit.elasticsearch.ElasticChangeIndex.ChangeMapping; |
| import com.google.gerrit.elasticsearch.ElasticGroupIndex.GroupMapping; |
| import com.google.gerrit.index.Schema; |
| import com.google.gerrit.server.account.AccountState; |
| import com.google.gerrit.server.group.InternalGroup; |
| import com.google.gerrit.server.index.IndexModule.IndexType; |
| import com.google.gerrit.server.index.account.AccountSchemaDefinitions; |
| import com.google.gerrit.server.index.change.ChangeSchemaDefinitions; |
| import com.google.gerrit.server.index.group.GroupSchemaDefinitions; |
| import com.google.gerrit.server.query.change.ChangeData; |
| import com.google.gson.FieldNamingPolicy; |
| import com.google.gson.Gson; |
| import com.google.gson.GsonBuilder; |
| import java.io.File; |
| import java.nio.file.Path; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.concurrent.ExecutionException; |
| 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; |
| |
| 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("elasticsearch", "test", "protocol", "http"); |
| config.setString("elasticsearch", "test", "hostname", "localhost"); |
| config.setString("elasticsearch", "test", "port", port); |
| } |
| |
| 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 deleteAllIndexes(ElasticNodeInfo nodeInfo) { |
| nodeInfo.node.client().admin().indices().prepareDelete("_all").execute(); |
| } |
| |
| static class NodeInfo { |
| String httpAddress; |
| } |
| |
| static class Info { |
| Map<String, NodeInfo> nodes; |
| } |
| |
| static void createAllIndexes(ElasticNodeInfo nodeInfo) { |
| Schema<ChangeData> changeSchema = ChangeSchemaDefinitions.INSTANCE.getLatest(); |
| ChangeMapping openChangesMapping = new ChangeMapping(changeSchema); |
| ChangeMapping closedChangesMapping = new ChangeMapping(changeSchema); |
| openChangesMapping.closedChanges = null; |
| closedChangesMapping.openChanges = null; |
| nodeInfo |
| .node |
| .client() |
| .admin() |
| .indices() |
| .prepareCreate(String.format("%s%04d", CHANGES_PREFIX, changeSchema.getVersion())) |
| .addMapping(OPEN_CHANGES, gson.toJson(openChangesMapping)) |
| .addMapping(CLOSED_CHANGES, gson.toJson(closedChangesMapping)) |
| .execute() |
| .actionGet(); |
| |
| Schema<AccountState> accountSchema = AccountSchemaDefinitions.INSTANCE.getLatest(); |
| AccountMapping accountMapping = new AccountMapping(accountSchema); |
| nodeInfo |
| .node |
| .client() |
| .admin() |
| .indices() |
| .prepareCreate(String.format("%s%04d", ACCOUNTS_PREFIX, accountSchema.getVersion())) |
| .addMapping(ElasticAccountIndex.ACCOUNTS, gson.toJson(accountMapping)) |
| .execute() |
| .actionGet(); |
| |
| Schema<InternalGroup> groupSchema = GroupSchemaDefinitions.INSTANCE.getLatest(); |
| GroupMapping groupMapping = new GroupMapping(groupSchema); |
| nodeInfo |
| .node |
| .client() |
| .admin() |
| .indices() |
| .prepareCreate(String.format("%s%04d", GROUPS_PREFIX, groupSchema.getVersion())) |
| .addMapping(ElasticGroupIndex.GROUPS, gson.toJson(groupMapping)) |
| .execute() |
| .actionGet(); |
| } |
| |
| 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 |
| } |
| } |