From 19accdeb26f857f29f5f7e4aa36578dd4eab5c8f Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Wed, 16 Jan 2019 11:48:50 -0800 Subject: [PATCH 01/12] Add a deprecation warning to RestCreateIndexAction. --- .../admin/indices/RestCreateIndexAction.java | 12 ++++ .../indices/RestCreateIndexActionTests.java | 62 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 server/src/test/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexActionTests.java diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexAction.java index ed2724b95bb47..61e8af47a43d5 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexAction.java @@ -19,9 +19,11 @@ package org.elasticsearch.rest.action.admin.indices; +import org.apache.logging.log4j.LogManager; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.support.ActiveShardCount; import org.elasticsearch.client.node.NodeClient; +import org.elasticsearch.common.logging.DeprecationLogger; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.LoggingDeprecationHandler; import org.elasticsearch.common.xcontent.XContentHelper; @@ -37,6 +39,11 @@ import java.util.Map; public class RestCreateIndexAction extends BaseRestHandler { + private static final DeprecationLogger deprecationLogger = new DeprecationLogger( + LogManager.getLogger(RestPutMappingAction.class)); + public static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Using include_type_name in create " + + "index requests is deprecated. The parameter will be removed in the next major version."; + public RestCreateIndexAction(Settings settings, RestController controller) { super(settings); controller.registerHandler(RestRequest.Method.PUT, "/{index}", this); @@ -51,6 +58,11 @@ public String getName() { public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final boolean includeTypeName = request.paramAsBoolean(INCLUDE_TYPE_NAME_PARAMETER, DEFAULT_INCLUDE_TYPE_NAME_POLICY); + + if (request.hasParam(INCLUDE_TYPE_NAME_PARAMETER)) { + deprecationLogger.deprecatedAndMaybeLog("create_index_with_types", TYPES_DEPRECATION_MESSAGE); + } + CreateIndexRequest createIndexRequest = new CreateIndexRequest(request.param("index")); if (request.hasContent()) { Map sourceAsMap = XContentHelper.convertToMap(request.content(), false, request.getXContentType()).v2(); diff --git a/server/src/test/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexActionTests.java b/server/src/test/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexActionTests.java new file mode 100644 index 0000000000000..1ec0a0f949965 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexActionTests.java @@ -0,0 +1,62 @@ +/* + * 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.rest.action.admin.indices; + +import org.elasticsearch.client.node.NodeClient; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.test.rest.FakeRestRequest; +import org.elasticsearch.test.rest.RestActionTestCase; +import org.junit.Before; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.elasticsearch.rest.BaseRestHandler.INCLUDE_TYPE_NAME_PARAMETER; +import static org.mockito.Mockito.mock; + +public class RestCreateIndexActionTests extends RestActionTestCase { + private RestCreateIndexAction action; + + @Before + public void setupAction() { + action = new RestCreateIndexAction(Settings.EMPTY, controller()); + } + + public void testIncludeTypeName() throws IOException { + Map params = new HashMap<>(); + params.put(INCLUDE_TYPE_NAME_PARAMETER, randomFrom("true", "false")); + RestRequest deprecatedRequest = new FakeRestRequest.Builder(xContentRegistry()) + .withMethod(RestRequest.Method.PUT) + .withPath("/some_index") + .withParams(params) + .build(); + + action.prepareRequest(deprecatedRequest, mock(NodeClient.class)); + assertWarnings(RestCreateIndexAction.TYPES_DEPRECATION_MESSAGE); + + RestRequest validRequest = new FakeRestRequest.Builder(xContentRegistry()) + .withMethod(RestRequest.Method.PUT) + .withPath("/some_index") + .build(); + action.prepareRequest(validRequest, mock(NodeClient.class)); + } +} From 6892e0fcf8a86a0bb0166808a81d3f4c0a9e61e8 Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Wed, 16 Jan 2019 13:53:53 -0800 Subject: [PATCH 02/12] Introduce a new typeless HLRC method. --- .../elasticsearch/client/IndicesClient.java | 58 ++- .../client/IndicesRequestConverters.java | 19 +- .../client/indices/CreateIndexRequest.java | 386 ++++++++++++++++++ .../client/indices/CreateIndexResponse.java | 74 ++++ .../java/org/elasticsearch/client/CCRIT.java | 4 +- .../client/ESRestHighLevelClientTestCase.java | 2 +- .../elasticsearch/client/IndicesClientIT.java | 79 +++- .../client/IndicesRequestConvertersTests.java | 38 +- .../client/MachineLearningIT.java | 12 +- .../documentation/CCRDocumentationIT.java | 4 +- .../documentation/CRUDDocumentationIT.java | 8 +- .../ClusterClientDocumentationIT.java | 2 +- .../documentation/ILMDocumentationIT.java | 18 +- .../IndicesClientDocumentationIT.java | 41 +- .../MlClientDocumentationIT.java | 8 +- .../documentation/SearchDocumentationIT.java | 10 +- .../SnapshotClientDocumentationIT.java | 2 +- .../indices/CreateIndexRequestTests.java | 99 +++++ .../indices/RandomCreateIndexGenerator.java | 150 +++++++ .../indices/create/CreateIndexResponse.java | 2 +- .../index/RandomCreateIndexGenerator.java | 6 +- 21 files changed, 940 insertions(+), 82 deletions(-) create mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java create mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexResponse.java create mode 100644 client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CreateIndexRequestTests.java create mode 100644 client/rest-high-level/src/test/java/org/elasticsearch/client/indices/RandomCreateIndexGenerator.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 325d22fa9a0dd..94578b6bc56f7 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 @@ -27,8 +27,6 @@ import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse; import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.flush.FlushResponse; @@ -60,6 +58,8 @@ import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse; 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.GetIndexTemplatesRequest; import org.elasticsearch.client.indices.IndexTemplatesExistRequest; @@ -120,9 +120,10 @@ public void deleteAsync(DeleteIndexRequest deleteIndexRequest, RequestOptions op * @return the response * @throws IOException in case there is a problem sending the request or parsing back the response */ - public CreateIndexResponse create(CreateIndexRequest createIndexRequest, RequestOptions options) throws IOException { + public CreateIndexResponse create(CreateIndexRequest createIndexRequest, + RequestOptions options) throws IOException { return restHighLevelClient.performRequestAndParseEntity(createIndexRequest, IndicesRequestConverters::createIndex, options, - CreateIndexResponse::fromXContent, emptySet()); + CreateIndexResponse::fromXContent, emptySet()); } /** @@ -133,9 +134,54 @@ public CreateIndexResponse create(CreateIndexRequest createIndexRequest, 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 */ - public void createAsync(CreateIndexRequest createIndexRequest, RequestOptions options, ActionListener listener) { + public void createAsync(CreateIndexRequest createIndexRequest, + RequestOptions options, + ActionListener listener) { restHighLevelClient.performRequestAsyncAndParseEntity(createIndexRequest, IndicesRequestConverters::createIndex, options, - CreateIndexResponse::fromXContent, listener, emptySet()); + CreateIndexResponse::fromXContent, listener, emptySet()); + } + + /** + * Creates an index using the Create Index API. + * See + * Create Index API on elastic.co + * @param createIndexRequest 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 #create(CreateIndexRequest, RequestOptions)} should be used instead, which accepts a new + * request object. + */ + @Deprecated + public org.elasticsearch.action.admin.indices.create.CreateIndexResponse create( + org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest, + RequestOptions options) throws IOException { + return restHighLevelClient.performRequestAndParseEntity(createIndexRequest, + IndicesRequestConverters::createIndex, options, + org.elasticsearch.action.admin.indices.create.CreateIndexResponse::fromXContent, emptySet()); + } + + /** + * Asynchronously creates an index using the Create Index API. + * See + * Create Index API on elastic.co + * @param createIndexRequest 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 #createAsync(CreateIndexRequest, RequestOptions, ActionListener)} should be used instead, + * which accepts a new request object. + */ + @Deprecated + public void createAsync(org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest, + RequestOptions options, + ActionListener listener) { + restHighLevelClient.performRequestAsyncAndParseEntity(createIndexRequest, + IndicesRequestConverters::createIndex, options, + org.elasticsearch.action.admin.indices.create.CreateIndexResponse::fromXContent, listener, emptySet()); } /** 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 79b0646770845..0ceecb87bcfe4 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 @@ -29,7 +29,6 @@ import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest; import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest; @@ -48,6 +47,7 @@ import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest; 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.GetIndexTemplatesRequest; import org.elasticsearch.client.indices.IndexTemplatesExistRequest; @@ -97,7 +97,22 @@ static Request closeIndex(CloseIndexRequest closeIndexRequest) { return request; } - static Request createIndex(CreateIndexRequest createIndexRequest) throws IOException { + static Request createIndex(CreateIndexRequest createIndexRequest) + throws IOException { + String endpoint = RequestConverters.endpoint(createIndexRequest.indices()); + Request request = new Request(HttpPut.METHOD_NAME, endpoint); + + RequestConverters.Params parameters = new RequestConverters.Params(request); + parameters.withTimeout(createIndexRequest.timeout()); + parameters.withMasterTimeout(createIndexRequest.masterNodeTimeout()); + parameters.withWaitForActiveShards(createIndexRequest.waitForActiveShards()); + + request.setEntity(RequestConverters.createEntity(createIndexRequest, RequestConverters.REQUEST_BODY_CONTENT_TYPE)); + return request; + } + + static Request createIndex(org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest) + throws IOException { String endpoint = RequestConverters.endpoint(createIndexRequest.indices()); Request request = new Request(HttpPut.METHOD_NAME, endpoint); diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java new file mode 100644 index 0000000000000..282d6367297e2 --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java @@ -0,0 +1,386 @@ +/* + * 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.ElasticsearchGenerationException; +import org.elasticsearch.ElasticsearchParseException; +import org.elasticsearch.action.IndicesRequest; +import org.elasticsearch.action.admin.indices.alias.Alias; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; +import org.elasticsearch.action.support.ActiveShardCount; +import org.elasticsearch.action.support.IndicesOptions; +import org.elasticsearch.client.TimedRequest; +import org.elasticsearch.client.Validatable; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.bytes.BytesArray; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.DeprecationHandler; +import org.elasticsearch.common.xcontent.LoggingDeprecationHandler; +import org.elasticsearch.common.xcontent.NamedXContentRegistry; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.mapper.MapperService; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS; + +/** + * A request to create an index. + */ +public class CreateIndexRequest extends TimedRequest implements Validatable, IndicesRequest, ToXContentObject { + static final ParseField MAPPINGS = new ParseField("mappings"); + static final ParseField SETTINGS = new ParseField("settings"); + static final ParseField ALIASES = new ParseField("aliases"); + + private final String index; + private Settings settings = EMPTY_SETTINGS; + private final Map mappings = new HashMap<>(); + private final Set aliases = new HashSet<>(); + + private ActiveShardCount waitForActiveShards = ActiveShardCount.DEFAULT; + + /** + * Constructs a new request to create an index with the specified name. + */ + public CreateIndexRequest(String index) { + if (index == null) { + throw new IllegalArgumentException("The index name cannot be null."); + } + this.index = index; + } + + @Override + public String[] indices() { + return new String[]{index}; + } + + @Override + public IndicesOptions indicesOptions() { + return IndicesOptions.strictSingleIndexNoExpandForbidClosed(); + } + + /** + * The name of the index to create. + */ + public String index() { + return index; + } + + /** + * The settings to create the index with. + */ + public Settings settings() { + return settings; + } + + /** + * The settings to create the index with. + */ + public CreateIndexRequest settings(Settings.Builder settings) { + this.settings = settings.build(); + return this; + } + + /** + * The settings to create the index with. + */ + public CreateIndexRequest settings(Settings settings) { + this.settings = settings; + return this; + } + + /** + * The settings to create the index with (either json or yaml format) + */ + public CreateIndexRequest settings(String source, XContentType xContentType) { + this.settings = Settings.builder().loadFromSource(source, xContentType).build(); + return this; + } + + /** + * Allows to set the settings using a json builder. + */ + public CreateIndexRequest settings(XContentBuilder builder) { + settings(Strings.toString(builder), builder.contentType()); + return this; + } + + /** + * The settings to create the index with (either json/yaml/properties format) + */ + public CreateIndexRequest settings(Map source) { + try { + XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); + builder.map(source); + settings(Strings.toString(builder), XContentType.JSON); + } catch (IOException e) { + throw new ElasticsearchGenerationException("Failed to generate [" + source + "]", e); + } + return this; + } + + /** + * Adds mapping that will be added when the index gets created. + * + * @param source The mapping source + * @param xContentType The content type of the source + */ + public CreateIndexRequest mapping(String source, XContentType xContentType) { + return mapping(new BytesArray(source), xContentType); + } + + /** + * Adds mapping that will be added when the index gets created. + * + * @param source The mapping source + * @param xContentType the content type of the mapping source + */ + private CreateIndexRequest mapping(BytesReference source, XContentType xContentType) { + Objects.requireNonNull(xContentType); + try { + mappings.put(MapperService.SINGLE_MAPPING_NAME, + XContentHelper.convertToJson(source, false, false, xContentType)); + return this; + } catch (IOException e) { + throw new UncheckedIOException("failed to convert to json", e); + } + } + + /** + * Adds mapping that will be added when the index gets created. + * + * @param source The mapping source + */ + public CreateIndexRequest mapping(XContentBuilder source) { + return mapping(BytesReference.bytes(source), source.contentType()); + } + + /** + * Adds mapping that will be added when the index gets created. + * + * @param source The mapping source + */ + public CreateIndexRequest mapping(Map source) { + try { + XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); + builder.map(source); + return mapping(builder); + } catch (IOException e) { + throw new ElasticsearchGenerationException("Failed to generate [" + source + "]", e); + } + } + + /** + * A specialized simplified mapping source method, takes the form of simple properties definition: + * ("field1", "type=string,store=true"). + */ + public CreateIndexRequest mapping(Object... source) { + mapping(PutMappingRequest.buildFromSimplifiedDef(null, source)); + return this; + } + + /** + * Sets the aliases that will be associated with the index when it gets created + */ + public CreateIndexRequest aliases(Map source) { + try { + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.map(source); + return aliases(BytesReference.bytes(builder)); + } catch (IOException e) { + throw new ElasticsearchGenerationException("Failed to generate [" + source + "]", e); + } + } + + /** + * Sets the aliases that will be associated with the index when it gets created + */ + public CreateIndexRequest aliases(XContentBuilder source) { + return aliases(BytesReference.bytes(source)); + } + + /** + * Sets the aliases that will be associated with the index when it gets created + */ + public CreateIndexRequest aliases(String source) { + return aliases(new BytesArray(source)); + } + + /** + * Sets the aliases that will be associated with the index when it gets created + */ + public CreateIndexRequest aliases(BytesReference source) { + // EMPTY is safe here because we never call namedObject + try (XContentParser parser = XContentHelper + .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, source)) { + //move to the first alias + parser.nextToken(); + while ((parser.nextToken()) != XContentParser.Token.END_OBJECT) { + alias(Alias.fromXContent(parser)); + } + return this; + } catch(IOException e) { + throw new ElasticsearchParseException("Failed to parse aliases", e); + } + } + + /** + * Adds an alias that will be associated with the index when it gets created + */ + public CreateIndexRequest alias(Alias alias) { + this.aliases.add(alias); + return this; + } + + /** + * Sets the settings and mappings as a single source. + */ + public CreateIndexRequest source(String source, XContentType xContentType) { + return source(new BytesArray(source), xContentType); + } + + /** + * Sets the settings and mappings as a single source. + */ + public CreateIndexRequest source(XContentBuilder source) { + return source(BytesReference.bytes(source), source.contentType()); + } + + /** + * Sets the settings and mappings as a single source. + */ + public CreateIndexRequest source(byte[] source, XContentType xContentType) { + return source(source, 0, source.length, xContentType); + } + + /** + * Sets the settings and mappings as a single source. + */ + public CreateIndexRequest source(byte[] source, int offset, int length, XContentType xContentType) { + return source(new BytesArray(source, offset, length), xContentType); + } + + /** + * Sets the settings and mappings as a single source. + */ + public CreateIndexRequest source(BytesReference source, XContentType xContentType) { + Objects.requireNonNull(xContentType); + source(XContentHelper.convertToMap(source, false, xContentType).v2(), LoggingDeprecationHandler.INSTANCE); + return this; + } + + /** + * Sets the settings and mappings as a single source. + */ + @SuppressWarnings("unchecked") + public CreateIndexRequest source(Map source, DeprecationHandler deprecationHandler) { + for (Map.Entry entry : source.entrySet()) { + String name = entry.getKey(); + if (SETTINGS.match(name, deprecationHandler)) { + settings((Map) entry.getValue()); + } else if (MAPPINGS.match(name, deprecationHandler)) { + Map mappings = (Map) entry.getValue(); + mapping(mappings); + } else if (ALIASES.match(name, deprecationHandler)) { + aliases((Map) entry.getValue()); + } + } + return this; + } + + public Map mappings() { + return this.mappings; + } + + public Set aliases() { + return this.aliases; + } + + public ActiveShardCount waitForActiveShards() { + return waitForActiveShards; + } + + /** + * Sets the number of shard copies that should be active for index creation to return. + * Defaults to {@link ActiveShardCount#DEFAULT}, which will wait for one shard copy + * (the primary) to become active. Set this value to {@link ActiveShardCount#ALL} to + * wait for all shards (primary and all replicas) to be active before returning. + * Otherwise, use {@link ActiveShardCount#from(int)} to set this value to any + * non-negative integer, up to the number of copies per shard (number of replicas + 1), + * to wait for the desired amount of shard copies to become active before returning. + * Index creation will only wait up until the timeout value for the number of shard copies + * to be active before returning. Check {@link CreateIndexResponse#isShardsAcknowledged()} to + * determine if the requisite shard copies were all started before returning or timing out. + * + * @param waitForActiveShards number of active shard copies to wait on + */ + public CreateIndexRequest waitForActiveShards(ActiveShardCount waitForActiveShards) { + this.waitForActiveShards = waitForActiveShards; + return this; + } + + /** + * A shortcut for {@link #waitForActiveShards(ActiveShardCount)} where the numerical + * shard count is passed in, instead of having to first call {@link ActiveShardCount#from(int)} + * to get the ActiveShardCount. + */ + public CreateIndexRequest waitForActiveShards(final int waitForActiveShards) { + return waitForActiveShards(ActiveShardCount.from(waitForActiveShards)); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + + builder.startObject(SETTINGS.getPreferredName()); + settings.toXContent(builder, params); + builder.endObject(); + + if (!mappings.isEmpty()) { + String mapping = mappings.get(MapperService.SINGLE_MAPPING_NAME); + try (InputStream stream = new BytesArray(mapping).streamInput()) { + builder.rawField(MAPPINGS.getPreferredName(), stream, XContentType.JSON); + } + } + + builder.startObject(ALIASES.getPreferredName()); + for (Alias alias : aliases) { + alias.toXContent(builder, params); + } + builder.endObject(); + + builder.endObject(); + return builder; + } +} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexResponse.java new file mode 100644 index 0000000000000..9755edd680f53 --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexResponse.java @@ -0,0 +1,74 @@ +/* + * 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.master.ShardsAcknowledgedResponse; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.XContentParser; + +import java.util.Objects; + +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; + +/** + * A response for a create index action. + */ +public class CreateIndexResponse extends ShardsAcknowledgedResponse { + + private static final ParseField INDEX = new ParseField("index"); + private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("create_index", + true, args -> new CreateIndexResponse((boolean) args[0], (boolean) args[1], (String) args[2])); + + static { + declareAcknowledgedAndShardsAcknowledgedFields(PARSER); + PARSER.declareField(constructorArg(), (parser, context) -> parser.textOrNull(), INDEX, ObjectParser.ValueType.STRING_OR_NULL); + } + + private String index; + + public CreateIndexResponse(boolean acknowledged, boolean shardsAcknowledged, String index) { + super(acknowledged, shardsAcknowledged); + this.index = index; + } + + public String index() { + return index; + } + + public static CreateIndexResponse fromXContent(XContentParser parser) { + return PARSER.apply(parser, null); + } + + @Override + public boolean equals(Object o) { + if (super.equals(o)) { + CreateIndexResponse that = (CreateIndexResponse) o; + return Objects.equals(index, that.index); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), index); + } +} diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java index 90799522372dc..97a379aa16a90 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java @@ -24,8 +24,6 @@ import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse; import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; @@ -46,6 +44,8 @@ import org.elasticsearch.client.ccr.ResumeFollowRequest; import org.elasticsearch.client.ccr.UnfollowRequest; import org.elasticsearch.client.core.AcknowledgedResponse; +import org.elasticsearch.client.indices.CreateIndexRequest; +import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.json.JsonXContent; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java index efe94596b81b6..976ae754d335f 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java @@ -21,11 +21,11 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.ingest.PutPipelineRequest; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.support.PlainActionFuture; +import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; 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 f3a2fd2baaa3a..c958334dcc990 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 @@ -33,8 +33,6 @@ import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheResponse; import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.flush.FlushResponse; @@ -71,6 +69,8 @@ import org.elasticsearch.action.support.broadcast.BroadcastResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse; 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.GetIndexTemplatesRequest; import org.elasticsearch.client.indices.IndexTemplatesExistRequest; @@ -93,6 +93,7 @@ import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.rest.RestStatus; +import org.elasticsearch.rest.action.admin.indices.RestCreateIndexAction; import java.io.IOException; import java.util.Arrays; @@ -210,7 +211,7 @@ public void testCreateIndex() throws IOException { mappingBuilder.startObject().startObject("properties").startObject("field"); mappingBuilder.field("type", "text"); mappingBuilder.endObject().endObject().endObject(); - createIndexRequest.mapping(MapperService.SINGLE_MAPPING_NAME, mappingBuilder); + createIndexRequest.mapping(mappingBuilder); CreateIndexResponse createIndexResponse = execute(createIndexRequest, highLevelClient().indices()::create, highLevelClient().indices()::createAsync); @@ -231,6 +232,70 @@ public void testCreateIndex() throws IOException { } } + @SuppressWarnings({"unchecked", "rawtypes"}) + public void testCreateIndexWithTypes() throws IOException { + { + // Create index + String indexName = "plain_index"; + assertFalse(indexExists(indexName)); + + org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest = + new org.elasticsearch.action.admin.indices.create.CreateIndexRequest(indexName); + + org.elasticsearch.action.admin.indices.create.CreateIndexResponse createIndexResponse = execute( + createIndexRequest, + highLevelClient().indices()::create, + highLevelClient().indices()::createAsync, + expectWarnings(RestCreateIndexAction.TYPES_DEPRECATION_MESSAGE)); + assertTrue(createIndexResponse.isAcknowledged()); + + assertTrue(indexExists(indexName)); + } + { + // Create index with mappings, aliases and settings + String indexName = "rich_index"; + assertFalse(indexExists(indexName)); + + org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest = + new org.elasticsearch.action.admin.indices.create.CreateIndexRequest(indexName); + + Alias alias = new Alias("alias_name"); + alias.filter("{\"term\":{\"year\":2016}}"); + alias.routing("1"); + createIndexRequest.alias(alias); + + Settings.Builder settings = Settings.builder(); + settings.put(SETTING_NUMBER_OF_REPLICAS, 2); + createIndexRequest.settings(settings); + + XContentBuilder mappingBuilder = JsonXContent.contentBuilder(); + mappingBuilder.startObject().startObject("properties").startObject("field"); + mappingBuilder.field("type", "text"); + mappingBuilder.endObject().endObject().endObject(); + createIndexRequest.mapping(MapperService.SINGLE_MAPPING_NAME, mappingBuilder); + + org.elasticsearch.action.admin.indices.create.CreateIndexResponse createIndexResponse = execute( + createIndexRequest, + highLevelClient().indices()::create, + highLevelClient().indices()::createAsync, + expectWarnings(RestCreateIndexAction.TYPES_DEPRECATION_MESSAGE)); + assertTrue(createIndexResponse.isAcknowledged()); + + Map getIndexResponse = getAsMap(indexName); + assertEquals("2", XContentMapValues.extractValue(indexName + ".settings.index.number_of_replicas", getIndexResponse)); + + Map aliasData = + (Map)XContentMapValues.extractValue(indexName + ".aliases.alias_name", getIndexResponse); + assertNotNull(aliasData); + assertEquals("1", aliasData.get("index_routing")); + Map filter = (Map) aliasData.get("filter"); + Map term = (Map) filter.get("term"); + assertEquals(2016, term.get("year")); + + assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.properties.field.type", getIndexResponse)); + } + } + public void testGetSettings() throws IOException { String indexName = "get_settings_index"; Settings basicSettings = Settings.builder() @@ -857,7 +922,9 @@ public void testShrink() throws IOException { .put("index.number_of_replicas", 0) .putNull("index.routing.allocation.require._name") .build(); - resizeRequest.setTargetIndex(new CreateIndexRequest("target").settings(targetSettings).alias(new Alias("alias"))); + resizeRequest.setTargetIndex(new org.elasticsearch.action.admin.indices.create.CreateIndexRequest("target") + .settings(targetSettings) + .alias(new Alias("alias"))); ResizeResponse resizeResponse = execute(resizeRequest, highLevelClient().indices()::shrink, highLevelClient().indices()::shrinkAsync); assertTrue(resizeResponse.isAcknowledged()); @@ -880,7 +947,9 @@ public void testSplit() throws IOException { ResizeRequest resizeRequest = new ResizeRequest("target", "source"); resizeRequest.setResizeType(ResizeType.SPLIT); Settings targetSettings = Settings.builder().put("index.number_of_shards", 4).put("index.number_of_replicas", 0).build(); - resizeRequest.setTargetIndex(new CreateIndexRequest("target").settings(targetSettings).alias(new Alias("alias"))); + resizeRequest.setTargetIndex(new org.elasticsearch.action.admin.indices.create.CreateIndexRequest("target") + .settings(targetSettings) + .alias(new Alias("alias"))); ResizeResponse resizeResponse = execute(resizeRequest, highLevelClient().indices()::split, highLevelClient().indices()::splitAsync); assertTrue(resizeResponse.isAcknowledged()); assertTrue(resizeResponse.isShardsAcknowledged()); 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 663c40b17a8b2..6ed740615eeab 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 @@ -32,7 +32,6 @@ import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest; import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest; @@ -52,14 +51,15 @@ import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest; import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest; import org.elasticsearch.action.support.master.AcknowledgedRequest; +import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.GetIndexTemplatesRequest; import org.elasticsearch.client.indices.IndexTemplatesExistRequest; +import org.elasticsearch.client.indices.RandomCreateIndexGenerator; import org.elasticsearch.common.CheckedFunction; import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.util.CollectionUtils; -import org.elasticsearch.index.RandomCreateIndexGenerator; import org.elasticsearch.test.ESTestCase; import org.junit.Assert; @@ -75,7 +75,6 @@ import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static org.elasticsearch.index.RandomCreateIndexGenerator.randomAliases; -import static org.elasticsearch.index.RandomCreateIndexGenerator.randomCreateIndexRequest; import static org.elasticsearch.index.RandomCreateIndexGenerator.randomIndexSettings; import static org.elasticsearch.index.alias.RandomAliasActionsGenerator.randomAliasAction; import static org.elasticsearch.rest.BaseRestHandler.INCLUDE_TYPE_NAME_PARAMETER; @@ -127,7 +126,23 @@ public void testIndicesExistEmptyIndices() { } public void testCreateIndex() throws IOException { - CreateIndexRequest createIndexRequest = randomCreateIndexRequest(); + CreateIndexRequest createIndexRequest = RandomCreateIndexGenerator.randomCreateIndexRequest(); + + Map expectedParams = new HashMap<>(); + RequestConvertersTests.setRandomTimeout(createIndexRequest, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams); + RequestConvertersTests.setRandomMasterTimeout(createIndexRequest, expectedParams); + RequestConvertersTests.setRandomWaitForActiveShards(createIndexRequest::waitForActiveShards, expectedParams); + + Request request = IndicesRequestConverters.createIndex(createIndexRequest); + Assert.assertEquals("/" + createIndexRequest.index(), request.getEndpoint()); + Assert.assertEquals(expectedParams, request.getParameters()); + Assert.assertEquals(HttpPut.METHOD_NAME, request.getMethod()); + RequestConvertersTests.assertToXContentBody(createIndexRequest, request.getEntity()); + } + + public void testCreateIndexWithTypes() throws IOException { + org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest = + org.elasticsearch.index.RandomCreateIndexGenerator.randomCreateIndexRequest(); Map expectedParams = new HashMap<>(); RequestConvertersTests.setRandomTimeout(createIndexRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams); @@ -143,8 +158,8 @@ public void testCreateIndex() throws IOException { } public void testCreateIndexNullIndex() { - ActionRequestValidationException validationException = new CreateIndexRequest(null).validate(); - Assert.assertNotNull(validationException); + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> new CreateIndexRequest(null)); + assertEquals(e.getMessage(), "The index name cannot be null."); } public void testUpdateAliases() throws IOException { @@ -687,7 +702,8 @@ private void resizeTest(ResizeType resizeType, CheckedFunction + request.mapping(// <1> "{\n" + - " \"_doc\": {\n" + - " \"properties\": {\n" + - " \"message\": {\n" + - " \"type\": \"text\"\n" + - " }\n" + + " \"properties\": {\n" + + " \"message\": {\n" + + " \"type\": \"text\"\n" + " }\n" + " }\n" + "}", // <2> @@ -325,7 +324,7 @@ public void testCreateIndex() throws IOException { Map mapping = new HashMap<>(); mapping.put("properties", properties); jsonMap.put("_doc", mapping); - request.mapping("_doc", jsonMap); // <1> + request.mapping(jsonMap); // <1> //end::create-index-mappings-map CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); assertTrue(createIndexResponse.isAcknowledged()); @@ -351,7 +350,7 @@ public void testCreateIndex() throws IOException { builder.endObject(); } builder.endObject(); - request.mapping("_doc", builder); // <1> + request.mapping(builder); // <1> //end::create-index-mappings-xcontent CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); assertTrue(createIndexResponse.isAcknowledged()); @@ -359,7 +358,7 @@ public void testCreateIndex() throws IOException { { request = new CreateIndexRequest("twitter4"); //tag::create-index-mappings-shortcut - request.mapping("_doc", "message", "type=text"); // <1> + request.mapping("message", "type=text"); // <1> //end::create-index-mappings-shortcut CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); assertTrue(createIndexResponse.isAcknowledged()); @@ -371,12 +370,10 @@ public void testCreateIndex() throws IOException { // end::create-index-request-aliases // tag::create-index-request-timeout - request.timeout(TimeValue.timeValueMinutes(2)); // <1> - request.timeout("2m"); // <2> + request.setTimeout(TimeValue.timeValueMinutes(2)); // <1> // end::create-index-request-timeout // tag::create-index-request-masterTimeout - request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1> - request.masterNodeTimeout("1m"); // <2> + request.setMasterTimeout(TimeValue.timeValueMinutes(1)); // <1> // end::create-index-request-masterTimeout // tag::create-index-request-waitForActiveShards request.waitForActiveShards(2); // <1> @@ -1133,7 +1130,7 @@ public void testGetSettings() throws Exception { { Settings settings = Settings.builder().put("number_of_shards", 3).build(); CreateIndexResponse createIndexResponse = client.indices().create( - new CreateIndexRequest("index", settings), RequestOptions.DEFAULT); + new CreateIndexRequest("index").settings(settings), RequestOptions.DEFAULT); assertTrue(createIndexResponse.isAcknowledged()); } @@ -1197,7 +1194,7 @@ public void testGetSettingsWithDefaults() throws Exception { { Settings settings = Settings.builder().put("number_of_shards", 3).build(); CreateIndexResponse createIndexResponse = client.indices().create( - new CreateIndexRequest("index", settings), RequestOptions.DEFAULT); + new CreateIndexRequest("index").settings(settings), RequestOptions.DEFAULT); assertTrue(createIndexResponse.isAcknowledged()); } @@ -1248,9 +1245,11 @@ public void testGetIndex() throws Exception { { Settings settings = Settings.builder().put("number_of_shards", 3).build(); String mappings = "{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}"; + CreateIndexRequest createIndexRequest = new CreateIndexRequest("index") + .settings(settings) + .mapping(mappings, XContentType.JSON); CreateIndexResponse createIndexResponse = client.indices().create( - new CreateIndexRequest("index", settings).mapping("_doc", mappings, XContentType.JSON), - RequestOptions.DEFAULT); + createIndexRequest, RequestOptions.DEFAULT); assertTrue(createIndexResponse.isAcknowledged()); } @@ -2119,7 +2118,7 @@ public void testPutTemplate() throws Exception { { // tag::put-template-request-mappings-json - request.mapping("_doc", // <1> + request.mapping("_doc",// <1> "{\n" + " \"_doc\": {\n" + " \"properties\": {\n" + diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java index eb74421c7a1c6..e1f3d09a1ed34 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java @@ -20,7 +20,6 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.LatchedActionListener; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.get.GetResponse; @@ -33,6 +32,7 @@ import org.elasticsearch.client.MlTestStateCleaner; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.ml.CloseJobRequest; import org.elasticsearch.client.ml.CloseJobResponse; import org.elasticsearch.client.ml.DeleteCalendarEventRequest; @@ -869,7 +869,7 @@ public void testPreviewDatafeed() throws Exception { String datafeedId = job.getId() + "-feed"; String indexName = "preview_data_2"; CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName); - createIndexRequest.mapping("_doc", "timestamp", "type=date", "total", "type=long"); + createIndexRequest.mapping("timestamp", "type=date", "total", "type=long"); highLevelClient().indices().create(createIndexRequest, RequestOptions.DEFAULT); DatafeedConfig datafeed = DatafeedConfig.builder(datafeedId, job.getId()) .setIndices(indexName) @@ -928,7 +928,7 @@ public void testStartDatafeed() throws Exception { String datafeedId = job.getId() + "-feed"; String indexName = "start_data_2"; CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName); - createIndexRequest.mapping("_doc", "timestamp", "type=date", "total", "type=long"); + createIndexRequest.mapping("timestamp", "type=date", "total", "type=long"); highLevelClient().indices().create(createIndexRequest, RequestOptions.DEFAULT); DatafeedConfig datafeed = DatafeedConfig.builder(datafeedId, job.getId()) .setIndices(indexName) @@ -1048,7 +1048,7 @@ public void testGetDatafeedStats() throws Exception { String datafeedId1 = job.getId() + "-feed"; String indexName = "datafeed_stats_data_2"; CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName); - createIndexRequest.mapping("_doc", "timestamp", "type=date", "total", "type=long"); + createIndexRequest.mapping("timestamp", "type=date", "total", "type=long"); highLevelClient().indices().create(createIndexRequest, RequestOptions.DEFAULT); DatafeedConfig datafeed = DatafeedConfig.builder(datafeedId1, job.getId()) .setIndices(indexName) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java index 3a49a13479e87..d97389a104537 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java @@ -23,8 +23,6 @@ import org.apache.lucene.search.TotalHits; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.LatchedActionListener; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.explain.ExplainRequest; @@ -52,6 +50,8 @@ import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.core.CountRequest; import org.elasticsearch.client.core.CountResponse; +import org.elasticsearch.client.indices.CreateIndexRequest; +import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.document.DocumentField; import org.elasticsearch.common.text.Text; @@ -1249,12 +1249,12 @@ public void onFailure(Exception e) { private void indexSearchTestData() throws IOException { CreateIndexRequest authorsRequest = new CreateIndexRequest("authors") - .mapping("_doc", "user", "type=keyword,doc_values=false"); + .mapping("user", "type=keyword,doc_values=false"); CreateIndexResponse authorsResponse = highLevelClient().indices().create(authorsRequest, RequestOptions.DEFAULT); assertTrue(authorsResponse.isAcknowledged()); CreateIndexRequest reviewersRequest = new CreateIndexRequest("contributors") - .mapping("_doc", "user", "type=keyword,store=true"); + .mapping("user", "type=keyword,store=true"); CreateIndexResponse reviewersResponse = highLevelClient().indices().create(reviewersRequest, RequestOptions.DEFAULT); assertTrue(reviewersResponse.isAcknowledged()); @@ -1368,7 +1368,7 @@ public void onFailure(Exception e) { private static void indexCountTestData() throws IOException { CreateIndexRequest authorsRequest = new CreateIndexRequest("author") - .mapping("_doc", "user", "type=keyword,doc_values=false"); + .mapping("user", "type=keyword,doc_values=false"); CreateIndexResponse authorsResponse = highLevelClient().indices().create(authorsRequest, RequestOptions.DEFAULT); assertTrue(authorsResponse.isAcknowledged()); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java index 22ef30c92b78c..d80c24be6618a 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SnapshotClientDocumentationIT.java @@ -38,7 +38,6 @@ import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotStatus; import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusRequest; import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusResponse; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.client.ESRestHighLevelClientTestCase; @@ -46,6 +45,7 @@ import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.Response; import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.cluster.SnapshotsInProgress; import org.elasticsearch.cluster.metadata.RepositoryMetaData; import org.elasticsearch.common.settings.Settings; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CreateIndexRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CreateIndexRequestTests.java new file mode 100644 index 0000000000000..5a168b695d6ce --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CreateIndexRequestTests.java @@ -0,0 +1,99 @@ +/* + * 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.admin.indices.alias.Alias; +import org.elasticsearch.common.xcontent.LoggingDeprecationHandler; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.json.JsonXContent; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; +import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; + +import static org.elasticsearch.client.indices.CreateIndexRequest.ALIASES; +import static org.elasticsearch.client.indices.CreateIndexRequest.MAPPINGS; +import static org.elasticsearch.client.indices.CreateIndexRequest.SETTINGS; + +public class CreateIndexRequestTests extends AbstractXContentTestCase { + + @Override + protected CreateIndexRequest createTestInstance() { + return RandomCreateIndexGenerator.randomCreateIndexRequest(); + } + + @Override + protected CreateIndexRequest doParseInstance(XContentParser parser) throws IOException { + CreateIndexRequest request = new CreateIndexRequest("index"); + request.source(parser.map(), LoggingDeprecationHandler.INSTANCE); + return request; + } + + @Override + protected void assertEqualInstances(CreateIndexRequest expectedInstance, CreateIndexRequest newInstance) { + assertEquals(expectedInstance.settings(), newInstance.settings()); + assertAliasesEqual(expectedInstance.aliases(), newInstance.aliases()); + assertMappingsEqual(expectedInstance.mappings(), newInstance.mappings()); + } + + private void assertMappingsEqual(Map expected, Map actual) { + assertEquals(expected.keySet(), actual.keySet()); + + for (Map.Entry expectedEntry : expected.entrySet()) { + String expectedValue = expectedEntry.getValue(); + String actualValue = actual.get(expectedEntry.getKey()); + try (XContentParser expectedJson = createParser(JsonXContent.jsonXContent, expectedValue); + XContentParser actualJson = createParser(JsonXContent.jsonXContent, actualValue)) { + assertEquals(expectedJson.map(), actualJson.map()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + private void assertAliasesEqual(Set expected, Set actual) { + assertEquals(expected, actual); + + for (Alias expectedAlias : expected) { + for (Alias actualAlias : actual) { + if (expectedAlias.equals(actualAlias)) { + // As Alias#equals only looks at name, we check the equality of the other Alias parameters here. + assertEquals(expectedAlias.filter(), actualAlias.filter()); + assertEquals(expectedAlias.indexRouting(), actualAlias.indexRouting()); + assertEquals(expectedAlias.searchRouting(), actualAlias.searchRouting()); + } + } + } + } + + @Override + protected Predicate getRandomFieldsExcludeFilter() { + return field -> field.startsWith(MAPPINGS.getPreferredName()) + || field.startsWith(SETTINGS.getPreferredName()) + || field.startsWith(ALIASES.getPreferredName()); + } + + @Override + protected boolean supportsUnknownFields() { + return true; + } +} diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/RandomCreateIndexGenerator.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/RandomCreateIndexGenerator.java new file mode 100644 index 0000000000000..d2bfe0773c57e --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/RandomCreateIndexGenerator.java @@ -0,0 +1,150 @@ +/* + * 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.admin.indices.alias.Alias; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; + +import java.io.IOException; + +import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS; +import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS; +import static org.elasticsearch.test.ESTestCase.frequently; +import static org.elasticsearch.test.ESTestCase.randomAlphaOfLength; +import static org.elasticsearch.test.ESTestCase.randomBoolean; +import static org.elasticsearch.test.ESTestCase.randomIntBetween; + +public final class RandomCreateIndexGenerator { + + private RandomCreateIndexGenerator() {} + + /** + * Returns a random {@link CreateIndexRequest}. + * + * Randomizes the index name, the aliases, mappings and settings associated with the + * index. When present, the mappings make no mention of types. + */ + public static CreateIndexRequest randomCreateIndexRequest() { + String index = randomAlphaOfLength(5); + CreateIndexRequest request = new CreateIndexRequest(index); + randomAliases(request); + if (frequently()) { + try { + request.mapping(randomMapping()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + if (randomBoolean()) { + request.settings(randomIndexSettings()); + } + return request; + } + + /** + * Returns a {@link Settings} instance which include random values for + * {@link org.elasticsearch.cluster.metadata.IndexMetaData#SETTING_NUMBER_OF_SHARDS} and + * {@link org.elasticsearch.cluster.metadata.IndexMetaData#SETTING_NUMBER_OF_REPLICAS} + */ + private static Settings randomIndexSettings() { + Settings.Builder builder = Settings.builder(); + + if (randomBoolean()) { + int numberOfShards = randomIntBetween(1, 10); + builder.put(SETTING_NUMBER_OF_SHARDS, numberOfShards); + } + + if (randomBoolean()) { + int numberOfReplicas = randomIntBetween(1, 10); + builder.put(SETTING_NUMBER_OF_REPLICAS, numberOfReplicas); + } + + return builder.build(); + } + + private static XContentBuilder randomMapping() throws IOException { + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.startObject(); + randomMappingFields(builder, true); + builder.endObject(); + return builder; + } + + /** + * Adds random mapping fields to the provided {@link XContentBuilder} + */ + private static void randomMappingFields(XContentBuilder builder, boolean allowObjectField) throws IOException { + builder.startObject("properties"); + + int fieldsNo = randomIntBetween(0, 5); + for (int i = 0; i < fieldsNo; i++) { + builder.startObject(randomAlphaOfLength(5)); + + if (allowObjectField && randomBoolean()) { + randomMappingFields(builder, false); + } else { + builder.field("type", "text"); + } + + builder.endObject(); + } + + builder.endObject(); + } + + /** + * Sets random aliases to the provided {@link CreateIndexRequest} + */ + public static void randomAliases(CreateIndexRequest request) { + int aliasesNo = randomIntBetween(0, 2); + for (int i = 0; i < aliasesNo; i++) { + request.alias(randomAlias()); + } + } + + private static Alias randomAlias() { + Alias alias = new Alias(randomAlphaOfLength(5)); + + if (randomBoolean()) { + if (randomBoolean()) { + alias.routing(randomAlphaOfLength(5)); + } else { + if (randomBoolean()) { + alias.indexRouting(randomAlphaOfLength(5)); + } + if (randomBoolean()) { + alias.searchRouting(randomAlphaOfLength(5)); + } + } + } + + if (randomBoolean()) { + alias.filter("{\"term\":{\"year\":2016}}"); + } + + if (randomBoolean()) { + alias.writeIndex(randomBoolean()); + } + + return alias; + } +} diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponse.java index 79192693620dd..7523772cb64ca 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponse.java @@ -56,7 +56,7 @@ protected static void declareFields(Constructing public CreateIndexResponse() {} - protected CreateIndexResponse(boolean acknowledged, boolean shardsAcknowledged, String index) { + public CreateIndexResponse(boolean acknowledged, boolean shardsAcknowledged, String index) { super(acknowledged, shardsAcknowledged); this.index = index; } diff --git a/test/framework/src/main/java/org/elasticsearch/index/RandomCreateIndexGenerator.java b/test/framework/src/main/java/org/elasticsearch/index/RandomCreateIndexGenerator.java index e88a9f0a38d2c..2c094458f352e 100644 --- a/test/framework/src/main/java/org/elasticsearch/index/RandomCreateIndexGenerator.java +++ b/test/framework/src/main/java/org/elasticsearch/index/RandomCreateIndexGenerator.java @@ -38,8 +38,10 @@ public final class RandomCreateIndexGenerator { private RandomCreateIndexGenerator() {} /** - * Returns a random {@link CreateIndexRequest}. Randomizes the index name, the aliases, - * mappings and settings associated with the index. + * Returns a random {@link CreateIndexRequest}. + * + * Randomizes the index name, the aliases, mappings and settings associated with the + * index. If present, the mapping definition will be nested under a type name. */ public static CreateIndexRequest randomCreateIndexRequest() throws IOException { String index = randomAlphaOfLength(5); From 8519ca2e2dc69fc9c258e27da5ef92994b23dbbf Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Thu, 17 Jan 2019 15:03:57 -0800 Subject: [PATCH 03/12] Remove CreateIndexRequest#mapping(Object... source), as it's not as useful for the HLRC. --- .../client/indices/CreateIndexRequest.java | 9 --- .../client/MachineLearningIT.java | 57 +++++++++++++++++-- .../documentation/CRUDDocumentationIT.java | 18 +++++- .../IndicesClientDocumentationIT.java | 8 --- .../MlClientDocumentationIT.java | 34 ++++++++++- .../documentation/SearchDocumentationIT.java | 28 ++++++++- .../high-level/indices/create_index.asciidoc | 7 --- 7 files changed, 124 insertions(+), 37 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java index 282d6367297e2..7d5b1bc6634b9 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java @@ -200,15 +200,6 @@ public CreateIndexRequest mapping(Map source) { throw new ElasticsearchGenerationException("Failed to generate [" + source + "]", e); } } - - /** - * A specialized simplified mapping source method, takes the form of simple properties definition: - * ("field1", "type=string,store=true"). - */ - public CreateIndexRequest mapping(Object... source) { - mapping(PutMappingRequest.buildFromSimplifiedDef(null, source)); - return this; - } /** * Sets the aliases that will be associated with the index when it gets created diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java index cc5c2ab08b5c0..162fceed9e572 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java @@ -113,6 +113,7 @@ import org.elasticsearch.client.ml.job.stats.JobStats; import org.elasticsearch.client.ml.job.util.PageParams; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.search.SearchHit; @@ -527,7 +528,16 @@ public void testStartDatafeed() throws Exception { // Set up the index and docs CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName); - createIndexRequest.mapping("timestamp", "type=date", "total", "type=long"); + createIndexRequest.mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("timestamp") + .field("type", "date") + .endObject() + .startObject("total") + .field("type", "long") + .endObject() + .endObject() + .endObject()); highLevelClient().indices().create(createIndexRequest, RequestOptions.DEFAULT); BulkRequest bulk = new BulkRequest(); bulk.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE); @@ -601,7 +611,16 @@ public void testStopDatafeed() throws Exception { // Set up the index CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName); - createIndexRequest.mapping("timestamp", "type=date", "total", "type=long"); + createIndexRequest.mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("timestamp") + .field("type", "date") + .endObject() + .startObject("total") + .field("type", "long") + .endObject() + .endObject() + .endObject()); highLevelClient().indices().create(createIndexRequest, RequestOptions.DEFAULT); // create the job and the datafeed @@ -665,7 +684,16 @@ public void testGetDatafeedStats() throws Exception { // Set up the index CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName); - createIndexRequest.mapping("timestamp", "type=date", "total", "type=long"); + createIndexRequest.mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("timestamp") + .field("type", "date") + .endObject() + .startObject("total") + .field("type", "long") + .endObject() + .endObject() + .endObject()); highLevelClient().indices().create(createIndexRequest, RequestOptions.DEFAULT); // create the job and the datafeed @@ -734,7 +762,16 @@ public void testPreviewDatafeed() throws Exception { // Set up the index and docs CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName); - createIndexRequest.mapping("timestamp", "type=date", "total", "type=long"); + createIndexRequest.mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("timestamp") + .field("type", "date") + .endObject() + .startObject("total") + .field("type", "long") + .endObject() + .endObject() + .endObject()); highLevelClient().indices().create(createIndexRequest, RequestOptions.DEFAULT); BulkRequest bulk = new BulkRequest(); bulk.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE); @@ -791,7 +828,17 @@ private String createExpiredData(String jobId) throws Exception { String indexId = jobId + "-data"; // Set up the index and docs CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexId); - createIndexRequest.mapping("timestamp", "type=date,format=epoch_millis", "total", "type=long"); + createIndexRequest.mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("timestamp") + .field("type", "date") + .field("format", "epoch_millis") + .endObject() + .startObject("total") + .field("type", "long") + .endObject() + .endObject() + .endObject()); highLevelClient().indices().create(createIndexRequest, RequestOptions.DEFAULT); BulkRequest bulk = new BulkRequest(); bulk.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CRUDDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CRUDDocumentationIT.java index 2c9c54d072e8b..1cd76e48ffff5 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CRUDDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CRUDDocumentationIT.java @@ -1547,7 +1547,14 @@ public void afterBulk(long executionId, BulkRequest request, // Not entirely sure if _termvectors belongs to CRUD, and in the absence of a better place, will have it here public void testTermVectors() throws Exception { RestHighLevelClient client = highLevelClient(); - CreateIndexRequest authorsRequest = new CreateIndexRequest("authors").mapping("user", "type=keyword"); + CreateIndexRequest authorsRequest = new CreateIndexRequest("authors") + .mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("user") + .field("type", "keyword") + .endObject() + .endObject() + .endObject()); CreateIndexResponse authorsResponse = client.indices().create(authorsRequest, RequestOptions.DEFAULT); assertTrue(authorsResponse.isAcknowledged()); client.index(new IndexRequest("index").id("1").source("user", "kimchy"), RequestOptions.DEFAULT); @@ -1671,7 +1678,14 @@ public void onFailure(Exception e) { // Not entirely sure if _mtermvectors belongs to CRUD, and in the absence of a better place, will have it here public void testMultiTermVectors() throws Exception { RestHighLevelClient client = highLevelClient(); - CreateIndexRequest authorsRequest = new CreateIndexRequest("authors").mapping("user", "type=text"); + CreateIndexRequest authorsRequest = new CreateIndexRequest("authors") + .mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("user") + .field("type", "keyword") + .endObject() + .endObject() + .endObject()); CreateIndexResponse authorsResponse = client.indices().create(authorsRequest, RequestOptions.DEFAULT); assertTrue(authorsResponse.isAcknowledged()); client.index(new IndexRequest("index").id("1").source("user", "kimchy"), RequestOptions.DEFAULT); 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 f108822a683d5..55e727d5f64dc 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 @@ -355,14 +355,6 @@ public void testCreateIndex() throws IOException { CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); assertTrue(createIndexResponse.isAcknowledged()); } - { - request = new CreateIndexRequest("twitter4"); - //tag::create-index-mappings-shortcut - request.mapping("message", "type=text"); // <1> - //end::create-index-mappings-shortcut - CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); - assertTrue(createIndexResponse.isAcknowledged()); - } request = new CreateIndexRequest("twitter5"); // tag::create-index-request-aliases diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java index e1f3d09a1ed34..68881206b487f 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java @@ -139,6 +139,7 @@ import org.elasticsearch.client.ml.job.util.PageParams; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.aggregations.AggregatorFactories; @@ -869,7 +870,16 @@ public void testPreviewDatafeed() throws Exception { String datafeedId = job.getId() + "-feed"; String indexName = "preview_data_2"; CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName); - createIndexRequest.mapping("timestamp", "type=date", "total", "type=long"); + createIndexRequest.mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("timestamp") + .field("type", "date") + .endObject() + .startObject("total") + .field("type", "long") + .endObject() + .endObject() + .endObject()); highLevelClient().indices().create(createIndexRequest, RequestOptions.DEFAULT); DatafeedConfig datafeed = DatafeedConfig.builder(datafeedId, job.getId()) .setIndices(indexName) @@ -928,7 +938,16 @@ public void testStartDatafeed() throws Exception { String datafeedId = job.getId() + "-feed"; String indexName = "start_data_2"; CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName); - createIndexRequest.mapping("timestamp", "type=date", "total", "type=long"); + createIndexRequest.mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("timestamp") + .field("type", "date") + .endObject() + .startObject("total") + .field("type", "long") + .endObject() + .endObject() + .endObject()); highLevelClient().indices().create(createIndexRequest, RequestOptions.DEFAULT); DatafeedConfig datafeed = DatafeedConfig.builder(datafeedId, job.getId()) .setIndices(indexName) @@ -1048,7 +1067,16 @@ public void testGetDatafeedStats() throws Exception { String datafeedId1 = job.getId() + "-feed"; String indexName = "datafeed_stats_data_2"; CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName); - createIndexRequest.mapping("timestamp", "type=date", "total", "type=long"); + createIndexRequest.mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("timestamp") + .field("type", "date") + .endObject() + .startObject("total") + .field("type", "long") + .endObject() + .endObject() + .endObject()); highLevelClient().indices().create(createIndexRequest, RequestOptions.DEFAULT); DatafeedConfig datafeed = DatafeedConfig.builder(datafeedId1, job.getId()) .setIndices(indexName) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java index d97389a104537..ff5deb5cbdfcc 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SearchDocumentationIT.java @@ -57,6 +57,7 @@ import org.elasticsearch.common.text.Text; import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.get.GetResult; import org.elasticsearch.index.query.MatchQueryBuilder; @@ -1249,12 +1250,26 @@ public void onFailure(Exception e) { private void indexSearchTestData() throws IOException { CreateIndexRequest authorsRequest = new CreateIndexRequest("authors") - .mapping("user", "type=keyword,doc_values=false"); + .mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("user") + .field("type", "keyword") + .field("doc_values", "false") + .endObject() + .endObject() + .endObject()); CreateIndexResponse authorsResponse = highLevelClient().indices().create(authorsRequest, RequestOptions.DEFAULT); assertTrue(authorsResponse.isAcknowledged()); CreateIndexRequest reviewersRequest = new CreateIndexRequest("contributors") - .mapping("user", "type=keyword,store=true"); + .mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("user") + .field("type", "keyword") + .field("store", "true") + .endObject() + .endObject() + .endObject()); CreateIndexResponse reviewersResponse = highLevelClient().indices().create(reviewersRequest, RequestOptions.DEFAULT); assertTrue(reviewersResponse.isAcknowledged()); @@ -1368,7 +1383,14 @@ public void onFailure(Exception e) { private static void indexCountTestData() throws IOException { CreateIndexRequest authorsRequest = new CreateIndexRequest("author") - .mapping("user", "type=keyword,doc_values=false"); + .mapping(XContentFactory.jsonBuilder().startObject() + .startObject("properties") + .startObject("user") + .field("type", "keyword") + .field("doc_values", "false") + .endObject() + .endObject() + .endObject()); CreateIndexResponse authorsResponse = highLevelClient().indices().create(authorsRequest, RequestOptions.DEFAULT); assertTrue(authorsResponse.isAcknowledged()); diff --git a/docs/java-rest/high-level/indices/create_index.asciidoc b/docs/java-rest/high-level/indices/create_index.asciidoc index 997b860b2786f..e6352d481ef86 100644 --- a/docs/java-rest/high-level/indices/create_index.asciidoc +++ b/docs/java-rest/high-level/indices/create_index.asciidoc @@ -55,13 +55,6 @@ include-tagged::{doc-tests-file}[{api}-mappings-xcontent] <1> Mapping source provided as an `XContentBuilder` object, the Elasticsearch built-in helpers to generate JSON content -["source","java",subs="attributes,callouts,macros"] --------------------------------------------------- -include-tagged::{doc-tests-file}[{api}-mappings-shortcut] --------------------------------------------------- -<1> Mapping source provided as `Object` key-pairs, which gets converted to -JSON format - ==== Index aliases Aliases can be set at index creation time From 457a69eef915c078ab69716bf6edc06fd1a27b50 Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Thu, 17 Jan 2019 17:33:21 -0800 Subject: [PATCH 04/12] More clean-up in CreateIndexRequest. --- .../client/indices/CreateIndexRequest.java | 97 +++++++++++-------- .../indices/CreateIndexRequestTests.java | 25 +++-- .../test/AbstractXContentTestCase.java | 2 +- 3 files changed, 69 insertions(+), 55 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java index 7d5b1bc6634b9..959a6e3f40c0f 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java @@ -23,7 +23,6 @@ import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.action.IndicesRequest; import org.elasticsearch.action.admin.indices.alias.Alias; -import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.action.support.ActiveShardCount; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.client.TimedRequest; @@ -34,7 +33,6 @@ import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.DeprecationHandler; -import org.elasticsearch.common.xcontent.LoggingDeprecationHandler; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -42,12 +40,9 @@ import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.mapper.MapperService; import java.io.IOException; import java.io.InputStream; -import java.io.UncheckedIOException; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Objects; @@ -65,7 +60,10 @@ public class CreateIndexRequest extends TimedRequest implements Validatable, Ind private final String index; private Settings settings = EMPTY_SETTINGS; - private final Map mappings = new HashMap<>(); + + private BytesReference mappings; + private XContentType mappingsXContentType; + private final Set aliases = new HashSet<>(); private ActiveShardCount waitForActiveShards = ActiveShardCount.DEFAULT; @@ -153,6 +151,8 @@ public CreateIndexRequest settings(Map source) { /** * Adds mapping that will be added when the index gets created. * + * Note that the definition should *not* be nested under a type name. + * * @param source The mapping source * @param xContentType The content type of the source */ @@ -163,22 +163,7 @@ public CreateIndexRequest mapping(String source, XContentType xContentType) { /** * Adds mapping that will be added when the index gets created. * - * @param source The mapping source - * @param xContentType the content type of the mapping source - */ - private CreateIndexRequest mapping(BytesReference source, XContentType xContentType) { - Objects.requireNonNull(xContentType); - try { - mappings.put(MapperService.SINGLE_MAPPING_NAME, - XContentHelper.convertToJson(source, false, false, xContentType)); - return this; - } catch (IOException e) { - throw new UncheckedIOException("failed to convert to json", e); - } - } - - /** - * Adds mapping that will be added when the index gets created. + * Note that the definition should *not* be nested under a type name. * * @param source The mapping source */ @@ -189,18 +174,35 @@ public CreateIndexRequest mapping(XContentBuilder source) { /** * Adds mapping that will be added when the index gets created. * + * Note that the definition should *not* be nested under a type name. + * * @param source The mapping source */ public CreateIndexRequest mapping(Map source) { try { XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); builder.map(source); - return mapping(builder); + return mapping(BytesReference.bytes(builder), builder.contentType()); } catch (IOException e) { throw new ElasticsearchGenerationException("Failed to generate [" + source + "]", e); } } - + + /** + * Adds mapping that will be added when the index gets created. + * + * Note that the definition should *not* be nested under a type name. + * + * @param source The mapping source + * @param xContentType the content type of the mapping source + */ + private CreateIndexRequest mapping(BytesReference source, XContentType xContentType) { + Objects.requireNonNull(xContentType); + mappings = source; + mappingsXContentType = xContentType; + return this; + } + /** * Sets the aliases that will be associated with the index when it gets created */ @@ -208,7 +210,7 @@ public CreateIndexRequest aliases(Map source) { try { XContentBuilder builder = XContentFactory.jsonBuilder(); builder.map(source); - return aliases(BytesReference.bytes(builder)); + return aliases(BytesReference.bytes(builder), builder.contentType()); } catch (IOException e) { throw new ElasticsearchGenerationException("Failed to generate [" + source + "]", e); } @@ -218,23 +220,23 @@ public CreateIndexRequest aliases(Map source) { * Sets the aliases that will be associated with the index when it gets created */ public CreateIndexRequest aliases(XContentBuilder source) { - return aliases(BytesReference.bytes(source)); + return aliases(BytesReference.bytes(source), source.contentType()); } /** * Sets the aliases that will be associated with the index when it gets created */ - public CreateIndexRequest aliases(String source) { - return aliases(new BytesArray(source)); + public CreateIndexRequest aliases(String source, XContentType contentType) { + return aliases(new BytesArray(source), contentType); } /** * Sets the aliases that will be associated with the index when it gets created */ - public CreateIndexRequest aliases(BytesReference source) { + public CreateIndexRequest aliases(BytesReference source, XContentType contentType) { // EMPTY is safe here because we never call namedObject - try (XContentParser parser = XContentHelper - .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, source)) { + try (XContentParser parser = XContentHelper.createParser(NamedXContentRegistry.EMPTY, + DeprecationHandler.THROW_UNSUPPORTED_OPERATION, source, contentType)) { //move to the first alias parser.nextToken(); while ((parser.nextToken()) != XContentParser.Token.END_OBJECT) { @@ -256,6 +258,8 @@ public CreateIndexRequest alias(Alias alias) { /** * Sets the settings and mappings as a single source. + * + * Note that the mapping definition should *not* be nested under a type name. */ public CreateIndexRequest source(String source, XContentType xContentType) { return source(new BytesArray(source), xContentType); @@ -263,6 +267,8 @@ public CreateIndexRequest source(String source, XContentType xContentType) { /** * Sets the settings and mappings as a single source. + * + * Note that the mapping definition should *not* be nested under a type name. */ public CreateIndexRequest source(XContentBuilder source) { return source(BytesReference.bytes(source), source.contentType()); @@ -270,6 +276,8 @@ public CreateIndexRequest source(XContentBuilder source) { /** * Sets the settings and mappings as a single source. + * + * Note that the mapping definition should *not* be nested under a type name. */ public CreateIndexRequest source(byte[] source, XContentType xContentType) { return source(source, 0, source.length, xContentType); @@ -277,6 +285,8 @@ public CreateIndexRequest source(byte[] source, XContentType xContentType) { /** * Sets the settings and mappings as a single source. + * + * Note that the mapping definition should *not* be nested under a type name. */ public CreateIndexRequest source(byte[] source, int offset, int length, XContentType xContentType) { return source(new BytesArray(source, offset, length), xContentType); @@ -284,15 +294,20 @@ public CreateIndexRequest source(byte[] source, int offset, int length, XContent /** * Sets the settings and mappings as a single source. + * + * Note that the mapping definition should *not* be nested under a type name. */ public CreateIndexRequest source(BytesReference source, XContentType xContentType) { Objects.requireNonNull(xContentType); - source(XContentHelper.convertToMap(source, false, xContentType).v2(), LoggingDeprecationHandler.INSTANCE); + source(XContentHelper.convertToMap(source, false, xContentType).v2(), + DeprecationHandler.THROW_UNSUPPORTED_OPERATION); return this; } /** * Sets the settings and mappings as a single source. + * + * Note that the mapping definition should *not* be nested under a type name. */ @SuppressWarnings("unchecked") public CreateIndexRequest source(Map source, DeprecationHandler deprecationHandler) { @@ -301,8 +316,7 @@ public CreateIndexRequest source(Map source, DeprecationHandler depre if (SETTINGS.match(name, deprecationHandler)) { settings((Map) entry.getValue()); } else if (MAPPINGS.match(name, deprecationHandler)) { - Map mappings = (Map) entry.getValue(); - mapping(mappings); + mapping((Map) entry.getValue()); } else if (ALIASES.match(name, deprecationHandler)) { aliases((Map) entry.getValue()); } @@ -310,8 +324,12 @@ public CreateIndexRequest source(Map source, DeprecationHandler depre return this; } - public Map mappings() { - return this.mappings; + public BytesReference mappings() { + return mappings; + } + + public XContentType mappingsXContentType() { + return mappingsXContentType; } public Set aliases() { @@ -358,10 +376,9 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws settings.toXContent(builder, params); builder.endObject(); - if (!mappings.isEmpty()) { - String mapping = mappings.get(MapperService.SINGLE_MAPPING_NAME); - try (InputStream stream = new BytesArray(mapping).streamInput()) { - builder.rawField(MAPPINGS.getPreferredName(), stream, XContentType.JSON); + if (mappings != null) { + try (InputStream stream = mappings.streamInput()) { + builder.rawField(MAPPINGS.getPreferredName(), stream, mappingsXContentType); } } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CreateIndexRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CreateIndexRequestTests.java index 5a168b695d6ce..d1919c14e81b2 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CreateIndexRequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CreateIndexRequestTests.java @@ -22,11 +22,9 @@ import org.elasticsearch.action.admin.indices.alias.Alias; import org.elasticsearch.common.xcontent.LoggingDeprecationHandler; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.test.AbstractXContentTestCase; import java.io.IOException; -import java.util.Map; import java.util.Set; import java.util.function.Predicate; @@ -49,20 +47,19 @@ protected CreateIndexRequest doParseInstance(XContentParser parser) throws IOExc } @Override - protected void assertEqualInstances(CreateIndexRequest expectedInstance, CreateIndexRequest newInstance) { - assertEquals(expectedInstance.settings(), newInstance.settings()); - assertAliasesEqual(expectedInstance.aliases(), newInstance.aliases()); - assertMappingsEqual(expectedInstance.mappings(), newInstance.mappings()); + protected void assertEqualInstances(CreateIndexRequest expected, CreateIndexRequest actual) { + assertEquals(expected.settings(), actual.settings()); + assertAliasesEqual(expected.aliases(), actual.aliases()); + assertMappingsEqual(expected, actual); } - private void assertMappingsEqual(Map expected, Map actual) { - assertEquals(expected.keySet(), actual.keySet()); - - for (Map.Entry expectedEntry : expected.entrySet()) { - String expectedValue = expectedEntry.getValue(); - String actualValue = actual.get(expectedEntry.getKey()); - try (XContentParser expectedJson = createParser(JsonXContent.jsonXContent, expectedValue); - XContentParser actualJson = createParser(JsonXContent.jsonXContent, actualValue)) { + private void assertMappingsEqual(CreateIndexRequest expected, CreateIndexRequest actual) { + if (expected.mappings() == null) { + assertNull(actual.mappings()); + } else { + assertNotNull(actual.mappings()); + try (XContentParser expectedJson = createParser(expected.mappingsXContentType().xContent(), expected.mappings()); + XContentParser actualJson = createParser(actual.mappingsXContentType().xContent(), actual.mappings())) { assertEquals(expectedJson.map(), actualJson.map()); } catch (IOException e) { throw new RuntimeException(e); diff --git a/test/framework/src/main/java/org/elasticsearch/test/AbstractXContentTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/AbstractXContentTestCase.java index 9507c5e12f8c2..136f51bed3c8c 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/AbstractXContentTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/AbstractXContentTestCase.java @@ -19,8 +19,8 @@ package org.elasticsearch.test; -import org.elasticsearch.common.CheckedBiFunction; import org.elasticsearch.common.CheckedBiConsumer; +import org.elasticsearch.common.CheckedBiFunction; import org.elasticsearch.common.CheckedFunction; import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesReference; From 0a6d80591ea02552670a300f2094343c65cd4af5 Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Fri, 18 Jan 2019 10:47:20 -0800 Subject: [PATCH 05/12] Remove the redundant method CreateIndexRequest#waitForActiveShards. --- .../elasticsearch/client/indices/CreateIndexRequest.java | 9 --------- .../documentation/IndicesClientDocumentationIT.java | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java index 959a6e3f40c0f..652f5479859b7 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java @@ -359,15 +359,6 @@ public CreateIndexRequest waitForActiveShards(ActiveShardCount waitForActiveShar return this; } - /** - * A shortcut for {@link #waitForActiveShards(ActiveShardCount)} where the numerical - * shard count is passed in, instead of having to first call {@link ActiveShardCount#from(int)} - * to get the ActiveShardCount. - */ - public CreateIndexRequest waitForActiveShards(final int waitForActiveShards) { - return waitForActiveShards(ActiveShardCount.from(waitForActiveShards)); - } - @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); 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 55e727d5f64dc..8aa8d52062b5a 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 @@ -368,7 +368,7 @@ public void testCreateIndex() throws IOException { request.setMasterTimeout(TimeValue.timeValueMinutes(1)); // <1> // end::create-index-request-masterTimeout // tag::create-index-request-waitForActiveShards - request.waitForActiveShards(2); // <1> + request.waitForActiveShards(ActiveShardCount.from(2)); // <1> request.waitForActiveShards(ActiveShardCount.DEFAULT); // <2> // end::create-index-request-waitForActiveShards { From 6329214c2003e6485224c78dfa11b14c2c179540 Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Fri, 18 Jan 2019 10:48:03 -0800 Subject: [PATCH 06/12] Undo an unintentional change to the server-side CreateIndexResponse. --- .../action/admin/indices/create/CreateIndexResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponse.java index 7523772cb64ca..79192693620dd 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexResponse.java @@ -56,7 +56,7 @@ protected static void declareFields(Constructing public CreateIndexResponse() {} - public CreateIndexResponse(boolean acknowledged, boolean shardsAcknowledged, String index) { + protected CreateIndexResponse(boolean acknowledged, boolean shardsAcknowledged, String index) { super(acknowledged, shardsAcknowledged); this.index = index; } From c9e20dd645d67591cab184bcdd9c49dca7d1c4e6 Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Fri, 18 Jan 2019 12:29:24 -0800 Subject: [PATCH 07/12] Avoid duplicating all logic in RandomCreateIndexGenerator. --- .../client/indices/CreateIndexRequest.java | 9 ++ .../client/IndicesRequestConvertersTests.java | 4 +- .../indices/RandomCreateIndexGenerator.java | 120 ++---------------- 3 files changed, 25 insertions(+), 108 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java index 652f5479859b7..76cd07203505d 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java @@ -43,6 +43,7 @@ import java.io.IOException; import java.io.InputStream; +import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Objects; @@ -256,6 +257,14 @@ public CreateIndexRequest alias(Alias alias) { return this; } + /** + * Adds aliases that will be associated with the index when it gets created + */ + public CreateIndexRequest aliases(Collection aliases) { + this.aliases.addAll(aliases); + return this; + } + /** * Sets the settings and mappings as a single source. * 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 6ed740615eeab..85535dc1b9623 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 @@ -52,9 +52,9 @@ import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest; import org.elasticsearch.action.support.master.AcknowledgedRequest; import org.elasticsearch.client.indices.CreateIndexRequest; +import org.elasticsearch.client.indices.RandomCreateIndexGenerator; import org.elasticsearch.client.indices.GetIndexTemplatesRequest; import org.elasticsearch.client.indices.IndexTemplatesExistRequest; -import org.elasticsearch.client.indices.RandomCreateIndexGenerator; import org.elasticsearch.common.CheckedFunction; import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; @@ -744,7 +744,7 @@ public void testRollover() throws IOException { org.elasticsearch.index.RandomCreateIndexGenerator.randomMapping(type)); } if (ESTestCase.randomBoolean()) { - org.elasticsearch.index.RandomCreateIndexGenerator.randomAliases(rolloverRequest.getCreateIndexRequest()); + randomAliases(rolloverRequest.getCreateIndexRequest()); } if (ESTestCase.randomBoolean()) { rolloverRequest.getCreateIndexRequest().settings( diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/RandomCreateIndexGenerator.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/RandomCreateIndexGenerator.java index d2bfe0773c57e..38028148237bc 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/RandomCreateIndexGenerator.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/RandomCreateIndexGenerator.java @@ -19,23 +19,12 @@ package org.elasticsearch.client.indices; -import org.elasticsearch.action.admin.indices.alias.Alias; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import java.io.IOException; -import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS; -import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS; -import static org.elasticsearch.test.ESTestCase.frequently; -import static org.elasticsearch.test.ESTestCase.randomAlphaOfLength; -import static org.elasticsearch.test.ESTestCase.randomBoolean; -import static org.elasticsearch.test.ESTestCase.randomIntBetween; - -public final class RandomCreateIndexGenerator { - - private RandomCreateIndexGenerator() {} +public class RandomCreateIndexGenerator { /** * Returns a random {@link CreateIndexRequest}. @@ -44,107 +33,26 @@ private RandomCreateIndexGenerator() {} * index. When present, the mappings make no mention of types. */ public static CreateIndexRequest randomCreateIndexRequest() { - String index = randomAlphaOfLength(5); - CreateIndexRequest request = new CreateIndexRequest(index); - randomAliases(request); - if (frequently()) { - try { - request.mapping(randomMapping()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - if (randomBoolean()) { - request.settings(randomIndexSettings()); - } - return request; - } - - /** - * Returns a {@link Settings} instance which include random values for - * {@link org.elasticsearch.cluster.metadata.IndexMetaData#SETTING_NUMBER_OF_SHARDS} and - * {@link org.elasticsearch.cluster.metadata.IndexMetaData#SETTING_NUMBER_OF_REPLICAS} - */ - private static Settings randomIndexSettings() { - Settings.Builder builder = Settings.builder(); - - if (randomBoolean()) { - int numberOfShards = randomIntBetween(1, 10); - builder.put(SETTING_NUMBER_OF_SHARDS, numberOfShards); + try { + // Create a random server request, and copy its contents into the HLRC request. + // Because client requests only accept typeless mappings, we must swap out the + // mapping definition for one that does not contain types. + org.elasticsearch.action.admin.indices.create.CreateIndexRequest serverRequest = + org.elasticsearch.index.RandomCreateIndexGenerator.randomCreateIndexRequest(); + return new CreateIndexRequest(serverRequest.index()) + .settings(serverRequest.settings()) + .aliases(serverRequest.aliases()) + .mapping(randomMapping()); + } catch (IOException e) { + throw new RuntimeException(e); } - - if (randomBoolean()) { - int numberOfReplicas = randomIntBetween(1, 10); - builder.put(SETTING_NUMBER_OF_REPLICAS, numberOfReplicas); - } - - return builder.build(); } private static XContentBuilder randomMapping() throws IOException { XContentBuilder builder = XContentFactory.jsonBuilder(); builder.startObject(); - randomMappingFields(builder, true); + org.elasticsearch.index.RandomCreateIndexGenerator.randomMappingFields(builder, true); builder.endObject(); return builder; } - - /** - * Adds random mapping fields to the provided {@link XContentBuilder} - */ - private static void randomMappingFields(XContentBuilder builder, boolean allowObjectField) throws IOException { - builder.startObject("properties"); - - int fieldsNo = randomIntBetween(0, 5); - for (int i = 0; i < fieldsNo; i++) { - builder.startObject(randomAlphaOfLength(5)); - - if (allowObjectField && randomBoolean()) { - randomMappingFields(builder, false); - } else { - builder.field("type", "text"); - } - - builder.endObject(); - } - - builder.endObject(); - } - - /** - * Sets random aliases to the provided {@link CreateIndexRequest} - */ - public static void randomAliases(CreateIndexRequest request) { - int aliasesNo = randomIntBetween(0, 2); - for (int i = 0; i < aliasesNo; i++) { - request.alias(randomAlias()); - } - } - - private static Alias randomAlias() { - Alias alias = new Alias(randomAlphaOfLength(5)); - - if (randomBoolean()) { - if (randomBoolean()) { - alias.routing(randomAlphaOfLength(5)); - } else { - if (randomBoolean()) { - alias.indexRouting(randomAlphaOfLength(5)); - } - if (randomBoolean()) { - alias.searchRouting(randomAlphaOfLength(5)); - } - } - } - - if (randomBoolean()) { - alias.filter("{\"term\":{\"year\":2016}}"); - } - - if (randomBoolean()) { - alias.writeIndex(randomBoolean()); - } - - return alias; - } } From 49d8e7033f004ebf41f82b5dcc364359c9ef9a5e Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Fri, 18 Jan 2019 18:35:21 -0800 Subject: [PATCH 08/12] Update PutMappingRequestTests to use the client-side RandomCreateIndexGenerator. --- .../client/indices/PutMappingRequestTests.java | 1 - .../client/indices/RandomCreateIndexGenerator.java | 5 ++++- .../index/RandomCreateIndexGenerator.java | 14 -------------- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/PutMappingRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/PutMappingRequestTests.java index 40b38e40b2647..44ca5e9feadbe 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/PutMappingRequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/PutMappingRequestTests.java @@ -21,7 +21,6 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.index.RandomCreateIndexGenerator; import org.elasticsearch.test.AbstractXContentTestCase; import java.io.IOException; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/RandomCreateIndexGenerator.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/RandomCreateIndexGenerator.java index 38028148237bc..179b7e728b620 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/RandomCreateIndexGenerator.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/RandomCreateIndexGenerator.java @@ -48,7 +48,10 @@ public static CreateIndexRequest randomCreateIndexRequest() { } } - private static XContentBuilder randomMapping() throws IOException { + /** + * Creates a random mapping, with no mention of types. + */ + public static XContentBuilder randomMapping() throws IOException { XContentBuilder builder = XContentFactory.jsonBuilder(); builder.startObject(); org.elasticsearch.index.RandomCreateIndexGenerator.randomMappingFields(builder, true); diff --git a/test/framework/src/main/java/org/elasticsearch/index/RandomCreateIndexGenerator.java b/test/framework/src/main/java/org/elasticsearch/index/RandomCreateIndexGenerator.java index 411a4ff717f1e..345ef1f58bcac 100644 --- a/test/framework/src/main/java/org/elasticsearch/index/RandomCreateIndexGenerator.java +++ b/test/framework/src/main/java/org/elasticsearch/index/RandomCreateIndexGenerator.java @@ -80,20 +80,6 @@ public static Settings randomIndexSettings() { return builder.build(); } - - /** - * Creates a random mapping, with no mention of types. - */ - public static XContentBuilder randomMapping() throws IOException { - XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values())); - builder.startObject(); - - randomMappingFields(builder, true); - - builder.endObject(); - return builder; - } - /** * Creates a random mapping, with the mapping definition nested * under the given type name. From 3f266f2f2242e01c9a34ceffab0b6512757727f7 Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Tue, 22 Jan 2019 13:40:53 -0800 Subject: [PATCH 09/12] Undo an accidental change in IndicesClientDocumentationIT. --- .../client/documentation/IndicesClientDocumentationIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f1ed4301aa668..bd88b69a503fd 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 @@ -2096,7 +2096,7 @@ public void testPutTemplate() throws Exception { { // tag::put-template-request-mappings-json - request.mapping("_doc",// <1> + request.mapping("_doc", // <1> "{\n" + " \"_doc\": {\n" + " \"properties\": {\n" + From 455def38bd283b7b2d94397e53aa0c9464846b44 Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Tue, 22 Jan 2019 13:45:18 -0800 Subject: [PATCH 10/12] In the new CreateIndexRequest, avoid extending IndicesRequest. --- .../client/IndicesRequestConverters.java | 6 +++--- .../client/indices/CreateIndexRequest.java | 14 +------------- 2 files changed, 4 insertions(+), 16 deletions(-) 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 76a789fd152f0..fcc4a2f2e1517 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 @@ -97,9 +97,9 @@ static Request closeIndex(CloseIndexRequest closeIndexRequest) { return request; } - static Request createIndex(CreateIndexRequest createIndexRequest) - throws IOException { - String endpoint = RequestConverters.endpoint(createIndexRequest.indices()); + static Request createIndex(CreateIndexRequest createIndexRequest) throws IOException { + String endpoint = new RequestConverters.EndpointBuilder() + .addPathPart(createIndexRequest.index()).build(); Request request = new Request(HttpPut.METHOD_NAME, endpoint); RequestConverters.Params parameters = new RequestConverters.Params(request); diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java index 76cd07203505d..a3779e1bebd53 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java @@ -21,10 +21,8 @@ import org.elasticsearch.ElasticsearchGenerationException; import org.elasticsearch.ElasticsearchParseException; -import org.elasticsearch.action.IndicesRequest; import org.elasticsearch.action.admin.indices.alias.Alias; import org.elasticsearch.action.support.ActiveShardCount; -import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.client.TimedRequest; import org.elasticsearch.client.Validatable; import org.elasticsearch.common.ParseField; @@ -54,7 +52,7 @@ /** * A request to create an index. */ -public class CreateIndexRequest extends TimedRequest implements Validatable, IndicesRequest, ToXContentObject { +public class CreateIndexRequest extends TimedRequest implements Validatable, ToXContentObject { static final ParseField MAPPINGS = new ParseField("mappings"); static final ParseField SETTINGS = new ParseField("settings"); static final ParseField ALIASES = new ParseField("aliases"); @@ -79,16 +77,6 @@ public CreateIndexRequest(String index) { this.index = index; } - @Override - public String[] indices() { - return new String[]{index}; - } - - @Override - public IndicesOptions indicesOptions() { - return IndicesOptions.strictSingleIndexNoExpandForbidClosed(); - } - /** * The name of the index to create. */ From 9c11c6700a2bf75c438383b2cc062f9024e795d1 Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Tue, 22 Jan 2019 14:09:28 -0800 Subject: [PATCH 11/12] Remove some non-critical setters from CreateIndexRequest. --- .../client/indices/CreateIndexRequest.java | 50 ++++++------------- .../indices/CreateIndexRequestTests.java | 5 +- 2 files changed, 17 insertions(+), 38 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java index a3779e1bebd53..f0bff6e6f4307 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indices/CreateIndexRequest.java @@ -137,6 +137,14 @@ public CreateIndexRequest settings(Map source) { return this; } + public BytesReference mappings() { + return mappings; + } + + public XContentType mappingsXContentType() { + return mappingsXContentType; + } + /** * Adds mapping that will be added when the index gets created. * @@ -185,13 +193,17 @@ public CreateIndexRequest mapping(Map source) { * @param source The mapping source * @param xContentType the content type of the mapping source */ - private CreateIndexRequest mapping(BytesReference source, XContentType xContentType) { + public CreateIndexRequest mapping(BytesReference source, XContentType xContentType) { Objects.requireNonNull(xContentType); mappings = source; mappingsXContentType = xContentType; return this; } + public Set aliases() { + return this.aliases; + } + /** * Sets the aliases that will be associated with the index when it gets created */ @@ -271,24 +283,6 @@ public CreateIndexRequest source(XContentBuilder source) { return source(BytesReference.bytes(source), source.contentType()); } - /** - * Sets the settings and mappings as a single source. - * - * Note that the mapping definition should *not* be nested under a type name. - */ - public CreateIndexRequest source(byte[] source, XContentType xContentType) { - return source(source, 0, source.length, xContentType); - } - - /** - * Sets the settings and mappings as a single source. - * - * Note that the mapping definition should *not* be nested under a type name. - */ - public CreateIndexRequest source(byte[] source, int offset, int length, XContentType xContentType) { - return source(new BytesArray(source, offset, length), xContentType); - } - /** * Sets the settings and mappings as a single source. * @@ -296,8 +290,7 @@ public CreateIndexRequest source(byte[] source, int offset, int length, XContent */ public CreateIndexRequest source(BytesReference source, XContentType xContentType) { Objects.requireNonNull(xContentType); - source(XContentHelper.convertToMap(source, false, xContentType).v2(), - DeprecationHandler.THROW_UNSUPPORTED_OPERATION); + source(XContentHelper.convertToMap(source, false, xContentType).v2()); return this; } @@ -307,7 +300,8 @@ public CreateIndexRequest source(BytesReference source, XContentType xContentTyp * Note that the mapping definition should *not* be nested under a type name. */ @SuppressWarnings("unchecked") - public CreateIndexRequest source(Map source, DeprecationHandler deprecationHandler) { + public CreateIndexRequest source(Map source) { + DeprecationHandler deprecationHandler = DeprecationHandler.THROW_UNSUPPORTED_OPERATION; for (Map.Entry entry : source.entrySet()) { String name = entry.getKey(); if (SETTINGS.match(name, deprecationHandler)) { @@ -321,18 +315,6 @@ public CreateIndexRequest source(Map source, DeprecationHandler depre return this; } - public BytesReference mappings() { - return mappings; - } - - public XContentType mappingsXContentType() { - return mappingsXContentType; - } - - public Set aliases() { - return this.aliases; - } - public ActiveShardCount waitForActiveShards() { return waitForActiveShards; } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CreateIndexRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CreateIndexRequestTests.java index d1919c14e81b2..374f024401155 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CreateIndexRequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indices/CreateIndexRequestTests.java @@ -20,7 +20,6 @@ package org.elasticsearch.client.indices; import org.elasticsearch.action.admin.indices.alias.Alias; -import org.elasticsearch.common.xcontent.LoggingDeprecationHandler; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.test.AbstractXContentTestCase; @@ -41,9 +40,7 @@ protected CreateIndexRequest createTestInstance() { @Override protected CreateIndexRequest doParseInstance(XContentParser parser) throws IOException { - CreateIndexRequest request = new CreateIndexRequest("index"); - request.source(parser.map(), LoggingDeprecationHandler.INSTANCE); - return request; + return new CreateIndexRequest("index").source(parser.map()); } @Override From 5ad7b3a93bca6e4ebcfe005d4330924a4f6b3c5a Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Wed, 23 Jan 2019 22:05:37 -0800 Subject: [PATCH 12/12] Fix a merge conflict. --- .../admin/indices/mapping/put/PutMappingRequestTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java index 593cdc60e8a23..53e188e36c9a8 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java @@ -134,7 +134,7 @@ private static PutMappingRequest createTestItem() throws IOException { String type = randomAlphaOfLength(5); request.type(type); - request.source(RandomCreateIndexGenerator.randomMapping()); + request.source(RandomCreateIndexGenerator.randomMapping(type)); return request; }