Merge branch 'stable-3.1' into stable-3.2
* stable-3.1: Update git submodules Update git submodules Compact the REST-API output JSON unconditionally Elasticsearch: Discontinue EOL versions 7.0 and 7.1 support Elasticsearch: Discontinue EOL version 6.8 thus whole V6 support Update git submodules Avoid logging "length=0" exception Change-Id: If2b3e33e574b8cb8672eed76edb7de31c70a8223
This commit is contained in:
		@@ -3201,10 +3201,6 @@ WARNING: Support for Elasticsearch is still experimental and is not recommended
 | 
			
		||||
for production use. For compatibility information, please refer to the
 | 
			
		||||
link:https://www.gerritcodereview.com/elasticsearch.html[project homepage,role=external,window=_blank].
 | 
			
		||||
 | 
			
		||||
In Elasticsearch version 6.2 or later, the open and closed changes are merged
 | 
			
		||||
into the default `_doc` type. The latter is also used for the accounts and groups
 | 
			
		||||
indices starting with Elasticsearch 6.2.
 | 
			
		||||
 | 
			
		||||
Note that when Gerrit is configured to use Elasticsearch, the Elasticsearch
 | 
			
		||||
server(s) must be reachable during the site initialization.
 | 
			
		||||
 | 
			
		||||
@@ -3234,7 +3230,7 @@ Sets the number of shards to use per index. Refer to the
 | 
			
		||||
link:https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#_static_index_settings[
 | 
			
		||||
Elasticsearch documentation,role=external,window=_blank] for details.
 | 
			
		||||
+
 | 
			
		||||
Defaults to 5 for Elasticsearch versions 5 and 6, and to 1 starting with Elasticsearch 7.
 | 
			
		||||
Defaults to 1.
 | 
			
		||||
 | 
			
		||||
[[elasticsearch.numberOfReplicas]]elasticsearch.numberOfReplicas::
 | 
			
		||||
+
 | 
			
		||||
 
 | 
			
		||||
@@ -127,7 +127,6 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
 | 
			
		||||
  private final SitePaths sitePaths;
 | 
			
		||||
  private final String indexNameRaw;
 | 
			
		||||
 | 
			
		||||
  protected final String type;
 | 
			
		||||
  protected final ElasticRestClientProvider client;
 | 
			
		||||
  protected final String indexName;
 | 
			
		||||
  protected final Gson gson;
 | 
			
		||||
@@ -147,7 +146,6 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
 | 
			
		||||
    this.indexName = config.getIndexName(indexName, schema.getVersion());
 | 
			
		||||
    this.indexNameRaw = indexName;
 | 
			
		||||
    this.client = client;
 | 
			
		||||
    this.type = client.adapter().getType();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
