diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/reservedstate/ReservedComposableIndexTemplateAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/reservedstate/ReservedComposableIndexTemplateAction.java index 8f7f716a56b46..a70052d135b42 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/reservedstate/ReservedComposableIndexTemplateAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/reservedstate/ReservedComposableIndexTemplateAction.java @@ -182,7 +182,7 @@ public TransformState transform(ProjectId projectId, ComponentsAndComposables so // 4. validate for v2 composable template overlaps for (var request : composables) { - MetadataIndexTemplateService.v2TemplateOverlaps(project, request.name(), request.indexTemplate(), true); + MetadataIndexTemplateService.v2TemplateOverlaps(project.templatesV2(), request.name(), request.indexTemplate(), true); } Set componentEntities = components.stream().map(r -> reservedComponentName(r.name())).collect(Collectors.toSet()); 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 ccddfd52b95bf..f9878cbbd8bac 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateService.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateService.java @@ -442,8 +442,16 @@ public ProjectMetadata addComponentTemplate( return ProjectMetadata.builder(project).put(name, finalComponentTemplate).build(); } + /** + * Mappings in templates don't have to include _doc, so update the mappings to include this single type if necessary + * + * @param mappings mappings from a template + * @param xContentRegistry the xcontent registry used for parsing + * @return a normalized form of the mapping provided + * @throws IOException if reading or writing the mapping encounters a problem + */ @Nullable - private static CompressedXContent wrapMappingsIfNecessary(@Nullable CompressedXContent mappings, NamedXContentRegistry xContentRegistry) + public static CompressedXContent wrapMappingsIfNecessary(@Nullable CompressedXContent mappings, NamedXContentRegistry xContentRegistry) throws IOException { // Mappings in templates don't have to include _doc, so update // the mappings to include this single type if necessary @@ -605,6 +613,14 @@ public ProjectMetadata execute(ProjectMetadata currentProject) throws Exception } public static void validateV2TemplateRequest(ProjectMetadata metadata, String name, ComposableIndexTemplate template) { + validateV2TemplateRequest(metadata.componentTemplates(), name, template); + } + + public static void validateV2TemplateRequest( + Map componentTemplates, + String name, + ComposableIndexTemplate template + ) { if (template.createdDateMillis().isPresent()) { throw new InvalidIndexTemplateException(name, "provided a template property which is managed by the system: created_date"); } @@ -612,7 +628,7 @@ public static void validateV2TemplateRequest(ProjectMetadata metadata, String na throw new InvalidIndexTemplateException(name, "provided a template property which is managed by the system: modified_date"); } if (template.indexPatterns().stream().anyMatch(Regex::isMatchAllPattern)) { - Settings mergedSettings = resolveSettings(template, metadata.componentTemplates()); + Settings mergedSettings = resolveSettings(template, componentTemplates); if (IndexMetadata.INDEX_HIDDEN_SETTING.exists(mergedSettings)) { throw new InvalidIndexTemplateException( name, @@ -621,7 +637,6 @@ public static void validateV2TemplateRequest(ProjectMetadata metadata, String na } } - final Map componentTemplates = metadata.componentTemplates(); final List ignoreMissingComponentTemplates = (template.getIgnoreMissingComponentTemplates() == null ? List.of() : template.getIgnoreMissingComponentTemplates()); @@ -673,7 +688,7 @@ public ProjectMetadata addIndexTemplateV2( throw new IllegalArgumentException("index template [" + name + "] already exists"); } - Map> overlaps = v2TemplateOverlaps(project, name, template, validateV2Overlaps); + Map> overlaps = v2TemplateOverlaps(project.templatesV2(), name, template, validateV2Overlaps); overlaps = findConflictingV1Templates(project, name, template.indexPatterns()); if (overlaps.size() > 0) { @@ -737,20 +752,20 @@ public ProjectMetadata addIndexTemplateV2( * we throw an {@link IllegalArgumentException} with information about the conflicting templates. *

* This method doesn't check for conflicting overlaps with v1 templates. - * @param project the current project + * @param templatesV2 the templates to check overlap against * @param name the composable index template name * @param template the full composable index template object we check for overlaps * @param validate should we throw {@link IllegalArgumentException} if conflicts are found or just compute them * @return a map of v2 template names to their index patterns for v2 templates that would overlap with the given template */ public static Map> v2TemplateOverlaps( - final ProjectMetadata project, + Map templatesV2, String name, final ComposableIndexTemplate template, boolean validate ) { Map> overlaps = findConflictingV2Templates( - project, + templatesV2, name, template.indexPatterns(), true, @@ -1040,7 +1055,7 @@ public static Map> findConflictingV2Templates( final String candidateName, final List indexPatterns ) { - return findConflictingV2Templates(project, candidateName, indexPatterns, false, 0L); + return findConflictingV2Templates(project.templatesV2(), candidateName, indexPatterns, false, 0L); } /** @@ -1054,7 +1069,7 @@ public static Map> findConflictingV2Templates( * index templates with the same priority). */ static Map> findConflictingV2Templates( - final ProjectMetadata project, + final Map templatesV2, final String candidateName, final List indexPatterns, boolean checkPriority, @@ -1062,7 +1077,7 @@ static Map> findConflictingV2Templates( ) { Automaton v1automaton = Regex.simpleMatchToAutomaton(indexPatterns.toArray(Strings.EMPTY_ARRAY)); Map> overlappingTemplates = new TreeMap<>(); - for (Map.Entry entry : project.templatesV2().entrySet()) { + for (Map.Entry entry : templatesV2.entrySet()) { String name = entry.getKey(); ComposableIndexTemplate template = entry.getValue(); Automaton v2automaton = Regex.simpleMatchToAutomaton(template.indexPatterns().toArray(Strings.EMPTY_ARRAY)); @@ -2005,7 +2020,8 @@ private static void validateCompositeTemplate( }); } - static void validateTemplate(Settings validateSettings, CompressedXContent mappings, IndicesService indicesService) throws Exception { + public static void validateTemplate(Settings validateSettings, CompressedXContent mappings, IndicesService indicesService) + throws Exception { // Hard to validate settings if they're non-existent, so used empty ones if none were provided Settings settings = validateSettings; if (settings == null) { @@ -2036,7 +2052,7 @@ static void validateTemplate(Settings validateSettings, CompressedXContent mappi }); } - private void validate(String name, ComponentTemplate template) { + public void validate(String name, ComponentTemplate template) { validate(name, template.template(), Collections.emptyList()); } 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 342132e5374cb..50d868dd9c35b 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateServiceTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateServiceTests.java @@ -2476,14 +2476,14 @@ public void testV2TemplateOverlaps() throws Exception { .build(); // when validating is false, we return the conflicts instead of throwing an exception - var overlaps = MetadataIndexTemplateService.v2TemplateOverlaps(project, "foo2", newTemplate, false); + var overlaps = MetadataIndexTemplateService.v2TemplateOverlaps(project.templatesV2(), "foo2", newTemplate, false); assertThat(overlaps, allOf(aMapWithSize(1), hasKey("foo"))); // try now the same thing with validation on IllegalArgumentException e = expectThrows( IllegalArgumentException.class, - () -> MetadataIndexTemplateService.v2TemplateOverlaps(project, "foo2", newTemplate, true) + () -> MetadataIndexTemplateService.v2TemplateOverlaps(project.templatesV2(), "foo2", newTemplate, true) ); assertThat( e.getMessage(), @@ -2499,7 +2499,7 @@ public void testV2TemplateOverlaps() throws Exception { .priority(1L) .build(); - overlaps = MetadataIndexTemplateService.v2TemplateOverlaps(project, "no-conflict", nonConflict, true); + overlaps = MetadataIndexTemplateService.v2TemplateOverlaps(project.templatesV2(), "no-conflict", nonConflict, true); assertTrue(overlaps.isEmpty()); } @@ -2513,7 +2513,7 @@ public void testV2TemplateOverlaps() throws Exception { .build(); IllegalArgumentException e = expectThrows( IllegalArgumentException.class, - () -> MetadataIndexTemplateService.v2TemplateOverlaps(project, "foo2", newTemplate, true) + () -> MetadataIndexTemplateService.v2TemplateOverlaps(project.templatesV2(), "foo2", newTemplate, true) ); assertThat( e.getMessage(),