From d25530358452b4abbf223017003692ea92e76f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BCscher?= Date: Tue, 5 Feb 2019 03:41:05 +0100 Subject: [PATCH] Add typless client side GetIndexRequest calls and response class (#37778) The HLRC client currently uses `org.elasticsearch.action.admin.indices.get.GetIndexRequest` and `org.elasticsearch.action.admin.indices.get.GetIndexResponse` in its get index calls. Both request and response are designed for the typed APIs, including some return types e.g. for `getMappings()` which in the maps it returns still use a level including the type name. In order to change this without breaking existing users of the HLRC API, this PR introduces two new request and response objects in the `org.elasticsearch.client.indices` client package. These are used by the IndicesClient#get and IndicesClient#exists calls now by default and support the type-less API. The old request and response objects are still kept for use in similarly named, but deprecated methods. The newly introduced client side classes are simplified versions of the server side request/response classes since they don't need to support wire serialization, and only the response needs fromXContent parsing (but no xContent-serialization, since this is the responsibility of the server-side class). Also changing the return type of `GetIndexResponse#getMapping` to `Map getMappings()`, while it previously was returning another map keyed by the type-name. Similar getters return simple Maps instead of the ImmutableOpenMaps that the server side response objects return. --- .../elasticsearch/client/IndicesClient.java | 122 ++++++++-- .../client/IndicesRequestConverters.java | 62 ++++- .../client/indices/GetIndexRequest.java | 132 +++++++++++ .../client/indices/GetIndexResponse.java | 222 ++++++++++++++++++ .../client/ClusterRequestConvertersTests.java | 2 +- .../java/org/elasticsearch/client/CrudIT.java | 6 +- .../elasticsearch/client/IndicesClientIT.java | 137 +++++++---- .../client/IndicesRequestConvertersTests.java | 99 ++++++-- .../client/RequestConvertersTests.java | 14 +- .../SnapshotRequestConvertersTests.java | 2 +- .../IndicesClientDocumentationIT.java | 29 +-- .../client/indices/GetIndexRequestTests.java | 68 ++++++ .../client/indices/GetIndexResponseTests.java | 195 +++++++++++++++ .../admin/indices/get/GetIndexResponse.java | 16 +- .../admin/indices/RestGetIndicesAction.java | 4 +- .../indices/get/GetIndexResponseTests.java | 24 +- 16 files changed, 990 insertions(+), 144 deletions(-) create mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/indices/GetIndexRequest.java create mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/indices/GetIndexResponse.java create mode 100644 client/rest-high-level/src/test/java/org/elasticsearch/client/indices/GetIndexRequestTests.java create mode 100644 client/rest-high-level/src/test/java/org/elasticsearch/client/indices/GetIndexResponseTests.java diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java index 8cae8630cd2..cbb1d95feae 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java @@ -33,10 +33,6 @@ import org.elasticsearch.action.admin.indices.flush.FlushResponse; import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest; import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest; import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse; -import org.elasticsearch.action.admin.indices.get.GetIndexRequest; -import org.elasticsearch.action.admin.indices.get.GetIndexResponse; -import org.elasticsearch.client.indices.GetFieldMappingsRequest; -import org.elasticsearch.client.indices.GetFieldMappingsResponse; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexResponse; import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; @@ -54,10 +50,14 @@ import org.elasticsearch.client.core.ShardsAcknowledgedResponse; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.client.indices.FreezeIndexRequest; +import org.elasticsearch.client.indices.GetFieldMappingsRequest; +import org.elasticsearch.client.indices.GetFieldMappingsResponse; +import org.elasticsearch.client.indices.GetIndexRequest; +import org.elasticsearch.client.indices.GetIndexResponse; import org.elasticsearch.client.indices.GetIndexTemplatesRequest; +import org.elasticsearch.client.indices.GetIndexTemplatesResponse; import org.elasticsearch.client.indices.GetMappingsRequest; import org.elasticsearch.client.indices.GetMappingsResponse; -import org.elasticsearch.client.indices.GetIndexTemplatesResponse; import org.elasticsearch.client.indices.IndexTemplatesExistRequest; import org.elasticsearch.client.indices.PutIndexTemplateRequest; import org.elasticsearch.client.indices.PutMappingRequest; @@ -649,6 +649,41 @@ public final class IndicesClient { GetIndexResponse::fromXContent, listener, emptySet()); } + /** + * Retrieve information about one or more indexes + * See + * Indices Get Index API on elastic.co + * @param getIndexRequest the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @return the response + * @throws IOException in case there is a problem sending the request or parsing back the response + * @deprecated This method uses an old request object which still refers to types, a deprecated feature. The method + * {@link #get(GetIndexRequest, RequestOptions)} should be used instead, which accepts a new request object. + */ + @Deprecated + public org.elasticsearch.action.admin.indices.get.GetIndexResponse get( + org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest, RequestOptions options) throws IOException { + return restHighLevelClient.performRequestAndParseEntity(getIndexRequest, IndicesRequestConverters::getIndex, options, + org.elasticsearch.action.admin.indices.get.GetIndexResponse::fromXContent, emptySet()); + } + + /** + * Retrieve information about one or more indexes + * See + * Indices Get Index API on elastic.co + * @param getIndexRequest the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @param listener the listener to be notified upon request completion + * @deprecated This method uses an old request object which still refers to types, a deprecated feature. The method + * {@link #getAsync(GetIndexRequest, RequestOptions, ActionListener)} should be used instead, which accepts a new request object. + */ + @Deprecated + public void getAsync(org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest, RequestOptions options, + ActionListener listener) { + restHighLevelClient.performRequestAsyncAndParseEntity(getIndexRequest, IndicesRequestConverters::getIndex, options, + org.elasticsearch.action.admin.indices.get.GetIndexResponse::fromXContent, listener, emptySet()); + } + /** * Force merge one or more indices using the Force Merge API. * See @@ -772,6 +807,51 @@ public final class IndicesClient { ); } + /** + * Checks if the index (indices) exists or not. + * See + * Indices Exists API on elastic.co + * @param request the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @return the response + * @throws IOException in case there is a problem sending the request + * @deprecated This method uses an old request object which still refers to types, a deprecated feature. The method + * {@link #exists(GetIndexRequest, RequestOptions)} should be used instead, which accepts a new request object. + */ + @Deprecated + public boolean exists(org.elasticsearch.action.admin.indices.get.GetIndexRequest request, RequestOptions options) throws IOException { + return restHighLevelClient.performRequest( + request, + IndicesRequestConverters::indicesExist, + options, + RestHighLevelClient::convertExistsResponse, + Collections.emptySet() + ); + } + + /** + * Asynchronously checks if the index (indices) exists or not. + * See + * Indices Exists API on elastic.co + * @param request the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @param listener the listener to be notified upon request completion + * @deprecated This method uses an old request object which still refers to types, a deprecated feature. The method + * {@link #existsAsync(GetIndexRequest, RequestOptions, ActionListener)} should be used instead, which accepts a new request object. + */ + @Deprecated + public void existsAsync(org.elasticsearch.action.admin.indices.get.GetIndexRequest request, RequestOptions options, + ActionListener listener) { + restHighLevelClient.performRequestAsync( + request, + IndicesRequestConverters::indicesExist, + options, + RestHighLevelClient::convertExistsResponse, + listener, + Collections.emptySet() + ); + } + /** * Shrinks an index using the Shrink Index API. * See @@ -948,7 +1028,7 @@ public final class IndicesClient { AcknowledgedResponse::fromXContent, listener, emptySet()); } - + /** * Puts an index template using the Index Templates API. * See Index Templates API @@ -957,7 +1037,7 @@ public final class IndicesClient { * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized * @return the response * @throws IOException in case there is a problem sending the request or parsing back the response - * @deprecated This old form of request allows types in mappings. Use {@link #putTemplate(PutIndexTemplateRequest, RequestOptions)} + * @deprecated This old form of request allows types in mappings. Use {@link #putTemplate(PutIndexTemplateRequest, RequestOptions)} * instead which introduces a new request object without types. */ @Deprecated @@ -975,18 +1055,18 @@ public final class IndicesClient { * @param putIndexTemplateRequest the request * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized * @param listener the listener to be notified upon request completion - * @deprecated This old form of request allows types in mappings. - * Use {@link #putTemplateAsync(PutIndexTemplateRequest, RequestOptions, ActionListener)} + * @deprecated This old form of request allows types in mappings. + * Use {@link #putTemplateAsync(PutIndexTemplateRequest, RequestOptions, ActionListener)} * instead which introduces a new request object without types. */ @Deprecated - public void putTemplateAsync(org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putIndexTemplateRequest, + public void putTemplateAsync(org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putIndexTemplateRequest, RequestOptions options, ActionListener listener) { restHighLevelClient.performRequestAsyncAndParseEntity(putIndexTemplateRequest, IndicesRequestConverters::putTemplate, options, AcknowledgedResponse::fromXContent, listener, emptySet()); } - - + + /** * Puts an index template using the Index Templates API. * See Index Templates API @@ -1011,7 +1091,7 @@ public final class IndicesClient { * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized * @param listener the listener to be notified upon request completion */ - public void putTemplateAsync(PutIndexTemplateRequest putIndexTemplateRequest, + public void putTemplateAsync(PutIndexTemplateRequest putIndexTemplateRequest, RequestOptions options, ActionListener listener) { restHighLevelClient.performRequestAsyncAndParseEntity(putIndexTemplateRequest, IndicesRequestConverters::putTemplate, options, AcknowledgedResponse::fromXContent, listener, emptySet()); @@ -1056,7 +1136,7 @@ public final class IndicesClient { * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized * @return the response * @throws IOException in case there is a problem sending the request or parsing back the response - * @deprecated This method uses an old response object which still refers to types, a deprecated feature. Use + * @deprecated This method uses an old response object which still refers to types, a deprecated feature. Use * {@link #getIndexTemplate(GetIndexTemplatesRequest, RequestOptions)} instead which returns a new response object */ @Deprecated @@ -1066,7 +1146,7 @@ public final class IndicesClient { IndicesRequestConverters::getTemplatesWithDocumentTypes, options, org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse::fromXContent, emptySet()); } - + /** * Gets index templates using the Index Templates API * See Index Templates API @@ -1081,17 +1161,17 @@ public final class IndicesClient { return restHighLevelClient.performRequestAndParseEntity(getIndexTemplatesRequest, IndicesRequestConverters::getTemplates, options, GetIndexTemplatesResponse::fromXContent, emptySet()); - } + } /** - * Asynchronously gets index templates using the Index Templates API. The mappings will be returned in a legacy deprecated format, + * Asynchronously gets index templates using the Index Templates API. The mappings will be returned in a legacy deprecated format, * where the mapping definition is nested under the type name. * See Index Templates API * on elastic.co * @param getIndexTemplatesRequest the request * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized * @param listener the listener to be notified upon request completion - * @deprecated This method uses an old response object which still refers to types, a deprecated feature. Use + * @deprecated This method uses an old response object which still refers to types, a deprecated feature. Use * {@link #getIndexTemplateAsync(GetIndexTemplatesRequest, RequestOptions, ActionListener)} instead which returns a new response object */ @Deprecated @@ -1101,7 +1181,7 @@ public final class IndicesClient { IndicesRequestConverters::getTemplatesWithDocumentTypes, options, org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse::fromXContent, listener, emptySet()); } - + /** * Asynchronously gets index templates using the Index Templates API * See Index Templates API @@ -1110,12 +1190,12 @@ public final class IndicesClient { * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized * @param listener the listener to be notified upon request completion */ - public void getIndexTemplateAsync(GetIndexTemplatesRequest getIndexTemplatesRequest, RequestOptions options, + public void getIndexTemplateAsync(GetIndexTemplatesRequest getIndexTemplatesRequest, RequestOptions options, ActionListener listener) { restHighLevelClient.performRequestAsyncAndParseEntity(getIndexTemplatesRequest, IndicesRequestConverters::getTemplates, options, GetIndexTemplatesResponse::fromXContent, listener, emptySet()); - } + } /** * Uses the Index Templates API to determine if index templates exist diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesRequestConverters.java index 9c2ba8b30bb..cc5adffd334 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesRequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesRequestConverters.java @@ -33,8 +33,6 @@ import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest; import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest; -import org.elasticsearch.action.admin.indices.get.GetIndexRequest; -import org.elasticsearch.client.indices.GetFieldMappingsRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest; @@ -45,6 +43,8 @@ import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplat import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.FreezeIndexRequest; +import org.elasticsearch.client.indices.GetFieldMappingsRequest; +import org.elasticsearch.client.indices.GetIndexRequest; import org.elasticsearch.client.indices.GetIndexTemplatesRequest; import org.elasticsearch.client.indices.GetMappingsRequest; import org.elasticsearch.client.indices.IndexTemplatesExistRequest; @@ -148,6 +148,10 @@ final class IndicesRequestConverters { return request; } + /** + * converter for the legacy server-side {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} that still supports + * types + */ @Deprecated static Request putMapping(org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest) throws IOException { // The concreteIndex is an internal concept, not applicable to requests made over the REST API. @@ -389,6 +393,28 @@ final class IndicesRequestConverters { return request; } + /** + * converter for the legacy server-side {@link org.elasticsearch.action.admin.indices.get.GetIndexRequest} that + * still supports types + */ + @Deprecated + static Request getIndex(org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest) { + String[] indices = getIndexRequest.indices() == null ? Strings.EMPTY_ARRAY : getIndexRequest.indices(); + + String endpoint = RequestConverters.endpoint(indices); + Request request = new Request(HttpGet.METHOD_NAME, endpoint); + + RequestConverters.Params params = new RequestConverters.Params(request); + params.withIndicesOptions(getIndexRequest.indicesOptions()); + params.withLocal(getIndexRequest.local()); + params.withIncludeDefaults(getIndexRequest.includeDefaults()); + params.withHuman(getIndexRequest.humanReadable()); + params.withMasterTimeout(getIndexRequest.masterNodeTimeout()); + params.putParam(INCLUDE_TYPE_NAME_PARAMETER, "true"); + + return request; + } + static Request getIndex(GetIndexRequest getIndexRequest) { String[] indices = getIndexRequest.indices() == null ? Strings.EMPTY_ARRAY : getIndexRequest.indices(); @@ -405,6 +431,28 @@ final class IndicesRequestConverters { return request; } + /** + * converter for the legacy server-side {@link org.elasticsearch.action.admin.indices.get.GetIndexRequest} that + * still supports types + */ + @Deprecated + static Request indicesExist(org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest) { + // this can be called with no indices as argument by transport client, not via REST though + if (getIndexRequest.indices() == null || getIndexRequest.indices().length == 0) { + throw new IllegalArgumentException("indices are mandatory"); + } + String endpoint = RequestConverters.endpoint(getIndexRequest.indices(), ""); + Request request = new Request(HttpHead.METHOD_NAME, endpoint); + + RequestConverters.Params params = new RequestConverters.Params(request); + params.withLocal(getIndexRequest.local()); + params.withHuman(getIndexRequest.humanReadable()); + params.withIndicesOptions(getIndexRequest.indicesOptions()); + params.withIncludeDefaults(getIndexRequest.includeDefaults()); + params.putParam(INCLUDE_TYPE_NAME_PARAMETER, "true"); + return request; + } + static Request indicesExist(GetIndexRequest getIndexRequest) { // this can be called with no indices as argument by transport client, not via REST though if (getIndexRequest.indices() == null || getIndexRequest.indices().length == 0) { @@ -436,11 +484,11 @@ final class IndicesRequestConverters { } /** - * @deprecated This uses the old form of PutIndexTemplateRequest which uses types. + * @deprecated This uses the old form of PutIndexTemplateRequest which uses types. * Use (@link {@link #putTemplate(PutIndexTemplateRequest)} instead */ @Deprecated - static Request putTemplate(org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putIndexTemplateRequest) + static Request putTemplate(org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putIndexTemplateRequest) throws IOException { String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_template") .addPathPart(putIndexTemplateRequest.name()).build(); @@ -503,11 +551,11 @@ final class IndicesRequestConverters { static Request getTemplatesWithDocumentTypes(GetIndexTemplatesRequest getIndexTemplatesRequest) { return getTemplates(getIndexTemplatesRequest, true); } - + static Request getTemplates(GetIndexTemplatesRequest getIndexTemplatesRequest) { return getTemplates(getIndexTemplatesRequest, false); } - + private static Request getTemplates(GetIndexTemplatesRequest getIndexTemplatesRequest, boolean includeTypeName) { final String endpoint = new RequestConverters.EndpointBuilder() .addPathPartAsIs("_template") @@ -521,7 +569,7 @@ final class IndicesRequestConverters { params.putParam(INCLUDE_TYPE_NAME_PARAMETER, "true"); } return request; - } + } static Request templatesExist(IndexTemplatesExistRequest indexTemplatesExistRequest) { final String endpoint = new RequestConverters.EndpointBuilder() diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/GetIndexRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/GetIndexRequest.java new file mode 100644 index 00000000000..227b1b4d36a --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/GetIndexRequest.java @@ -0,0 +1,132 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.client.indices; + +import org.elasticsearch.action.support.IndicesOptions; +import org.elasticsearch.client.TimedRequest; +import org.elasticsearch.common.util.ArrayUtils; + +/** + * A request to retrieve information about an index. + */ +public class GetIndexRequest extends TimedRequest { + + public enum Feature { + ALIASES, + MAPPINGS, + SETTINGS; + } + + static final Feature[] DEFAULT_FEATURES = new Feature[] { Feature.ALIASES, Feature.MAPPINGS, Feature.SETTINGS }; + private Feature[] features = DEFAULT_FEATURES; + private boolean humanReadable = false; + private transient boolean includeDefaults = false; + + private final String[] indices; + private IndicesOptions indicesOptions = IndicesOptions.fromOptions(false, false, true, true); + private boolean local = false; + + public GetIndexRequest(String... indices) { + this.indices = indices; + } + + /** + * The indices into which the mappings will be put. + */ + public String[] indices() { + return indices; + } + + public IndicesOptions indicesOptions() { + return indicesOptions; + } + + public GetIndexRequest indicesOptions(IndicesOptions indicesOptions) { + this.indicesOptions = indicesOptions; + return this; + } + + public final GetIndexRequest local(boolean local) { + this.local = local; + return this; + } + + /** + * Return local information, do not retrieve the state from master node (default: false). + * @return true if local information is to be returned; + * false if information is to be retrieved from master node (default). + */ + public final boolean local() { + return local; + } + + public GetIndexRequest features(Feature... features) { + if (features == null) { + throw new IllegalArgumentException("features cannot be null"); + } else { + this.features = features; + } + return this; + } + + public GetIndexRequest addFeatures(Feature... features) { + if (this.features == DEFAULT_FEATURES) { + return features(features); + } else { + return features(ArrayUtils.concat(features(), features, Feature.class)); + } + } + + public Feature[] features() { + return features; + } + + public GetIndexRequest humanReadable(boolean humanReadable) { + this.humanReadable = humanReadable; + return this; + } + + public boolean humanReadable() { + return humanReadable; + } + + /** + * Sets the value of "include_defaults". + * + * @param includeDefaults value of "include_defaults" to be set. + * @return this request + */ + public GetIndexRequest includeDefaults(boolean includeDefaults) { + this.includeDefaults = includeDefaults; + return this; + } + + /** + * Whether to return all default settings for each of the indices. + * + * @return true if defaults settings for each of the indices need to returned; + * false otherwise. + */ + public boolean includeDefaults() { + return includeDefaults; + } + + +} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/GetIndexResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/GetIndexResponse.java new file mode 100644 index 00000000000..3d98f93df47 --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/GetIndexResponse.java @@ -0,0 +1,222 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.client.indices; + +import org.apache.lucene.util.CollectionUtil; +import org.elasticsearch.cluster.metadata.AliasMetaData; +import org.elasticsearch.cluster.metadata.MappingMetaData; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentParser.Token; +import org.elasticsearch.index.mapper.MapperService; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken; + +/** + * A client side response for a get index action. + */ +public class GetIndexResponse { + + private Map mappings; + private Map> aliases; + private Map settings; + private Map defaultSettings; + private String[] indices; + + GetIndexResponse(String[] indices, + Map mappings, + Map> aliases, + Map settings, + Map defaultSettings) { + this.indices = indices; + // to have deterministic order + Arrays.sort(indices); + if (mappings != null) { + this.mappings = mappings; + } + if (aliases != null) { + this.aliases = aliases; + } + if (settings != null) { + this.settings = settings; + } + if (defaultSettings != null) { + this.defaultSettings = defaultSettings; + } + } + + public String[] getIndices() { + return indices; + } + + public Map getMappings() { + return mappings; + } + + public Map> getAliases() { + return aliases; + } + + /** + * If the originating {@link GetIndexRequest} object was configured to include + * defaults, this will contain a mapping of index name to {@link Settings} objects. + * The returned {@link Settings} objects will contain only those settings taking + * effect as defaults. Any settings explicitly set on the index will be available + * via {@link #getSettings()}. + * See also {@link GetIndexRequest#includeDefaults(boolean)} + */ + public Map getDefaultSettings() { + return defaultSettings; + } + + public Map getSettings() { + return settings; + } + + /** + * Returns the string value for the specified index and setting. If the includeDefaults flag was not set or set to + * false on the {@link GetIndexRequest}, this method will only return a value where the setting was explicitly set + * on the index. If the includeDefaults flag was set to true on the {@link GetIndexRequest}, this method will fall + * back to return the default value if the setting was not explicitly set. + */ + public String getSetting(String index, String setting) { + Settings indexSettings = settings.get(index); + if (setting != null) { + if (indexSettings != null && indexSettings.hasValue(setting)) { + return indexSettings.get(setting); + } else { + Settings defaultIndexSettings = defaultSettings.get(index); + if (defaultIndexSettings != null) { + return defaultIndexSettings.get(setting); + } else { + return null; + } + } + } else { + return null; + } + } + + private static List parseAliases(XContentParser parser) throws IOException { + List indexAliases = new ArrayList<>(); + // We start at START_OBJECT since parseIndexEntry ensures that + while (parser.nextToken() != Token.END_OBJECT) { + ensureExpectedToken(Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation); + indexAliases.add(AliasMetaData.Builder.fromXContent(parser)); + } + return indexAliases; + } + + private static MappingMetaData parseMappings(XContentParser parser) throws IOException { + return new MappingMetaData(MapperService.SINGLE_MAPPING_NAME, parser.map()); + } + + private static IndexEntry parseIndexEntry(XContentParser parser) throws IOException { + List indexAliases = null; + MappingMetaData indexMappings = null; + Settings indexSettings = null; + Settings indexDefaultSettings = null; + // We start at START_OBJECT since fromXContent ensures that + while (parser.nextToken() != Token.END_OBJECT) { + ensureExpectedToken(Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation); + parser.nextToken(); + if (parser.currentToken() == Token.START_OBJECT) { + switch (parser.currentName()) { + case "aliases": + indexAliases = parseAliases(parser); + break; + case "mappings": + indexMappings = parseMappings(parser); + break; + case "settings": + indexSettings = Settings.fromXContent(parser); + break; + case "defaults": + indexDefaultSettings = Settings.fromXContent(parser); + break; + default: + parser.skipChildren(); + } + } else if (parser.currentToken() == Token.START_ARRAY) { + parser.skipChildren(); + } + } + return new IndexEntry(indexAliases, indexMappings, indexSettings, indexDefaultSettings); + } + + // This is just an internal container to make stuff easier for returning + private static class IndexEntry { + List indexAliases = new ArrayList<>(); + MappingMetaData indexMappings; + Settings indexSettings = Settings.EMPTY; + Settings indexDefaultSettings = Settings.EMPTY; + IndexEntry(List indexAliases, MappingMetaData indexMappings, Settings indexSettings, Settings indexDefaultSettings) { + if (indexAliases != null) this.indexAliases = indexAliases; + if (indexMappings != null) this.indexMappings = indexMappings; + if (indexSettings != null) this.indexSettings = indexSettings; + if (indexDefaultSettings != null) this.indexDefaultSettings = indexDefaultSettings; + } + } + + public static GetIndexResponse fromXContent(XContentParser parser) throws IOException { + Map> aliases = new HashMap<>(); + Map mappings = new HashMap<>(); + Map settings = new HashMap<>(); + Map defaultSettings = new HashMap<>(); + List indices = new ArrayList<>(); + + if (parser.currentToken() == null) { + parser.nextToken(); + } + ensureExpectedToken(Token.START_OBJECT, parser.currentToken(), parser::getTokenLocation); + parser.nextToken(); + + while (!parser.isClosed()) { + if (parser.currentToken() == Token.START_OBJECT) { + // we assume this is an index entry + String indexName = parser.currentName(); + indices.add(indexName); + IndexEntry indexEntry = parseIndexEntry(parser); + // make the order deterministic + CollectionUtil.timSort(indexEntry.indexAliases, Comparator.comparing(AliasMetaData::alias)); + aliases.put(indexName, Collections.unmodifiableList(indexEntry.indexAliases)); + mappings.put(indexName, indexEntry.indexMappings); + settings.put(indexName, indexEntry.indexSettings); + if (indexEntry.indexDefaultSettings.isEmpty() == false) { + defaultSettings.put(indexName, indexEntry.indexDefaultSettings); + } + } else if (parser.currentToken() == Token.START_ARRAY) { + parser.skipChildren(); + } else { + parser.nextToken(); + } + } + return new GetIndexResponse(indices.toArray(new String[0]), mappings, aliases, settings, defaultSettings); + } +} diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterRequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterRequestConvertersTests.java index 9a7596957d0..9b7b5b0d284 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterRequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterRequestConvertersTests.java @@ -72,7 +72,7 @@ public class ClusterRequestConvertersTests extends ESTestCase { public void testClusterHealth() { ClusterHealthRequest healthRequest = new ClusterHealthRequest(); Map expectedParams = new HashMap<>(); - RequestConvertersTests.setRandomLocal(healthRequest, expectedParams); + RequestConvertersTests.setRandomLocal(healthRequest::local, expectedParams); String timeoutType = ESTestCase.randomFrom("timeout", "masterTimeout", "both", "none"); String timeout = ESTestCase.randomTimeValue(); String masterTimeout = ESTestCase.randomTimeValue(); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/CrudIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/CrudIT.java index 1bf1f2487cd..3bd3c79072d 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/CrudIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/CrudIT.java @@ -27,7 +27,6 @@ import org.elasticsearch.action.DocWriteResponse; import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest; import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse; import org.elasticsearch.action.admin.cluster.node.tasks.list.TaskGroup; -import org.elasticsearch.action.admin.indices.get.GetIndexRequest; import org.elasticsearch.action.bulk.BulkItemResponse; import org.elasticsearch.action.bulk.BulkProcessor; import org.elasticsearch.action.bulk.BulkRequest; @@ -48,6 +47,7 @@ import org.elasticsearch.client.core.MultiTermVectorsRequest; import org.elasticsearch.client.core.MultiTermVectorsResponse; import org.elasticsearch.client.core.TermVectorsRequest; import org.elasticsearch.client.core.TermVectorsResponse; +import org.elasticsearch.client.indices.GetIndexRequest; import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.settings.Settings; @@ -1105,7 +1105,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase { }; try (BulkProcessor processor = BulkProcessor.builder( - (request, bulkListener) -> highLevelClient().bulkAsync(request, + (request, bulkListener) -> highLevelClient().bulkAsync(request, RequestOptions.DEFAULT, bulkListener), listener) .setConcurrentRequests(0) .setBulkSize(new ByteSizeValue(5, ByteSizeUnit.GB)) @@ -1231,7 +1231,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase { assertEquals(docId, getResponse.getId()); } - assertTrue(highLevelClient().indices().exists(new GetIndexRequest().indices(indexPattern, "index"), RequestOptions.DEFAULT)); + assertTrue(highLevelClient().indices().exists(new GetIndexRequest(indexPattern, "index"), RequestOptions.DEFAULT)); } public void testParamsEncode() throws IOException { diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java index ee57c32b237..a7aa5177093 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java @@ -39,8 +39,6 @@ import org.elasticsearch.action.admin.indices.flush.FlushResponse; import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest; import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest; import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse; -import org.elasticsearch.action.admin.indices.get.GetIndexRequest; -import org.elasticsearch.action.admin.indices.get.GetIndexResponse; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexResponse; import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; @@ -65,10 +63,12 @@ import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.client.indices.FreezeIndexRequest; import org.elasticsearch.client.indices.GetFieldMappingsRequest; import org.elasticsearch.client.indices.GetFieldMappingsResponse; +import org.elasticsearch.client.indices.GetIndexRequest; +import org.elasticsearch.client.indices.GetIndexResponse; import org.elasticsearch.client.indices.GetIndexTemplatesRequest; +import org.elasticsearch.client.indices.GetIndexTemplatesResponse; import org.elasticsearch.client.indices.GetMappingsRequest; import org.elasticsearch.client.indices.GetMappingsResponse; -import org.elasticsearch.client.indices.GetIndexTemplatesResponse; import org.elasticsearch.client.indices.IndexTemplateMetaData; import org.elasticsearch.client.indices.IndexTemplatesExistRequest; import org.elasticsearch.client.indices.PutIndexTemplateRequest; @@ -78,6 +78,7 @@ import org.elasticsearch.client.indices.rollover.RolloverRequest; import org.elasticsearch.client.indices.rollover.RolloverResponse; import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.metadata.MappingMetaData; import org.elasticsearch.common.ValidationException; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.settings.Setting; @@ -96,10 +97,11 @@ import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.action.admin.indices.RestCreateIndexAction; import org.elasticsearch.rest.action.admin.indices.RestGetFieldMappingAction; -import org.elasticsearch.rest.action.admin.indices.RestGetMappingAction; -import org.elasticsearch.rest.action.admin.indices.RestPutMappingAction; import org.elasticsearch.rest.action.admin.indices.RestGetIndexTemplateAction; +import org.elasticsearch.rest.action.admin.indices.RestGetIndicesAction; +import org.elasticsearch.rest.action.admin.indices.RestGetMappingAction; import org.elasticsearch.rest.action.admin.indices.RestPutIndexTemplateAction; +import org.elasticsearch.rest.action.admin.indices.RestPutMappingAction; import org.elasticsearch.rest.action.admin.indices.RestRolloverIndexAction; import java.io.IOException; @@ -137,8 +139,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { String indexName = "test_index_exists_index_present"; createIndex(indexName, Settings.EMPTY); - GetIndexRequest request = new GetIndexRequest(); - request.indices(indexName); + GetIndexRequest request = new GetIndexRequest(indexName); boolean response = execute( request, @@ -152,8 +153,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { { String indexName = "non_existent_index"; - GetIndexRequest request = new GetIndexRequest(); - request.indices(indexName); + GetIndexRequest request = new GetIndexRequest(indexName); boolean response = execute( request, @@ -170,8 +170,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { String nonExistentIndex = "oranges"; - GetIndexRequest request = new GetIndexRequest(); - request.indices(existingIndex, nonExistentIndex); + GetIndexRequest request = new GetIndexRequest(existingIndex, nonExistentIndex); boolean response = execute( request, @@ -180,7 +179,20 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { ); assertFalse(response); } + } + public void testIndicesExistsWithTypes() throws IOException { + // Index present + String indexName = "test_index_exists_index_present"; + createIndex(indexName, Settings.EMPTY); + + org.elasticsearch.action.admin.indices.get.GetIndexRequest request + = new org.elasticsearch.action.admin.indices.get.GetIndexRequest(); + request.indices(indexName); + + boolean response = execute(request, highLevelClient().indices()::exists, highLevelClient().indices()::existsAsync, + expectWarnings(RestGetIndicesAction.TYPES_DEPRECATION_MESSAGE)); + assertTrue(response); } @SuppressWarnings({"unchecked", "rawtypes"}) @@ -416,8 +428,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { String mappings = "\"properties\":{\"field-1\":{\"type\":\"integer\"}}"; createIndex(indexName, basicSettings, mappings); - GetIndexRequest getIndexRequest = new GetIndexRequest() - .indices(indexName).includeDefaults(false); + GetIndexRequest getIndexRequest = new GetIndexRequest(indexName).includeDefaults(false); GetIndexResponse getIndexResponse = execute(getIndexRequest, highLevelClient().indices()::get, highLevelClient().indices()::getAsync); @@ -426,8 +437,12 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { assertEquals("1", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_SHARDS)); assertEquals("0", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_REPLICAS)); assertNotNull(getIndexResponse.getMappings().get(indexName)); - assertNotNull(getIndexResponse.getMappings().get(indexName).get("_doc")); - Object o = getIndexResponse.getMappings().get(indexName).get("_doc").getSourceAsMap().get("properties"); + assertNotNull(getIndexResponse.getMappings().get(indexName)); + MappingMetaData mappingMetaData = getIndexResponse.getMappings().get(indexName); + assertNotNull(mappingMetaData); + assertEquals("_doc", mappingMetaData.type()); + assertEquals("{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}", mappingMetaData.source().string()); + Object o = mappingMetaData.getSourceAsMap().get("properties"); assertThat(o, instanceOf(Map.class)); //noinspection unchecked assertThat(((Map) o).get("field-1"), instanceOf(Map.class)); @@ -436,6 +451,33 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { assertEquals("integer", fieldMapping.get("type")); } + @SuppressWarnings("unchecked") + public void testGetIndexWithTypes() throws IOException { + String indexName = "get_index_test"; + Settings basicSettings = Settings.builder() + .put(SETTING_NUMBER_OF_SHARDS, 1) + .put(SETTING_NUMBER_OF_REPLICAS, 0) + .build(); + String mappings = "\"properties\":{\"field-1\":{\"type\":\"integer\"}}"; + createIndex(indexName, basicSettings, mappings); + + org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest = + new org.elasticsearch.action.admin.indices.get.GetIndexRequest().indices(indexName).includeDefaults(false); + org.elasticsearch.action.admin.indices.get.GetIndexResponse getIndexResponse = execute(getIndexRequest, + highLevelClient().indices()::get, highLevelClient().indices()::getAsync, + expectWarnings(RestGetIndicesAction.TYPES_DEPRECATION_MESSAGE)); + + // default settings should be null + assertNull(getIndexResponse.getSetting(indexName, "index.refresh_interval")); + assertEquals("1", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_SHARDS)); + assertEquals("0", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_REPLICAS)); + assertNotNull(getIndexResponse.getMappings().get(indexName)); + MappingMetaData mappingMetaData = getIndexResponse.getMappings().get(indexName).get("_doc"); + assertNotNull(mappingMetaData); + assertEquals("_doc", mappingMetaData.type()); + assertEquals("{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}", mappingMetaData.source().string()); + } + @SuppressWarnings("unchecked") public void testGetIndexWithDefaults() throws IOException { String indexName = "get_index_test"; @@ -446,19 +488,18 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { String mappings = "\"properties\":{\"field-1\":{\"type\":\"integer\"}}"; createIndex(indexName, basicSettings, mappings); - GetIndexRequest getIndexRequest = new GetIndexRequest() - .indices(indexName).includeDefaults(true); + GetIndexRequest getIndexRequest = new GetIndexRequest(indexName).includeDefaults(true); GetIndexResponse getIndexResponse = execute(getIndexRequest, highLevelClient().indices()::get, highLevelClient().indices()::getAsync); assertNotNull(getIndexResponse.getSetting(indexName, "index.refresh_interval")); assertEquals(IndexSettings.DEFAULT_REFRESH_INTERVAL, - getIndexResponse.defaultSettings().get(indexName).getAsTime("index.refresh_interval", null)); + getIndexResponse.getDefaultSettings().get(indexName).getAsTime("index.refresh_interval", null)); assertEquals("1", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_SHARDS)); assertEquals("0", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_REPLICAS)); assertNotNull(getIndexResponse.getMappings().get(indexName)); - assertNotNull(getIndexResponse.getMappings().get(indexName).get("_doc")); - Object o = getIndexResponse.getMappings().get(indexName).get("_doc").getSourceAsMap().get("properties"); + assertNotNull(getIndexResponse.getMappings().get(indexName)); + Object o = getIndexResponse.getMappings().get(indexName).getSourceAsMap().get("properties"); assertThat(o, instanceOf(Map.class)); assertThat(((Map) o).get("field-1"), instanceOf(Map.class)); Map fieldMapping = (Map) ((Map) o).get("field-1"); @@ -469,7 +510,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { String nonExistentIndex = "index_that_doesnt_exist"; assertFalse(indexExists(nonExistentIndex)); - GetIndexRequest getIndexRequest = new GetIndexRequest().indices(nonExistentIndex); + GetIndexRequest getIndexRequest = new GetIndexRequest(nonExistentIndex); ElasticsearchException exception = expectThrows(ElasticsearchException.class, () -> execute(getIndexRequest, highLevelClient().indices()::get, highLevelClient().indices()::getAsync)); assertEquals(RestStatus.NOT_FOUND, exception.status()); @@ -1432,7 +1473,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { @SuppressWarnings("unchecked") public void testPutTemplateWithTypes() throws Exception { - org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putTemplateRequest = + org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putTemplateRequest = new org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest() .name("my-template") .patterns(Arrays.asList("pattern-1", "name-*")) @@ -1459,7 +1500,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { assertThat((Map) extractValue("my-template.aliases.alias-1", templates), hasEntry("index_routing", "abc")); assertThat((Map) extractValue("my-template.aliases.{index}-write", templates), hasEntry("search_routing", "xyz")); } - + @SuppressWarnings("unchecked") public void testPutTemplate() throws Exception { PutIndexTemplateRequest putTemplateRequest = new PutIndexTemplateRequest("my-template") @@ -1487,7 +1528,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { assertThat((Map) extractValue("my-template.aliases.alias-1", templates), hasEntry("index_routing", "abc")); assertThat((Map) extractValue("my-template.aliases.{index}-write", templates), hasEntry("search_routing", "xyz")); } - + public void testPutTemplateWithTypesUsingUntypedAPI() throws Exception { PutIndexTemplateRequest putTemplateRequest = new PutIndexTemplateRequest("my-template") .patterns(Arrays.asList("pattern-1", "name-*")) @@ -1503,17 +1544,17 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { + "}", XContentType.JSON) .alias(new Alias("alias-1").indexRouting("abc")).alias(new Alias("{index}-write").searchRouting("xyz")); - + ElasticsearchStatusException badMappingError = expectThrows(ElasticsearchStatusException.class, () -> execute(putTemplateRequest, highLevelClient().indices()::putTemplate, highLevelClient().indices()::putTemplateAsync)); - assertThat(badMappingError.getDetailedMessage(), + assertThat(badMappingError.getDetailedMessage(), containsString("Root mapping definition has unsupported parameters: [my_doc_type")); - } - + } + @SuppressWarnings("unchecked") public void testPutTemplateWithNoTypesUsingTypedApi() throws Exception { - org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putTemplateRequest = + org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putTemplateRequest = new org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest() .name("my-template") .patterns(Arrays.asList("pattern-1", "name-*")) @@ -1521,7 +1562,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { .create(randomBoolean()) .settings(Settings.builder().put("number_of_shards", "3").put("number_of_replicas", "0")) .mapping("my_doc_type", - // Note that the declared type is missing from the mapping + // Note that the declared type is missing from the mapping "{ " + "\"properties\":{" + "\"host_name\": {\"type\":\"keyword\"}," @@ -1546,7 +1587,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { assertThat(extractValue("my-template.mappings.properties.description.type", templates), equalTo("text")); assertThat((Map) extractValue("my-template.aliases.alias-1", templates), hasEntry("index_routing", "abc")); assertThat((Map) extractValue("my-template.aliases.{index}-write", templates), hasEntry("search_routing", "xyz")); - } + } public void testPutTemplateBadRequests() throws Exception { RestHighLevelClient client = highLevelClient(); @@ -1615,35 +1656,35 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { public void testCRUDIndexTemplateWithTypes() throws Exception { RestHighLevelClient client = highLevelClient(); - org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putTemplate1 = + org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putTemplate1 = new org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest().name("template-1") .patterns(Arrays.asList("pattern-1", "name-1")).alias(new Alias("alias-1")); assertThat(execute(putTemplate1, client.indices()::putTemplate, client.indices()::putTemplateAsync , expectWarnings(RestPutIndexTemplateAction.TYPES_DEPRECATION_MESSAGE)) .isAcknowledged(), equalTo(true)); - org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putTemplate2 = + org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putTemplate2 = new org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest().name("template-2") .patterns(Arrays.asList("pattern-2", "name-2")) .mapping("custom_doc_type", "name", "type=text") .settings(Settings.builder().put("number_of_shards", "2").put("number_of_replicas", "0")); - assertThat(execute(putTemplate2, client.indices()::putTemplate, client.indices()::putTemplateAsync, + assertThat(execute(putTemplate2, client.indices()::putTemplate, client.indices()::putTemplateAsync, expectWarnings(RestPutIndexTemplateAction.TYPES_DEPRECATION_MESSAGE)) .isAcknowledged(), equalTo(true)); org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse getTemplate1 = execute( new GetIndexTemplatesRequest("template-1"), - client.indices()::getTemplate, client.indices()::getTemplateAsync, + client.indices()::getTemplate, client.indices()::getTemplateAsync, expectWarnings(RestGetIndexTemplateAction.TYPES_DEPRECATION_MESSAGE)); assertThat(getTemplate1.getIndexTemplates(), hasSize(1)); org.elasticsearch.cluster.metadata.IndexTemplateMetaData template1 = getTemplate1.getIndexTemplates().get(0); assertThat(template1.name(), equalTo("template-1")); assertThat(template1.patterns(), contains("pattern-1", "name-1")); assertTrue(template1.aliases().containsKey("alias-1")); - - //Check the typed version of the call - org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse getTemplate2 = + + //Check the typed version of the call + org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse getTemplate2 = execute(new GetIndexTemplatesRequest("template-2"), - client.indices()::getTemplate, client.indices()::getTemplateAsync, + client.indices()::getTemplate, client.indices()::getTemplateAsync, expectWarnings(RestGetIndexTemplateAction.TYPES_DEPRECATION_MESSAGE)); assertThat(getTemplate2.getIndexTemplates(), hasSize(1)); org.elasticsearch.cluster.metadata.IndexTemplateMetaData template2 = getTemplate2.getIndexTemplates().get(0); @@ -1651,7 +1692,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { assertThat(template2.patterns(), contains("pattern-2", "name-2")); assertTrue(template2.aliases().isEmpty()); assertThat(template2.settings().get("index.number_of_shards"), equalTo("2")); - assertThat(template2.settings().get("index.number_of_replicas"), equalTo("0")); + assertThat(template2.settings().get("index.number_of_replicas"), equalTo("0")); // Ugly deprecated form of API requires use of doc type to get at mapping object which is CompressedXContent assertTrue(template2.mappings().containsKey("custom_doc_type")); @@ -1683,21 +1724,21 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { client.indices()::deleteTemplate, client.indices()::deleteTemplateAsync)).status(), equalTo(RestStatus.NOT_FOUND)); assertThat(execute(new GetIndexTemplatesRequest("template-*"), - client.indices()::getTemplate, client.indices()::getTemplateAsync, + client.indices()::getTemplate, client.indices()::getTemplateAsync, expectWarnings(RestGetIndexTemplateAction.TYPES_DEPRECATION_MESSAGE)).getIndexTemplates(), hasSize(1)); assertThat(execute(new GetIndexTemplatesRequest("template-*"), - client.indices()::getTemplate, client.indices()::getTemplateAsync, + client.indices()::getTemplate, client.indices()::getTemplateAsync, expectWarnings(RestGetIndexTemplateAction.TYPES_DEPRECATION_MESSAGE)).getIndexTemplates() .get(0).name(), equalTo("template-2")); assertTrue(execute(new DeleteIndexTemplateRequest("template-*"), client.indices()::deleteTemplate, client.indices()::deleteTemplateAsync).isAcknowledged()); assertThat(expectThrows(ElasticsearchException.class, () -> execute(new GetIndexTemplatesRequest("template-*"), - client.indices()::getTemplate, client.indices()::getTemplateAsync, + client.indices()::getTemplate, client.indices()::getTemplateAsync, expectWarnings(RestGetIndexTemplateAction.TYPES_DEPRECATION_MESSAGE))).status(), equalTo(RestStatus.NOT_FOUND)); } - + public void testCRUDIndexTemplate() throws Exception { RestHighLevelClient client = highLevelClient(); @@ -1720,7 +1761,7 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { assertThat(template1.name(), equalTo("template-1")); assertThat(template1.patterns(), contains("pattern-1", "name-1")); assertTrue(template1.aliases().containsKey("alias-1")); - + GetIndexTemplatesResponse getTemplate2 = execute(new GetIndexTemplatesRequest("template-2"), client.indices()::getIndexTemplate, client.indices()::getIndexTemplateAsync); assertThat(getTemplate2.getIndexTemplates(), hasSize(1)); @@ -1729,14 +1770,14 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase { assertThat(template2.patterns(), contains("pattern-2", "name-2")); assertTrue(template2.aliases().isEmpty()); assertThat(template2.settings().get("index.number_of_shards"), equalTo("2")); - assertThat(template2.settings().get("index.number_of_replicas"), equalTo("0")); + assertThat(template2.settings().get("index.number_of_replicas"), equalTo("0")); // New API returns a MappingMetaData class rather than CompressedXContent for the mapping assertTrue(template2.mappings().sourceAsMap().containsKey("properties")); @SuppressWarnings("unchecked") Map props = (Map) template2.mappings().sourceAsMap().get("properties"); assertTrue(props.containsKey("name")); - - + + List names = randomBoolean() ? Arrays.asList("*-1", "template-2") diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesRequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesRequestConvertersTests.java index 0c94cb61a79..f7d5ac51a73 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesRequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesRequestConvertersTests.java @@ -36,7 +36,6 @@ import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest; import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest; -import org.elasticsearch.action.admin.indices.get.GetIndexRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest; @@ -48,6 +47,7 @@ import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryReques import org.elasticsearch.action.support.master.AcknowledgedRequest; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.GetFieldMappingsRequest; +import org.elasticsearch.client.indices.GetIndexRequest; import org.elasticsearch.client.indices.GetIndexTemplatesRequest; import org.elasticsearch.client.indices.GetMappingsRequest; import org.elasticsearch.client.indices.IndexTemplatesExistRequest; @@ -104,13 +104,13 @@ public class IndicesRequestConvertersTests extends ESTestCase { public void testIndicesExist() { String[] indices = RequestConvertersTests.randomIndicesNames(1, 10); - GetIndexRequest getIndexRequest = new GetIndexRequest().indices(indices); + GetIndexRequest getIndexRequest = new GetIndexRequest(indices); Map expectedParams = new HashMap<>(); RequestConvertersTests.setRandomIndicesOptions(getIndexRequest::indicesOptions, getIndexRequest::indicesOptions, expectedParams); - RequestConvertersTests.setRandomLocal(getIndexRequest, expectedParams); - RequestConvertersTests.setRandomHumanReadable(getIndexRequest, expectedParams); - RequestConvertersTests.setRandomIncludeDefaults(getIndexRequest, expectedParams); + RequestConvertersTests.setRandomLocal(getIndexRequest::local, expectedParams); + RequestConvertersTests.setRandomHumanReadable(getIndexRequest::humanReadable, expectedParams); + RequestConvertersTests.setRandomIncludeDefaults(getIndexRequest::includeDefaults, expectedParams); final Request request = IndicesRequestConverters.indicesExist(getIndexRequest); @@ -124,7 +124,35 @@ public class IndicesRequestConvertersTests extends ESTestCase { LuceneTestCase.expectThrows(IllegalArgumentException.class, () -> IndicesRequestConverters.indicesExist(new GetIndexRequest())); LuceneTestCase.expectThrows(IllegalArgumentException.class, () - -> IndicesRequestConverters.indicesExist(new GetIndexRequest().indices((String[]) null))); + -> IndicesRequestConverters.indicesExist(new GetIndexRequest((String[]) null))); + } + + public void testIndicesExistEmptyIndicesWithTypes() { + LuceneTestCase.expectThrows(IllegalArgumentException.class, + () -> IndicesRequestConverters.indicesExist(new org.elasticsearch.action.admin.indices.get.GetIndexRequest())); + LuceneTestCase.expectThrows(IllegalArgumentException.class, () -> IndicesRequestConverters + .indicesExist(new org.elasticsearch.action.admin.indices.get.GetIndexRequest().indices((String[]) null))); + } + + public void testIndicesExistWithTypes() { + String[] indices = RequestConvertersTests.randomIndicesNames(1, 10); + + org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest = + new org.elasticsearch.action.admin.indices.get.GetIndexRequest().indices(indices); + + Map expectedParams = new HashMap<>(); + RequestConvertersTests.setRandomIndicesOptions(getIndexRequest::indicesOptions, getIndexRequest::indicesOptions, expectedParams); + RequestConvertersTests.setRandomLocal(getIndexRequest::local, expectedParams); + RequestConvertersTests.setRandomHumanReadable(getIndexRequest::humanReadable, expectedParams); + RequestConvertersTests.setRandomIncludeDefaults(getIndexRequest::includeDefaults, expectedParams); + expectedParams.put(INCLUDE_TYPE_NAME_PARAMETER, "true"); + + final Request request = IndicesRequestConverters.indicesExist(getIndexRequest); + + Assert.assertEquals(HttpHead.METHOD_NAME, request.getMethod()); + Assert.assertEquals("/" + String.join(",", indices), request.getEndpoint()); + Assert.assertThat(expectedParams, equalTo(request.getParameters())); + Assert.assertNull(request.getEntity()); } public void testCreateIndex() throws IOException { @@ -288,7 +316,7 @@ public class IndicesRequestConvertersTests extends ESTestCase { RequestConvertersTests.setRandomIndicesOptions(getMappingRequest::indicesOptions, getMappingRequest::indicesOptions, expectedParams); RequestConvertersTests.setRandomMasterTimeout(getMappingRequest, expectedParams); - RequestConvertersTests.setRandomLocal(getMappingRequest, expectedParams); + RequestConvertersTests.setRandomLocal(getMappingRequest::local, expectedParams); expectedParams.put(INCLUDE_TYPE_NAME_PARAMETER, "true"); Request request = IndicesRequestConverters.getMappings(getMappingRequest); @@ -436,7 +464,7 @@ public class IndicesRequestConvertersTests extends ESTestCase { RequestConvertersTests.setRandomIndicesOptions(getSettingsRequest::indicesOptions, getSettingsRequest::indicesOptions, expectedParams); - RequestConvertersTests.setRandomLocal(getSettingsRequest, expectedParams); + RequestConvertersTests.setRandomLocal(getSettingsRequest::local, expectedParams); if (ESTestCase.randomBoolean()) { // the request object will not have include_defaults present unless it is set to @@ -477,13 +505,48 @@ public class IndicesRequestConvertersTests extends ESTestCase { public void testGetIndex() throws IOException { String[] indicesUnderTest = ESTestCase.randomBoolean() ? null : RequestConvertersTests.randomIndicesNames(0, 5); - GetIndexRequest getIndexRequest = new GetIndexRequest().indices(indicesUnderTest); + GetIndexRequest getIndexRequest = new GetIndexRequest(indicesUnderTest); Map expectedParams = new HashMap<>(); RequestConvertersTests.setRandomMasterTimeout(getIndexRequest, expectedParams); RequestConvertersTests.setRandomIndicesOptions(getIndexRequest::indicesOptions, getIndexRequest::indicesOptions, expectedParams); - RequestConvertersTests.setRandomLocal(getIndexRequest, expectedParams); - RequestConvertersTests.setRandomHumanReadable(getIndexRequest, expectedParams); + RequestConvertersTests.setRandomLocal(getIndexRequest::local, expectedParams); + RequestConvertersTests.setRandomHumanReadable(getIndexRequest::humanReadable, expectedParams); + + if (ESTestCase.randomBoolean()) { + // the request object will not have include_defaults present unless it is set to + // true + getIndexRequest.includeDefaults(ESTestCase.randomBoolean()); + if (getIndexRequest.includeDefaults()) { + expectedParams.put("include_defaults", Boolean.toString(true)); + } + } + + StringJoiner endpoint = new StringJoiner("/", "/", ""); + if (indicesUnderTest != null && indicesUnderTest.length > 0) { + endpoint.add(String.join(",", indicesUnderTest)); + } + + Request request = IndicesRequestConverters.getIndex(getIndexRequest); + + Assert.assertThat(endpoint.toString(), equalTo(request.getEndpoint())); + Assert.assertThat(request.getParameters(), equalTo(expectedParams)); + Assert.assertThat(request.getMethod(), equalTo(HttpGet.METHOD_NAME)); + Assert.assertThat(request.getEntity(), nullValue()); + } + + public void testGetIndexWithTypes() throws IOException { + String[] indicesUnderTest = ESTestCase.randomBoolean() ? null : RequestConvertersTests.randomIndicesNames(0, 5); + + org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest = + new org.elasticsearch.action.admin.indices.get.GetIndexRequest().indices(indicesUnderTest); + + Map expectedParams = new HashMap<>(); + RequestConvertersTests.setRandomMasterTimeout(getIndexRequest, expectedParams); + RequestConvertersTests.setRandomIndicesOptions(getIndexRequest::indicesOptions, getIndexRequest::indicesOptions, expectedParams); + RequestConvertersTests.setRandomLocal(getIndexRequest::local, expectedParams); + RequestConvertersTests.setRandomHumanReadable(getIndexRequest::humanReadable, expectedParams); + expectedParams.put(INCLUDE_TYPE_NAME_PARAMETER, "true"); if (ESTestCase.randomBoolean()) { // the request object will not have include_defaults present unless it is set to @@ -734,7 +797,7 @@ public class IndicesRequestConvertersTests extends ESTestCase { } getAliasesRequest.aliases(aliases); Map expectedParams = new HashMap<>(); - RequestConvertersTests.setRandomLocal(getAliasesRequest, expectedParams); + RequestConvertersTests.setRandomLocal(getAliasesRequest::local, expectedParams); RequestConvertersTests.setRandomIndicesOptions(getAliasesRequest::indicesOptions, getAliasesRequest::indicesOptions, expectedParams); @@ -910,7 +973,7 @@ public class IndicesRequestConvertersTests extends ESTestCase { GetAliasesRequest getAliasesRequest = new GetAliasesRequest(); Map expectedParams = new HashMap<>(); - RequestConvertersTests.setRandomLocal(getAliasesRequest, expectedParams); + RequestConvertersTests.setRandomLocal(getAliasesRequest::local, expectedParams); RequestConvertersTests.setRandomIndicesOptions(getAliasesRequest::indicesOptions, getAliasesRequest::indicesOptions, expectedParams); @@ -971,7 +1034,7 @@ public class IndicesRequestConvertersTests extends ESTestCase { names.put("-#template", "-%23template"); names.put("foo^bar", "foo%5Ebar"); - org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putTemplateRequest = + org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest putTemplateRequest = new org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest() .name(ESTestCase.randomFrom(names.keySet())) .patterns(Arrays.asList(ESTestCase.generateRandomStringArray(20, 100, false, false))); @@ -1001,7 +1064,7 @@ public class IndicesRequestConvertersTests extends ESTestCase { String cause = ESTestCase.randomUnicodeOfCodepointLengthBetween(1, 50); putTemplateRequest.cause(cause); expectedParams.put("cause", cause); - } + } RequestConvertersTests.setRandomMasterTimeout(putTemplateRequest, expectedParams); Request request = IndicesRequestConverters.putTemplate(putTemplateRequest); @@ -1017,7 +1080,7 @@ public class IndicesRequestConvertersTests extends ESTestCase { names.put("-#template", "-%23template"); names.put("foo^bar", "foo%5Ebar"); - PutIndexTemplateRequest putTemplateRequest = + PutIndexTemplateRequest putTemplateRequest = new PutIndexTemplateRequest(ESTestCase.randomFrom(names.keySet())) .patterns(Arrays.asList(ESTestCase.generateRandomStringArray(20, 100, false, false))); if (ESTestCase.randomBoolean()) { @@ -1031,7 +1094,7 @@ public class IndicesRequestConvertersTests extends ESTestCase { } Map expectedParams = new HashMap<>(); if (ESTestCase.randomBoolean()) { - putTemplateRequest.mapping("{ \"properties\": { \"field-" + ESTestCase.randomInt() + + putTemplateRequest.mapping("{ \"properties\": { \"field-" + ESTestCase.randomInt() + "\" : { \"type\" : \"" + ESTestCase.randomFrom("text", "keyword") + "\" }}}", XContentType.JSON); } if (ESTestCase.randomBoolean()) { @@ -1045,7 +1108,7 @@ public class IndicesRequestConvertersTests extends ESTestCase { String cause = ESTestCase.randomUnicodeOfCodepointLengthBetween(1, 50); putTemplateRequest.cause(cause); expectedParams.put("cause", cause); - } + } RequestConvertersTests.setRandomMasterTimeout(putTemplateRequest, expectedParams); Request request = IndicesRequestConverters.putTemplate(putTemplateRequest); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java index 95971ad40ce..b58e5ae8852 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java @@ -32,7 +32,6 @@ import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRe import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest; import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptRequest; import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest; -import org.elasticsearch.action.admin.indices.get.GetIndexRequest; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkShardRequest; import org.elasticsearch.action.delete.DeleteRequest; @@ -50,7 +49,6 @@ import org.elasticsearch.action.support.ActiveShardCount; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.action.support.master.AcknowledgedRequest; -import org.elasticsearch.action.support.master.MasterNodeReadRequest; import org.elasticsearch.action.support.master.MasterNodeRequest; import org.elasticsearch.action.support.replication.ReplicationRequest; import org.elasticsearch.action.update.UpdateRequest; @@ -1905,20 +1903,20 @@ public class RequestConvertersTests extends ESTestCase { return indicesOptions; } - static void setRandomIncludeDefaults(GetIndexRequest request, Map expectedParams) { + static void setRandomIncludeDefaults(Consumer setter, Map expectedParams) { if (randomBoolean()) { boolean includeDefaults = randomBoolean(); - request.includeDefaults(includeDefaults); + setter.accept(includeDefaults); if (includeDefaults) { expectedParams.put("include_defaults", String.valueOf(includeDefaults)); } } } - static void setRandomHumanReadable(GetIndexRequest request, Map expectedParams) { + static void setRandomHumanReadable(Consumer setter, Map expectedParams) { if (randomBoolean()) { boolean humanReadable = randomBoolean(); - request.humanReadable(humanReadable); + setter.accept(humanReadable); if (humanReadable) { expectedParams.put("human", String.valueOf(humanReadable)); } @@ -1935,10 +1933,6 @@ public class RequestConvertersTests extends ESTestCase { } } - static void setRandomLocal(MasterNodeReadRequest request, Map expectedParams) { - setRandomLocal(request::local, expectedParams); - } - static void setRandomTimeout(TimedRequest request, TimeValue defaultTimeout, Map expectedParams) { setRandomTimeout(s -> request.setTimeout(TimeValue.parseTimeValue(s, request.getClass().getName() + ".timeout")), diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotRequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotRequestConvertersTests.java index ca86a912042..66720b70ee3 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotRequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/SnapshotRequestConvertersTests.java @@ -58,7 +58,7 @@ public class SnapshotRequestConvertersTests extends ESTestCase { GetRepositoriesRequest getRepositoriesRequest = new GetRepositoriesRequest(); RequestConvertersTests.setRandomMasterTimeout(getRepositoriesRequest, expectedParams); - RequestConvertersTests.setRandomLocal(getRepositoriesRequest, expectedParams); + RequestConvertersTests.setRandomLocal(getRepositoriesRequest::local, expectedParams); if (randomBoolean()) { String[] entries = new String[]{"a", "b", "c"}; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java index 64741da1224..02b7d597ce2 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java @@ -38,10 +38,6 @@ import org.elasticsearch.action.admin.indices.flush.FlushResponse; import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest; import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest; import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse; -import org.elasticsearch.action.admin.indices.get.GetIndexRequest; -import org.elasticsearch.action.admin.indices.get.GetIndexResponse; -import org.elasticsearch.client.indices.GetFieldMappingsRequest; -import org.elasticsearch.client.indices.GetFieldMappingsResponse; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexResponse; import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; @@ -69,10 +65,14 @@ import org.elasticsearch.client.core.ShardsAcknowledgedResponse; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.client.indices.FreezeIndexRequest; +import org.elasticsearch.client.indices.GetFieldMappingsRequest; +import org.elasticsearch.client.indices.GetFieldMappingsResponse; +import org.elasticsearch.client.indices.GetIndexRequest; +import org.elasticsearch.client.indices.GetIndexResponse; import org.elasticsearch.client.indices.GetIndexTemplatesRequest; +import org.elasticsearch.client.indices.GetIndexTemplatesResponse; import org.elasticsearch.client.indices.GetMappingsRequest; import org.elasticsearch.client.indices.GetMappingsResponse; -import org.elasticsearch.client.indices.GetIndexTemplatesResponse; import org.elasticsearch.client.indices.IndexTemplateMetaData; import org.elasticsearch.client.indices.IndexTemplatesExistRequest; import org.elasticsearch.client.indices.PutIndexTemplateRequest; @@ -82,7 +82,6 @@ import org.elasticsearch.client.indices.rollover.RolloverRequest; import org.elasticsearch.client.indices.rollover.RolloverResponse; import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.MappingMetaData; -import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.ByteSizeUnit; import org.elasticsearch.common.unit.ByteSizeValue; @@ -139,8 +138,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase { // tag::indices-exists-request - GetIndexRequest request = new GetIndexRequest(); - request.indices("twitter"); // <1> + GetIndexRequest request = new GetIndexRequest("twitter"); // <1> // end::indices-exists-request IndicesOptions indicesOptions = IndicesOptions.strictExpand(); @@ -167,8 +165,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase } { - GetIndexRequest request = new GetIndexRequest(); - request.indices("twitter"); + GetIndexRequest request = new GetIndexRequest("twitter"); // tag::indices-exists-execute-listener ActionListener listener = new ActionListener() { @@ -1230,7 +1227,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase } // tag::get-index-request - GetIndexRequest request = new GetIndexRequest().indices("index"); // <1> + GetIndexRequest request = new GetIndexRequest("index"); // <1> // end::get-index-request // tag::get-index-request-indicesOptions @@ -1246,13 +1243,13 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase // end::get-index-execute // tag::get-index-response - ImmutableOpenMap indexMappings = getIndexResponse.getMappings().get("index"); // <1> - Map indexTypeMappings = indexMappings.get("_doc").getSourceAsMap(); // <2> + MappingMetaData indexMappings = getIndexResponse.getMappings().get("index"); // <1> + Map indexTypeMappings = indexMappings.getSourceAsMap(); // <2> List indexAliases = getIndexResponse.getAliases().get("index"); // <3> String numberOfShardsString = getIndexResponse.getSetting("index", "index.number_of_shards"); // <4> Settings indexSettings = getIndexResponse.getSettings().get("index"); // <5> Integer numberOfShards = indexSettings.getAsInt("index.number_of_shards", null); // <6> - TimeValue time = getIndexResponse.defaultSettings().get("index") + TimeValue time = getIndexResponse.getDefaultSettings().get("index") .getAsTime("index.refresh_interval", null); // <7> // end::get-index-response @@ -2100,7 +2097,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase " \"type\": \"text\"\n" + " }\n" + " }\n" + - "}", + "}", XContentType.JSON); // end::put-template-request-mappings-json assertTrue(client.indices().putTemplate(request, RequestOptions.DEFAULT).isAcknowledged()); @@ -2115,7 +2112,7 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase message.put("type", "text"); properties.put("message", message); } - jsonMap.put("properties", properties); + jsonMap.put("properties", properties); } request.mapping(jsonMap); // <1> //end::put-template-request-mappings-map diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/GetIndexRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/GetIndexRequestTests.java new file mode 100644 index 00000000000..46b64aab6d4 --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/GetIndexRequestTests.java @@ -0,0 +1,68 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.client.indices; + +import org.elasticsearch.action.support.IndicesOptions; +import org.elasticsearch.client.indices.GetIndexRequest.Feature; +import org.elasticsearch.test.ESTestCase; + +public class GetIndexRequestTests extends ESTestCase { + + public void testIndices() { + String[] indices = generateRandomStringArray(5, 5, false, true); + GetIndexRequest request = new GetIndexRequest(indices); + assertArrayEquals(indices, request.indices()); + } + + public void testFeatures() { + int numFeature = randomIntBetween(0, 3); + Feature[] features = new Feature[numFeature]; + for (int i = 0; i < numFeature; i++) { + features[i] = randomFrom(GetIndexRequest.DEFAULT_FEATURES); + } + GetIndexRequest request = new GetIndexRequest().addFeatures(features); + assertArrayEquals(features, request.features()); + } + + public void testLocal() { + boolean local = randomBoolean(); + GetIndexRequest request = new GetIndexRequest().local(local); + assertEquals(local, request.local()); + } + + public void testHumanReadable() { + boolean humanReadable = randomBoolean(); + GetIndexRequest request = new GetIndexRequest().humanReadable(humanReadable); + assertEquals(humanReadable, request.humanReadable()); + } + + public void testIncludeDefaults() { + boolean includeDefaults = randomBoolean(); + GetIndexRequest request = new GetIndexRequest().includeDefaults(includeDefaults); + assertEquals(includeDefaults, request.includeDefaults()); + } + + public void testIndicesOptions() { + IndicesOptions indicesOptions = IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean()); + GetIndexRequest request = new GetIndexRequest().indicesOptions(indicesOptions); + assertEquals(indicesOptions, request.indicesOptions()); + } + +} diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/GetIndexResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/GetIndexResponseTests.java new file mode 100644 index 00000000000..19c25fd11f6 --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/GetIndexResponseTests.java @@ -0,0 +1,195 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.client.indices; + +import org.apache.lucene.util.CollectionUtil; +import org.elasticsearch.client.GetAliasesResponseTests; +import org.elasticsearch.cluster.metadata.AliasMetaData; +import org.elasticsearch.cluster.metadata.MappingMetaData; +import org.elasticsearch.common.collect.ImmutableOpenMap; +import org.elasticsearch.common.settings.IndexScopedSettings; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.ToXContent.Params; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.index.RandomCreateIndexGenerator; +import org.elasticsearch.index.mapper.MapperService; +import org.elasticsearch.rest.BaseRestHandler; +import org.elasticsearch.test.ESTestCase; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static org.elasticsearch.test.AbstractXContentTestCase.xContentTester; + +public class GetIndexResponseTests extends ESTestCase { + + // Because the client-side class does not have a toXContent method, we test xContent serialization by creating + // a random client object, converting it to a server object then serializing it to xContent, and finally + // parsing it back as a client object. We check equality between the original client object, and the parsed one. + public void testFromXContent() throws IOException { + xContentTester( + this::createParser, + GetIndexResponseTests::createTestInstance, + GetIndexResponseTests::toXContent, + GetIndexResponse::fromXContent) + .supportsUnknownFields(false) + .assertToXContentEquivalence(false) + .assertEqualsConsumer(GetIndexResponseTests::assertEqualInstances) + .test(); + } + + private static void assertEqualInstances(GetIndexResponse expected, GetIndexResponse actual) { + assertArrayEquals(expected.getIndices(), actual.getIndices()); + assertEquals(expected.getMappings(), actual.getMappings()); + assertEquals(expected.getSettings(), actual.getSettings()); + assertEquals(expected.getDefaultSettings(), actual.getDefaultSettings()); + assertEquals(expected.getAliases(), actual.getAliases()); + } + + private static GetIndexResponse createTestInstance() { + String[] indices = generateRandomStringArray(5, 5, false, false); + Map mappings = new HashMap<>(); + Map> aliases = new HashMap<>(); + Map settings = new HashMap<>(); + Map defaultSettings = new HashMap<>(); + IndexScopedSettings indexScopedSettings = IndexScopedSettings.DEFAULT_SCOPED_SETTINGS; + boolean includeDefaults = randomBoolean(); + for (String index: indices) { + mappings.put(index, createMappingsForIndex()); + + List aliasMetaDataList = new ArrayList<>(); + int aliasesNum = randomIntBetween(0, 3); + for (int i=0; i mappings = new HashMap<>(); + mappings.put("field-" + i, randomFieldMapping()); + if (randomBoolean()) { + mappings.put("field2-" + i, randomFieldMapping()); + } + + try { + String typeName = MapperService.SINGLE_MAPPING_NAME; + mmd = new MappingMetaData(typeName, mappings); + } catch (IOException e) { + fail("shouldn't have failed " + e); + } + } + } + return mmd; + } + + // Not meant to be exhaustive + private static Map randomFieldMapping() { + Map mappings = new HashMap<>(); + if (randomBoolean()) { + mappings.put("type", randomBoolean() ? "text" : "keyword"); + mappings.put("index", "analyzed"); + mappings.put("analyzer", "english"); + } else if (randomBoolean()) { + mappings.put("type", randomFrom("integer", "float", "long", "double")); + mappings.put("index", Objects.toString(randomBoolean())); + } else if (randomBoolean()) { + mappings.put("type", "object"); + mappings.put("dynamic", "strict"); + Map properties = new HashMap<>(); + Map props1 = new HashMap<>(); + props1.put("type", randomFrom("text", "keyword")); + props1.put("analyzer", "keyword"); + properties.put("subtext", props1); + Map props2 = new HashMap<>(); + props2.put("type", "object"); + Map prop2properties = new HashMap<>(); + Map props3 = new HashMap<>(); + props3.put("type", "integer"); + props3.put("index", "false"); + prop2properties.put("subsubfield", props3); + props2.put("properties", prop2properties); + mappings.put("properties", properties); + } else { + mappings.put("type", "keyword"); + } + return mappings; + } + + private static void toXContent(GetIndexResponse response, XContentBuilder builder) throws IOException { + // first we need to repackage from GetIndexResponse to org.elasticsearch.action.admin.indices.get.GetIndexResponse + ImmutableOpenMap.Builder> allMappings = ImmutableOpenMap.builder(); + ImmutableOpenMap.Builder> aliases = ImmutableOpenMap.builder(); + ImmutableOpenMap.Builder settings = ImmutableOpenMap.builder(); + ImmutableOpenMap.Builder defaultSettings = ImmutableOpenMap.builder(); + + Map indexMappings = response.getMappings(); + for (String index : response.getIndices()) { + MappingMetaData mmd = indexMappings.get(index); + ImmutableOpenMap.Builder typedMappings = ImmutableOpenMap.builder(); + if (mmd != null) { + typedMappings.put(MapperService.SINGLE_MAPPING_NAME, mmd); + } + allMappings.put(index, typedMappings.build()); + aliases.put(index, response.getAliases().get(index)); + settings.put(index, response.getSettings().get(index)); + defaultSettings.put(index, response.getDefaultSettings().get(index)); + } + + org.elasticsearch.action.admin.indices.get.GetIndexResponse serverResponse + = new org.elasticsearch.action.admin.indices.get.GetIndexResponse( + response.getIndices(), + allMappings.build(), + aliases.build(), + settings.build(), + defaultSettings.build()); + + // then we can call its toXContent method, forcing no output of types + Params params = new ToXContent.MapParams(Collections.singletonMap(BaseRestHandler.INCLUDE_TYPE_NAME_PARAMETER, "false")); + serverResponse.toXContent(builder, params); + } +} diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java index 9482a42a56e..235df6d4c33 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java @@ -43,7 +43,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Map; import java.util.Objects; import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken; @@ -61,7 +60,7 @@ public class GetIndexResponse extends ActionResponse implements ToXContentObject private ImmutableOpenMap defaultSettings = ImmutableOpenMap.of(); private String[] indices; - GetIndexResponse(String[] indices, + public GetIndexResponse(String[] indices, ImmutableOpenMap> mappings, ImmutableOpenMap> aliases, ImmutableOpenMap settings, @@ -315,9 +314,16 @@ public class GetIndexResponse extends ActionResponse implements ToXContentObject private static ImmutableOpenMap parseMappings(XContentParser parser) throws IOException { ImmutableOpenMap.Builder indexMappings = ImmutableOpenMap.builder(); - Map map = parser.map(); - if (map.isEmpty() == false) { - indexMappings.put(MapperService.SINGLE_MAPPING_NAME, new MappingMetaData(MapperService.SINGLE_MAPPING_NAME, map)); + // We start at START_OBJECT since parseIndexEntry ensures that + while (parser.nextToken() != Token.END_OBJECT) { + ensureExpectedToken(Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation); + parser.nextToken(); + if (parser.currentToken() == Token.START_OBJECT) { + String mappingType = parser.currentName(); + indexMappings.put(mappingType, new MappingMetaData(mappingType, parser.map())); + } else if (parser.currentToken() == Token.START_ARRAY) { + parser.skipChildren(); + } } return indexMappings.build(); } diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java index f38df932694..842741872fd 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java @@ -47,8 +47,8 @@ import static org.elasticsearch.rest.RestRequest.Method.HEAD; public class RestGetIndicesAction extends BaseRestHandler { private static final DeprecationLogger deprecationLogger = new DeprecationLogger(LogManager.getLogger(RestGetIndicesAction.class)); - static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Using `include_type_name` in get indices requests is deprecated. " - + "The parameter will be removed in the next major version."; + public static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Using `include_type_name` in get indices requests" + + " is deprecated. The parameter will be removed in the next major version."; private static final Set allowedResponseParameters = Collections .unmodifiableSet(Stream.concat(Collections.singleton(INCLUDE_TYPE_NAME_PARAMETER).stream(), Settings.FORMAT_PARAMS.stream()) diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java index af3ab33e915..86e1973ed0a 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/get/GetIndexResponseTests.java @@ -31,9 +31,10 @@ import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.settings.IndexScopedSettings; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.RandomCreateIndexGenerator; +import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.test.AbstractStreamableXContentTestCase; import org.junit.Assert; @@ -73,10 +74,6 @@ public class GetIndexResponseTests extends AbstractStreamableXContentTestCase> mappings = ImmutableOpenMap.builder(); ImmutableOpenMap.Builder> aliases = ImmutableOpenMap.builder(); @@ -87,7 +84,7 @@ public class GetIndexResponseTests extends AbstractStreamableXContentTestCase aliasMetaDataList = new ArrayList<>(); int aliasesNum = randomIntBetween(0, 3); @@ -110,12 +107,6 @@ public class GetIndexResponseTests extends AbstractStreamableXContentTestCase getRandomFieldsExcludeFilter() { //we do not want to add new fields at the root (index-level), or inside the blocks @@ -203,4 +194,13 @@ public class GetIndexResponseTests extends AbstractStreamableXContentTestCase