diff --git a/docs/changelog/87260.yaml b/docs/changelog/87260.yaml new file mode 100644 index 0000000000000..92141a922522d --- /dev/null +++ b/docs/changelog/87260.yaml @@ -0,0 +1,5 @@ +pr: 87260 +summary: System indices ignore all user templates +area: Infra/Core +type: bug +issues: [42508,74271] diff --git a/qa/system-indices/src/javaRestTest/java/org/elasticsearch/system/indices/SystemAliasIT.java b/qa/system-indices/src/javaRestTest/java/org/elasticsearch/system/indices/SystemAliasIT.java index ec4df990bf93e..217b0640b6a7c 100644 --- a/qa/system-indices/src/javaRestTest/java/org/elasticsearch/system/indices/SystemAliasIT.java +++ b/qa/system-indices/src/javaRestTest/java/org/elasticsearch/system/indices/SystemAliasIT.java @@ -45,8 +45,8 @@ public void testCreatingSystemIndexWithAlias() throws Exception { assertThat(response.getStatusLine().getStatusCode(), is(200)); } - assertAliasIsHiddenInIndexResponse(".internal-unmanaged-index-8", ".internal-unmanaged-alias"); - assertAliasIsHiddenInAliasesEndpoint(".internal-unmanaged-index-8", ".internal-unmanaged-alias"); + assertAliasIsHiddenInIndexResponse(".internal-unmanaged-index-8", ".internal-unmanaged-alias", true); + assertAliasIsHiddenInAliasesEndpoint(".internal-unmanaged-index-8", ".internal-unmanaged-alias", true); } public void testCreatingSystemIndexWithLegacyAlias() throws Exception { @@ -71,8 +71,8 @@ public void testCreatingSystemIndexWithLegacyAlias() throws Exception { assertThat(response.getStatusLine().getStatusCode(), is(200)); } - assertAliasIsHiddenInIndexResponse(".internal-unmanaged-index-8", ".internal-unmanaged-alias"); - assertAliasIsHiddenInAliasesEndpoint(".internal-unmanaged-index-8", ".internal-unmanaged-alias"); + assertAliasIsHiddenInIndexResponse(".internal-unmanaged-index-8", ".internal-unmanaged-alias", false); + assertAliasIsHiddenInAliasesEndpoint(".internal-unmanaged-index-8", ".internal-unmanaged-alias", false); } public void testCreatingSystemIndexWithIndexAliasEndpoint() throws Exception { @@ -94,8 +94,8 @@ public void testCreatingSystemIndexWithIndexAliasEndpoint() throws Exception { assertThat(response.getStatusLine().getStatusCode(), is(200)); } - assertAliasIsHiddenInIndexResponse(".internal-unmanaged-index-8", ".internal-unmanaged-alias"); - assertAliasIsHiddenInAliasesEndpoint(".internal-unmanaged-index-8", ".internal-unmanaged-alias"); + assertAliasIsHiddenInIndexResponse(".internal-unmanaged-index-8", ".internal-unmanaged-alias", true); + assertAliasIsHiddenInAliasesEndpoint(".internal-unmanaged-index-8", ".internal-unmanaged-alias", true); } public void testCreatingSystemIndexWithAliasEndpoint() throws Exception { @@ -118,8 +118,8 @@ public void testCreatingSystemIndexWithAliasEndpoint() throws Exception { assertThat(response.getStatusLine().getStatusCode(), is(200)); } - assertAliasIsHiddenInIndexResponse(".internal-unmanaged-index-8", ".internal-unmanaged-alias"); - assertAliasIsHiddenInAliasesEndpoint(".internal-unmanaged-index-8", ".internal-unmanaged-alias"); + assertAliasIsHiddenInIndexResponse(".internal-unmanaged-index-8", ".internal-unmanaged-alias", true); + assertAliasIsHiddenInAliasesEndpoint(".internal-unmanaged-index-8", ".internal-unmanaged-alias", true); } public void testCreatingSystemIndexWithAliasesEndpoint() throws Exception { @@ -154,12 +154,12 @@ public void testCreatingSystemIndexWithAliasesEndpoint() throws Exception { assertThat(response.getStatusLine().getStatusCode(), is(200)); } - assertAliasIsHiddenInIndexResponse(".internal-unmanaged-index-8", ".internal-unmanaged-alias"); - assertAliasIsHiddenInAliasesEndpoint(".internal-unmanaged-index-8", ".internal-unmanaged-alias"); + assertAliasIsHiddenInIndexResponse(".internal-unmanaged-index-8", ".internal-unmanaged-alias", true); + assertAliasIsHiddenInAliasesEndpoint(".internal-unmanaged-index-8", ".internal-unmanaged-alias", true); } @SuppressWarnings("unchecked") - private void assertAliasIsHiddenInIndexResponse(String indexName, String aliasName) throws IOException { + private void assertAliasIsHiddenInIndexResponse(String indexName, String aliasName, boolean expectMatch) throws IOException { Request request = new Request("GET", "/" + indexName); request.setOptions( expectWarnings( @@ -177,14 +177,18 @@ private void assertAliasIsHiddenInIndexResponse(String indexName, String aliasNa assertThat(indexSettingsMap.get("hidden"), equalTo("true")); Map aliasesMap = (Map) indexMap.get("aliases"); - assertThat(aliasesMap.keySet(), equalTo(Set.of(aliasName))); - Map aliasMap = (Map) aliasesMap.get(aliasName); - assertThat(aliasMap.get("is_hidden"), notNullValue()); - assertThat(aliasMap.get("is_hidden"), equalTo(true)); + if (expectMatch == false) { + assertTrue(aliasesMap.keySet().isEmpty()); + } else { + assertThat(aliasesMap.keySet(), equalTo(Set.of(aliasName))); + Map aliasMap = (Map) aliasesMap.get(aliasName); + assertThat(aliasMap.get("is_hidden"), notNullValue()); + assertThat(aliasMap.get("is_hidden"), equalTo(true)); + } } @SuppressWarnings("unchecked") - private void assertAliasIsHiddenInAliasesEndpoint(String indexName, String aliasName) throws IOException { + private void assertAliasIsHiddenInAliasesEndpoint(String indexName, String aliasName, boolean expectMatch) throws IOException { Request request = new Request("GET", "/_aliases"); request.setOptions( expectWarnings( @@ -199,7 +203,11 @@ private void assertAliasIsHiddenInAliasesEndpoint(String indexName, String alias Map indexAliasMap = (Map) responseMap.get(indexName); Map aliasesMap = (Map) indexAliasMap.get("aliases"); Map aliasMap = (Map) aliasesMap.get(aliasName); - assertThat(aliasMap.get("is_hidden"), notNullValue()); - assertThat(aliasMap.get("is_hidden"), equalTo(true)); + if (expectMatch == false) { + assertNull(aliasMap); + } else { + assertThat(aliasMap.get("is_hidden"), notNullValue()); + assertThat(aliasMap.get("is_hidden"), equalTo(true)); + } } } diff --git a/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/AutoCreateSystemIndexIT.java b/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/AutoCreateSystemIndexIT.java index 8332699ddc7d2..6a55aca85b844 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/AutoCreateSystemIndexIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/AutoCreateSystemIndexIT.java @@ -23,6 +23,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.CollectionUtils; import org.elasticsearch.indices.SystemIndexDescriptor; +import org.elasticsearch.indices.TestSystemIndexDescriptorAllowsTemplates; import org.elasticsearch.indices.TestSystemIndexPlugin; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.SystemIndexPlugin; @@ -167,40 +168,56 @@ public void testSystemIndicesAutoCreateRejectedWhenNotHidden() { ); } - /** - * Check that a template applying a system alias creates a hidden alias. - */ - public void testAutoCreateSystemAliasViaV1Template() throws Exception { + private String autoCreateSystemAliasViaV1Template(String indexName) throws Exception { assertAcked( client().admin() .indices() .preparePutTemplate("test-template") - .setPatterns(List.of(INDEX_NAME + "*")) - .addAlias(new Alias(INDEX_NAME + "-legacy-alias")) + .setPatterns(List.of(indexName + "*")) + .addAlias(new Alias(indexName + "-legacy-alias")) .get() ); - String nonPrimaryIndex = INDEX_NAME + "-2"; + String nonPrimaryIndex = indexName + "-2"; CreateIndexRequest request = new CreateIndexRequest(nonPrimaryIndex); assertAcked(client().execute(AutoCreateAction.INSTANCE, request).get()); - assertTrue(indexExists(nonPrimaryIndex)); - assertAliasesHidden(nonPrimaryIndex, Set.of(".test-index", ".test-index-legacy-alias")); + return nonPrimaryIndex; + } - assertAcked(client().admin().indices().prepareDeleteTemplate("*").get()); + /** + * Check that a legacy template does not create an alias for a system index + */ + public void testAutoCreateSystemAliasViaV1Template() throws Exception { + var nonPrimaryIndex = autoCreateSystemAliasViaV1Template(INDEX_NAME); + + assertAliasesHidden(nonPrimaryIndex, Set.of(INDEX_NAME), 1); } /** - * Check that a composable template applying a system alias creates a hidden alias. + * Check that a legacy template does create an alias for a system index, because of allows templates */ - public void testAutoCreateSystemAliasViaComposableTemplate() throws Exception { + public void testAutoCreateSystemAliasViaV1TemplateAllowsTemplates() throws Exception { + var nonPrimaryIndex = autoCreateSystemAliasViaV1Template(TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME); + + assertAliasesHidden( + nonPrimaryIndex, + Set.of( + TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME, + TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME + "-legacy-alias" + ), + 2 + ); + } + + private String autoCreateSystemAliasViaComposableTemplate(String indexName) throws Exception { ComposableIndexTemplate cit = new ComposableIndexTemplate( - Collections.singletonList(INDEX_NAME + "*"), + Collections.singletonList(indexName + "*"), new Template( null, null, - Map.of(INDEX_NAME + "-composable-alias", AliasMetadata.builder(INDEX_NAME + "-composable-alias").build()) + Map.of(indexName + "-composable-alias", AliasMetadata.builder(indexName + "-composable-alias").build()) ), Collections.emptyList(), 4L, @@ -214,13 +231,45 @@ public void testAutoCreateSystemAliasViaComposableTemplate() throws Exception { ).get() ); - String nonPrimaryIndex = INDEX_NAME + "-2"; + String nonPrimaryIndex = indexName + "-2"; CreateIndexRequest request = new CreateIndexRequest(nonPrimaryIndex); assertAcked(client().execute(AutoCreateAction.INSTANCE, request).get()); assertTrue(indexExists(nonPrimaryIndex)); - assertAliasesHidden(nonPrimaryIndex, Set.of(".test-index", ".test-index-composable-alias")); + return nonPrimaryIndex; + } + + /** + * Check that a composable template does not create an alias for a system index + */ + public void testAutoCreateSystemAliasViaComposableTemplate() throws Exception { + String nonPrimaryIndex = autoCreateSystemAliasViaComposableTemplate(INDEX_NAME); + + assertAliasesHidden(nonPrimaryIndex, Set.of(INDEX_NAME), 1); + + assertAcked( + client().execute( + DeleteComposableIndexTemplateAction.INSTANCE, + new DeleteComposableIndexTemplateAction.Request("test-composable-template") + ).get() + ); + } + + /** + * Check that a composable template does create an alias for a system index, because of allows templates + */ + public void testAutoCreateSystemAliasViaComposableTemplateAllowsTemplates() throws Exception { + String nonPrimaryIndex = autoCreateSystemAliasViaComposableTemplate(TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME); + + assertAliasesHidden( + nonPrimaryIndex, + Set.of( + TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME, + TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME + "-composable-alias" + ), + 2 + ); assertAcked( client().execute( @@ -230,14 +279,15 @@ public void testAutoCreateSystemAliasViaComposableTemplate() throws Exception { ); } - private void assertAliasesHidden(String nonPrimaryIndex, Set aliasNames) throws InterruptedException, ExecutionException { + private void assertAliasesHidden(String nonPrimaryIndex, Set aliasNames, int aliasCount) throws InterruptedException, + ExecutionException { final GetAliasesResponse getAliasesResponse = client().admin() .indices() .getAliases(new GetAliasesRequest().indicesOptions(IndicesOptions.strictExpandHidden())) .get(); assertThat(getAliasesResponse.getAliases().size(), equalTo(1)); - assertThat(getAliasesResponse.getAliases().get(nonPrimaryIndex).size(), equalTo(2)); + assertThat(getAliasesResponse.getAliases().get(nonPrimaryIndex).size(), equalTo(aliasCount)); assertThat( getAliasesResponse.getAliases().get(nonPrimaryIndex).stream().map(AliasMetadata::alias).collect(Collectors.toSet()), equalTo(aliasNames) diff --git a/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/CreateSystemIndicesIT.java b/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/CreateSystemIndicesIT.java index 65eda7953aba0..9c9822318c73b 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/CreateSystemIndicesIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/CreateSystemIndicesIT.java @@ -30,6 +30,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.CollectionUtils; import org.elasticsearch.indices.TestSystemIndexDescriptor; +import org.elasticsearch.indices.TestSystemIndexDescriptorAllowsTemplates; import org.elasticsearch.indices.TestSystemIndexPlugin; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.test.ESIntegTestCase; @@ -157,37 +158,56 @@ public void testCreateSystemIndexViaConcreteName() { doCreateTest(() -> assertAcked(prepareCreate(PRIMARY_INDEX_NAME)), PRIMARY_INDEX_NAME); } - /** - * Check that a legacy template applying a system alias creates a hidden alias. - */ - public void testCreateSystemAliasViaV1Template() throws Exception { + private void createSystemAliasViaV1Template(String indexName, String primaryIndexName) throws Exception { assertAcked( client().admin() .indices() .preparePutTemplate("test-template") - .setPatterns(List.of(INDEX_NAME + "*")) - .addAlias(new Alias(INDEX_NAME + "-legacy-alias")) + .setPatterns(List.of(indexName + "*")) + .addAlias(new Alias(indexName + "-legacy-alias")) .get() ); - assertAcked(prepareCreate(PRIMARY_INDEX_NAME)); - ensureGreen(PRIMARY_INDEX_NAME); + assertAcked(prepareCreate(primaryIndexName)); + ensureGreen(primaryIndexName); + } - assertHasAliases(Set.of(".test-index", ".test-index-legacy-alias")); + /** + * Check that a legacy template does not create an alias for a system index + */ + public void testCreateSystemAliasViaV1Template() throws Exception { + createSystemAliasViaV1Template(INDEX_NAME, PRIMARY_INDEX_NAME); - assertAcked(client().admin().indices().prepareDeleteTemplate("*").get()); + assertHasAliases(Set.of(INDEX_NAME), INDEX_NAME, PRIMARY_INDEX_NAME, 1); } /** - * Check that a composable template applying a system alias creates a hidden alias. + * Check that a legacy template does create an alias for a system index because of allows templates */ - public void testCreateSystemAliasViaComposableTemplate() throws Exception { + public void testCreateSystemAliasViaV1TemplateAllowsTemplates() throws Exception { + createSystemAliasViaV1Template( + TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME, + TestSystemIndexDescriptorAllowsTemplates.PRIMARY_INDEX_NAME + ); + + assertHasAliases( + Set.of( + TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME, + TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME + "-legacy-alias" + ), + TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME, + TestSystemIndexDescriptorAllowsTemplates.PRIMARY_INDEX_NAME, + 2 + ); + } + + private void createIndexWithComposableTemplates(String indexName, String primaryIndexName) throws Exception { ComposableIndexTemplate cit = new ComposableIndexTemplate( - Collections.singletonList(INDEX_NAME + "*"), + Collections.singletonList(indexName + "*"), new Template( null, null, - Map.of(INDEX_NAME + "-composable-alias", AliasMetadata.builder(INDEX_NAME + "-composable-alias").build()) + Map.of(indexName + "-composable-alias", AliasMetadata.builder(indexName + "-composable-alias").build()) ), Collections.emptyList(), 4L, @@ -201,10 +221,44 @@ public void testCreateSystemAliasViaComposableTemplate() throws Exception { ).get() ); - assertAcked(prepareCreate(PRIMARY_INDEX_NAME)); - ensureGreen(PRIMARY_INDEX_NAME); + assertAcked(prepareCreate(primaryIndexName)); + ensureGreen(primaryIndexName); + } - assertHasAliases(Set.of(".test-index", ".test-index-composable-alias")); + /** + * Check that a composable template does not create an alias for a system index + */ + public void testCreateSystemAliasViaComposableTemplate() throws Exception { + createIndexWithComposableTemplates(INDEX_NAME, PRIMARY_INDEX_NAME); + + assertHasAliases(Set.of(INDEX_NAME), INDEX_NAME, PRIMARY_INDEX_NAME, 1); + + assertAcked( + client().execute( + DeleteComposableIndexTemplateAction.INSTANCE, + new DeleteComposableIndexTemplateAction.Request("test-composable-template") + ).get() + ); + } + + /** + * Check that a composable template does create an alias for a system index because of allows templates + */ + public void testCreateSystemAliasViaComposableTemplateWithAllowsTemplates() throws Exception { + createIndexWithComposableTemplates( + TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME, + TestSystemIndexDescriptorAllowsTemplates.PRIMARY_INDEX_NAME + ); + + assertHasAliases( + Set.of( + TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME, + TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME + "-composable-alias" + ), + TestSystemIndexDescriptorAllowsTemplates.INDEX_NAME, + TestSystemIndexDescriptorAllowsTemplates.PRIMARY_INDEX_NAME, + 2 + ); assertAcked( client().execute( @@ -278,21 +332,22 @@ private void assertAliases(String concreteIndex) { assertThat(getAliasesResponse.getAliases().get(concreteIndex).get(0).writeIndex(), equalTo(true)); } - private void assertHasAliases(Set aliasNames) throws InterruptedException, java.util.concurrent.ExecutionException { + private void assertHasAliases(Set aliasNames, String name, String primaryName, int aliasCount) throws InterruptedException, + java.util.concurrent.ExecutionException { final GetAliasesResponse getAliasesResponse = client().admin() .indices() .getAliases(new GetAliasesRequest().indicesOptions(IndicesOptions.strictExpandHidden())) .get(); assertThat(getAliasesResponse.getAliases().size(), equalTo(1)); - assertThat(getAliasesResponse.getAliases().get(PRIMARY_INDEX_NAME).size(), equalTo(2)); + assertThat(getAliasesResponse.getAliases().get(primaryName).size(), equalTo(aliasCount)); assertThat( - getAliasesResponse.getAliases().get(PRIMARY_INDEX_NAME).stream().map(AliasMetadata::alias).collect(Collectors.toSet()), + getAliasesResponse.getAliases().get(primaryName).stream().map(AliasMetadata::alias).collect(Collectors.toSet()), equalTo(aliasNames) ); - for (AliasMetadata aliasMetadata : getAliasesResponse.getAliases().get(PRIMARY_INDEX_NAME)) { + for (AliasMetadata aliasMetadata : getAliasesResponse.getAliases().get(primaryName)) { assertThat(aliasMetadata.isHidden(), equalTo(true)); - if (aliasMetadata.alias().equals(INDEX_NAME)) { + if (aliasMetadata.alias().equals(name)) { assertThat(aliasMetadata.writeIndex(), is(true)); } else { assertThat(aliasMetadata.writeIndex(), is(nullValue())); diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptor.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptor.java index de5ba3a621dc4..58830f978ee30 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptor.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptor.java @@ -59,6 +59,27 @@ public class TestSystemIndexDescriptor extends SystemIndexDescriptor { ); } + TestSystemIndexDescriptor(String name, String primaryName, boolean allowsTemplates) { + super( + name + "*", + primaryName, + "Test system index", + getOldMappings(), + SETTINGS, + name, + 0, + "version", + "stack", + Version.CURRENT.minimumCompatibilityVersion(), + Type.INTERNAL_MANAGED, + List.of(), + List.of(), + null, + false, + allowsTemplates + ); + } + @Override public boolean isAutomaticallyManaged() { return true; diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptorAllowsTemplates.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptorAllowsTemplates.java new file mode 100644 index 0000000000000..1cfbea473ce6f --- /dev/null +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexDescriptorAllowsTemplates.java @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch.indices; + +/** + * A special kind of {@link SystemIndexDescriptor} that is exactly like {@link TestSystemIndexDescriptor}, + * but it allows for user defined templates to apply to it. + */ +public class TestSystemIndexDescriptorAllowsTemplates extends TestSystemIndexDescriptor { + + public static final String INDEX_NAME = ".templates-index"; + public static final String PRIMARY_INDEX_NAME = INDEX_NAME + "-1"; + + TestSystemIndexDescriptorAllowsTemplates() { + super(INDEX_NAME, PRIMARY_INDEX_NAME, true); + } +} diff --git a/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexPlugin.java b/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexPlugin.java index dfcd4a90ee174..e11e85e610f6e 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexPlugin.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/indices/TestSystemIndexPlugin.java @@ -21,7 +21,7 @@ public class TestSystemIndexPlugin extends Plugin implements SystemIndexPlugin { @Override public Collection getSystemIndexDescriptors(Settings settings) { - return List.of(new TestSystemIndexDescriptor()); + return List.of(new TestSystemIndexDescriptor(), new TestSystemIndexDescriptorAllowsTemplates()); } @Override diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java index 7510de0ecee5d..358134b0ca202 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java @@ -66,6 +66,7 @@ import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.InvalidIndexNameException; import org.elasticsearch.indices.ShardLimitValidator; +import org.elasticsearch.indices.SystemIndexDescriptor; import org.elasticsearch.indices.SystemIndices; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xcontent.NamedXContentRegistry; @@ -352,6 +353,13 @@ public ClusterState applyCreateIndexRequest( return applyCreateIndexRequestForSystemDataStream(currentState, request, silent, metadataTransformer); } + SystemIndexDescriptor descriptor = systemIndices.findMatchingDescriptor(request.index()); + // ignore all templates for all system indices that do not allow templates. + // Essentially, all but .kibana indices, see KibanaPlugin.java. + if (Objects.nonNull(descriptor) && descriptor.allowsTemplates() == false) { + return applyCreateIndexRequestForSystemIndex(currentState, request, silent, descriptor.getIndexPattern()); + } + // Hidden indices apply templates slightly differently (ignoring wildcard '*' // templates), so we need to check to see if the request is creating a hidden index // prior to resolving which templates it matches @@ -632,6 +640,52 @@ private ClusterState applyCreateIndexRequestWithV2Template( ); } + private ClusterState applyCreateIndexRequestForSystemIndex( + final ClusterState currentState, + final CreateIndexClusterStateUpdateRequest request, + final boolean silent, + final String indexPattern + ) throws Exception { + logger.debug("applying create index request for system index [{}] matching pattern [{}]", request.index(), indexPattern); + + final Settings aggregatedIndexSettings = aggregateIndexSettings( + currentState, + request, + Settings.EMPTY, + null, + null, + settings, + indexScopedSettings, + shardLimitValidator, + indexSettingProviders + ); + final int routingNumShards = getIndexNumberOfRoutingShards(aggregatedIndexSettings, null); + final IndexMetadata tmpImd = buildAndValidateTemporaryIndexMetadata(aggregatedIndexSettings, request, routingNumShards); + + return applyCreateIndexWithTemporaryService( + currentState, + request, + silent, + null, + tmpImd, + List.of(new CompressedXContent(MapperService.parseMapping(xContentRegistry, request.mappings()))), + indexService -> resolveAndValidateAliases( + request.index(), + request.aliases(), + List.of(), + currentState.metadata(), + // the context is only used for validation so it's fine to pass fake values for the + // shard id and the current timestamp + xContentRegistry, + indexService.newSearchExecutionContext(0, 0, null, () -> 0L, null, emptyMap()), + IndexService.dateMathExpressionResolverAt(request.getNameResolvedAt()), + systemIndices::isSystemName + ), + List.of(), + null + ); + } + private ClusterState applyCreateIndexRequestForSystemDataStream( final ClusterState currentState, final CreateIndexClusterStateUpdateRequest request,