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 890a44441edec..a024df14bfcf2 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 @@ -113,6 +113,9 @@ static Request createIndex(CreateIndexRequest createIndexRequest) throws IOExcep parameters.withTimeout(createIndexRequest.timeout()); parameters.withMasterTimeout(createIndexRequest.masterNodeTimeout()); parameters.withWaitForActiveShards(createIndexRequest.waitForActiveShards()); + if (createIndexRequest.preferV2Templates() != null) { + parameters.putParam(IndexMetadata.PREFER_V2_TEMPLATES_FLAG, Boolean.toString(createIndexRequest.preferV2Templates())); + } request.addParameters(parameters.asMap()); request.setEntity(RequestConverters.createEntity(createIndexRequest, RequestConverters.REQUEST_BODY_CONTENT_TYPE)); return request; diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java index d0cd3ea5a0091..ccbe33f4b2250 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java @@ -56,6 +56,7 @@ import org.elasticsearch.client.security.RefreshPolicy; import org.elasticsearch.client.tasks.TaskId; import org.elasticsearch.cluster.health.ClusterHealthStatus; +import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Priority; import org.elasticsearch.common.Strings; @@ -131,6 +132,9 @@ static Request bulk(BulkRequest bulkRequest) throws IOException { parameters.withRefreshPolicy(bulkRequest.getRefreshPolicy()); parameters.withPipeline(bulkRequest.pipeline()); parameters.withRouting(bulkRequest.routing()); + if (bulkRequest.preferV2Templates() != null) { + parameters.putParam(IndexMetadata.PREFER_V2_TEMPLATES_FLAG, Boolean.toString(bulkRequest.preferV2Templates())); + } // Bulk API only supports newline delimited JSON or Smile. Before executing // the bulk, we need to check that all requests have the same content-type // and this content-type is supported by the Bulk API. @@ -331,6 +335,9 @@ static Request index(IndexRequest indexRequest) { parameters.withPipeline(indexRequest.getPipeline()); parameters.withRefreshPolicy(indexRequest.getRefreshPolicy()); parameters.withWaitForActiveShards(indexRequest.waitForActiveShards()); + if (indexRequest.preferV2Templates() != null) { + parameters.putParam(IndexMetadata.PREFER_V2_TEMPLATES_FLAG, Boolean.toString(indexRequest.preferV2Templates())); + } BytesRef source = indexRequest.source().toBytesRef(); ContentType contentType = createContentType(indexRequest.getContentType()); @@ -357,6 +364,9 @@ static Request update(UpdateRequest updateRequest) throws IOException { parameters.withRetryOnConflict(updateRequest.retryOnConflict()); parameters.withVersion(updateRequest.version()); parameters.withVersionType(updateRequest.versionType()); + if (updateRequest.preferV2Templates() != null) { + parameters.putParam(IndexMetadata.PREFER_V2_TEMPLATES_FLAG, Boolean.toString(updateRequest.preferV2Templates())); + } // The Java API allows update requests with different content types // set for the partial document and the upsert document. This client 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 1a018591dc770..2e55165b5746d 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 @@ -25,6 +25,7 @@ import org.elasticsearch.action.support.ActiveShardCount; import org.elasticsearch.client.TimedRequest; import org.elasticsearch.client.Validatable; +import org.elasticsearch.common.Nullable; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesArray; @@ -62,6 +63,7 @@ public class CreateIndexRequest extends TimedRequest implements Validatable, ToX private BytesReference mappings; private XContentType mappingsXContentType; + private Boolean preferV2Templates; private final Set aliases = new HashSet<>(); @@ -265,6 +267,16 @@ public CreateIndexRequest aliases(Collection aliases) { return this; } + public CreateIndexRequest preferV2Templates(Boolean preferV2Templates) { + this.preferV2Templates = preferV2Templates; + return this; + } + + @Nullable + public Boolean preferV2Templates() { + return this.preferV2Templates; + } + /** * Sets the settings and mappings as a single source. * diff --git a/docs/reference/api-conventions.asciidoc b/docs/reference/api-conventions.asciidoc index 3921aab0d1354..24ec5621ad578 100644 --- a/docs/reference/api-conventions.asciidoc +++ b/docs/reference/api-conventions.asciidoc @@ -385,6 +385,7 @@ Returns: "settings": { "index.number_of_replicas": "1", "index.number_of_shards": "1", + "index.prefer_v2_templates": "false", "index.creation_date": "1474389951325", "index.uuid": "n6gzFZTgS664GUfx0Xrpjw", "index.version.created": ..., @@ -421,7 +422,8 @@ Returns: "version": { "created": ... }, - "provided_name" : "twitter" + "provided_name" : "twitter", + "prefer_v2_templates": "false" } } } diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/bulk.json b/rest-api-spec/src/main/resources/rest-api-spec/api/bulk.json index 085ff88d0c135..34b4bd9939ad3 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/bulk.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/bulk.json @@ -87,6 +87,10 @@ "pipeline":{ "type":"string", "description":"The pipeline id to preprocess incoming documents with" + }, + "prefer_v2_templates": { + "type": "boolean", + "description": "favor V2 templates instead of V1 templates during automatic index creation" } }, "body":{ diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/create.json b/rest-api-spec/src/main/resources/rest-api-spec/api/create.json index 171f3da44d36d..21eca1bc792be 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/create.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/create.json @@ -90,6 +90,10 @@ "pipeline":{ "type":"string", "description":"The pipeline id to preprocess incoming documents with" + }, + "prefer_v2_templates": { + "type": "boolean", + "description": "favor V2 templates instead of V1 templates during automatic index creation" } }, "body":{ diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/index.json b/rest-api-spec/src/main/resources/rest-api-spec/api/index.json index 34608160c915e..f7fe9ac954001 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/index.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/index.json @@ -92,6 +92,10 @@ "pipeline":{ "type":"string", "description":"The pipeline id to preprocess incoming documents with" + }, + "prefer_v2_templates": { + "type": "boolean", + "description": "favor V2 templates instead of V1 templates during automatic index creation" } }, "body":{ diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/indices.create.json b/rest-api-spec/src/main/resources/rest-api-spec/api/indices.create.json index 922183d628ac6..da34028d87a78 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/indices.create.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/indices.create.json @@ -33,6 +33,10 @@ "master_timeout":{ "type":"time", "description":"Specify timeout for connection to master" + }, + "prefer_v2_templates": { + "type": "boolean", + "description": "favor V2 templates instead of V1 templates during index creation" } }, "body":{ diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/indices.rollover.json b/rest-api-spec/src/main/resources/rest-api-spec/api/indices.rollover.json index fef1f03d1c9a7..0fd311878736f 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/indices.rollover.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/indices.rollover.json @@ -53,6 +53,10 @@ "wait_for_active_shards":{ "type":"string", "description":"Set the number of active shards to wait for on the newly created rollover index before the operation returns." + }, + "prefer_v2_templates": { + "type": "boolean", + "description": "favor V2 templates instead of V1 templates during automatic index creation" } }, "body":{ diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/update.json b/rest-api-spec/src/main/resources/rest-api-spec/api/update.json index 45b6f764387eb..479a9111ac2a6 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/update.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/update.json @@ -99,6 +99,10 @@ "if_primary_term":{ "type":"number", "description":"only perform the update operation if the last operation that has changed the document has the specified primary term" + }, + "prefer_v2_templates": { + "type": "boolean", + "description": "favor V2 templates instead of V1 templates during automatic index creation" } }, "body":{ diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.put_index_template/15_composition.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.put_index_template/15_composition.yml index 0099ec96b2e9d..e2ce42dd8ddf1 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.put_index_template/15_composition.yml +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.put_index_template/15_composition.yml @@ -1,7 +1,7 @@ --- "Component and index template composition": - skip: - version: " - 7.7.99" + version: " - 7.9.99" reason: "index template v2 API unavailable before 7.8" features: allowed_warnings @@ -61,6 +61,7 @@ - do: indices.create: index: bar-baz + prefer_v2_templates: true body: settings: index.priority: 17 @@ -88,7 +89,7 @@ --- "Index template priority": - skip: - version: " - 7.7.99" + version: " - 7.9.99" reason: "index template v2 API unavailable before 7.8" features: allowed_warnings @@ -120,6 +121,7 @@ - do: indices.create: + prefer_v2_templates: true index: bar-baz - do: @@ -131,7 +133,7 @@ --- "Component template only composition": - skip: - version: " - 7.7.99" + version: " - 7.9.99" reason: "index template v2 API unavailable before 7.8" features: allowed_warnings @@ -164,6 +166,7 @@ - do: indices.create: + prefer_v2_templates: true index: bazfoo - do: @@ -176,7 +179,7 @@ --- "Index template without component templates": - skip: - version: " - 7.7.99" + version: " - 7.9.99" reason: "index template v2 API unavailable before 7.8" features: allowed_warnings @@ -193,6 +196,7 @@ - do: indices.create: + prefer_v2_templates: true index: eggplant - do: @@ -200,3 +204,32 @@ index: eggplant - match: {eggplant.settings.index.number_of_shards: "3"} + +--- +"Version 1 templates are preferred if the flag is set": + - skip: + version: " - 7.9.99" + reason: "not backported yet" + features: allowed_warnings + + - do: + allowed_warnings: + - "index template [my-template] has index patterns [eggplant] matching patterns from existing older templates [global] with patterns (global => [*]); this template [my-template] will take precedence during new index creation" + indices.put_index_template: + name: my-template + body: + index_patterns: ["eggplant"] + template: + settings: + number_of_replicas: 2 + + - do: + indices.create: + prefer_v2_templates: false + index: eggplant + + - do: + indices.get: + index: eggplant + + - match: {eggplant.settings.index.number_of_replicas: "1"} diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java index fc035529fb522..5a0af6a975336 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java @@ -25,6 +25,7 @@ import org.elasticsearch.cluster.ack.ClusterStateUpdateRequest; import org.elasticsearch.cluster.block.ClusterBlock; import org.elasticsearch.cluster.metadata.IndexMetadata; +import org.elasticsearch.common.Nullable; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.Index; @@ -42,6 +43,7 @@ public class CreateIndexClusterStateUpdateRequest extends ClusterStateUpdateRequ private Index recoverFrom; private ResizeType resizeType; private boolean copySettings; + private Boolean preferV2Templates; private Settings settings = Settings.Builder.EMPTY_SETTINGS; @@ -94,6 +96,11 @@ public CreateIndexClusterStateUpdateRequest copySettings(final boolean copySetti return this; } + public CreateIndexClusterStateUpdateRequest preferV2Templates(@Nullable Boolean preferV2Templates) { + this.preferV2Templates = preferV2Templates; + return this; + } + public String cause() { return cause; } @@ -145,6 +152,11 @@ public boolean copySettings() { return copySettings; } + @Nullable + public Boolean preferV2Templates() { + return preferV2Templates; + } + @Override public String toString() { return "CreateIndexClusterStateUpdateRequest{" + @@ -158,6 +170,7 @@ public String toString() { ", aliases=" + aliases + ", blocks=" + blocks + ", waitForActiveShards=" + waitForActiveShards + + ", preferV2Templates=" + preferV2Templates + '}'; } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java index 58b65a80b3844..60fc8d300ecdd 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java @@ -29,6 +29,7 @@ import org.elasticsearch.action.support.ActiveShardCount; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.master.AcknowledgedRequest; +import org.elasticsearch.common.Nullable; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesArray; @@ -80,6 +81,8 @@ public class CreateIndexRequest extends AcknowledgedRequest private String mappings = "{}"; + private Boolean preferV2Templates; + private final Set aliases = new HashSet<>(); private ActiveShardCount waitForActiveShards = ActiveShardCount.DEFAULT; @@ -107,6 +110,9 @@ public CreateIndexRequest(StreamInput in) throws IOException { aliases.add(new Alias(in)); } waitForActiveShards = ActiveShardCount.readFrom(in); + if (in.getVersion().onOrAfter(Version.V_8_0_0)) { + preferV2Templates = in.readOptionalBoolean(); + } } public CreateIndexRequest() { @@ -158,6 +164,16 @@ public CreateIndexRequest index(String index) { return this; } + public CreateIndexRequest preferV2Templates(@Nullable Boolean preferV2Templates) { + this.preferV2Templates = preferV2Templates; + return this; + } + + @Nullable + public Boolean preferV2Templates() { + return this.preferV2Templates; + } + /** * The settings to create the index with. */ @@ -468,6 +484,9 @@ public void writeTo(StreamOutput out) throws IOException { alias.writeTo(out); } waitForActiveShards.writeTo(out); + if (out.getVersion().onOrAfter(Version.V_8_0_0)) { + out.writeOptionalBoolean(preferV2Templates); + } } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexAction.java index 690fd5b1ef762..bfa99c768ffa5 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexAction.java @@ -82,6 +82,7 @@ protected void masterOperation(Task task, final CreateIndexRequest request, fina .ackTimeout(request.timeout()).masterNodeTimeout(request.masterNodeTimeout()) .settings(request.settings()).mappings(request.mappings()) .aliases(request.aliases()) + .preferV2Templates(request.preferV2Templates()) .waitForActiveShards(request.waitForActiveShards()); createIndexService.createIndex(updateRequest, ActionListener.map(listener, response -> diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MetadataRolloverService.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MetadataRolloverService.java index c273051ba7c48..f5c3131d7fcbc 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MetadataRolloverService.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MetadataRolloverService.java @@ -138,7 +138,8 @@ static CreateIndexClusterStateUpdateRequest prepareCreateIndexRequest(final Stri .settings(createIndexRequest.settings()) .aliases(createIndexRequest.aliases()) .waitForActiveShards(ActiveShardCount.NONE) // not waiting for shards here, will wait on the alias switch operation - .mappings(createIndexRequest.mappings()); + .mappings(createIndexRequest.mappings()) + .preferV2Templates(createIndexRequest.preferV2Templates()); } /** diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java index a607ea01cca98..1f5e51b5f0e0d 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java @@ -40,6 +40,7 @@ import org.elasticsearch.common.Nullable; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.index.shard.DocsStats; import org.elasticsearch.tasks.Task; @@ -127,6 +128,13 @@ public void onResponse(IndicesStatsResponse statsResponse) { + rolloverIndexName + "]", new ClusterStateUpdateTask() { @Override public ClusterState execute(ClusterState currentState) throws Exception { + // If they haven't explicitly specified whether to use V2 or V1 templates, inherit their preference + // from the existing index (the source index) settings. + if (rolloverRequest.getCreateIndexRequest().preferV2Templates() == null) { + Settings originalIndexSettings = currentState.metadata().index(sourceIndexName).getSettings(); + rolloverRequest.getCreateIndexRequest() + .preferV2Templates(IndexMetadata.PREFER_V2_TEMPLATES_SETTING.get(originalIndexSettings)); + } MetadataRolloverService.RolloverResult rolloverResult = rolloverService.rolloverClusterState(currentState, rolloverRequest.getAlias(), rolloverRequest.getNewIndexName(), rolloverRequest.getCreateIndexRequest(), metConditions, false); diff --git a/server/src/main/java/org/elasticsearch/action/bulk/BulkRequest.java b/server/src/main/java/org/elasticsearch/action/bulk/BulkRequest.java index 9484e1582d93c..9751aee59ba38 100644 --- a/server/src/main/java/org/elasticsearch/action/bulk/BulkRequest.java +++ b/server/src/main/java/org/elasticsearch/action/bulk/BulkRequest.java @@ -19,6 +19,7 @@ package org.elasticsearch.action.bulk; +import org.elasticsearch.Version; import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.action.CompositeIndicesRequest; @@ -73,6 +74,7 @@ public class BulkRequest extends ActionRequest implements CompositeIndicesReques private String globalPipeline; private String globalRouting; private String globalIndex; + private Boolean preferV2Templates; private long sizeInBytes = 0; @@ -87,6 +89,9 @@ public BulkRequest(StreamInput in) throws IOException { } refreshPolicy = RefreshPolicy.readFrom(in); timeout = in.readTimeValue(); + if (in.getVersion().onOrAfter(Version.V_8_0_0)) { + this.preferV2Templates = in.readOptionalBoolean(); + } } public BulkRequest(@Nullable String globalIndex) { @@ -196,6 +201,16 @@ public List> requests() { return this.requests; } + public BulkRequest preferV2Templates(@Nullable Boolean preferV2Templates) { + this.preferV2Templates = preferV2Templates; + return this; + } + + @Nullable + public Boolean preferV2Templates() { + return this.preferV2Templates; + } + /** * The number of actions in the bulk request. */ @@ -356,6 +371,9 @@ public void writeTo(StreamOutput out) throws IOException { } refreshPolicy.writeTo(out); out.writeTimeValue(timeout); + if (out.getVersion().onOrAfter(Version.V_8_0_0)) { + out.writeOptionalBoolean(preferV2Templates); + } } @Override diff --git a/server/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java b/server/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java index ff11617993fde..cfedb5777e790 100644 --- a/server/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java +++ b/server/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java @@ -164,7 +164,9 @@ protected void doExecute(Task task, BulkRequest bulkRequest, ActionListener() { + createIndex(index, bulkRequest.preferV2Templates(), bulkRequest.timeout(), new ActionListener<>() { @Override public void onResponse(CreateIndexResponse result) { if (counter.decrementAndGet() == 0) { @@ -270,7 +272,8 @@ public void onFailure(Exception e) { } } - static boolean resolvePipelines(final DocWriteRequest originalRequest, final IndexRequest indexRequest, final Metadata metadata) { + static boolean resolvePipelines(final DocWriteRequest originalRequest, final IndexRequest indexRequest, + final boolean preferV2Templates, final Metadata metadata) { if (indexRequest.isPipelineResolved() == false) { final String requestPipeline = indexRequest.getPipeline(); indexRequest.setPipeline(IngestService.NOOP_PIPELINE_NAME); @@ -310,7 +313,7 @@ static boolean resolvePipelines(final DocWriteRequest originalRequest, final // templates to look for pipelines in either a matching V2 template (which takes // precedence), or if a V2 template does not match, any V1 templates String v2Template = MetadataIndexTemplateService.findV2Template(metadata, indexRequest.index(), false); - if (v2Template != null) { + if (v2Template != null && preferV2Templates) { Settings settings = MetadataIndexTemplateService.resolveSettings(metadata, v2Template); if (defaultPipeline == null && IndexSettings.DEFAULT_PIPELINE.exists(settings)) { defaultPipeline = IndexSettings.DEFAULT_PIPELINE.get(settings); @@ -378,11 +381,12 @@ boolean shouldAutoCreate(String index, ClusterState state) { return autoCreateIndex.shouldAutoCreate(index, state); } - void createIndex(String index, TimeValue timeout, ActionListener listener) { + void createIndex(String index, Boolean preferV2Templates, TimeValue timeout, ActionListener listener) { CreateIndexRequest createIndexRequest = new CreateIndexRequest(); createIndexRequest.index(index); createIndexRequest.cause("auto(bulk api)"); createIndexRequest.masterNodeTimeout(timeout); + createIndexRequest.preferV2Templates(preferV2Templates); client.admin().indices().create(createIndexRequest, listener); } diff --git a/server/src/main/java/org/elasticsearch/action/bulk/TransportSingleItemBulkWriteAction.java b/server/src/main/java/org/elasticsearch/action/bulk/TransportSingleItemBulkWriteAction.java index c080006b19d77..60f144f5ead68 100644 --- a/server/src/main/java/org/elasticsearch/action/bulk/TransportSingleItemBulkWriteAction.java +++ b/server/src/main/java/org/elasticsearch/action/bulk/TransportSingleItemBulkWriteAction.java @@ -22,6 +22,7 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.DocWriteRequest; import org.elasticsearch.action.DocWriteResponse; +import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; import org.elasticsearch.action.support.WriteRequest; @@ -72,6 +73,9 @@ public static BulkRequest toSingleItemBulkRequest(ReplicatedWriteRequest requ bulkRequest.setRefreshPolicy(request.getRefreshPolicy()); bulkRequest.timeout(request.timeout()); bulkRequest.waitForActiveShards(request.waitForActiveShards()); + if (request instanceof IndexRequest) { + bulkRequest.preferV2Templates(((IndexRequest) request).preferV2Templates()); + } request.setRefreshPolicy(WriteRequest.RefreshPolicy.NONE); return bulkRequest; } diff --git a/server/src/main/java/org/elasticsearch/action/index/IndexRequest.java b/server/src/main/java/org/elasticsearch/action/index/IndexRequest.java index 18db319dc214a..7ee41fe6a1d12 100644 --- a/server/src/main/java/org/elasticsearch/action/index/IndexRequest.java +++ b/server/src/main/java/org/elasticsearch/action/index/IndexRequest.java @@ -114,6 +114,7 @@ public class IndexRequest extends ReplicatedWriteRequest implement private boolean isRetry = false; private long ifSeqNo = UNASSIGNED_SEQ_NO; private long ifPrimaryTerm = UNASSIGNED_PRIMARY_TERM; + private Boolean preferV2Templates; public IndexRequest(StreamInput in) throws IOException { super(in); @@ -143,6 +144,9 @@ public IndexRequest(StreamInput in) throws IOException { } ifSeqNo = in.readZLong(); ifPrimaryTerm = in.readVLong(); + if (in.getVersion().onOrAfter(Version.V_8_0_0)) { + this.preferV2Templates = in.readOptionalBoolean(); + } } public IndexRequest() { @@ -561,6 +565,16 @@ public long ifSeqNo() { return ifSeqNo; } + public IndexRequest preferV2Templates(@Nullable Boolean preferV2Templates) { + this.preferV2Templates = preferV2Templates; + return this; + } + + @Nullable + public Boolean preferV2Templates() { + return this.preferV2Templates; + } + /** * If set, only perform this indexing request if the document was last modification was assigned this primary term. * @@ -642,6 +656,9 @@ public void writeTo(StreamOutput out) throws IOException { } out.writeZLong(ifSeqNo); out.writeVLong(ifPrimaryTerm); + if (out.getVersion().onOrAfter(Version.V_8_0_0)) { + out.writeOptionalBoolean(preferV2Templates); + } } @Override diff --git a/server/src/main/java/org/elasticsearch/action/update/TransportUpdateAction.java b/server/src/main/java/org/elasticsearch/action/update/TransportUpdateAction.java index 012c601003178..4204840d20f32 100644 --- a/server/src/main/java/org/elasticsearch/action/update/TransportUpdateAction.java +++ b/server/src/main/java/org/elasticsearch/action/update/TransportUpdateAction.java @@ -117,8 +117,11 @@ public static void resolveAndValidateRouting(Metadata metadata, String concreteI protected void doExecute(Task task, final UpdateRequest request, final ActionListener listener) { // if we don't have a master, we don't have metadata, that's fine, let it find a master using create index API if (autoCreateIndex.shouldAutoCreate(request.index(), clusterService.state())) { - client.admin().indices().create(new CreateIndexRequest().index(request.index()).cause("auto(update api)") - .masterNodeTimeout(request.timeout()), new ActionListener() { + client.admin().indices().create(new CreateIndexRequest() + .index(request.index()) + .cause("auto(update api)") + .preferV2Templates(request.preferV2Templates()) + .masterNodeTimeout(request.timeout()), new ActionListener() { @Override public void onResponse(CreateIndexResponse result) { innerExecute(task, request, listener); diff --git a/server/src/main/java/org/elasticsearch/action/update/UpdateRequest.java b/server/src/main/java/org/elasticsearch/action/update/UpdateRequest.java index 9847ed74112e9..804f6ff819aeb 100644 --- a/server/src/main/java/org/elasticsearch/action/update/UpdateRequest.java +++ b/server/src/main/java/org/elasticsearch/action/update/UpdateRequest.java @@ -120,6 +120,7 @@ public class UpdateRequest extends InstanceShardOperationRequest private boolean scriptedUpsert = false; private boolean docAsUpsert = false; private boolean detectNoop = true; + private Boolean preferV2Templates; @Nullable private IndexRequest doc; @@ -152,6 +153,9 @@ public UpdateRequest(StreamInput in) throws IOException { ifPrimaryTerm = in.readVLong(); detectNoop = in.readBoolean(); scriptedUpsert = in.readBoolean(); + if (in.getVersion().onOrAfter(Version.V_8_0_0)) { + preferV2Templates = in.readOptionalBoolean(); + } } public UpdateRequest(String index, String id) { @@ -800,6 +804,16 @@ public UpdateRequest scriptedUpsert(boolean scriptedUpsert) { return this; } + @Nullable + public Boolean preferV2Templates() { + return this.preferV2Templates; + } + + public UpdateRequest preferV2Templates(@Nullable Boolean preferV2Templates) { + this.preferV2Templates = preferV2Templates; + return this; + } + @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); @@ -841,6 +855,9 @@ public void writeTo(StreamOutput out) throws IOException { out.writeVLong(ifPrimaryTerm); out.writeBoolean(detectNoop); out.writeBoolean(scriptedUpsert); + if (out.getVersion().onOrAfter(Version.V_8_0_0)) { + out.writeOptionalBoolean(preferV2Templates); + } } @Override diff --git a/server/src/main/java/org/elasticsearch/client/IndicesAdminClient.java b/server/src/main/java/org/elasticsearch/client/IndicesAdminClient.java index 13f28dbbce210..e763ab0a2d0a7 100644 --- a/server/src/main/java/org/elasticsearch/client/IndicesAdminClient.java +++ b/server/src/main/java/org/elasticsearch/client/IndicesAdminClient.java @@ -709,7 +709,7 @@ public interface IndicesAdminClient extends ElasticsearchClient { /** * Swaps the index pointed to by an alias given all provided conditions are satisfied */ - ActionFuture rolloversIndex(RolloverRequest request); + ActionFuture rolloverIndex(RolloverRequest request); /** * Swaps the index pointed to by an alias given all provided conditions are satisfied diff --git a/server/src/main/java/org/elasticsearch/client/support/AbstractClient.java b/server/src/main/java/org/elasticsearch/client/support/AbstractClient.java index 669df02de212b..4598d7fc1b09b 100644 --- a/server/src/main/java/org/elasticsearch/client/support/AbstractClient.java +++ b/server/src/main/java/org/elasticsearch/client/support/AbstractClient.java @@ -1642,7 +1642,7 @@ public RolloverRequestBuilder prepareRolloverIndex(String alias) { } @Override - public ActionFuture rolloversIndex(RolloverRequest request) { + public ActionFuture rolloverIndex(RolloverRequest request) { return execute(RolloverAction.INSTANCE, request); } diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetadata.java b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetadata.java index ecfd6a6311411..09c4e677a1851 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetadata.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetadata.java @@ -247,6 +247,10 @@ public Iterator> settings() { public static final Setting.AffixSetting INDEX_ROUTING_INITIAL_RECOVERY_GROUP_SETTING = Setting.prefixKeySetting("index.routing.allocation.initial_recovery.", key -> Setting.simpleString(key)); // this is only setable internally not a registered setting!! + public static final String PREFER_V2_TEMPLATES_FLAG = "prefer_v2_templates"; + public static final String SETTING_PREFER_V2_TEMPLATES = "index." + PREFER_V2_TEMPLATES_FLAG; + public static final Setting PREFER_V2_TEMPLATES_SETTING = Setting.boolSetting(SETTING_PREFER_V2_TEMPLATES, false, + Property.Dynamic, Property.IndexScope); /** * The number of active shard copies to check for before proceeding with a write operation. @@ -1077,7 +1081,6 @@ private void initializePrimaryTerms() { Arrays.fill(primaryTerms, SequenceNumbers.UNASSIGNED_PRIMARY_TERM); } - public IndexMetadata build() { ImmutableOpenMap.Builder tmpAliases = aliases; Settings tmpSettings = settings; diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java index a3159268c3fce..d059ab537066e 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java @@ -329,14 +329,19 @@ public ClusterState applyCreateIndexRequest(ClusterState currentState, CreateInd // Check to see if a v2 template matched final String v2Template = MetadataIndexTemplateService.findV2Template(currentState.metadata(), request.index(), isHiddenFromRequest == null ? false : isHiddenFromRequest); + final boolean preferV2Templates = resolvePreferV2Templates(request); - if (v2Template != null) { + if (v2Template != null && preferV2Templates) { // If a v2 template was found, it takes precedence over all v1 templates, so create // the index using that template and the request's specified settings return applyCreateIndexRequestWithV2Template(currentState, request, silent, v2Template, metadataTransformer); } else { - // A v2 template wasn't found, check the v1 templates, in the event no templates are - // found creation still works using the request's specified index settings + if (v2Template != null) { + logger.debug("ignoring matching index template [{}] as [prefer_v2_templates] is set to false", v2Template); + } + // A v2 template wasn't found (or is not preferred), check the v1 templates, in the + // event no templates are found creation still works using the request's specified + // index settings final List v1Templates = MetadataIndexTemplateService.findV1Templates(currentState.metadata(), request.index(), isHiddenFromRequest); @@ -345,6 +350,11 @@ public ClusterState applyCreateIndexRequest(ClusterState currentState, CreateInd } } + private static boolean resolvePreferV2Templates(CreateIndexClusterStateUpdateRequest request) { + return request.preferV2Templates() == null ? + IndexMetadata.PREFER_V2_TEMPLATES_SETTING.get(request.settings()) : request.preferV2Templates(); + } + public ClusterState applyCreateIndexRequest(ClusterState currentState, CreateIndexClusterStateUpdateRequest request, boolean silent) throws Exception { return applyCreateIndexRequest(currentState, request, silent, null); @@ -413,7 +423,8 @@ private ClusterState applyCreateIndexWithTemporaryService(final ClusterState cur private IndexMetadata buildAndValidateTemporaryIndexMetadata(final ClusterState currentState, final Settings aggregatedIndexSettings, final CreateIndexClusterStateUpdateRequest request, - final int routingNumShards) { + final int routingNumShards, + final boolean preferV2Templates) { final boolean isHiddenAfterTemplates = IndexMetadata.INDEX_HIDDEN_SETTING.get(aggregatedIndexSettings); validateDotIndex(request.index(), currentState, isHiddenAfterTemplates); @@ -421,6 +432,7 @@ private IndexMetadata buildAndValidateTemporaryIndexMetadata(final ClusterState // remove the setting it's temporary and is only relevant once we create the index final Settings.Builder settingsBuilder = Settings.builder().put(aggregatedIndexSettings); settingsBuilder.remove(IndexMetadata.INDEX_NUMBER_OF_ROUTING_SHARDS_SETTING.getKey()); + settingsBuilder.put(IndexMetadata.PREFER_V2_TEMPLATES_SETTING.getKey(), preferV2Templates); final Settings indexSettings = settingsBuilder.build(); final IndexMetadata.Builder tmpImdBuilder = IndexMetadata.builder(request.index()); @@ -441,7 +453,8 @@ private ClusterState applyCreateIndexRequestWithV1Templates(final ClusterState c final List templates, final BiConsumer metadataTransformer) throws Exception { - logger.info("applying create index request using v1 templates {}", templates); + logger.info("applying create index request using v1 templates {}", + templates.stream().map(IndexTemplateMetadata::name).collect(Collectors.toList())); final Map mappings = Collections.unmodifiableMap(parseMappings(request.mappings(), templates.stream().map(IndexTemplateMetadata::getMappings).collect(toList()), xContentRegistry)); @@ -450,7 +463,8 @@ private ClusterState applyCreateIndexRequestWithV1Templates(final ClusterState c aggregateIndexSettings(currentState, request, MetadataIndexTemplateService.resolveSettings(templates), mappings, null, settings, indexScopedSettings); int routingNumShards = getIndexNumberOfRoutingShards(aggregatedIndexSettings, null); - IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(currentState, aggregatedIndexSettings, request, routingNumShards); + IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(currentState, aggregatedIndexSettings, request, routingNumShards, + resolvePreferV2Templates(request)); return applyCreateIndexWithTemporaryService(currentState, request, silent, null, tmpImd, mappings, indexService -> resolveAndValidateAliases(request.index(), request.aliases(), @@ -477,7 +491,8 @@ private ClusterState applyCreateIndexRequestWithV2Template(final ClusterState cu MetadataIndexTemplateService.resolveSettings(currentState.metadata(), templateName), mappings, null, settings, indexScopedSettings); int routingNumShards = getIndexNumberOfRoutingShards(aggregatedIndexSettings, null); - IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(currentState, aggregatedIndexSettings, request, routingNumShards); + IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(currentState, aggregatedIndexSettings, request, routingNumShards, + resolvePreferV2Templates(request)); return applyCreateIndexWithTemporaryService(currentState, request, silent, null, tmpImd, mappings, indexService -> resolveAndValidateAliases(request.index(), request.aliases(), @@ -501,7 +516,8 @@ private ClusterState applyCreateIndexRequestWithExistingMetadata(final ClusterSt final Settings aggregatedIndexSettings = aggregateIndexSettings(currentState, request, Settings.EMPTY, mappings, sourceMetadata, settings, indexScopedSettings); final int routingNumShards = getIndexNumberOfRoutingShards(aggregatedIndexSettings, sourceMetadata); - IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(currentState, aggregatedIndexSettings, request, routingNumShards); + IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(currentState, aggregatedIndexSettings, request, routingNumShards, + IndexMetadata.PREFER_V2_TEMPLATES_SETTING.get(sourceMetadata.getSettings())); return applyCreateIndexWithTemporaryService(currentState, request, silent, sourceMetadata, tmpImd, mappings, indexService -> resolveAndValidateAliases(request.index(), request.aliases(), Collections.emptyList(), diff --git a/server/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java b/server/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java index 96e5c31c1baa9..0a3bd99b3b4ee 100644 --- a/server/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java +++ b/server/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java @@ -80,6 +80,7 @@ public final class IndexScopedSettings extends AbstractScopedSettings { IndexMetadata.INDEX_DATA_PATH_SETTING, IndexMetadata.INDEX_HIDDEN_SETTING, IndexMetadata.INDEX_FORMAT_SETTING, + IndexMetadata.PREFER_V2_TEMPLATES_SETTING, SearchSlowLog.INDEX_SEARCH_SLOWLOG_THRESHOLD_FETCH_DEBUG_SETTING, SearchSlowLog.INDEX_SEARCH_SLOWLOG_THRESHOLD_FETCH_WARN_SETTING, SearchSlowLog.INDEX_SEARCH_SLOWLOG_THRESHOLD_FETCH_INFO_SETTING, 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 3519fe48f6a8a..1b7b3effb08d9 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 @@ -22,6 +22,8 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.support.ActiveShardCount; import org.elasticsearch.client.node.NodeClient; +import org.elasticsearch.cluster.metadata.IndexMetadata; +import org.elasticsearch.common.Nullable; import org.elasticsearch.common.xcontent.LoggingDeprecationHandler; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.index.mapper.MapperService; @@ -49,10 +51,16 @@ public String getName() { return "create_index_action"; } + @Nullable + public static Boolean preferV2Templates(final RestRequest request) { + return request.paramAsBoolean(IndexMetadata.PREFER_V2_TEMPLATES_FLAG, null); + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { CreateIndexRequest createIndexRequest = new CreateIndexRequest(request.param("index")); + createIndexRequest.preferV2Templates(preferV2Templates(request)); if (request.hasContent()) { Map sourceAsMap = XContentHelper.convertToMap(request.requiredContent(), false, diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRolloverIndexAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRolloverIndexAction.java index ad41baaf99c6a..878343a3109cb 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRolloverIndexAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRolloverIndexAction.java @@ -54,6 +54,7 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC rolloverIndexRequest.masterNodeTimeout(request.paramAsTime("master_timeout", rolloverIndexRequest.masterNodeTimeout())); rolloverIndexRequest.getCreateIndexRequest().waitForActiveShards( ActiveShardCount.parseString(request.param("wait_for_active_shards"))); + rolloverIndexRequest.getCreateIndexRequest().preferV2Templates(RestCreateIndexAction.preferV2Templates(request)); return channel -> client.admin().indices().rolloverIndex(rolloverIndexRequest, new RestToXContentListener<>(channel)); } } diff --git a/server/src/main/java/org/elasticsearch/rest/action/document/RestBulkAction.java b/server/src/main/java/org/elasticsearch/rest/action/document/RestBulkAction.java index ffe21bce355a4..bf35bb1e28dcc 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/document/RestBulkAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/document/RestBulkAction.java @@ -28,6 +28,7 @@ import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.action.RestStatusToXContentListener; +import org.elasticsearch.rest.action.admin.indices.RestCreateIndexAction; import org.elasticsearch.search.fetch.subphase.FetchSourceContext; import java.io.IOException; @@ -82,6 +83,7 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC bulkRequest.setRefreshPolicy(request.param("refresh")); bulkRequest.add(request.requiredContent(), defaultIndex, defaultRouting, defaultFetchSourceContext, defaultPipeline, allowExplicitIndex, request.getXContentType()); + bulkRequest.preferV2Templates(RestCreateIndexAction.preferV2Templates(request)); return channel -> client.bulk(bulkRequest, new RestStatusToXContentListener<>(channel)); } diff --git a/server/src/main/java/org/elasticsearch/rest/action/document/RestIndexAction.java b/server/src/main/java/org/elasticsearch/rest/action/document/RestIndexAction.java index 6c54285d67dad..27d8896678d4b 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/document/RestIndexAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/document/RestIndexAction.java @@ -29,6 +29,7 @@ import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.action.RestActions; import org.elasticsearch.rest.action.RestStatusToXContentListener; +import org.elasticsearch.rest.action.admin.indices.RestCreateIndexAction; import java.io.IOException; import java.util.List; @@ -122,6 +123,7 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC indexRequest.versionType(VersionType.fromString(request.param("version_type"), indexRequest.versionType())); indexRequest.setIfSeqNo(request.paramAsLong("if_seq_no", indexRequest.ifSeqNo())); indexRequest.setIfPrimaryTerm(request.paramAsLong("if_primary_term", indexRequest.ifPrimaryTerm())); + indexRequest.preferV2Templates(RestCreateIndexAction.preferV2Templates(request)); String sOpType = request.param("op_type"); String waitForActiveShards = request.param("wait_for_active_shards"); if (waitForActiveShards != null) { diff --git a/server/src/main/java/org/elasticsearch/rest/action/document/RestUpdateAction.java b/server/src/main/java/org/elasticsearch/rest/action/document/RestUpdateAction.java index af451c02ecc58..facee1a96a817 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/document/RestUpdateAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/document/RestUpdateAction.java @@ -29,6 +29,7 @@ import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.action.RestActions; import org.elasticsearch.rest.action.RestStatusToXContentListener; +import org.elasticsearch.rest.action.admin.indices.RestCreateIndexAction; import org.elasticsearch.search.fetch.subphase.FetchSourceContext; import java.io.IOException; @@ -54,6 +55,7 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC updateRequest.routing(request.param("routing")); updateRequest.timeout(request.paramAsTime("timeout", updateRequest.timeout())); updateRequest.setRefreshPolicy(request.param("refresh")); + updateRequest.preferV2Templates(RestCreateIndexAction.preferV2Templates(request)); String waitForActiveShards = request.param("wait_for_active_shards"); if (waitForActiveShards != null) { updateRequest.waitForActiveShards(ActiveShardCount.parseString(waitForActiveShards)); diff --git a/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionIndicesThatCannotBeCreatedTests.java b/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionIndicesThatCannotBeCreatedTests.java index e287704698532..096b5fca490c7 100644 --- a/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionIndicesThatCannotBeCreatedTests.java +++ b/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionIndicesThatCannotBeCreatedTests.java @@ -137,7 +137,8 @@ boolean shouldAutoCreate(String index, ClusterState state) { } @Override - void createIndex(String index, TimeValue timeout, ActionListener listener) { + void createIndex(String index, Boolean preferV2Templates, + TimeValue timeout, ActionListener listener) { // If we try to create an index just immediately assume it worked listener.onResponse(new CreateIndexResponse(true, true, index) {}); } diff --git a/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionIngestTests.java b/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionIngestTests.java index 154e0c1af26bc..abbae57a0ac9a 100644 --- a/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionIngestTests.java +++ b/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionIngestTests.java @@ -157,7 +157,8 @@ void executeBulk(Task task, final BulkRequest bulkRequest, final long startTimeN } @Override - void createIndex(String index, TimeValue timeout, ActionListener listener) { + void createIndex(String index, Boolean preferV2Templates, + TimeValue timeout, ActionListener listener) { indexCreated = true; listener.onResponse(null); } @@ -590,6 +591,7 @@ public void testFindDefaultPipelineFromV2TemplateMatch() { when(state.getMetadata()).thenReturn(metadata); IndexRequest indexRequest = new IndexRequest("missing_index").id("id"); + indexRequest.preferV2Templates(true); indexRequest.source(Collections.emptyMap()); AtomicBoolean responseCalled = new AtomicBoolean(false); AtomicBoolean failureCalled = new AtomicBoolean(false); diff --git a/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionTests.java b/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionTests.java index 3f3404a9270ae..1d25a18c883b8 100644 --- a/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/bulk/TransportBulkActionTests.java @@ -81,7 +81,8 @@ protected boolean needToCheck() { } @Override - void createIndex(String index, TimeValue timeout, ActionListener listener) { + void createIndex(String index, Boolean preferV2Templates, + TimeValue timeout, ActionListener listener) { indexCreated = true; listener.onResponse(null); } @@ -175,14 +176,14 @@ public void testResolveRequiredOrDefaultPipelineDefaultPipeline() { // index name matches with IDM: IndexRequest indexRequest = new IndexRequest("idx"); - boolean result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, metadata); + boolean result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, false, metadata); assertThat(result, is(true)); assertThat(indexRequest.isPipelineResolved(), is(true)); assertThat(indexRequest.getPipeline(), equalTo("default-pipeline")); // alias name matches with IDM: indexRequest = new IndexRequest("alias"); - result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, metadata); + result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, false, metadata); assertThat(result, is(true)); assertThat(indexRequest.isPipelineResolved(), is(true)); assertThat(indexRequest.getPipeline(), equalTo("default-pipeline")); @@ -193,7 +194,7 @@ public void testResolveRequiredOrDefaultPipelineDefaultPipeline() { .settings(settings(Version.CURRENT).put(IndexSettings.DEFAULT_PIPELINE.getKey(), "default-pipeline")); metadata = Metadata.builder().put(templateBuilder).build(); indexRequest = new IndexRequest("idx"); - result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, metadata); + result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, false, metadata); assertThat(result, is(true)); assertThat(indexRequest.isPipelineResolved(), is(true)); assertThat(indexRequest.getPipeline(), equalTo("default-pipeline")); @@ -209,7 +210,7 @@ public void testResolveFinalPipeline() { // index name matches with IDM: IndexRequest indexRequest = new IndexRequest("idx"); - boolean result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, metadata); + boolean result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, false, metadata); assertThat(result, is(true)); assertThat(indexRequest.isPipelineResolved(), is(true)); assertThat(indexRequest.getPipeline(), equalTo("_none")); @@ -217,7 +218,7 @@ public void testResolveFinalPipeline() { // alias name matches with IDM: indexRequest = new IndexRequest("alias"); - result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, metadata); + result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, false, metadata); assertThat(result, is(true)); assertThat(indexRequest.isPipelineResolved(), is(true)); assertThat(indexRequest.getPipeline(), equalTo("_none")); @@ -229,7 +230,7 @@ public void testResolveFinalPipeline() { .settings(settings(Version.CURRENT).put(IndexSettings.FINAL_PIPELINE.getKey(), "final-pipeline")); metadata = Metadata.builder().put(templateBuilder).build(); indexRequest = new IndexRequest("idx"); - result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, metadata); + result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, false, metadata); assertThat(result, is(true)); assertThat(indexRequest.isPipelineResolved(), is(true)); assertThat(indexRequest.getPipeline(), equalTo("_none")); @@ -241,7 +242,7 @@ public void testResolveRequestOrDefaultPipelineAndFinalPipeline() { { Metadata metadata = Metadata.builder().build(); IndexRequest indexRequest = new IndexRequest("idx"); - boolean result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, metadata); + boolean result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, false, metadata); assertThat(result, is(false)); assertThat(indexRequest.isPipelineResolved(), is(true)); assertThat(indexRequest.getPipeline(), equalTo(IngestService.NOOP_PIPELINE_NAME)); @@ -251,7 +252,7 @@ public void testResolveRequestOrDefaultPipelineAndFinalPipeline() { { Metadata metadata = Metadata.builder().build(); IndexRequest indexRequest = new IndexRequest("idx").setPipeline("request-pipeline"); - boolean result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, metadata); + boolean result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, false, metadata); assertThat(result, is(true)); assertThat(indexRequest.isPipelineResolved(), is(true)); assertThat(indexRequest.getPipeline(), equalTo("request-pipeline")); @@ -265,7 +266,7 @@ public void testResolveRequestOrDefaultPipelineAndFinalPipeline() { .numberOfReplicas(0); Metadata metadata = Metadata.builder().put(builder).build(); IndexRequest indexRequest = new IndexRequest("idx").setPipeline("request-pipeline"); - boolean result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, metadata); + boolean result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, false, metadata); assertThat(result, is(true)); assertThat(indexRequest.isPipelineResolved(), is(true)); assertThat(indexRequest.getPipeline(), equalTo("request-pipeline")); @@ -279,7 +280,7 @@ public void testResolveRequestOrDefaultPipelineAndFinalPipeline() { .numberOfReplicas(0); Metadata metadata = Metadata.builder().put(builder).build(); IndexRequest indexRequest = new IndexRequest("idx").setPipeline("request-pipeline"); - boolean result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, metadata); + boolean result = TransportBulkAction.resolvePipelines(indexRequest, indexRequest, false, metadata); assertThat(result, is(true)); assertThat(indexRequest.isPipelineResolved(), is(true)); assertThat(indexRequest.getPipeline(), equalTo("request-pipeline")); diff --git a/server/src/test/java/org/elasticsearch/indices/template/TemplatePreferenceIT.java b/server/src/test/java/org/elasticsearch/indices/template/TemplatePreferenceIT.java new file mode 100644 index 0000000000000..c978a348b5926 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/indices/template/TemplatePreferenceIT.java @@ -0,0 +1,251 @@ +/* + * 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.indices.template; + +import org.elasticsearch.action.admin.indices.alias.Alias; +import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; +import org.elasticsearch.action.admin.indices.rollover.RolloverRequest; +import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse; +import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateV2Action; +import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateV2Action; +import org.elasticsearch.action.bulk.BulkRequest; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.update.UpdateRequest; +import org.elasticsearch.cluster.metadata.IndexTemplateV2; +import org.elasticsearch.cluster.metadata.Template; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.test.ESSingleNodeTestCase; +import org.junit.After; +import org.junit.Before; + +import java.util.Collections; + +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; +import static org.hamcrest.Matchers.equalTo; + +public class TemplatePreferenceIT extends ESSingleNodeTestCase { + + private static final String INDEX = "index"; + + @Before + public void setup() throws Exception { + assertAcked(client().admin().indices().preparePutTemplate("v1") + .setSettings(Settings.builder() + .put("index.priority", 15) + .build()) + .setPatterns(Collections.singletonList(INDEX + "*")).get()); + + Template v2Settings = new Template(Settings.builder() + .put("index.priority", 23) + .build(), null, null); + IndexTemplateV2 v2template = new IndexTemplateV2(Collections.singletonList(INDEX + "*"), v2Settings, null, null, null, null); + PutIndexTemplateV2Action.Request request = new PutIndexTemplateV2Action.Request("v2"); + request.indexTemplate(v2template); + assertAcked(client().execute(PutIndexTemplateV2Action.INSTANCE, request).get()); + } + + @After + public void cleanup() throws Exception { + assertAcked(client().admin().indices().prepareDeleteTemplate("v1").get()); + assertAcked(client().execute(DeleteIndexTemplateV2Action.INSTANCE, new DeleteIndexTemplateV2Action.Request("v2")).get()); + } + + public void testCreateIndexPreference() throws Exception { + client().admin().indices().prepareCreate(INDEX).get(); + assertUsedV1(); + + client().admin().indices().create(new CreateIndexRequest(INDEX).preferV2Templates(false)).get(); + assertUsedV1(); + + client().admin().indices().create(new CreateIndexRequest(INDEX).preferV2Templates(true)).get(); + assertUsedV2(); + } + + public void testIndexingRequestPreference() throws Exception { + client().index(new IndexRequest(INDEX).source("foo", "bar")).get(); + assertUsedV1(); + + client().index(new IndexRequest(INDEX).source("foo", "bar").preferV2Templates(false)).get(); + assertUsedV1(); + + client().index(new IndexRequest(INDEX).source("foo", "bar").preferV2Templates(true)).get(); + assertUsedV2(); + + client().update(new UpdateRequest(INDEX, "1").doc("foo", "bar").docAsUpsert(true)).get(); + assertUsedV1(); + + client().update(new UpdateRequest(INDEX, "1").doc("foo", "bar").docAsUpsert(true).preferV2Templates(false)).get(); + assertUsedV1(); + + client().update(new UpdateRequest(INDEX, "1").doc("foo", "bar").docAsUpsert(true).preferV2Templates(true)).get(); + assertUsedV2(); + + client().bulk(new BulkRequest(INDEX).add(new IndexRequest(INDEX).source("foo", "bar"))).get(); + assertUsedV1(); + + client().bulk(new BulkRequest(INDEX).add(new IndexRequest(INDEX).source("foo", "bar")).preferV2Templates(false)).get(); + assertUsedV1(); + + client().bulk(new BulkRequest(INDEX).add(new IndexRequest(INDEX).source("foo", "bar")).preferV2Templates(true)).get(); + assertUsedV2(); + } + + public void testRolloverMaintainsSetting() throws Exception { + { + client().admin().indices().prepareCreate(INDEX + "-1") + .addAlias(new Alias("alias").writeIndex(true)) + .get(); + + client().admin().indices().prepareRolloverIndex("alias").get(); + GetSettingsResponse resp = client().admin().indices().prepareGetSettings().setIndices(INDEX + "-000002").get(); + assertThat("expected index to use V1 template and have priority of 15", + resp.getSetting(INDEX + "-000002", "index.priority"), equalTo("15")); + client().admin().indices().prepareDelete(INDEX + "*").get(); + } + + { + client().admin().indices().prepareCreate(INDEX + "-1") + .addAlias(new Alias("alias").writeIndex(true)) + .get(); + + RolloverRequest request = new RolloverRequest("alias", INDEX + "-000002"); + request.getCreateIndexRequest().preferV2Templates(false); + client().admin().indices().rolloverIndex(request).get(); + GetSettingsResponse resp = client().admin().indices().prepareGetSettings().setIndices(INDEX + "-000002").get(); + assertThat("expected index to use V1 template and have priority of 15", + resp.getSetting(INDEX + "-000002", "index.priority"), equalTo("15")); + client().admin().indices().prepareDelete(INDEX + "*").get(); + } + + { + client().admin().indices().prepareCreate(INDEX + "-1") + .addAlias(new Alias("alias").writeIndex(true)) + .get(); + + RolloverRequest request = new RolloverRequest("alias", INDEX + "-000002"); + request.getCreateIndexRequest().preferV2Templates(true); + client().admin().indices().rolloverIndex(request).get(); + GetSettingsResponse resp = client().admin().indices().prepareGetSettings().setIndices(INDEX + "-000002").get(); + assertThat("expected index to use V2 template and have priority of 23", + resp.getSetting(INDEX + "-000002", "index.priority"), equalTo("23")); + client().admin().indices().prepareDelete(INDEX + "*").get(); + } + + { + client().admin().indices().create(new CreateIndexRequest(INDEX + "-1") + .alias(new Alias("alias").writeIndex(true)) + .preferV2Templates(false)) + .get(); + + client().admin().indices().prepareRolloverIndex("alias").get(); + GetSettingsResponse resp = client().admin().indices().prepareGetSettings().setIndices(INDEX + "-000002").get(); + assertThat("expected index to use V1 template and have priority of 15", + resp.getSetting(INDEX + "-000002", "index.priority"), equalTo("15")); + client().admin().indices().prepareDelete(INDEX + "*").get(); + } + + { + client().admin().indices().create(new CreateIndexRequest(INDEX + "-1") + .alias(new Alias("alias").writeIndex(true)) + .preferV2Templates(false)) + .get(); + + RolloverRequest request = new RolloverRequest("alias", INDEX + "-000002"); + request.getCreateIndexRequest().preferV2Templates(false); + client().admin().indices().rolloverIndex(request).get(); + GetSettingsResponse resp = client().admin().indices().prepareGetSettings().setIndices(INDEX + "-000002").get(); + assertThat("expected index to use V1 template and have priority of 15", + resp.getSetting(INDEX + "-000002", "index.priority"), equalTo("15")); + client().admin().indices().prepareDelete(INDEX + "*").get(); + } + + { + client().admin().indices().create(new CreateIndexRequest(INDEX + "-1") + .alias(new Alias("alias").writeIndex(true)) + .preferV2Templates(false)) + .get(); + + RolloverRequest request = new RolloverRequest("alias", INDEX + "-000002"); + request.getCreateIndexRequest().preferV2Templates(true); + client().admin().indices().rolloverIndex(request).get(); + GetSettingsResponse resp = client().admin().indices().prepareGetSettings().setIndices(INDEX + "-000002").get(); + assertThat("expected index to use V2 template and have priority of 23", + resp.getSetting(INDEX + "-000002", "index.priority"), equalTo("23")); + client().admin().indices().prepareDelete(INDEX + "*").get(); + } + + { + client().admin().indices().create(new CreateIndexRequest(INDEX + "-1") + .alias(new Alias("alias").writeIndex(true)) + .preferV2Templates(true)) + .get(); + + client().admin().indices().prepareRolloverIndex("alias").get(); + GetSettingsResponse resp = client().admin().indices().prepareGetSettings().setIndices(INDEX + "-000002").get(); + assertThat("expected index to use V2 template and have priority of 23", + resp.getSetting(INDEX + "-000002", "index.priority"), equalTo("23")); + client().admin().indices().prepareDelete(INDEX + "*").get(); + } + + { + client().admin().indices().create(new CreateIndexRequest(INDEX + "-1") + .alias(new Alias("alias").writeIndex(true)) + .preferV2Templates(true)) + .get(); + + RolloverRequest request = new RolloverRequest("alias", INDEX + "-000002"); + request.getCreateIndexRequest().preferV2Templates(false); + client().admin().indices().rolloverIndex(request).get(); + GetSettingsResponse resp = client().admin().indices().prepareGetSettings().setIndices(INDEX + "-000002").get(); + assertThat("expected index to use V1 template and have priority of 15", + resp.getSetting(INDEX + "-000002", "index.priority"), equalTo("15")); + client().admin().indices().prepareDelete(INDEX + "*").get(); + } + + { + client().admin().indices().create(new CreateIndexRequest(INDEX + "-1") + .alias(new Alias("alias").writeIndex(true)) + .preferV2Templates(true)) + .get(); + + RolloverRequest request = new RolloverRequest("alias", INDEX + "-000002"); + request.getCreateIndexRequest().preferV2Templates(true); + client().admin().indices().rolloverIndex(request).get(); + GetSettingsResponse resp = client().admin().indices().prepareGetSettings().setIndices(INDEX + "-000002").get(); + assertThat("expected index to use V2 template and have priority of 23", + resp.getSetting(INDEX + "-000002", "index.priority"), equalTo("23")); + client().admin().indices().prepareDelete(INDEX + "*").get(); + } + } + + private void assertUsedV1() { + GetSettingsResponse resp = client().admin().indices().prepareGetSettings().setIndices(INDEX).get(); + assertThat("expected index to use V1 template and have priority of 15", + resp.getSetting(INDEX, "index.priority"), equalTo("15")); + client().admin().indices().prepareDelete(INDEX).get(); + } + + private void assertUsedV2() { + GetSettingsResponse resp = client().admin().indices().prepareGetSettings().setIndices(INDEX).get(); + assertThat("expected index to use V2 template and have priority of 23", + resp.getSetting(INDEX, "index.priority"), equalTo("23")); + client().admin().indices().prepareDelete(INDEX).get(); + } +} diff --git a/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportResumeFollowAction.java b/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportResumeFollowAction.java index 0bf78fd9bca36..1ad13b4209b0c 100644 --- a/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportResumeFollowAction.java +++ b/x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportResumeFollowAction.java @@ -365,6 +365,7 @@ static String[] extractLeaderShardHistoryUUIDs(Map ccrIndexMetad IndexMetadata.INDEX_PRIORITY_SETTING, IndexMetadata.SETTING_WAIT_FOR_ACTIVE_SHARDS, IndexMetadata.INDEX_HIDDEN_SETTING, + IndexMetadata.PREFER_V2_TEMPLATES_SETTING, EnableAllocationDecider.INDEX_ROUTING_REBALANCE_ENABLE_SETTING, EnableAllocationDecider.INDEX_ROUTING_ALLOCATION_ENABLE_SETTING, ShardsLimitAllocationDecider.INDEX_TOTAL_SHARDS_PER_NODE_SETTING,