From 37e20c6f340fcfa745e3605cc1ed0b89070c8f45 Mon Sep 17 00:00:00 2001 From: Adrien Grand Date: Mon, 18 Jul 2016 16:47:44 +0200 Subject: [PATCH] Automatically created indices should honor `index.mapper.dynamic`. #19478 Today they don't because the create index request that is implicitly created adds an empty mapping for the type of the document. So to Elasticsearch it looks like this type was explicitly created and `index.mapper.dynamic` is not checked. Closes #17592 --- .../action/bulk/TransportBulkAction.java | 16 +++-------- .../action/index/TransportIndexAction.java | 1 - .../index/mapper/MapperService.java | 3 +- .../indices/TypeMissingException.java | 7 ++++- ...tegrationIT.java => DynamicMappingIT.java} | 28 ++++++++++++++++++- 5 files changed, 39 insertions(+), 16 deletions(-) rename core/src/test/java/org/elasticsearch/index/mapper/{DynamicMappingIntegrationIT.java => DynamicMappingIT.java} (77%) diff --git a/core/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java b/core/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java index f23c91be201..84c11d9fc8e 100644 --- a/core/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java +++ b/core/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java @@ -119,29 +119,21 @@ public class TransportBulkAction extends HandledTransportAction> indicesAndTypes = new HashMap<>(); + final Set autoCreateIndices = new HashSet<>(); for (ActionRequest request : bulkRequest.requests) { if (request instanceof DocumentRequest) { DocumentRequest req = (DocumentRequest) request; - Set types = indicesAndTypes.get(req.index()); - if (types == null) { - indicesAndTypes.put(req.index(), types = new HashSet<>()); - } - types.add(req.type()); + autoCreateIndices.add(req.index()); } else { throw new ElasticsearchException("Parsed unknown request in bulk actions: " + request.getClass().getSimpleName()); } } - final AtomicInteger counter = new AtomicInteger(indicesAndTypes.size()); + final AtomicInteger counter = new AtomicInteger(autoCreateIndices.size()); ClusterState state = clusterService.state(); - for (Map.Entry> entry : indicesAndTypes.entrySet()) { - final String index = entry.getKey(); + for (String index : autoCreateIndices) { if (shouldAutoCreate(index, state)) { CreateIndexRequest createIndexRequest = new CreateIndexRequest(); createIndexRequest.index(index); - for (String type : entry.getValue()) { - createIndexRequest.mapping(type); - } createIndexRequest.cause("auto(bulk api)"); createIndexRequest.masterNodeTimeout(bulkRequest.timeout()); createIndexAction.execute(createIndexRequest, new ActionListener() { diff --git a/core/src/main/java/org/elasticsearch/action/index/TransportIndexAction.java b/core/src/main/java/org/elasticsearch/action/index/TransportIndexAction.java index fb42ef236d8..8d2234aa27e 100644 --- a/core/src/main/java/org/elasticsearch/action/index/TransportIndexAction.java +++ b/core/src/main/java/org/elasticsearch/action/index/TransportIndexAction.java @@ -91,7 +91,6 @@ public class TransportIndexAction extends TransportWriteAction() { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java b/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java index d706823d157..527518ecf43 100755 --- a/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java @@ -538,7 +538,8 @@ public class MapperService extends AbstractIndexComponent { return new DocumentMapperForType(mapper, null); } if (!dynamic) { - throw new TypeMissingException(index(), type, "trying to auto create mapping, but dynamic mapping is disabled"); + throw new TypeMissingException(index(), + new IllegalStateException("trying to auto create mapping, but dynamic mapping is disabled"), type); } mapper = parse(type, null, true); return new DocumentMapperForType(mapper, mapper.mapping()); diff --git a/core/src/main/java/org/elasticsearch/indices/TypeMissingException.java b/core/src/main/java/org/elasticsearch/indices/TypeMissingException.java index 6c952fb2416..5ab9744933b 100644 --- a/core/src/main/java/org/elasticsearch/indices/TypeMissingException.java +++ b/core/src/main/java/org/elasticsearch/indices/TypeMissingException.java @@ -33,7 +33,12 @@ import java.util.Arrays; public class TypeMissingException extends ElasticsearchException { public TypeMissingException(Index index, String... types) { - super("type[" + Arrays.toString(types) + "] missing"); + super("type" + Arrays.toString(types) + " missing"); + setIndex(index); + } + + public TypeMissingException(Index index, Throwable cause, String... types) { + super("type" + Arrays.toString(types) + " missing", cause); setIndex(index); } diff --git a/core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingIntegrationIT.java b/core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingIT.java similarity index 77% rename from core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingIntegrationIT.java rename to core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingIT.java index 71628c06128..70d7daef717 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingIntegrationIT.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingIT.java @@ -18,10 +18,13 @@ */ package org.elasticsearch.index.mapper; +import org.elasticsearch.action.admin.indices.get.GetIndexResponse; import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.cluster.metadata.MappingMetaData; import org.elasticsearch.common.collect.ImmutableOpenMap; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.indices.TypeMissingException; import org.elasticsearch.test.ESIntegTestCase; import java.io.IOException; @@ -29,8 +32,9 @@ import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; -public class DynamicMappingIntegrationIT extends ESIntegTestCase { +public class DynamicMappingIT extends ESIntegTestCase { public void testConflictingDynamicMappings() { // we don't use indexRandom because the order of requests is important here @@ -120,4 +124,26 @@ public class DynamicMappingIntegrationIT extends ESIntegTestCase { } } + public void testAutoCreateWithDisabledDynamicMappings() throws Exception { + assertAcked(client().admin().indices().preparePutTemplate("my_template") + .setCreate(true) + .setTemplate("index_*") + .addMapping("foo", "field", "type=keyword") + .setSettings(Settings.builder().put("index.mapper.dynamic", false).build()) + .get()); + + // succeeds since 'foo' has an explicit mapping in the template + indexRandom(true, false, client().prepareIndex("index_1", "foo", "1").setSource("field", "abc")); + + // fails since 'bar' does not have an explicit mapping in the template and dynamic template creation is disabled + TypeMissingException e1 = expectThrows(TypeMissingException.class, + () -> client().prepareIndex("index_2", "bar", "1").setSource("field", "abc").get()); + assertEquals("type[bar] missing", e1.getMessage()); + assertEquals("trying to auto create mapping, but dynamic mapping is disabled", e1.getCause().getMessage()); + + // make sure no mappings were created for bar + GetIndexResponse getIndexResponse = client().admin().indices().prepareGetIndex().addIndices("index_2").get(); + assertFalse(getIndexResponse.mappings().containsKey("bar")); + } + }