@@ -167,7 +165,7 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void delete(K id) {
 | 
			
		||||
    String uri = getURI(type, BULK);
 | 
			
		||||
    String uri = getURI(BULK);
 | 
			
		||||
    Response response = postRequest(uri, getDeleteActions(id), getRefreshParam());
 | 
			
		||||
    int statusCode = response.getStatusLine().getStatusCode();
 | 
			
		||||
    if (statusCode != HttpStatus.SC_OK) {
 | 
			
		||||
@@ -192,10 +190,8 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Recreate the index.
 | 
			
		||||
    String indexCreationFields = concatJsonString(getSettings(client.adapter()), getMappings());
 | 
			
		||||
    response =
 | 
			
		||||
        performRequest(
 | 
			
		||||
            "PUT", indexName + client.adapter().includeTypeNameParam(), indexCreationFields);
 | 
			
		||||
    String indexCreationFields = concatJsonString(getSettings(), getMappings());
 | 
			
		||||
    response = performRequest("PUT", indexName, indexCreationFields);
 | 
			
		||||
    statusCode = response.getStatusLine().getStatusCode();
 | 
			
		||||
    if (statusCode != HttpStatus.SC_OK) {
 | 
			
		||||
      String error = String.format("Failed to create index %s: %s", indexName, statusCode);
 | 
			
		||||
@@ -207,26 +203,20 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
 | 
			
		||||
 | 
			
		||||
  protected abstract String getMappings();
 | 
			
		||||
 | 
			
		||||
  private String getSettings(ElasticQueryAdapter adapter) {
 | 
			
		||||
    return gson.toJson(ImmutableMap.of(SETTINGS, ElasticSetting.createSetting(config, adapter)));
 | 
			
		||||
  private String getSettings() {
 | 
			
		||||
    return gson.toJson(ImmutableMap.of(SETTINGS, ElasticSetting.createSetting(config)));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected abstract String getId(V v);
 | 
			
		||||
 | 
			
		||||
  protected String getMappingsForSingleType(MappingProperties properties) {
 | 
			
		||||
    return getMappingsFor(client.adapter().getType(), properties);
 | 
			
		||||
    return getMappingsFor(properties);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected String getMappingsFor(String type, MappingProperties properties) {
 | 
			
		||||
  protected String getMappingsFor(MappingProperties properties) {
 | 
			
		||||
    JsonObject mappings = new JsonObject();
 | 
			
		||||
 | 
			
		||||
    if (client.adapter().omitType()) {
 | 
			
		||||
    mappings.add(MAPPINGS, gson.toJsonTree(properties));
 | 
			
		||||
    } else {
 | 
			
		||||
      JsonObject mappingType = new JsonObject();
 | 
			
		||||
      mappingType.add(type, gson.toJsonTree(properties));
 | 
			
		||||
      mappings.add(MAPPINGS, gson.toJsonTree(mappingType));
 | 
			
		||||
    }
 | 
			
		||||
    return gson.toJson(mappings);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -305,15 +295,9 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
 | 
			
		||||
    return sortArray;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected String getURI(String type, String request) {
 | 
			
		||||
  protected String getURI(String request) {
 | 
			
		||||
    try {
 | 
			
		||||
      String encodedIndexName = URLEncoder.encode(indexName, UTF_8.toString());
 | 
			
		||||
      if (SEARCH.equals(request) && client.adapter().omitType()) {
 | 
			
		||||
        return encodedIndexName + "/" + request;
 | 
			
		||||
      }
 | 
			
		||||
      String encodedTypeIfAny =
 | 
			
		||||
          client.adapter().omitType() ? "" : "/" + URLEncoder.encode(type, UTF_8.toString());
 | 
			
		||||
      return encodedIndexName + encodedTypeIfAny + "/" + request;
 | 
			
		||||
      return URLEncoder.encode(indexName, UTF_8.toString()) + "/" + request;
 | 
			
		||||
    } catch (UnsupportedEncodingException e) {
 | 
			
		||||
      throw new StorageException(e);
 | 
			
		||||
    }
 | 
			
		||||
@@ -359,12 +343,10 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
 | 
			
		||||
  protected class ElasticQuerySource implements DataSource<V> {
 | 
			
		||||
    private final QueryOptions opts;
 | 
			
		||||
    private final String search;
 | 
			
		||||
    private final String index;
 | 
			
		||||
 | 
			
		||||
    ElasticQuerySource(Predicate<V> p, QueryOptions opts, String index, JsonArray sortArray)
 | 
			
		||||
    ElasticQuerySource(Predicate<V> p, QueryOptions opts, JsonArray sortArray)
 | 
			
		||||
        throws QueryParseException {
 | 
			
		||||
      this.opts = opts;
 | 
			
		||||
      this.index = index;
 | 
			
		||||
      QueryBuilder qb = queryBuilder.toQueryBuilder(p);
 | 
			
		||||
      SearchSourceBuilder searchSource =
 | 
			
		||||
          new SearchSourceBuilder(client.adapter())
 | 
			
		||||
@@ -392,7 +374,7 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
 | 
			
		||||
 | 
			
		||||
    private <T> ResultSet<T> readImpl(Function<JsonObject, T> mapper) {
 | 
			
		||||
      try {
 | 
			
		||||
        String uri = getURI(index, SEARCH);
 | 
			
		||||
        String uri = getURI(SEARCH);
 | 
			
		||||
        Response response =
 | 
			
		||||
            performRequest(HttpPost.METHOD_NAME, uri, search, Collections.emptyMap());
 | 
			
		||||
        StatusLine statusLine = response.getStatusLine();
 | 
			
		||||
 
 | 
			
		||||
@@ -77,7 +77,7 @@ public class ElasticAccountIndex extends AbstractElasticIndex<Account.Id, Accoun
 | 
			
		||||
        new IndexRequest(getId(as), indexName)
 | 
			
		||||
            .add(new UpdateRequest<>(schema, as, ImmutableSet.of()));
 | 
			
		||||
 | 
			
		||||
    String uri = getURI(type, BULK);
 | 
			
		||||
    String uri = getURI(BULK);
 | 
			
		||||
    Response response = postRequest(uri, bulk, getRefreshParam());
 | 
			
		||||
    int statusCode = response.getStatusLine().getStatusCode();
 | 
			
		||||
    if (statusCode != HttpStatus.SC_OK) {
 | 
			
		||||
@@ -99,7 +99,6 @@ public class ElasticAccountIndex extends AbstractElasticIndex<Account.Id, Accoun
 | 
			
		||||
    return new ElasticQuerySource(
 | 
			
		||||
        p,
 | 
			
		||||
        opts.filterFields(o -> IndexUtils.accountFields(o, schema.useLegacyNumericFields())),
 | 
			
		||||
        type,
 | 
			
		||||
        sortArray);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,8 +14,6 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.elasticsearch;
 | 
			
		||||
 | 
			
		||||
import static com.google.gerrit.server.index.change.ChangeIndexRewriter.CLOSED_STATUSES;
 | 
			
		||||
import static com.google.gerrit.server.index.change.ChangeIndexRewriter.OPEN_STATUSES;
 | 
			
		||||
import static java.nio.charset.StandardCharsets.UTF_8;
 | 
			
		||||
import static java.util.Objects.requireNonNull;
 | 
			
		||||
 | 
			
		||||
@@ -24,7 +22,6 @@ import com.google.common.collect.ImmutableListMultimap;
 | 
			
		||||
import com.google.common.collect.ImmutableSet;
 | 
			
		||||
import com.google.common.collect.Iterables;
 | 
			
		||||
import com.google.common.collect.ListMultimap;
 | 
			
		||||
import com.google.common.collect.Lists;
 | 
			
		||||
import com.google.common.collect.MultimapBuilder;
 | 
			
		||||
import com.google.common.collect.Sets;
 | 
			
		||||
import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
 | 
			
		||||
@@ -53,7 +50,6 @@ import com.google.gerrit.server.config.SitePaths;
 | 
			
		||||
import com.google.gerrit.server.index.IndexUtils;
 | 
			
		||||
import com.google.gerrit.server.index.change.ChangeField;
 | 
			
		||||
import com.google.gerrit.server.index.change.ChangeIndex;
 | 
			
		||||
import com.google.gerrit.server.index.change.ChangeIndexRewriter;
 | 
			
		||||
import com.google.gerrit.server.project.SubmitRuleOptions;
 | 
			
		||||
import com.google.gerrit.server.query.change.ChangeData;
 | 
			
		||||
import com.google.gson.JsonArray;
 | 
			
		||||
@@ -62,7 +58,6 @@ import com.google.gson.JsonObject;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.assistedinject.Assisted;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import org.apache.http.HttpStatus;
 | 
			
		||||
@@ -86,8 +81,6 @@ class ElasticChangeIndex extends AbstractElasticIndex<Change.Id, ChangeData>
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static final String CHANGES = "changes";
 | 
			
		||||
  private static final String OPEN_CHANGES = "open_" + CHANGES;
 | 
			
		||||
  private static final String CLOSED_CHANGES = "closed_" + CHANGES;
 | 
			
		||||
 | 
			
		||||
  private final ChangeMapping mapping;
 | 
			
		||||
  private final ChangeData.Factory changeDataFactory;
 | 
			
		||||
@@ -120,7 +113,7 @@ class ElasticChangeIndex extends AbstractElasticIndex<Change.Id, ChangeData>
 | 
			
		||||
    BulkRequest bulk =
 | 
			
		||||
        new IndexRequest(getId(cd), indexName).add(new UpdateRequest<>(schema, cd, skipFields));
 | 
			
		||||
 | 
			
		||||
    String uri = getURI(type, BULK);
 | 
			
		||||
    String uri = getURI(BULK);
 | 
			
		||||
    Response response = postRequest(uri, bulk, getRefreshParam());
 | 
			
		||||
    int statusCode = response.getStatusLine().getStatusCode();
 | 
			
		||||
    if (statusCode != HttpStatus.SC_OK) {
 | 
			
		||||
@@ -133,27 +126,9 @@ class ElasticChangeIndex extends AbstractElasticIndex<Change.Id, ChangeData>
 | 
			
		||||
  @Override
 | 
			
		||||
  public DataSource<ChangeData> getSource(Predicate<ChangeData> p, QueryOptions opts)
 | 
			
		||||
      throws QueryParseException {
 | 
			
		||||
    Set<Change.Status> statuses = ChangeIndexRewriter.getPossibleStatus(p);
 | 
			
		||||
    List<String> indexes = Lists.newArrayListWithCapacity(2);
 | 
			
		||||
    if (!client.adapter().omitType()) {
 | 
			
		||||
      if (client.adapter().useV6Type()) {
 | 
			
		||||
        if (!Sets.intersection(statuses, OPEN_STATUSES).isEmpty()
 | 
			
		||||
            || !Sets.intersection(statuses, CLOSED_STATUSES).isEmpty()) {
 | 
			
		||||
          indexes.add(ElasticQueryAdapter.V6_TYPE);
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        if (!Sets.intersection(statuses, OPEN_STATUSES).isEmpty()) {
 | 
			
		||||
          indexes.add(OPEN_CHANGES);
 | 
			
		||||
        }
 | 
			
		||||
        if (!Sets.intersection(statuses, CLOSED_STATUSES).isEmpty()) {
 | 
			
		||||
          indexes.add(CLOSED_CHANGES);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QueryOptions filteredOpts =
 | 
			
		||||
        opts.filterFields(o -> IndexUtils.changeFields(o, schema.useLegacyNumericFields()));
 | 
			
		||||
    return new ElasticQuerySource(p, filteredOpts, getURI(indexes), getSortArray());
 | 
			
		||||
    return new ElasticQuerySource(p, filteredOpts, getSortArray());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private JsonArray getSortArray() {
 | 
			
		||||
@@ -166,10 +141,6 @@ class ElasticChangeIndex extends AbstractElasticIndex<Change.Id, ChangeData>
 | 
			
		||||
    return sortArray;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private String getURI(List<String> types) {
 | 
			
		||||
    return String.join(",", types);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected String getDeleteActions(Change.Id c) {
 | 
			
		||||
    return getDeleteRequest(c);
 | 
			
		||||
@@ -177,7 +148,7 @@ class ElasticChangeIndex extends AbstractElasticIndex<Change.Id, ChangeData>
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected String getMappings() {
 | 
			
		||||
    return getMappingsFor(client.adapter().getType(), mapping.changes);
 | 
			
		||||
    return getMappingsFor(mapping.changes);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ class ElasticConfiguration {
 | 
			
		||||
 | 
			
		||||
  static final String DEFAULT_PORT = "9200";
 | 
			
		||||
  static final String DEFAULT_USERNAME = "elastic";
 | 
			
		||||
  static final int DEFAULT_NUMBER_OF_SHARDS = 0;
 | 
			
		||||
  static final int DEFAULT_NUMBER_OF_SHARDS = 1;
 | 
			
		||||
  static final int DEFAULT_NUMBER_OF_REPLICAS = 1;
 | 
			
		||||
  static final int DEFAULT_MAX_RESULT_WINDOW = 10000;
 | 
			
		||||
 | 
			
		||||
@@ -107,10 +107,7 @@ class ElasticConfiguration {
 | 
			
		||||
    return String.format("%s%s_%04d", prefix, name, schemaVersion);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int getNumberOfShards(ElasticQueryAdapter adapter) {
 | 
			
		||||
    if (numberOfShards == DEFAULT_NUMBER_OF_SHARDS) {
 | 
			
		||||
      return adapter.getDefaultNumberOfShards();
 | 
			
		||||
    }
 | 
			
		||||
  int getNumberOfShards() {
 | 
			
		||||
    return numberOfShards;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -77,7 +77,7 @@ public class ElasticGroupIndex extends AbstractElasticIndex<AccountGroup.UUID, I
 | 
			
		||||
        new IndexRequest(getId(group), indexName)
 | 
			
		||||
            .add(new UpdateRequest<>(schema, group, ImmutableSet.of()));
 | 
			
		||||
 | 
			
		||||
    String uri = getURI(type, BULK);
 | 
			
		||||
    String uri = getURI(BULK);
 | 
			
		||||
    Response response = postRequest(uri, bulk, getRefreshParam());
 | 
			
		||||
    int statusCode = response.getStatusLine().getStatusCode();
 | 
			
		||||
    if (statusCode != HttpStatus.SC_OK) {
 | 
			
		||||
@@ -92,7 +92,7 @@ public class ElasticGroupIndex extends AbstractElasticIndex<AccountGroup.UUID, I
 | 
			
		||||
  public DataSource<InternalGroup> getSource(Predicate<InternalGroup> p, QueryOptions opts)
 | 
			
		||||
      throws QueryParseException {
 | 
			
		||||
    JsonArray sortArray = getSortArray(GroupField.UUID.getName());
 | 
			
		||||
    return new ElasticQuerySource(p, opts.filterFields(IndexUtils::groupFields), type, sortArray);
 | 
			
		||||
    return new ElasticQuerySource(p, opts.filterFields(IndexUtils::groupFields), sortArray);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -79,7 +79,7 @@ public class ElasticProjectIndex extends AbstractElasticIndex<Project.NameKey, P
 | 
			
		||||
        new IndexRequest(projectState.getProject().getName(), indexName)
 | 
			
		||||
            .add(new UpdateRequest<>(schema, projectState, ImmutableSet.of()));
 | 
			
		||||
 | 
			
		||||
    String uri = getURI(type, BULK);
 | 
			
		||||
    String uri = getURI(BULK);
 | 
			
		||||
    Response response = postRequest(uri, bulk, getRefreshParam());
 | 
			
		||||
    int statusCode = response.getStatusLine().getStatusCode();
 | 
			
		||||
    if (statusCode != HttpStatus.SC_OK) {
 | 
			
		||||
@@ -94,7 +94,7 @@ public class ElasticProjectIndex extends AbstractElasticIndex<Project.NameKey, P
 | 
			
		||||
  public DataSource<ProjectData> getSource(Predicate<ProjectData> p, QueryOptions opts)
 | 
			
		||||
      throws QueryParseException {
 | 
			
		||||
    JsonArray sortArray = getSortArray(ProjectField.NAME.getName());
 | 
			
		||||
    return new ElasticQuerySource(p, opts.filterFields(IndexUtils::projectFields), type, sortArray);
 | 
			
		||||
    return new ElasticQuerySource(p, opts.filterFields(IndexUtils::projectFields), sortArray);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -14,42 +14,23 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.elasticsearch;
 | 
			
		||||
 | 
			
		||||
import static com.google.gerrit.elasticsearch.ElasticVersion.V6_8;
 | 
			
		||||
 | 
			
		||||
public class ElasticQueryAdapter {
 | 
			
		||||
  static final String V6_TYPE = "_doc";
 | 
			
		||||
 | 
			
		||||
  private static final String INCLUDE_TYPE = "include_type_name=true";
 | 
			
		||||
  private static final String INDICES = "?allow_no_indices=false";
 | 
			
		||||
 | 
			
		||||
  private final boolean useV6Type;
 | 
			
		||||
  private final boolean omitType;
 | 
			
		||||
  private final int defaultNumberOfShards;
 | 
			
		||||
 | 
			
		||||
  private final String searchFilteringName;
 | 
			
		||||
  private final String indicesExistParams;
 | 
			
		||||
  private final String exactFieldType;
 | 
			
		||||
  private final String stringFieldType;
 | 
			
		||||
  private final String indexProperty;
 | 
			
		||||
  private final String rawFieldsKey;
 | 
			
		||||
  private final String versionDiscoveryUrl;
 | 
			
		||||
  private final String includeTypeNameParam;
 | 
			
		||||
 | 
			
		||||
  ElasticQueryAdapter(ElasticVersion version) {
 | 
			
		||||
    this.useV6Type = version.isV6();
 | 
			
		||||
    this.omitType = version.isV7OrLater();
 | 
			
		||||
    this.defaultNumberOfShards = version.isV7OrLater() ? 1 : 5;
 | 
			
		||||
    this.versionDiscoveryUrl = version.isV6OrLater() ? "/%s*" : "/%s*/_aliases";
 | 
			
		||||
  ElasticQueryAdapter() {
 | 
			
		||||
    this.versionDiscoveryUrl = "/%s*";
 | 
			
		||||
    this.searchFilteringName = "_source";
 | 
			
		||||
    this.exactFieldType = "keyword";
 | 
			
		||||
    this.stringFieldType = "text";
 | 
			
		||||
    this.indexProperty = "true";
 | 
			
		||||
    this.rawFieldsKey = "_source";
 | 
			
		||||
 | 
			
		||||
    // Since v6.7 (end-of-life), in fact, for these two parameters:
 | 
			
		||||
    this.indicesExistParams =
 | 
			
		||||
        version.isAtLeastMinorVersion(V6_8) ? INDICES + "&" + INCLUDE_TYPE : INDICES;
 | 
			
		||||
    this.includeTypeNameParam = version.isAtLeastMinorVersion(V6_8) ? "?" + INCLUDE_TYPE : "";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public String searchFilteringName() {
 | 
			
		||||
@@ -57,7 +38,7 @@ public class ElasticQueryAdapter {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String indicesExistParams() {
 | 
			
		||||
    return indicesExistParams;
 | 
			
		||||
    return INDICES;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String exactFieldType() {
 | 
			
		||||
@@ -76,27 +57,7 @@ public class ElasticQueryAdapter {
 | 
			
		||||
    return rawFieldsKey;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  boolean useV6Type() {
 | 
			
		||||
    return useV6Type;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  boolean omitType() {
 | 
			
		||||
    return omitType;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int getDefaultNumberOfShards() {
 | 
			
		||||
    return defaultNumberOfShards;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String getType() {
 | 
			
		||||
    return useV6Type() ? V6_TYPE : "";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String getVersionDiscoveryUrl(String name) {
 | 
			
		||||
    return String.format(versionDiscoveryUrl, name);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String includeTypeNameParam() {
 | 
			
		||||
    return includeTypeNameParam;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ class ElasticRestClientProvider implements Provider<RestClient>, LifecycleListen
 | 
			
		||||
          client = build();
 | 
			
		||||
          ElasticVersion version = getVersion();
 | 
			
		||||
          logger.atInfo().log("Elasticsearch integration version %s", version);
 | 
			
		||||
          adapter = new ElasticQueryAdapter(version);
 | 
			
		||||
          adapter = new ElasticQueryAdapter();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -22,18 +22,18 @@ class ElasticSetting {
 | 
			
		||||
  private static final ImmutableMap<String, String> CUSTOM_CHAR_MAPPING =
 | 
			
		||||
      ImmutableMap.of("\\u002E", "\\u0020", "\\u005F", "\\u0020");
 | 
			
		||||
 | 
			
		||||
  static SettingProperties createSetting(ElasticConfiguration config, ElasticQueryAdapter adapter) {
 | 
			
		||||
    return new ElasticSetting.Builder().addCharFilter().addAnalyzer().build(config, adapter);
 | 
			
		||||
  static SettingProperties createSetting(ElasticConfiguration config) {
 | 
			
		||||
    return new ElasticSetting.Builder().addCharFilter().addAnalyzer().build(config);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static class Builder {
 | 
			
		||||
    private final ImmutableMap.Builder<String, FieldProperties> fields =
 | 
			
		||||
        new ImmutableMap.Builder<>();
 | 
			
		||||
 | 
			
		||||
    SettingProperties build(ElasticConfiguration config, ElasticQueryAdapter adapter) {
 | 
			
		||||
    SettingProperties build(ElasticConfiguration config) {
 | 
			
		||||
      SettingProperties properties = new SettingProperties();
 | 
			
		||||
      properties.analysis = fields.build();
 | 
			
		||||
      properties.numberOfShards = config.getNumberOfShards(adapter);
 | 
			
		||||
      properties.numberOfShards = config.getNumberOfShards();
 | 
			
		||||
      properties.numberOfReplicas = config.numberOfReplicas;
 | 
			
		||||
      properties.maxResultWindow = config.maxResultWindow;
 | 
			
		||||
      return properties;
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,6 @@ import com.google.common.base.Joiner;
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
 | 
			
		||||
public enum ElasticVersion {
 | 
			
		||||
  V6_8("6.8.*"),
 | 
			
		||||
  V7_0("7.0.*"),
 | 
			
		||||
  V7_1("7.1.*"),
 | 
			
		||||
  V7_2("7.2.*"),
 | 
			
		||||
  V7_3("7.3.*"),
 | 
			
		||||
  V7_4("7.4.*"),
 | 
			
		||||
@@ -67,34 +64,6 @@ public enum ElasticVersion {
 | 
			
		||||
    return Joiner.on(", ").join(ElasticVersion.values());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean isV6() {
 | 
			
		||||
    return getMajor() == 6;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean isV6OrLater() {
 | 
			
		||||
    return isAtLeastVersion(6);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean isV7OrLater() {
 | 
			
		||||
    return isAtLeastVersion(7);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private boolean isAtLeastVersion(int major) {
 | 
			
		||||
    return getMajor() >= major;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean isAtLeastMinorVersion(ElasticVersion version) {
 | 
			
		||||
    return getMajor().equals(version.getMajor()) && getMinor() >= version.getMinor();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private Integer getMajor() {
 | 
			
		||||
    return Integer.valueOf(version.split("\\.")[0]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private Integer getMinor() {
 | 
			
		||||
    return Integer.valueOf(version.split("\\.")[1]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public String toString() {
 | 
			
		||||
    return version;
 | 
			
		||||
 
 | 
			
		||||
@@ -1329,7 +1329,7 @@ public class RestApiServlet extends HttpServlet {
 | 
			
		||||
    TemporaryBuffer.Heap buf = heap(HEAP_EST_SIZE, Integer.MAX_VALUE);
 | 
			
		||||
    buf.write(JSON_MAGIC);
 | 
			
		||||
    Writer w = new BufferedWriter(new OutputStreamWriter(buf, UTF_8));
 | 
			
		||||
    Gson gson = newGson(config, req);
 | 
			
		||||
    Gson gson = newGson(config);
 | 
			
		||||
    if (result instanceof JsonElement) {
 | 
			
		||||
      gson.toJson((JsonElement) result, w);
 | 
			
		||||
    } else {
 | 
			
		||||
@@ -1356,25 +1356,18 @@ public class RestApiServlet extends HttpServlet {
 | 
			
		||||
        req, res, asBinaryResult(buf).setContentType(JSON_TYPE).setCharacterEncoding(UTF_8));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static Gson newGson(
 | 
			
		||||
      ListMultimap<String, String> config, @Nullable HttpServletRequest req) {
 | 
			
		||||
  private static Gson newGson(ListMultimap<String, String> config) {
 | 
			
		||||
    GsonBuilder gb = OutputFormat.JSON_COMPACT.newGsonBuilder();
 | 
			
		||||
 | 
			
		||||
    enablePrettyPrint(gb, config, req);
 | 
			
		||||
    enablePrettyPrint(gb, config);
 | 
			
		||||
    enablePartialGetFields(gb, config);
 | 
			
		||||
 | 
			
		||||
    return gb.create();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static void enablePrettyPrint(
 | 
			
		||||
      GsonBuilder gb, ListMultimap<String, String> config, @Nullable HttpServletRequest req) {
 | 
			
		||||
    String pp = Iterables.getFirst(config.get("pp"), null);
 | 
			
		||||
    if (pp == null) {
 | 
			
		||||
      pp = Iterables.getFirst(config.get("prettyPrint"), null);
 | 
			
		||||
      if (pp == null && req != null) {
 | 
			
		||||
        pp = acceptsJson(req) ? "0" : "1";
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  private static void enablePrettyPrint(GsonBuilder gb, ListMultimap<String, String> config) {
 | 
			
		||||
    String pp =
 | 
			
		||||
        Iterables.getFirst(config.get("pp"), Iterables.getFirst(config.get("prettyPrint"), "0"));
 | 
			
		||||
    if ("1".equals(pp) || "true".equals(pp)) {
 | 
			
		||||
      gb.setPrettyPrinting();
 | 
			
		||||
    }
 | 
			
		||||
@@ -1887,10 +1880,6 @@ public class RestApiServlet extends HttpServlet {
 | 
			
		||||
    return CharMatcher.anyOf("<&").matchesAnyOf(text);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static boolean acceptsJson(HttpServletRequest req) {
 | 
			
		||||
    return req != null && isType(JSON_TYPE, req.getHeader(HttpHeaders.ACCEPT));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static boolean acceptsGzip(HttpServletRequest req) {
 | 
			
		||||
    if (req != null) {
 | 
			
		||||
      String accepts = req.getHeader(HttpHeaders.ACCEPT_ENCODING);
 | 
			
		||||
 
 | 
			
		||||
@@ -51,6 +51,7 @@ import java.io.OutputStreamWriter;
 | 
			
		||||
import java.io.PrintWriter;
 | 
			
		||||
import java.io.StringWriter;
 | 
			
		||||
import java.nio.charset.Charset;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.concurrent.Future;
 | 
			
		||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
 | 
			
		||||
import java.util.concurrent.atomic.AtomicReference;
 | 
			
		||||
@@ -356,7 +357,7 @@ public abstract class BaseCommand implements Command {
 | 
			
		||||
      }
 | 
			
		||||
      m.append(" during ");
 | 
			
		||||
      m.append(context.getCommandLine());
 | 
			
		||||
      logger.atSevere().withCause(e).log(m.toString());
 | 
			
		||||
      logCauseIfRelevant(e, m);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (e instanceof Failure) {
 | 
			
		||||
@@ -383,6 +384,20 @@ public abstract class BaseCommand implements Command {
 | 
			
		||||
    return 128;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private void logCauseIfRelevant(Throwable e, StringBuilder message) {
 | 
			
		||||
    String zeroLength = "length=0";
 | 
			
		||||
    String streamAlreadyClosed = "stream is already closed";
 | 
			
		||||
    boolean isZeroLength = false;
 | 
			
		||||
 | 
			
		||||
    if (streamAlreadyClosed.equals(e.getMessage())) {
 | 
			
		||||
      StackTraceElement[] stackTrace = e.getStackTrace();
 | 
			
		||||
      isZeroLength = Arrays.stream(stackTrace).anyMatch(s -> s.toString().contains(zeroLength));
 | 
			
		||||
    }
 | 
			
		||||
    if (!isZeroLength) {
 | 
			
		||||
      logger.atSevere().withCause(e).log(message.toString());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected UnloggedFailure die(String msg) {
 | 
			
		||||
    return new UnloggedFailure(1, "fatal: " + msg);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -25,11 +25,6 @@ import org.eclipse.jgit.lib.Config;
 | 
			
		||||
public class ElasticReindexIT extends AbstractReindexTests {
 | 
			
		||||
 | 
			
		||||
  @ConfigSuite.Default
 | 
			
		||||
  public static Config elasticsearchV6() {
 | 
			
		||||
    return getConfig(ElasticVersion.V6_8);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @ConfigSuite.Config
 | 
			
		||||
  public static Config elasticsearchV7() {
 | 
			
		||||
    return getConfig(ElasticVersion.V7_8);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,76 @@
 | 
			
		||||
// Copyright (C) 2020 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.acceptance.rest;
 | 
			
		||||
 | 
			
		||||
import static com.google.common.truth.Truth.assertThat;
 | 
			
		||||
import static org.apache.http.HttpStatus.SC_OK;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
 | 
			
		||||
import com.google.gerrit.acceptance.RestResponse;
 | 
			
		||||
import com.google.gerrit.httpd.restapi.RestApiServlet;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
import org.apache.http.message.BasicHeader;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
public class RestApiServletIT extends AbstractDaemonTest {
 | 
			
		||||
  private static String ANY_REST_API = "/accounts/self/capabilities";
 | 
			
		||||
  private static BasicHeader ACCEPT_STAR_HEADER = new BasicHeader("Accept", "*/*");
 | 
			
		||||
  private static Pattern ANY_SPACE = Pattern.compile("\\s");
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void restResponseBodyShouldBeCompactWithoutSpaces() throws Exception {
 | 
			
		||||
    RestResponse response = adminRestSession.getWithHeader(ANY_REST_API, ACCEPT_STAR_HEADER);
 | 
			
		||||
    assertThat(response.getStatusCode()).isEqualTo(SC_OK);
 | 
			
		||||
 | 
			
		||||
    assertThat(contentWithoutMagicJson(response)).doesNotContainMatch(ANY_SPACE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void restResponseBodyShouldBeCompactWithoutSpacesWhenPPIsZero() throws Exception {
 | 
			
		||||
    assertThat(contentWithoutMagicJson(prettyJsonRestResponse("prettyPrint", 0)))
 | 
			
		||||
        .doesNotContainMatch(ANY_SPACE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void restResponseBodyShouldBeCompactWithoutSpacesWhenPrerryPrintIsZero() throws Exception {
 | 
			
		||||
    assertThat(contentWithoutMagicJson(prettyJsonRestResponse("pp", 0)))
 | 
			
		||||
        .doesNotContainMatch(ANY_SPACE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void restResponseBodyShouldBePrettyfiedWhenPPIsOne() throws Exception {
 | 
			
		||||
    assertThat(contentWithoutMagicJson(prettyJsonRestResponse("pp", 1))).containsMatch(ANY_SPACE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void restResponseBodyShouldBePrettyfiedWhenPrettyPrintIsOne() throws Exception {
 | 
			
		||||
    assertThat(contentWithoutMagicJson(prettyJsonRestResponse("prettyPrint", 1)))
 | 
			
		||||
        .containsMatch(ANY_SPACE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private RestResponse prettyJsonRestResponse(String ppArgument, int ppValue) throws Exception {
 | 
			
		||||
    RestResponse response =
 | 
			
		||||
        adminRestSession.getWithHeader(
 | 
			
		||||
            ANY_REST_API + "?" + ppArgument + "=" + ppValue, ACCEPT_STAR_HEADER);
 | 
			
		||||
    assertThat(response.getStatusCode()).isEqualTo(SC_OK);
 | 
			
		||||
 | 
			
		||||
    return response;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private String contentWithoutMagicJson(RestResponse response) throws IOException {
 | 
			
		||||
    return response.getEntityContent().substring(RestApiServlet.JSON_MAGIC.length);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -27,11 +27,6 @@ import org.eclipse.jgit.lib.Config;
 | 
			
		||||
public class ElasticIndexIT extends AbstractIndexTests {
 | 
			
		||||
 | 
			
		||||
  @ConfigSuite.Default
 | 
			
		||||
  public static Config elasticsearchV6() {
 | 
			
		||||
    return getConfig(ElasticVersion.V6_8);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @ConfigSuite.Config
 | 
			
		||||
  public static Config elasticsearchV7() {
 | 
			
		||||
    return getConfig(ElasticVersion.V7_8);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -50,8 +50,6 @@ TYPES = [
 | 
			
		||||
 | 
			
		||||
SUFFIX = "sTest.java"
 | 
			
		||||
 | 
			
		||||
ELASTICSEARCH_TESTS_V6 = {i: "ElasticV6Query" + i.capitalize() + SUFFIX for i in TYPES}
 | 
			
		||||
 | 
			
		||||
ELASTICSEARCH_TESTS_V7 = {i: "ElasticV7Query" + i.capitalize() + SUFFIX for i in TYPES}
 | 
			
		||||
 | 
			
		||||
ELASTICSEARCH_TAGS = [
 | 
			
		||||
@@ -60,14 +58,6 @@ ELASTICSEARCH_TAGS = [
 | 
			
		||||
    "exclusive",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[junit_tests(
 | 
			
		||||
    name = "elasticsearch_query_%ss_test_V6" % name,
 | 
			
		||||
    size = "large",
 | 
			
		||||
    srcs = [src],
 | 
			
		||||
    tags = ELASTICSEARCH_TAGS,
 | 
			
		||||
    deps = ELASTICSEARCH_DEPS + [QUERY_TESTS_DEP % name] + HTTP_TEST_DEPS,
 | 
			
		||||
) for name, src in ELASTICSEARCH_TESTS_V6.items()]
 | 
			
		||||
 | 
			
		||||
[junit_tests(
 | 
			
		||||
    name = "elasticsearch_query_%ss_test_V7" % name,
 | 
			
		||||
    size = "large",
 | 
			
		||||
 
 | 
			
		||||
@@ -39,12 +39,6 @@ public class ElasticContainer extends ElasticsearchContainer {
 | 
			
		||||
 | 
			
		||||
  private static String getImageName(ElasticVersion version) {
 | 
			
		||||
    switch (version) {
 | 
			
		||||
      case V6_8:
 | 
			
		||||
        return "blacktop/elasticsearch:6.8.13";
 | 
			
		||||
      case V7_0:
 | 
			
		||||
        return "blacktop/elasticsearch:7.0.1";
 | 
			
		||||
      case V7_1:
 | 
			
		||||
        return "blacktop/elasticsearch:7.1.1";
 | 
			
		||||
      case V7_2:
 | 
			
		||||
        return "blacktop/elasticsearch:7.2.1";
 | 
			
		||||
      case V7_3:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,64 +0,0 @@
 | 
			
		||||
// Copyright (C) 2018 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 com.google.gerrit.server.query.account.AbstractQueryAccountsTest;
 | 
			
		||||
import com.google.gerrit.testing.ConfigSuite;
 | 
			
		||||
import com.google.gerrit.testing.InMemoryModule;
 | 
			
		||||
import com.google.gerrit.testing.IndexConfig;
 | 
			
		||||
import com.google.inject.Guice;
 | 
			
		||||
import com.google.inject.Injector;
 | 
			
		||||
import org.eclipse.jgit.lib.Config;
 | 
			
		||||
import org.junit.AfterClass;
 | 
			
		||||
import org.junit.BeforeClass;
 | 
			
		||||
 | 
			
		||||
public class ElasticV6QueryAccountsTest extends AbstractQueryAccountsTest {
 | 
			
		||||
  @ConfigSuite.Default
 | 
			
		||||
  public static Config defaultConfig() {
 | 
			
		||||
    return IndexConfig.createForElasticsearch();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static ElasticContainer container;
 | 
			
		||||
 | 
			
		||||
  @BeforeClass
 | 
			
		||||
  public static void startIndexService() {
 | 
			
		||||
    if (container == null) {
 | 
			
		||||
      // Only start Elasticsearch once
 | 
			
		||||
      container = ElasticContainer.createAndStart(ElasticVersion.V6_8);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @AfterClass
 | 
			
		||||
  public static void stopElasticsearchServer() {
 | 
			
		||||
    if (container != null) {
 | 
			
		||||
      container.stop();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected void initAfterLifecycleStart() throws Exception {
 | 
			
		||||
    super.initAfterLifecycleStart();
 | 
			
		||||
    ElasticTestUtils.createAllIndexes(injector);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected Injector createInjector() {
 | 
			
		||||
    Config elasticsearchConfig = new Config(config);
 | 
			
		||||
    InMemoryModule.setDefaults(elasticsearchConfig);
 | 
			
		||||
    String indicesPrefix = testName.getSanitizedMethodName();
 | 
			
		||||
    ElasticTestUtils.configure(elasticsearchConfig, container, indicesPrefix);
 | 
			
		||||
    return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,95 +0,0 @@
 | 
			
		||||
// Copyright (C) 2018 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 java.util.concurrent.TimeUnit.MINUTES;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.server.query.change.AbstractQueryChangesTest;
 | 
			
		||||
import com.google.gerrit.testing.ConfigSuite;
 | 
			
		||||
import com.google.gerrit.testing.GerritTestName;
 | 
			
		||||
import com.google.gerrit.testing.InMemoryModule;
 | 
			
		||||
import com.google.gerrit.testing.IndexConfig;
 | 
			
		||||
import com.google.inject.Guice;
 | 
			
		||||
import com.google.inject.Injector;
 | 
			
		||||
import org.apache.http.client.methods.HttpPost;
 | 
			
		||||
import org.apache.http.client.protocol.HttpClientContext;
 | 
			
		||||
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
 | 
			
		||||
import org.apache.http.impl.nio.client.HttpAsyncClients;
 | 
			
		||||
import org.eclipse.jgit.lib.Config;
 | 
			
		||||
import org.junit.After;
 | 
			
		||||
import org.junit.AfterClass;
 | 
			
		||||
import org.junit.BeforeClass;
 | 
			
		||||
import org.junit.Rule;
 | 
			
		||||
 | 
			
		||||
public class ElasticV6QueryChangesTest extends AbstractQueryChangesTest {
 | 
			
		||||
  @ConfigSuite.Default
 | 
			
		||||
  public static Config defaultConfig() {
 | 
			
		||||
    return IndexConfig.createForElasticsearch();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static ElasticContainer container;
 | 
			
		||||
  private static CloseableHttpAsyncClient client;
 | 
			
		||||
 | 
			
		||||
  @BeforeClass
 | 
			
		||||
  public static void startIndexService() {
 | 
			
		||||
    if (container == null) {
 | 
			
		||||
      // Only start Elasticsearch once
 | 
			
		||||
      container = ElasticContainer.createAndStart(ElasticVersion.V6_8);
 | 
			
		||||
      client = HttpAsyncClients.createDefault();
 | 
			
		||||
      client.start();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @AfterClass
 | 
			
		||||
  public static void stopElasticsearchServer() {
 | 
			
		||||
    if (container != null) {
 | 
			
		||||
      container.stop();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Rule public final GerritTestName testName = new GerritTestName();
 | 
			
		||||
 | 
			
		||||
  @After
 | 
			
		||||
  public void closeIndex() throws Exception {
 | 
			
		||||
    // Close the index after each test to prevent exceeding Elasticsearch's
 | 
			
		||||
    // shard limit (see Issue 10120).
 | 
			
		||||
    client
 | 
			
		||||
        .execute(
 | 
			
		||||
            new HttpPost(
 | 
			
		||||
                String.format(
 | 
			
		||||
                    "http://%s:%d/%s*/_close",
 | 
			
		||||
                    container.getHttpHost().getHostName(),
 | 
			
		||||
                    container.getHttpHost().getPort(),
 | 
			
		||||
                    testName.getSanitizedMethodName())),
 | 
			
		||||
            HttpClientContext.create(),
 | 
			
		||||
            null)
 | 
			
		||||
        .get(5, MINUTES);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected void initAfterLifecycleStart() throws Exception {
 | 
			
		||||
    super.initAfterLifecycleStart();
 | 
			
		||||
    ElasticTestUtils.createAllIndexes(injector);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected Injector createInjector() {
 | 
			
		||||
    Config elasticsearchConfig = new Config(config);
 | 
			
		||||
    InMemoryModule.setDefaults(elasticsearchConfig);
 | 
			
		||||
    String indicesPrefix = testName.getSanitizedMethodName();
 | 
			
		||||
    ElasticTestUtils.configure(elasticsearchConfig, container, indicesPrefix);
 | 
			
		||||
    return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,64 +0,0 @@
 | 
			
		||||
// Copyright (C) 2018 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 com.google.gerrit.server.query.group.AbstractQueryGroupsTest;
 | 
			
		||||
import com.google.gerrit.testing.ConfigSuite;
 | 
			
		||||
import com.google.gerrit.testing.InMemoryModule;
 | 
			
		||||
import com.google.gerrit.testing.IndexConfig;
 | 
			
		||||
import com.google.inject.Guice;
 | 
			
		||||
import com.google.inject.Injector;
 | 
			
		||||
import org.eclipse.jgit.lib.Config;
 | 
			
		||||
import org.junit.AfterClass;
 | 
			
		||||
import org.junit.BeforeClass;
 | 
			
		||||
 | 
			
		||||
public class ElasticV6QueryGroupsTest extends AbstractQueryGroupsTest {
 | 
			
		||||
  @ConfigSuite.Default
 | 
			
		||||
  public static Config defaultConfig() {
 | 
			
		||||
    return IndexConfig.createForElasticsearch();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static ElasticContainer container;
 | 
			
		||||
 | 
			
		||||
  @BeforeClass
 | 
			
		||||
  public static void startIndexService() {
 | 
			
		||||
    if (container == null) {
 | 
			
		||||
      // Only start Elasticsearch once
 | 
			
		||||
      container = ElasticContainer.createAndStart(ElasticVersion.V6_8);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @AfterClass
 | 
			
		||||
  public static void stopElasticsearchServer() {
 | 
			
		||||
    if (container != null) {
 | 
			
		||||
      container.stop();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected void initAfterLifecycleStart() throws Exception {
 | 
			
		||||
    super.initAfterLifecycleStart();
 | 
			
		||||
    ElasticTestUtils.createAllIndexes(injector);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected Injector createInjector() {
 | 
			
		||||
    Config elasticsearchConfig = new Config(config);
 | 
			
		||||
    InMemoryModule.setDefaults(elasticsearchConfig);
 | 
			
		||||
    String indicesPrefix = testName.getSanitizedMethodName();
 | 
			
		||||
    ElasticTestUtils.configure(elasticsearchConfig, container, indicesPrefix);
 | 
			
		||||
    return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,64 +0,0 @@
 | 
			
		||||
// Copyright (C) 2018 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 com.google.gerrit.server.query.project.AbstractQueryProjectsTest;
 | 
			
		||||
import com.google.gerrit.testing.ConfigSuite;
 | 
			
		||||
import com.google.gerrit.testing.InMemoryModule;
 | 
			
		||||
import com.google.gerrit.testing.IndexConfig;
 | 
			
		||||
import com.google.inject.Guice;
 | 
			
		||||
import com.google.inject.Injector;
 | 
			
		||||
import org.eclipse.jgit.lib.Config;
 | 
			
		||||
import org.junit.AfterClass;
 | 
			
		||||
import org.junit.BeforeClass;
 | 
			
		||||
 | 
			
		||||
public class ElasticV6QueryProjectsTest extends AbstractQueryProjectsTest {
 | 
			
		||||
  @ConfigSuite.Default
 | 
			
		||||
  public static Config defaultConfig() {
 | 
			
		||||
    return IndexConfig.createForElasticsearch();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static ElasticContainer container;
 | 
			
		||||
 | 
			
		||||
  @BeforeClass
 | 
			
		||||
  public static void startIndexService() {
 | 
			
		||||
    if (container == null) {
 | 
			
		||||
      // Only start Elasticsearch once
 | 
			
		||||
      container = ElasticContainer.createAndStart(ElasticVersion.V6_8);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @AfterClass
 | 
			
		||||
  public static void stopElasticsearchServer() {
 | 
			
		||||
    if (container != null) {
 | 
			
		||||
      container.stop();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected void initAfterLifecycleStart() throws Exception {
 | 
			
		||||
    super.initAfterLifecycleStart();
 | 
			
		||||
    ElasticTestUtils.createAllIndexes(injector);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected Injector createInjector() {
 | 
			
		||||
    Config elasticsearchConfig = new Config(config);
 | 
			
		||||
    InMemoryModule.setDefaults(elasticsearchConfig);
 | 
			
		||||
    String indicesPrefix = testName.getSanitizedMethodName();
 | 
			
		||||
    ElasticTestUtils.configure(elasticsearchConfig, container, indicesPrefix);
 | 
			
		||||
    return Guice.createInjector(new InMemoryModule(elasticsearchConfig));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -22,15 +22,6 @@ import org.junit.Test;
 | 
			
		||||
public class ElasticVersionTest {
 | 
			
		||||
  @Test
 | 
			
		||||
  public void supportedVersion() throws Exception {
 | 
			
		||||
    assertThat(ElasticVersion.forVersion("6.8.0")).isEqualTo(ElasticVersion.V6_8);
 | 
			
		||||
    assertThat(ElasticVersion.forVersion("6.8.1")).isEqualTo(ElasticVersion.V6_8);
 | 
			
		||||
 | 
			
		||||
    assertThat(ElasticVersion.forVersion("7.0.0")).isEqualTo(ElasticVersion.V7_0);
 | 
			
		||||
    assertThat(ElasticVersion.forVersion("7.0.1")).isEqualTo(ElasticVersion.V7_0);
 | 
			
		||||
 | 
			
		||||
    assertThat(ElasticVersion.forVersion("7.1.0")).isEqualTo(ElasticVersion.V7_1);
 | 
			
		||||
    assertThat(ElasticVersion.forVersion("7.1.1")).isEqualTo(ElasticVersion.V7_1);
 | 
			
		||||
 | 
			
		||||
    assertThat(ElasticVersion.forVersion("7.2.0")).isEqualTo(ElasticVersion.V7_2);
 | 
			
		||||
    assertThat(ElasticVersion.forVersion("7.2.1")).isEqualTo(ElasticVersion.V7_2);
 | 
			
		||||
 | 
			
		||||
@@ -64,46 +55,4 @@ public class ElasticVersionTest {
 | 
			
		||||
            "Unsupported version: [4.0.0]. Supported versions: "
 | 
			
		||||
                + ElasticVersion.supportedVersions());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void atLeastMinorVersion() throws Exception {
 | 
			
		||||
    assertThat(ElasticVersion.V6_8.isAtLeastMinorVersion(ElasticVersion.V6_8)).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_0.isAtLeastMinorVersion(ElasticVersion.V6_8)).isFalse();
 | 
			
		||||
    assertThat(ElasticVersion.V7_1.isAtLeastMinorVersion(ElasticVersion.V6_8)).isFalse();
 | 
			
		||||
    assertThat(ElasticVersion.V7_2.isAtLeastMinorVersion(ElasticVersion.V6_8)).isFalse();
 | 
			
		||||
    assertThat(ElasticVersion.V7_3.isAtLeastMinorVersion(ElasticVersion.V6_8)).isFalse();
 | 
			
		||||
    assertThat(ElasticVersion.V7_4.isAtLeastMinorVersion(ElasticVersion.V6_8)).isFalse();
 | 
			
		||||
    assertThat(ElasticVersion.V7_5.isAtLeastMinorVersion(ElasticVersion.V6_8)).isFalse();
 | 
			
		||||
    assertThat(ElasticVersion.V7_6.isAtLeastMinorVersion(ElasticVersion.V6_8)).isFalse();
 | 
			
		||||
    assertThat(ElasticVersion.V7_7.isAtLeastMinorVersion(ElasticVersion.V6_8)).isFalse();
 | 
			
		||||
    assertThat(ElasticVersion.V7_8.isAtLeastMinorVersion(ElasticVersion.V6_8)).isFalse();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void version6OrLater() throws Exception {
 | 
			
		||||
    assertThat(ElasticVersion.V6_8.isV6OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_0.isV6OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_1.isV6OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_2.isV6OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_3.isV6OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_4.isV6OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_5.isV6OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_6.isV6OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_7.isV6OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_8.isV6OrLater()).isTrue();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void version7OrLater() throws Exception {
 | 
			
		||||
    assertThat(ElasticVersion.V6_8.isV7OrLater()).isFalse();
 | 
			
		||||
    assertThat(ElasticVersion.V7_0.isV7OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_1.isV7OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_2.isV7OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_3.isV7OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_4.isV7OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_5.isV7OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_6.isV7OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_7.isV7OrLater()).isTrue();
 | 
			
		||||
    assertThat(ElasticVersion.V7_8.isV7OrLater()).isTrue();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user