diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateService.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateService.java index 2b74714791f..063e9f8bed4 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateService.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateService.java @@ -305,7 +305,23 @@ public class MetadataIndexTemplateService { throw new IllegalArgumentException("index template [" + name + "] already exists"); } - Map> overlaps = findConflictingV1Templates(currentState, name, template.indexPatterns()); + Map> overlaps = findConflictingV2Templates(currentState, name, template.indexPatterns(), true, + template.priority()); + if (overlaps.size() > 0) { + String error = String.format(Locale.ROOT, "index template [%s] has index patterns %s matching patterns from " + + "existing templates [%s] with patterns (%s) that have the same priority [%d], multiple index templates may not " + + "match during index creation, please use a different priority", + name, + template.indexPatterns(), + Strings.collectionToCommaDelimitedString(overlaps.keySet()), + overlaps.entrySet().stream() + .map(e -> e.getKey() + " => " + e.getValue()) + .collect(Collectors.joining(",")), + template.priority()); + throw new IllegalArgumentException(error); + } + + overlaps = findConflictingV1Templates(currentState, name, template.indexPatterns()); if (overlaps.size() > 0) { String warning = String.format(Locale.ROOT, "index template [%s] has index patterns %s matching patterns from " + "existing older templates [%s] with patterns (%s); this template [%s] will take precedence during new index creation", @@ -385,6 +401,15 @@ public class MetadataIndexTemplateService { */ static Map> findConflictingV2Templates(final ClusterState state, final String candidateName, final List indexPatterns) { + return findConflictingV2Templates(state, candidateName, indexPatterns, false, null); + } + + /** + * Return a map of v2 template names to their index patterns for v2 templates that would overlap + * with the given template's index patterns. + */ + static Map> findConflictingV2Templates(final ClusterState state, final String candidateName, + final List indexPatterns, boolean checkPriority, Long priority) { Automaton v1automaton = Regex.simpleMatchToAutomaton(indexPatterns.toArray(Strings.EMPTY_ARRAY)); Map> overlappingTemplates = new HashMap<>(); for (Map.Entry entry : state.metadata().templatesV2().entrySet()) { @@ -392,9 +417,11 @@ public class MetadataIndexTemplateService { IndexTemplateV2 template = entry.getValue(); Automaton v2automaton = Regex.simpleMatchToAutomaton(template.indexPatterns().toArray(Strings.EMPTY_ARRAY)); if (Operations.isEmpty(Operations.intersection(v1automaton, v2automaton)) == false) { - logger.debug("old template {} and index template {} would overlap: {} <=> {}", - candidateName, name, indexPatterns, template.indexPatterns()); - overlappingTemplates.put(name, template.indexPatterns()); + if (checkPriority == false || Objects.equals(priority, template.priority())) { + logger.debug("old template {} and index template {} would overlap: {} <=> {}", + candidateName, name, indexPatterns, template.indexPatterns()); + overlappingTemplates.put(name, template.indexPatterns()); + } } } return overlappingTemplates; diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateServiceTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateServiceTests.java index 24644778d00..ac802fb7ac1 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateServiceTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateServiceTests.java @@ -300,12 +300,16 @@ public class MetadataIndexTemplateServiceTests extends ESSingleNodeTestCase { assertNotNull(state.metadata().templatesV2().get("foo")); assertTemplatesEqual(state.metadata().templatesV2().get("foo"), template); + + IndexTemplateV2 newTemplate = randomValueOtherThanMany(t -> Objects.equals(template.priority(), t.priority()), + IndexTemplateV2Tests::randomInstance); + final ClusterState throwState = ClusterState.builder(state).build(); IllegalArgumentException e = expectThrows(IllegalArgumentException.class, - () -> metadataIndexTemplateService.addIndexTemplateV2(throwState, true, "foo", template)); + () -> metadataIndexTemplateService.addIndexTemplateV2(throwState, true, "foo", newTemplate)); assertThat(e.getMessage(), containsString("index template [foo] already exists")); - state = metadataIndexTemplateService.addIndexTemplateV2(state, randomBoolean(), "bar", template); + state = metadataIndexTemplateService.addIndexTemplateV2(state, randomBoolean(), "bar", newTemplate); assertNotNull(state.metadata().templatesV2().get("bar")); } @@ -471,6 +475,18 @@ public class MetadataIndexTemplateServiceTests extends ESSingleNodeTestCase { "templates (/_index_template) instead")); } + public void testPuttingOverlappingV2Template() throws Exception { + IndexTemplateV2 template = new IndexTemplateV2(Arrays.asList("egg*", "baz"), null, null, 1L, null, null); + MetadataIndexTemplateService metadataIndexTemplateService = getMetadataIndexTemplateService(); + ClusterState state = metadataIndexTemplateService.addIndexTemplateV2(ClusterState.EMPTY_STATE, false, "foo", template); + IndexTemplateV2 newTemplate = new IndexTemplateV2(Arrays.asList("abc", "baz*"), null, null, 1L, null, null); + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, + () -> metadataIndexTemplateService.addIndexTemplateV2(state, false, "foo2", newTemplate)); + assertThat(e.getMessage(), equalTo("index template [foo2] has index patterns [abc, baz*] matching patterns from existing " + + "templates [foo] with patterns (foo => [egg*, baz]) that have the same priority [1], multiple index templates may not " + + "match during index creation, please use a different priority")); + } + public void testFindV2Templates() throws Exception { final MetadataIndexTemplateService service = getMetadataIndexTemplateService(); ClusterState state = ClusterState.EMPTY_STATE;