Backports the following commits to 7.x: Disallow deletion of composable template if in use by data stream (#57957)
This commit is contained in:
parent
d9e547dbd3
commit
ffc3c77f75
|
@ -24,6 +24,7 @@ import org.elasticsearch.ElasticsearchException;
|
|||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.admin.indices.alias.Alias;
|
||||
import org.elasticsearch.action.admin.indices.datastream.DeleteDataStreamAction;
|
||||
import org.elasticsearch.action.admin.indices.datastream.GetDataStreamAction;
|
||||
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.get.GetIndexResponse;
|
||||
|
@ -271,6 +272,8 @@ public class BulkIntegrationIT extends ESIntegTestCase {
|
|||
assertThat(getIndexResponse.getIndices(), hasItemInArray("logs-barfoo2"));
|
||||
assertThat(getIndexResponse.getIndices(), hasItemInArray("logs-barfoo3"));
|
||||
|
||||
DeleteDataStreamAction.Request deleteDSReq = new DeleteDataStreamAction.Request("*");
|
||||
client().execute(DeleteDataStreamAction.INSTANCE, deleteDSReq).actionGet();
|
||||
DeleteComposableIndexTemplateAction.Request deleteTemplateRequest = new DeleteComposableIndexTemplateAction.Request("*");
|
||||
client().execute(DeleteComposableIndexTemplateAction.INSTANCE, deleteTemplateRequest).actionGet();
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.elasticsearch.indices;
|
||||
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.action.ActionRequestBuilder;
|
||||
import org.elasticsearch.action.DocWriteRequest;
|
||||
import org.elasticsearch.action.admin.indices.datastream.CreateDataStreamAction;
|
||||
|
@ -61,6 +62,7 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.elasticsearch.indices.IndicesOptionsIntegrationIT._flush;
|
||||
import static org.elasticsearch.indices.IndicesOptionsIntegrationIT.clearCache;
|
||||
|
@ -87,6 +89,8 @@ public class DataStreamIT extends ESIntegTestCase {
|
|||
|
||||
@After
|
||||
public void deleteAllComposableTemplates() {
|
||||
DeleteDataStreamAction.Request deleteDSRequest = new DeleteDataStreamAction.Request("*");
|
||||
client().execute(DeleteDataStreamAction.INSTANCE, deleteDSRequest).actionGet();
|
||||
DeleteComposableIndexTemplateAction.Request deleteTemplateRequest = new DeleteComposableIndexTemplateAction.Request("*");
|
||||
client().execute(DeleteComposableIndexTemplateAction.INSTANCE, deleteTemplateRequest).actionGet();
|
||||
}
|
||||
|
@ -363,6 +367,29 @@ public class DataStreamIT extends ESIntegTestCase {
|
|||
verifyResolvability(wildcardExpression, client().admin().indices().prepareGetIndex().addIndices(wildcardExpression), false);
|
||||
}
|
||||
|
||||
public void testCannotDeleteComposableTemplateUsedByDataStream() throws Exception {
|
||||
createIndexTemplate("id", "metrics-foobar*", "@timestamp1");
|
||||
String dataStreamName = "metrics-foobar-baz";
|
||||
CreateDataStreamAction.Request createDataStreamRequest = new CreateDataStreamAction.Request(dataStreamName);
|
||||
client().admin().indices().createDataStream(createDataStreamRequest).get();
|
||||
createDataStreamRequest = new CreateDataStreamAction.Request(dataStreamName + "-eggplant");
|
||||
client().admin().indices().createDataStream(createDataStreamRequest).get();
|
||||
|
||||
DeleteComposableIndexTemplateAction.Request req = new DeleteComposableIndexTemplateAction.Request("id");
|
||||
Exception e = expectThrows(Exception.class, () -> client().execute(DeleteComposableIndexTemplateAction.INSTANCE, req).get());
|
||||
Optional<Exception> maybeE = ExceptionsHelper.unwrapCausesAndSuppressed(e, err ->
|
||||
err.getMessage().contains("unable to remove composable templates [id] " +
|
||||
"as they are in use by a data streams [metrics-foobar-baz, metrics-foobar-baz-eggplant]"));
|
||||
assertTrue(maybeE.isPresent());
|
||||
|
||||
DeleteComposableIndexTemplateAction.Request req2 = new DeleteComposableIndexTemplateAction.Request("i*");
|
||||
Exception e2 = expectThrows(Exception.class, () -> client().execute(DeleteComposableIndexTemplateAction.INSTANCE, req2).get());
|
||||
maybeE = ExceptionsHelper.unwrapCausesAndSuppressed(e2, err ->
|
||||
err.getMessage().contains("unable to remove composable templates [id] " +
|
||||
"as they are in use by a data streams [metrics-foobar-baz, metrics-foobar-baz-eggplant]"));
|
||||
assertTrue(maybeE.isPresent());
|
||||
}
|
||||
|
||||
private static void verifyResolvability(String dataStream, ActionRequestBuilder requestBuilder, boolean fail) {
|
||||
verifyResolvability(dataStream, requestBuilder, fail, 0);
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -611,6 +612,17 @@ public class MetadataIndexTemplateService {
|
|||
}
|
||||
throw new IndexTemplateMissingException(name);
|
||||
}
|
||||
|
||||
Optional<Set<String>> dataStreamsUsingTemplates = templateNames.stream()
|
||||
.map(templateName -> dataStreamsUsingTemplate(currentState, templateName))
|
||||
.reduce(Sets::union);
|
||||
dataStreamsUsingTemplates.ifPresent(set -> {
|
||||
if (set.size() > 0) {
|
||||
throw new IllegalArgumentException("unable to remove composable templates " + new TreeSet<>(templateNames) +
|
||||
" as they are in use by a data streams " + new TreeSet<>(set));
|
||||
}
|
||||
});
|
||||
|
||||
Metadata.Builder metadata = Metadata.builder(currentState.metadata());
|
||||
for (String templateName : templateNames) {
|
||||
logger.info("removing index template [{}]", templateName);
|
||||
|
@ -619,6 +631,18 @@ public class MetadataIndexTemplateService {
|
|||
return ClusterState.builder(currentState).metadata(metadata).build();
|
||||
}
|
||||
|
||||
static Set<String> dataStreamsUsingTemplate(final ClusterState state, final String templateName) {
|
||||
final ComposableIndexTemplate template = state.metadata().templatesV2().get(templateName);
|
||||
if (template == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
final Set<String> dataStreams = state.metadata().dataStreams().keySet();
|
||||
Set<String> matches = new HashSet<>();
|
||||
template.indexPatterns().forEach(indexPattern ->
|
||||
matches.addAll(dataStreams.stream().filter(stream -> Regex.simpleMatch(indexPattern, stream)).collect(Collectors.toList())));
|
||||
return matches;
|
||||
}
|
||||
|
||||
public void putTemplate(final PutRequest request, final PutListener listener) {
|
||||
Settings.Builder updatedSettingsBuilder = Settings.builder();
|
||||
updatedSettingsBuilder.put(request.settings).normalizePrefix(IndexMetadata.INDEX_SETTING_PREFIX);
|
||||
|
|
Loading…
Reference in New Issue