diff --git a/server/src/main/java/org/opensearch/cluster/metadata/MetadataIndexTemplateService.java b/server/src/main/java/org/opensearch/cluster/metadata/MetadataIndexTemplateService.java index a7b9eba6dbc05..a2e69fefef87c 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/MetadataIndexTemplateService.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/MetadataIndexTemplateService.java @@ -52,6 +52,7 @@ import org.opensearch.common.Priority; import org.opensearch.common.UUIDs; import org.opensearch.common.ValidationException; +import org.opensearch.common.collect.Tuple; import org.opensearch.common.compress.CompressedXContent; import org.opensearch.common.inject.Inject; import org.opensearch.common.logging.HeaderWarning; @@ -474,6 +475,29 @@ static void validateNotInUse(Metadata metadata, String templateNameOrWildcard) { + templatesStillUsing ); } + + validateNoIndexUsesContext(metadata, matchingComponentTemplates); + } + + /** + * Validate that a system template is not being used directly by an index. + */ + static void validateNoIndexUsesContext(Metadata metadata, Set matchingComponentTemplates) { + List> indicesUsingSpecifiedContexts = metadata.indices() + .values() + .stream() + .filter(imd -> imd.context() != null) + .filter(imd -> matchingComponentTemplates.contains(findContextTemplateName(metadata, imd.context()))) + .map(imd -> Tuple.tuple(imd.getIndex().getName(), findContextTemplateName(metadata, imd.context()))) + .collect(Collectors.toList()); + + if (!indicesUsingSpecifiedContexts.isEmpty()) { + throw new IllegalArgumentException( + "Cannot process request to remove component templates as they are being used by indices." + + "First few indices preventing the deletion are: " + + indicesUsingSpecifiedContexts.subList(0, Math.min(10, indicesUsingSpecifiedContexts.size())) + ); + } } /** diff --git a/server/src/test/java/org/opensearch/cluster/metadata/MetadataIndexTemplateServiceTests.java b/server/src/test/java/org/opensearch/cluster/metadata/MetadataIndexTemplateServiceTests.java index 8312267205d62..d310eda69e76c 100644 --- a/server/src/test/java/org/opensearch/cluster/metadata/MetadataIndexTemplateServiceTests.java +++ b/server/src/test/java/org/opensearch/cluster/metadata/MetadataIndexTemplateServiceTests.java @@ -81,6 +81,8 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.TreeMap; +import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -2017,6 +2019,43 @@ public void testRemoveComponentTemplateInUse() throws Exception { ); } + public void testValidateNoIndexUsesContextWithIndexUsingContext() throws Exception { + String contextName = "testcontext"; + String indexName = "index"; + Metadata metadata = mock(Metadata.class); + when(metadata.systemTemplatesLookup()).thenReturn(Map.of(contextName, new TreeMap<>() { + { + put(1L, contextName); + } + })); + + IndexMetadata indexMetadata = mock(IndexMetadata.class); + when(indexMetadata.context()).thenReturn(new Context(contextName)); + when(indexMetadata.getIndex()).thenReturn(new Index(indexName, UUID.randomUUID().toString())); + when(metadata.indices()).thenReturn(Map.of(indexName, indexMetadata)); + + expectThrows( + IllegalArgumentException.class, + () -> MetadataIndexTemplateService.validateNoIndexUsesContext(metadata, Set.of(contextName)) + ); + } + + public void testValidateNoIndexUsesContextWithNoIndexUsingContext() throws Exception { + String contextName = "testcontext"; + String indexName = "index"; + Metadata metadata = mock(Metadata.class); + when(metadata.systemTemplatesLookup()).thenReturn(Map.of(contextName, new TreeMap<>() { + { + put(1L, contextName); + } + })); + + IndexMetadata indexMetadata = mock(IndexMetadata.class); + when(metadata.indices()).thenReturn(Map.of(indexName, indexMetadata)); + + MetadataIndexTemplateService.validateNoIndexUsesContext(metadata, Set.of(contextName)); + } + /** * Tests that we check that settings/mappings/etc are valid even after template composition, * when adding/updating a composable index template