|
@@ -20,6 +20,7 @@
|
|
package org.elasticsearch.cluster.metadata;
|
|
package org.elasticsearch.cluster.metadata;
|
|
|
|
|
|
import com.fasterxml.jackson.core.JsonParseException;
|
|
import com.fasterxml.jackson.core.JsonParseException;
|
|
|
|
+import org.elasticsearch.Version;
|
|
import org.elasticsearch.action.ActionListener;
|
|
import org.elasticsearch.action.ActionListener;
|
|
import org.elasticsearch.action.admin.indices.alias.Alias;
|
|
import org.elasticsearch.action.admin.indices.alias.Alias;
|
|
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
|
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
|
@@ -37,6 +38,7 @@ import org.elasticsearch.common.xcontent.XContentFactory;
|
|
import org.elasticsearch.common.xcontent.XContentParser;
|
|
import org.elasticsearch.common.xcontent.XContentParser;
|
|
import org.elasticsearch.common.xcontent.XContentType;
|
|
import org.elasticsearch.common.xcontent.XContentType;
|
|
import org.elasticsearch.env.Environment;
|
|
import org.elasticsearch.env.Environment;
|
|
|
|
+import org.elasticsearch.index.Index;
|
|
import org.elasticsearch.index.mapper.MapperParsingException;
|
|
import org.elasticsearch.index.mapper.MapperParsingException;
|
|
import org.elasticsearch.index.mapper.MapperService;
|
|
import org.elasticsearch.index.mapper.MapperService;
|
|
import org.elasticsearch.indices.IndexTemplateMissingException;
|
|
import org.elasticsearch.indices.IndexTemplateMissingException;
|
|
@@ -1062,6 +1064,88 @@ public class MetadataIndexTemplateServiceTests extends ESSingleNodeTestCase {
|
|
assertThat(metadataIndexTemplateService.addIndexTemplateV2(state, false, "foo", template), equalTo(state));
|
|
assertThat(metadataIndexTemplateService.addIndexTemplateV2(state, false, "foo", template), equalTo(state));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public void testUnreferencedDataStreamsWhenAddingTemplate() throws Exception {
|
|
|
|
+ ClusterState state = ClusterState.EMPTY_STATE;
|
|
|
|
+ final MetadataIndexTemplateService service = getMetadataIndexTemplateService();
|
|
|
|
+ state = ClusterState.builder(state)
|
|
|
|
+ .metadata(Metadata.builder(state.metadata())
|
|
|
|
+ .put(new DataStream("unreferenced",
|
|
|
|
+ new DataStream.TimestampField("@timestamp", Collections.singletonMap("type", "date")),
|
|
|
|
+ Collections.singletonList(new Index(".ds-unreferenced-000001", "uuid2"))))
|
|
|
|
+ .put(IndexMetadata.builder(".ds-unreferenced-000001")
|
|
|
|
+ .settings(Settings.builder()
|
|
|
|
+ .put(IndexMetadata.SETTING_INDEX_UUID, "uuid2")
|
|
|
|
+ .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
|
|
|
|
+ .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
|
|
|
|
+ .put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT)
|
|
|
|
+ .build()))
|
|
|
|
+ .build())
|
|
|
|
+ .build();
|
|
|
|
+
|
|
|
|
+ ComposableIndexTemplate template = new ComposableIndexTemplate(Collections.singletonList("logs-*-*"), null, null,
|
|
|
|
+ 100L, null, null, new ComposableIndexTemplate.DataStreamTemplate("@timestamp"));
|
|
|
|
+
|
|
|
|
+ state = service.addIndexTemplateV2(state, false, "logs", template);
|
|
|
|
+
|
|
|
|
+ ClusterState stateWithDS = ClusterState.builder(state)
|
|
|
|
+ .metadata(Metadata.builder(state.metadata())
|
|
|
|
+ .put(new DataStream("logs-mysql-default",
|
|
|
|
+ new DataStream.TimestampField("@timestamp", Collections.singletonMap("type", "date")),
|
|
|
|
+ Collections.singletonList(new Index(".ds-logs-mysql-default-000001", "uuid"))))
|
|
|
|
+ .put(IndexMetadata.builder(".ds-logs-mysql-default-000001")
|
|
|
|
+ .settings(Settings.builder()
|
|
|
|
+ .put(IndexMetadata.SETTING_INDEX_UUID, "uuid")
|
|
|
|
+ .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
|
|
|
|
+ .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
|
|
|
|
+ .put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT)
|
|
|
|
+ .build()))
|
|
|
|
+ .build())
|
|
|
|
+ .build();
|
|
|
|
+
|
|
|
|
+ // Test replacing it with a version without the data stream config
|
|
|
|
+ IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> {
|
|
|
|
+ ComposableIndexTemplate nonDSTemplate = new ComposableIndexTemplate(Collections.singletonList("logs-*-*"), null, null,
|
|
|
|
+ 100L, null, null, null);
|
|
|
|
+ service.addIndexTemplateV2(stateWithDS, false, "logs", nonDSTemplate);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ assertThat(e.getMessage(),
|
|
|
|
+ containsString("composable template [logs] with index patterns [logs-*-*], priority [100] and no data stream " +
|
|
|
|
+ "configuration would cause data streams [unreferenced, logs-mysql-default] to no longer match a data stream template"));
|
|
|
|
+
|
|
|
|
+ // Test adding a higher priority version that would cause problems
|
|
|
|
+ e = expectThrows(IllegalArgumentException.class, () -> {
|
|
|
|
+ ComposableIndexTemplate nonDSTemplate = new ComposableIndexTemplate(Collections.singletonList("logs-my*-*"), null, null,
|
|
|
|
+ 105L, null, null, null);
|
|
|
|
+ service.addIndexTemplateV2(stateWithDS, false, "logs2", nonDSTemplate);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ assertThat(e.getMessage(),
|
|
|
|
+ containsString("composable template [logs2] with index patterns [logs-my*-*], priority [105] and no data stream " +
|
|
|
|
+ "configuration would cause data streams [unreferenced, logs-mysql-default] to no longer match a data stream template"));
|
|
|
|
+
|
|
|
|
+ // Change the pattern to one that doesn't match the data stream
|
|
|
|
+ e = expectThrows(IllegalArgumentException.class, () -> {
|
|
|
|
+ ComposableIndexTemplate newTemplate = new ComposableIndexTemplate(Collections.singletonList("logs-postgres-*"), null, null,
|
|
|
|
+ 100L, null, null, new ComposableIndexTemplate.DataStreamTemplate("@timestamp"));
|
|
|
|
+ service.addIndexTemplateV2(stateWithDS, false, "logs", newTemplate);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ assertThat(e.getMessage(),
|
|
|
|
+ containsString("composable template [logs] with index patterns [logs-postgres-*], priority [100] would " +
|
|
|
|
+ "cause data streams [unreferenced, logs-mysql-default] to no longer match a data stream template"));
|
|
|
|
+
|
|
|
|
+ // Add an additional template that matches our data stream at a lower priority
|
|
|
|
+ ComposableIndexTemplate mysqlTemplate = new ComposableIndexTemplate(Collections.singletonList("logs-mysql-*"), null, null,
|
|
|
|
+ 50L, null, null, new ComposableIndexTemplate.DataStreamTemplate("@timestamp"));
|
|
|
|
+ ClusterState stateWithDSAndTemplate = service.addIndexTemplateV2(stateWithDS, false, "logs-mysql", mysqlTemplate);
|
|
|
|
+
|
|
|
|
+ // We should be able to replace the "logs" template, because we have the "logs-mysql" template that can handle the data stream
|
|
|
|
+ ComposableIndexTemplate nonDSTemplate = new ComposableIndexTemplate(Collections.singletonList("logs-postgres-*"), null, null,
|
|
|
|
+ 100L, null, null, null);
|
|
|
|
+ service.addIndexTemplateV2(stateWithDSAndTemplate, false, "logs", nonDSTemplate);
|
|
|
|
+ }
|
|
|
|
+
|
|
private static List<Throwable> putTemplate(NamedXContentRegistry xContentRegistry, PutRequest request) {
|
|
private static List<Throwable> putTemplate(NamedXContentRegistry xContentRegistry, PutRequest request) {
|
|
MetadataCreateIndexService createIndexService = new MetadataCreateIndexService(
|
|
MetadataCreateIndexService createIndexService = new MetadataCreateIndexService(
|
|
Settings.EMPTY,
|
|
Settings.EMPTY,
|