Prevent putting V2 index template when overlapping with existing template (#54933) (#55042)

* Prevent putting V2 index template when overlapping with existing template

This change prevents putting V2 index template when it would overlap with existing V2 template
of the same priority

Relates to #53101
This commit is contained in:
Przemko Robakowski 2020-04-10 10:31:37 +02:00 committed by GitHub
parent a7e4f79e8f
commit 35c195b224
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 6 deletions

View File

@ -305,7 +305,23 @@ public class MetadataIndexTemplateService {
throw new IllegalArgumentException("index template [" + name + "] already exists");
}
Map<String, List<String>> overlaps = findConflictingV1Templates(currentState, name, template.indexPatterns());
Map<String, List<String>> overlaps = findConflictingV2Templates(currentState, name, template.indexPatterns(), true,
template.priority());
if (overlaps.size() > 0) {
String error = String.format(Locale.ROOT, "index template [%s] has index patterns %s matching patterns from " +
"existing templates [%s] with patterns (%s) that have the same priority [%d], multiple index templates may not " +
"match during index creation, please use a different priority",
name,
template.indexPatterns(),
Strings.collectionToCommaDelimitedString(overlaps.keySet()),
overlaps.entrySet().stream()
.map(e -> e.getKey() + " => " + e.getValue())
.collect(Collectors.joining(",")),
template.priority());
throw new IllegalArgumentException(error);
}
overlaps = findConflictingV1Templates(currentState, name, template.indexPatterns());
if (overlaps.size() > 0) {
String warning = String.format(Locale.ROOT, "index template [%s] has index patterns %s matching patterns from " +
"existing older templates [%s] with patterns (%s); this template [%s] will take precedence during new index creation",
@ -385,6 +401,15 @@ public class MetadataIndexTemplateService {
*/
static Map<String, List<String>> findConflictingV2Templates(final ClusterState state, final String candidateName,
final List<String> indexPatterns) {
return findConflictingV2Templates(state, candidateName, indexPatterns, false, null);
}
/**
* Return a map of v2 template names to their index patterns for v2 templates that would overlap
* with the given template's index patterns.
*/
static Map<String, List<String>> findConflictingV2Templates(final ClusterState state, final String candidateName,
final List<String> indexPatterns, boolean checkPriority, Long priority) {
Automaton v1automaton = Regex.simpleMatchToAutomaton(indexPatterns.toArray(Strings.EMPTY_ARRAY));
Map<String, List<String>> overlappingTemplates = new HashMap<>();
for (Map.Entry<String, IndexTemplateV2> entry : state.metadata().templatesV2().entrySet()) {
@ -392,9 +417,11 @@ public class MetadataIndexTemplateService {
IndexTemplateV2 template = entry.getValue();
Automaton v2automaton = Regex.simpleMatchToAutomaton(template.indexPatterns().toArray(Strings.EMPTY_ARRAY));
if (Operations.isEmpty(Operations.intersection(v1automaton, v2automaton)) == false) {
logger.debug("old template {} and index template {} would overlap: {} <=> {}",
candidateName, name, indexPatterns, template.indexPatterns());
overlappingTemplates.put(name, template.indexPatterns());
if (checkPriority == false || Objects.equals(priority, template.priority())) {
logger.debug("old template {} and index template {} would overlap: {} <=> {}",
candidateName, name, indexPatterns, template.indexPatterns());
overlappingTemplates.put(name, template.indexPatterns());
}
}
}
return overlappingTemplates;

View File

@ -300,12 +300,16 @@ public class MetadataIndexTemplateServiceTests extends ESSingleNodeTestCase {
assertNotNull(state.metadata().templatesV2().get("foo"));
assertTemplatesEqual(state.metadata().templatesV2().get("foo"), template);
IndexTemplateV2 newTemplate = randomValueOtherThanMany(t -> Objects.equals(template.priority(), t.priority()),
IndexTemplateV2Tests::randomInstance);
final ClusterState throwState = ClusterState.builder(state).build();
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> metadataIndexTemplateService.addIndexTemplateV2(throwState, true, "foo", template));
() -> metadataIndexTemplateService.addIndexTemplateV2(throwState, true, "foo", newTemplate));
assertThat(e.getMessage(), containsString("index template [foo] already exists"));
state = metadataIndexTemplateService.addIndexTemplateV2(state, randomBoolean(), "bar", template);
state = metadataIndexTemplateService.addIndexTemplateV2(state, randomBoolean(), "bar", newTemplate);
assertNotNull(state.metadata().templatesV2().get("bar"));
}
@ -471,6 +475,18 @@ public class MetadataIndexTemplateServiceTests extends ESSingleNodeTestCase {
"templates (/_index_template) instead"));
}
public void testPuttingOverlappingV2Template() throws Exception {
IndexTemplateV2 template = new IndexTemplateV2(Arrays.asList("egg*", "baz"), null, null, 1L, null, null);
MetadataIndexTemplateService metadataIndexTemplateService = getMetadataIndexTemplateService();
ClusterState state = metadataIndexTemplateService.addIndexTemplateV2(ClusterState.EMPTY_STATE, false, "foo", template);
IndexTemplateV2 newTemplate = new IndexTemplateV2(Arrays.asList("abc", "baz*"), null, null, 1L, null, null);
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> metadataIndexTemplateService.addIndexTemplateV2(state, false, "foo2", newTemplate));
assertThat(e.getMessage(), equalTo("index template [foo2] has index patterns [abc, baz*] matching patterns from existing " +
"templates [foo] with patterns (foo => [egg*, baz]) that have the same priority [1], multiple index templates may not " +
"match during index creation, please use a different priority"));
}
public void testFindV2Templates() throws Exception {
final MetadataIndexTemplateService service = getMetadataIndexTemplateService();
ClusterState state = ClusterState.EMPTY_STATE;