From b88d2f62554ffa2f4b9e762417633c562595fbfb Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Fri, 14 Aug 2015 10:03:06 -0700 Subject: [PATCH] Validate settings specified in index templates at template creation time Previously settings specified in index templates were not validated upon template creation. Creating an index from an index template with invalid settings could lead to cluster stability issues because creation of such indexes would bypass index settings validation. This commit adds validation of settings specified in index templates at template creation time. This works by routing the index template settings through the index settings validation mechanism. Closes #12865 --- .../MetaDataIndexTemplateService.java | 11 ++- .../MetaDataIndexTemplateServiceTests.java | 81 +++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 core/src/test/java/org/elasticsearch/action/admin/indices/template/put/MetaDataIndexTemplateServiceTests.java diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexTemplateService.java b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexTemplateService.java index 840532e8637..96f79155955 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexTemplateService.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexTemplateService.java @@ -34,6 +34,7 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.indices.IndexCreationException; import org.elasticsearch.indices.IndexTemplateAlreadyExistsException; import org.elasticsearch.indices.IndexTemplateMissingException; import org.elasticsearch.indices.InvalidIndexTemplateException; @@ -50,12 +51,14 @@ public class MetaDataIndexTemplateService extends AbstractComponent { private final ClusterService clusterService; private final AliasValidator aliasValidator; + private final MetaDataCreateIndexService metaDataCreateIndexService; @Inject - public MetaDataIndexTemplateService(Settings settings, ClusterService clusterService, AliasValidator aliasValidator) { + public MetaDataIndexTemplateService(Settings settings, ClusterService clusterService, MetaDataCreateIndexService metaDataCreateIndexService, AliasValidator aliasValidator) { super(settings); this.clusterService = clusterService; this.aliasValidator = aliasValidator; + this.metaDataCreateIndexService = metaDataCreateIndexService; } public void removeTemplates(final RemoveRequest request, final RemoveListener listener) { @@ -207,6 +210,12 @@ public class MetaDataIndexTemplateService extends AbstractComponent { throw new InvalidIndexTemplateException(request.name, "template must not container the following characters " + Strings.INVALID_FILENAME_CHARS); } + try { + metaDataCreateIndexService.validateIndexSettings(request.name, request.settings); + } catch (IndexCreationException exception) { + throw new InvalidIndexTemplateException(request.name, exception.getDetailedMessage()); + } + for (Alias alias : request.aliases) { //we validate the alias only partially, as we don't know yet to which index it'll get applied to aliasValidator.validateAliasStandalone(alias); diff --git a/core/src/test/java/org/elasticsearch/action/admin/indices/template/put/MetaDataIndexTemplateServiceTests.java b/core/src/test/java/org/elasticsearch/action/admin/indices/template/put/MetaDataIndexTemplateServiceTests.java new file mode 100644 index 00000000000..197a6b3b351 --- /dev/null +++ b/core/src/test/java/org/elasticsearch/action/admin/indices/template/put/MetaDataIndexTemplateServiceTests.java @@ -0,0 +1,81 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.action.admin.indices.template.put; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.elasticsearch.Version; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.metadata.IndexTemplateFilter; +import org.elasticsearch.cluster.metadata.MetaDataCreateIndexService; +import org.elasticsearch.cluster.metadata.MetaDataIndexTemplateService; +import org.elasticsearch.cluster.metadata.MetaDataIndexTemplateService.PutRequest; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.indices.InvalidIndexTemplateException; +import org.elasticsearch.test.ESTestCase; +import org.junit.Test; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +public class MetaDataIndexTemplateServiceTests extends ESTestCase { + @Test + public void testIndexTemplateInvalidNumberOfShards() throws IOException { + MetaDataCreateIndexService createIndexService = new MetaDataCreateIndexService( + Settings.EMPTY, + null, + null, + null, + null, + null, + Version.CURRENT, + null, + Sets.newHashSet(), + null, + null + ); + MetaDataIndexTemplateService service = new MetaDataIndexTemplateService(Settings.EMPTY, null, createIndexService, null); + + PutRequest request = new PutRequest("test", "test_shards"); + request.template("test_shards*"); + + Map map = Maps.newHashMap(); + map.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, "0"); + request.settings(Settings.settingsBuilder().put(map).build()); + + final List throwables = Lists.newArrayList(); + service.putTemplate(request, new MetaDataIndexTemplateService.PutListener() { + @Override + public void onResponse(MetaDataIndexTemplateService.PutResponse response) { + + } + + @Override + public void onFailure(Throwable t) { + throwables.add(t); + } + }); + assertEquals(throwables.size(), 1); + assertTrue(throwables.get(0) instanceof InvalidIndexTemplateException); + assertTrue(throwables.get(0).getMessage().contains("index must have 1 or more primary shards")); + } +}