Prevent constructing index template without patterns (#27662)
Today, we prevent the system from storing a broken index template in the transport layer, however we don't prevent this in XContent. A broken index template can break the whole cluster state. This commit attempts to prevent the system from constructing an index template without a proper index patterns.
This commit is contained in:
parent
2f9a882061
commit
ed2caf2bad
|
@ -93,6 +93,9 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
|
|||
ImmutableOpenMap<String, CompressedXContent> mappings,
|
||||
ImmutableOpenMap<String, AliasMetaData> aliases,
|
||||
ImmutableOpenMap<String, IndexMetaData.Custom> customs) {
|
||||
if (patterns == null || patterns.isEmpty()) {
|
||||
throw new IllegalArgumentException("Index patterns must not be null or empty; got " + patterns);
|
||||
}
|
||||
this.name = name;
|
||||
this.order = order;
|
||||
this.version = version;
|
||||
|
@ -244,7 +247,7 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
|
|||
if (out.getVersion().onOrAfter(Version.V_6_0_0_alpha1)) {
|
||||
out.writeStringList(patterns);
|
||||
} else {
|
||||
out.writeString(patterns.size() > 0 ? patterns.get(0) : "");
|
||||
out.writeString(patterns.get(0));
|
||||
}
|
||||
Settings.writeSettingsToStream(settings, out);
|
||||
out.writeVInt(mappings.size());
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.elasticsearch.cluster.metadata;
|
|||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
||||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
@ -120,4 +121,45 @@ public class IndexTemplateMetaDataTests extends ESTestCase {
|
|||
assertThat(indexTemplateMetaData, equalTo(indexTemplateMetaDataRoundTrip));
|
||||
}
|
||||
|
||||
public void testValidateInvalidIndexPatterns() throws Exception {
|
||||
final IllegalArgumentException emptyPatternError = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new IndexTemplateMetaData(randomRealisticUnicodeOfLengthBetween(5, 10), randomInt(), randomInt(),
|
||||
Collections.emptyList(), Settings.EMPTY, ImmutableOpenMap.of(), ImmutableOpenMap.of(), ImmutableOpenMap.of());
|
||||
});
|
||||
assertThat(emptyPatternError.getMessage(), equalTo("Index patterns must not be null or empty; got []"));
|
||||
|
||||
final IllegalArgumentException nullPatternError = expectThrows(IllegalArgumentException.class, () -> {
|
||||
new IndexTemplateMetaData(randomRealisticUnicodeOfLengthBetween(5, 10), randomInt(), randomInt(),
|
||||
null, Settings.EMPTY, ImmutableOpenMap.of(), ImmutableOpenMap.of(), ImmutableOpenMap.of());
|
||||
});
|
||||
assertThat(nullPatternError.getMessage(), equalTo("Index patterns must not be null or empty; got null"));
|
||||
|
||||
final String templateWithEmptyPattern = "{\"index_patterns\" : [],\"order\" : 1000," +
|
||||
"\"settings\" : {\"number_of_shards\" : 10,\"number_of_replicas\" : 1}," +
|
||||
"\"mappings\" : {\"doc\" :" +
|
||||
"{\"properties\":{\"" +
|
||||
randomAlphaOfLength(10) + "\":{\"type\":\"text\"},\"" +
|
||||
randomAlphaOfLength(10) + "\":{\"type\":\"keyword\"}}" +
|
||||
"}}}";
|
||||
try (XContentParser parser =
|
||||
XContentHelper.createParser(NamedXContentRegistry.EMPTY, new BytesArray(templateWithEmptyPattern), XContentType.JSON)) {
|
||||
final IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> IndexTemplateMetaData.Builder.fromXContent(parser, randomAlphaOfLengthBetween(1, 100)));
|
||||
assertThat(ex.getMessage(), equalTo("Index patterns must not be null or empty; got []"));
|
||||
}
|
||||
|
||||
final String templateWithoutPattern = "{\"order\" : 1000," +
|
||||
"\"settings\" : {\"number_of_shards\" : 10,\"number_of_replicas\" : 1}," +
|
||||
"\"mappings\" : {\"doc\" :" +
|
||||
"{\"properties\":{\"" +
|
||||
randomAlphaOfLength(10) + "\":{\"type\":\"text\"},\"" +
|
||||
randomAlphaOfLength(10) + "\":{\"type\":\"keyword\"}}" +
|
||||
"}}}";
|
||||
try (XContentParser parser =
|
||||
XContentHelper.createParser(NamedXContentRegistry.EMPTY, new BytesArray(templateWithoutPattern), XContentType.JSON)) {
|
||||
final IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
|
||||
() -> IndexTemplateMetaData.Builder.fromXContent(parser, randomAlphaOfLengthBetween(1, 100)));
|
||||
assertThat(ex.getMessage(), equalTo("Index patterns must not be null or empty; got null"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@ import java.util.Set;
|
|||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static org.elasticsearch.test.VersionUtils.randomVersion;
|
||||
|
@ -61,9 +63,7 @@ import static org.hamcrest.CoreMatchers.nullValue;
|
|||
import static org.hamcrest.CoreMatchers.startsWith;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
|
@ -83,16 +83,17 @@ public class TemplateUpgradeServiceTests extends ESTestCase {
|
|||
boolean shouldChange = randomBoolean();
|
||||
|
||||
MetaData metaData = randomMetaData(
|
||||
IndexTemplateMetaData.builder("user_template").build(),
|
||||
IndexTemplateMetaData.builder("removed_test_template").build(),
|
||||
IndexTemplateMetaData.builder("changed_test_template").build()
|
||||
IndexTemplateMetaData.builder("user_template").patterns(randomIndexPatterns()).build(),
|
||||
IndexTemplateMetaData.builder("removed_test_template").patterns(randomIndexPatterns()).build(),
|
||||
IndexTemplateMetaData.builder("changed_test_template").patterns(randomIndexPatterns()).build()
|
||||
);
|
||||
|
||||
TemplateUpgradeService service = new TemplateUpgradeService(Settings.EMPTY, null, clusterService, null,
|
||||
Arrays.asList(
|
||||
templates -> {
|
||||
if (shouldAdd) {
|
||||
assertNull(templates.put("added_test_template", IndexTemplateMetaData.builder("added_test_template").build()));
|
||||
assertNull(templates.put("added_test_template",
|
||||
IndexTemplateMetaData.builder("added_test_template").patterns(randomIndexPatterns()).build()));
|
||||
}
|
||||
return templates;
|
||||
},
|
||||
|
@ -105,7 +106,7 @@ public class TemplateUpgradeServiceTests extends ESTestCase {
|
|||
templates -> {
|
||||
if (shouldChange) {
|
||||
assertNotNull(templates.put("changed_test_template",
|
||||
IndexTemplateMetaData.builder("changed_test_template").order(10).build()));
|
||||
IndexTemplateMetaData.builder("changed_test_template").patterns(randomIndexPatterns()).order(10).build()));
|
||||
}
|
||||
return templates;
|
||||
}
|
||||
|
@ -234,9 +235,9 @@ public class TemplateUpgradeServiceTests extends ESTestCase {
|
|||
AtomicInteger updateInvocation = new AtomicInteger();
|
||||
|
||||
MetaData metaData = randomMetaData(
|
||||
IndexTemplateMetaData.builder("user_template").build(),
|
||||
IndexTemplateMetaData.builder("removed_test_template").build(),
|
||||
IndexTemplateMetaData.builder("changed_test_template").build()
|
||||
IndexTemplateMetaData.builder("user_template").patterns(randomIndexPatterns()).build(),
|
||||
IndexTemplateMetaData.builder("removed_test_template").patterns(randomIndexPatterns()).build(),
|
||||
IndexTemplateMetaData.builder("changed_test_template").patterns(randomIndexPatterns()).build()
|
||||
);
|
||||
|
||||
ThreadPool threadPool = mock(ThreadPool.class);
|
||||
|
@ -390,4 +391,10 @@ public class TemplateUpgradeServiceTests extends ESTestCase {
|
|||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
List<String> randomIndexPatterns() {
|
||||
return IntStream.range(0, between(1, 10))
|
||||
.mapToObj(n -> randomUnicodeOfCodepointLengthBetween(1, 100))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.elasticsearch.test.VersionUtils;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
@ -170,8 +171,8 @@ public class ClusterSerializationTests extends ESAllocationTestCase {
|
|||
public void testObjectReuseWhenApplyingClusterStateDiff() throws Exception {
|
||||
IndexMetaData indexMetaData
|
||||
= IndexMetaData.builder("test").settings(settings(Version.CURRENT)).numberOfShards(10).numberOfReplicas(1).build();
|
||||
IndexTemplateMetaData indexTemplateMetaData
|
||||
= IndexTemplateMetaData.builder("test-template").patterns(new ArrayList<>()).build();
|
||||
IndexTemplateMetaData indexTemplateMetaData = IndexTemplateMetaData.builder("test-template")
|
||||
.patterns(Arrays.asList(generateRandomStringArray(10, 100, false, false))).build();
|
||||
MetaData metaData = MetaData.builder().put(indexMetaData, true).put(indexTemplateMetaData).build();
|
||||
|
||||
RoutingTable routingTable = RoutingTable.builder().addAsNew(metaData.index("test")).build();
|
||||
|
|
|
@ -32,6 +32,8 @@ import org.elasticsearch.cluster.routing.allocation.AllocationService;
|
|||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -40,7 +42,8 @@ public class ClusterStateToStringTests extends ESAllocationTestCase {
|
|||
public void testClusterStateSerialization() throws Exception {
|
||||
MetaData metaData = MetaData.builder()
|
||||
.put(IndexMetaData.builder("test_idx").settings(settings(Version.CURRENT)).numberOfShards(10).numberOfReplicas(1))
|
||||
.put(IndexTemplateMetaData.builder("test_template").build())
|
||||
.put(IndexTemplateMetaData.builder("test_template")
|
||||
.patterns(Arrays.asList(generateRandomStringArray(10, 100, false,false))).build())
|
||||
.build();
|
||||
|
||||
RoutingTable routingTable = RoutingTable.builder()
|
||||
|
|
|
@ -308,7 +308,8 @@ public class GatewayMetaStateTests extends ESAllocationTestCase {
|
|||
Collections.emptyList(),
|
||||
Collections.singletonList(
|
||||
templates -> {
|
||||
templates.put("added_test_template", IndexTemplateMetaData.builder("added_test_template").build());
|
||||
templates.put("added_test_template", IndexTemplateMetaData.builder("added_test_template")
|
||||
.patterns(Arrays.asList(generateRandomStringArray(10, 100, false, false))).build());
|
||||
return templates;
|
||||
}
|
||||
));
|
||||
|
@ -438,14 +439,17 @@ public class GatewayMetaStateTests extends ESAllocationTestCase {
|
|||
Collections.emptyList(),
|
||||
Arrays.asList(
|
||||
indexTemplateMetaDatas -> {
|
||||
indexTemplateMetaDatas.put("template1", IndexTemplateMetaData.builder("template1").settings(
|
||||
Settings.builder().put(IndexMetaData.INDEX_NUMBER_OF_SHARDS_SETTING.getKey(), 20).build()).build());
|
||||
indexTemplateMetaDatas.put("template1", IndexTemplateMetaData.builder("template1")
|
||||
.patterns(Arrays.asList(generateRandomStringArray(10, 100, false, false)))
|
||||
.settings(Settings.builder().put(IndexMetaData.INDEX_NUMBER_OF_SHARDS_SETTING.getKey(), 20).build())
|
||||
.build());
|
||||
return indexTemplateMetaDatas;
|
||||
|
||||
},
|
||||
indexTemplateMetaDatas -> {
|
||||
indexTemplateMetaDatas.put("template2", IndexTemplateMetaData.builder("template2").settings(
|
||||
Settings.builder().put(IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING.getKey(), 10).build()).build());
|
||||
indexTemplateMetaDatas.put("template2", IndexTemplateMetaData.builder("template2")
|
||||
.patterns(Arrays.asList(generateRandomStringArray(10, 100, false, false)))
|
||||
.settings(Settings.builder().put(IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING.getKey(), 10).build()).build());
|
||||
return indexTemplateMetaDatas;
|
||||
|
||||
}
|
||||
|
@ -535,6 +539,7 @@ public class GatewayMetaStateTests extends ESAllocationTestCase {
|
|||
.settings(settings(Version.CURRENT)
|
||||
.put(IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING.getKey(), randomIntBetween(0, 3))
|
||||
.put(IndexMetaData.INDEX_NUMBER_OF_SHARDS_SETTING.getKey(), randomIntBetween(1, 5)))
|
||||
.patterns(Arrays.asList(generateRandomStringArray(10, 100, false, false)))
|
||||
.build();
|
||||
builder.put(templateMetaData);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue