Skip to content

Add request parameter to block index auto creation #34737

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ static Request delete(DeleteRequest deleteRequest) {
parameters.withVersionType(deleteRequest.versionType());
parameters.withRefreshPolicy(deleteRequest.getRefreshPolicy());
parameters.withWaitForActiveShards(deleteRequest.waitForActiveShards());
if (deleteRequest.isAutoCreateIndexIfPermitted() == false) {
parameters.putParam("auto_create_index", Boolean.toString(deleteRequest.isAutoCreateIndexIfPermitted()));
}
return request;
}

Expand Down Expand Up @@ -201,6 +204,9 @@ static Request bulk(BulkRequest bulkRequest) throws IOException {
metadata.field("_source", updateRequest.fetchSource());
}
}
if (action.isAutoCreateIndexIfPermitted() == false) {
metadata.field("auto_create_index", Boolean.toString(action.isAutoCreateIndexIfPermitted()));
}
metadata.endObject();
}
metadata.endObject();
Expand Down Expand Up @@ -304,6 +310,9 @@ static Request index(IndexRequest indexRequest) {
parameters.withPipeline(indexRequest.getPipeline());
parameters.withRefreshPolicy(indexRequest.getRefreshPolicy());
parameters.withWaitForActiveShards(indexRequest.waitForActiveShards());
if (indexRequest.isAutoCreateIndexIfPermitted() == false) {
parameters.putParam("auto_create_index", Boolean.toString(indexRequest.isAutoCreateIndexIfPermitted()));
}

BytesRef source = indexRequest.source().toBytesRef();
ContentType contentType = createContentType(indexRequest.getContentType());
Expand All @@ -329,6 +338,9 @@ static Request update(UpdateRequest updateRequest) throws IOException {
parameters.withRetryOnConflict(updateRequest.retryOnConflict());
parameters.withVersion(updateRequest.version());
parameters.withVersionType(updateRequest.versionType());
if (updateRequest.isAutoCreateIndexIfPermitted() == false) {
parameters.putParam("auto_create_index", Boolean.toString(updateRequest.isAutoCreateIndexIfPermitted()));
}

// The Java API allows update requests with different content types
// set for the partial document and the upsert document. This client
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ public void testIndex() throws IOException {

setRandomTimeout(indexRequest::timeout, ReplicationRequest.DEFAULT_TIMEOUT, expectedParams);
setRandomRefreshPolicy(indexRequest::setRefreshPolicy, expectedParams);
setRandomlyDisableAutoCreateIndex(indexRequest::setAutoCreateIndexIfPermitted, expectedParams);

// There is some logic around _create endpoint and version/version type
if (indexRequest.opType() == DocWriteRequest.OpType.CREATE) {
Expand Down Expand Up @@ -642,6 +643,7 @@ public void testUpdate() throws IOException {
if (randomBoolean()) {
randomizeFetchSourceContextParams(updateRequest::fetchSource, expectedParams);
}
setRandomlyDisableAutoCreateIndex(updateRequest::setAutoCreateIndexIfPermitted, expectedParams);

Request request = RequestConverters.update(updateRequest);
assertEquals("/" + index + "/" + type + "/" + id + "/_update", request.getEndpoint());
Expand Down Expand Up @@ -711,18 +713,23 @@ public void testBulk() throws IOException {
BytesReference source = RandomObjects.randomSource(random(), xContentType);
DocWriteRequest.OpType opType = randomFrom(DocWriteRequest.OpType.values());

final boolean autoCreateIndex = randomBoolean();

DocWriteRequest<?> docWriteRequest;
if (opType == DocWriteRequest.OpType.INDEX) {
IndexRequest indexRequest = new IndexRequest(index, type, id).source(source, xContentType);
indexRequest.setAutoCreateIndexIfPermitted(autoCreateIndex);
docWriteRequest = indexRequest;
if (randomBoolean()) {
indexRequest.setPipeline(randomAlphaOfLength(5));
}
} else if (opType == DocWriteRequest.OpType.CREATE) {
IndexRequest createRequest = new IndexRequest(index, type, id).source(source, xContentType).create(true);
createRequest.setAutoCreateIndexIfPermitted(autoCreateIndex);
docWriteRequest = createRequest;
} else if (opType == DocWriteRequest.OpType.UPDATE) {
final UpdateRequest updateRequest = new UpdateRequest(index, type, id).doc(new IndexRequest().source(source, xContentType));
final UpdateRequest updateRequest = new UpdateRequest(index, type, id).doc(new IndexRequest()
.source(source, xContentType)).autoCreateIndexIfPermitted(autoCreateIndex);
docWriteRequest = updateRequest;
if (randomBoolean()) {
updateRequest.retryOnConflict(randomIntBetween(1, 5));
Expand All @@ -731,7 +738,8 @@ public void testBulk() throws IOException {
randomizeFetchSourceContextParams(updateRequest::fetchSource, new HashMap<>());
}
} else if (opType == DocWriteRequest.OpType.DELETE) {
docWriteRequest = new DeleteRequest(index, type, id);
docWriteRequest = new DeleteRequest(index, type, id)
.autoCreateIndexIfPermitted(autoCreateIndex);
} else {
throw new UnsupportedOperationException("optype [" + opType + "] not supported");
}
Expand Down Expand Up @@ -773,6 +781,7 @@ public void testBulk() throws IOException {
assertEquals(originalRequest.routing(), parsedRequest.routing());
assertEquals(originalRequest.version(), parsedRequest.version());
assertEquals(originalRequest.versionType(), parsedRequest.versionType());
assertEquals(originalRequest.isAutoCreateIndexIfPermitted(), parsedRequest.isAutoCreateIndexIfPermitted());

DocWriteRequest.OpType opType = originalRequest.opType();
if (opType == DocWriteRequest.OpType.INDEX) {
Expand Down Expand Up @@ -1816,6 +1825,14 @@ static void setRandomWaitForActiveShards(Consumer<ActiveShardCount> setter, Acti
}
}

private static void setRandomlyDisableAutoCreateIndex(Consumer<Boolean> setter, Map<String, String> expectedParams) {
final boolean autoCreateIndexDisabled = randomBoolean();
if (autoCreateIndexDisabled == false) {
setter.accept(autoCreateIndexDisabled);
expectedParams.put("auto_create_index", Boolean.toString(autoCreateIndexDisabled));
}
}

private static void setRandomRefreshPolicy(Consumer<WriteRequest.RefreshPolicy> setter, Map<String, String> expectedParams) {
if (randomBoolean()) {
WriteRequest.RefreshPolicy refreshPolicy = randomFrom(WriteRequest.RefreshPolicy.values());
Expand Down
25 changes: 25 additions & 0 deletions docs/reference/docs/bulk.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,31 @@ before starting to process the bulk request. See
<<index-wait-for-active-shards,here>> for further details and a usage
example.

[float]
[[bulk-auto-create-index]]
=== Disable auto create index

To disable automatic index creation for a single request set field `auto_create_index`
to `false` in action meta data. To follow default behaviour defined by
<<index-creation,`action.auto_create_index`>>) skip this field:

[source,js]
--------------------------------------------------
POST _bulk
{ "index" : { "_index" : "non_existed_index", "_type" : "_doc", "_id" : "1", "auto_create_index": "false" } }
{ "field1" : "value1" }
{ "index" : { "_index" : "existed_index", "_type" : "_doc", "_id" : "1" } }
{ "field1" : "value1" }
--------------------------------------------------
// CONSOLE

Result of an operation for non existed index is failure and does not affect indexing
to other indices.

[WARNING]
Note: Default behaviour for automatic index creation is applied in case of
mixed values of `auto_create_index` for the *same* index.

[float]
[[bulk-refresh]]
=== Refresh
Expand Down
3 changes: 3 additions & 0 deletions docs/reference/docs/delete.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ dynamic type mapping for the specific type if it has not been created
before (check out the <<indices-put-mapping,put mapping>>
API for manually creating type mapping).

Another option to disable automatic index creation for a single
request is to set `auto_create_index` request parameter to `false`.

[float]
[[delete-distributed]]
=== Distributed
Expand Down
15 changes: 15 additions & 0 deletions docs/reference/docs/index_.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ Automatic index creation can include a pattern based white/black list,
for example, set `action.auto_create_index` to `+aaa*,-bbb*,+ccc*,-*` (+
meaning allowed, and - meaning disallowed).

There is an option to disable automatic index creation for a single
request is to set `auto_create_index` request parameter to `false`:

[source,js]
--------------------------------------------------
PUT twitter/_doc/42?auto_create_index=false
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
--------------------------------------------------
// CONSOLE
// TEST[setup:twitter]

[float]
[[index-versioning]]
=== Versioning
Expand Down
5 changes: 5 additions & 0 deletions docs/reference/docs/update.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,11 @@ Allows to control if and how the updated source should be returned in the respon
By default the updated source is not returned.
See <<search-request-source-filtering, `source filtering`>> for details.

`auto_create_index`::

To disable automatic index creation `auto_create_index` request parameter has
to be set to `false`, skip this parameter to follow default behaviour
defined by <<index-creation,`action.auto_create_index`>>.

`version`::

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ static void validateAgainstAliases(SearchRequest source, IndexRequest destinatio
return;
}
String target = destination.index();
if (false == autoCreateIndex.shouldAutoCreate(target, clusterState)) {
if (false == autoCreateIndex.shouldAutoCreate(target, clusterState, true)) {
/*
* If we're going to autocreate the index we don't need to resolve
* it. This is the same sort of dance that TransportIndexRequest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
"type" : "enum",
"options" : ["internal", "external", "external_gte", "force"],
"description" : "Specific version type"
},
"auto_create_index": {
"type": "boolean",
"description": "false to disable auto create index"
}
}
},
Expand Down
4 changes: 4 additions & 0 deletions rest-api-spec/src/main/resources/rest-api-spec/api/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@
"pipeline" : {
"type" : "string",
"description" : "The pipeline id to preprocess incoming documents with"
},
"auto_create_index": {
"type": "boolean",
"description": "false to disable auto create index"
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@
"type": "enum",
"options": ["internal", "force"],
"description": "Specific version type"
},
"auto_create_index": {
"type": "boolean",
"description": "false to disable auto create index"
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ public interface DocWriteRequest<T> extends IndicesRequest {
*/
OpType opType();

/**
* Auto index creation for a request. Default is {@code true}
* It has to be permitted by {@link org.elasticsearch.action.support.AutoCreateIndex#AUTO_CREATE_INDEX_SETTING}
*/
boolean isAutoCreateIndexIfPermitted();

/**
* Requested operation type to perform on the document
*/
Expand Down
39 changes: 25 additions & 14 deletions server/src/main/java/org/elasticsearch/action/bulk/BulkRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public class BulkRequest extends ActionRequest implements CompositeIndicesReques
private static final ParseField RETRY_ON_CONFLICT = new ParseField("retry_on_conflict");
private static final ParseField PIPELINE = new ParseField("pipeline");
private static final ParseField SOURCE = new ParseField("_source");
private static final ParseField AUTO_CREATE_INDEX = new ParseField("auto_create_index");

/**
* Requests that are part of this request. It is only possible to add things that are both {@link ActionRequest}s and
Expand Down Expand Up @@ -354,6 +355,7 @@ public BulkRequest add(BytesReference data, @Nullable String defaultIndex, @Null
// or START_OBJECT which will have another set of parameters
token = parser.nextToken();

boolean autoCreateIndexPerRequest = true;
if (token == XContentParser.Token.START_OBJECT) {
String currentFieldName = null;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
Expand Down Expand Up @@ -383,6 +385,12 @@ public BulkRequest add(BytesReference data, @Nullable String defaultIndex, @Null
pipeline = parser.text();
} else if (SOURCE.match(currentFieldName, parser.getDeprecationHandler())) {
fetchSourceContext = FetchSourceContext.fromXContent(parser);
} else if (AUTO_CREATE_INDEX.match(currentFieldName, parser.getDeprecationHandler())) {
final boolean value = parser.booleanValue();
if (value) {
throw new IllegalArgumentException("field [auto_create_index] could not be set to [true]");
}
autoCreateIndexPerRequest = value;
} else {
throw new IllegalArgumentException("Action/metadata line [" + line + "] contains an unknown parameter ["
+ currentFieldName + "]");
Expand All @@ -404,7 +412,8 @@ public BulkRequest add(BytesReference data, @Nullable String defaultIndex, @Null
}

if ("delete".equals(action)) {
add(new DeleteRequest(index, type, id).routing(routing).version(version).versionType(versionType), payload);
add(new DeleteRequest(index, type, id).routing(routing)
.version(version).versionType(versionType).autoCreateIndexIfPermitted(autoCreateIndexPerRequest), payload);
} else {
nextMarker = findNextMarker(marker, from, data, length);
if (nextMarker == -1) {
Expand All @@ -415,23 +424,23 @@ public BulkRequest add(BytesReference data, @Nullable String defaultIndex, @Null
// we use internalAdd so we don't fork here, this allows us not to copy over the big byte array to small chunks
// of index request.
if ("index".equals(action)) {
if (opType == null) {
internalAdd(new IndexRequest(index, type, id).routing(routing).version(version).versionType(versionType)
.setPipeline(pipeline)
.source(sliceTrimmingCarriageReturn(data, from, nextMarker,xContentType), xContentType), payload);
} else {
internalAdd(new IndexRequest(index, type, id).routing(routing).version(version).versionType(versionType)
.create("create".equals(opType)).setPipeline(pipeline)
.source(sliceTrimmingCarriageReturn(data, from, nextMarker, xContentType), xContentType), payload);
final IndexRequest indexRequest = new IndexRequest(index, type, id).routing(routing)
.version(version).versionType(versionType).setPipeline(pipeline)
.source(sliceTrimmingCarriageReturn(data, from, nextMarker, xContentType), xContentType)
.autoCreateIndexIfPermitted(autoCreateIndexPerRequest);
if (opType != null) {
indexRequest.create("create".equals(opType));
}
internalAdd(indexRequest, payload);
} else if ("create".equals(action)) {
internalAdd(new IndexRequest(index, type, id).routing(routing).version(version).versionType(versionType)
.create(true).setPipeline(pipeline)
.source(sliceTrimmingCarriageReturn(data, from, nextMarker, xContentType), xContentType), payload);
internalAdd(new IndexRequest(index, type, id).routing(routing)
.version(version).versionType(versionType).create(true).setPipeline(pipeline)
.source(sliceTrimmingCarriageReturn(data, from, nextMarker, xContentType), xContentType)
.autoCreateIndexIfPermitted(autoCreateIndexPerRequest), payload);
} else if ("update".equals(action)) {
UpdateRequest updateRequest = new UpdateRequest(index, type, id).routing(routing).retryOnConflict(retryOnConflict)
.version(version).versionType(versionType)
.routing(routing);
.version(version).versionType(versionType)
.routing(routing).autoCreateIndexIfPermitted(autoCreateIndexPerRequest);
// EMPTY is safe here because we never call namedObject
try (InputStream dataStream = sliceTrimmingCarriageReturn(data, from, nextMarker, xContentType).streamInput();
XContentParser sliceParser = xContent.createParser(NamedXContentRegistry.EMPTY,
Expand All @@ -446,11 +455,13 @@ public BulkRequest add(BytesReference data, @Nullable String defaultIndex, @Null
upsertRequest.version(version);
upsertRequest.versionType(versionType);
upsertRequest.setPipeline(defaultPipeline);
upsertRequest.setAutoCreateIndexIfPermitted(autoCreateIndexPerRequest);
}
IndexRequest doc = updateRequest.doc();
if (doc != null) {
doc.version(version);
doc.versionType(versionType);
doc.setAutoCreateIndexIfPermitted(autoCreateIndexPerRequest);
}

internalAdd(updateRequest, payload);
Expand Down
Loading