Browse Source

Create data stream aliases from component templates (#75956)

Dan Hermann 4 years ago
parent
commit
10ffb9396c

+ 3 - 2
server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateDataStreamService.java

@@ -221,8 +221,9 @@ public class MetadataCreateDataStreamService {
         Metadata.Builder builder = Metadata.builder(currentState.metadata()).put(newDataStream);
 
         List<String> aliases = new ArrayList<>();
-        if (template.template() != null && template.template().aliases() != null) {
-            for (var alias : template.template().aliases().values()) {
+        var resolvedAliases = MetadataIndexTemplateService.resolveAliases(currentState.metadata(), template);
+        for (var resolvedAliasMap : resolvedAliases) {
+            for (var alias : resolvedAliasMap.values()) {
                 aliases.add(alias.getAlias());
                 builder.put(alias.getAlias(), dataStreamName, alias.writeIndex(), alias.filter() == null ? null : alias.filter().string());
             }

+ 1 - 1
server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java

@@ -577,7 +577,7 @@ public class MetadataCreateIndexService {
 
         return applyCreateIndexWithTemporaryService(currentState, request, silent, null, tmpImd, mappings,
             indexService -> resolveAndValidateAliases(request.index(), request.aliases(),
-                MetadataIndexTemplateService.resolveAliases(template, componentTemplates, null), currentState.metadata(),
+                MetadataIndexTemplateService.resolveAliases(template, componentTemplates), currentState.metadata(),
                 // the context is only used for validation so it's fine to pass fake values for the
                 // shard id and the current timestamp
                 aliasValidator, xContentRegistry, indexService.newSearchExecutionContext(0, 0, null, () -> 0L, null, emptyMap()),

+ 10 - 4
server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateService.java

@@ -1112,25 +1112,31 @@ public class MetadataIndexTemplateService {
     }
 
     /**
-     * Resolve the given v2 template into an ordered list of aliases
+     * Resolve the given v2 template name into an ordered list of aliases
      */
     public static List<Map<String, AliasMetadata>> resolveAliases(final Metadata metadata, final String templateName) {
         final ComposableIndexTemplate template = metadata.templatesV2().get(templateName);
         assert template != null : "attempted to resolve aliases for a template [" + templateName +
             "] that did not exist in the cluster state";
+        return resolveAliases(metadata, template);
+    }
+
+    /**
+     * Resolve the given v2 template into an ordered list of aliases
+     */
+    static List<Map<String, AliasMetadata>> resolveAliases(final Metadata metadata, final ComposableIndexTemplate template) {
         if (template == null) {
             return List.of();
         }
         final Map<String, ComponentTemplate> componentTemplates = metadata.componentTemplates();
-        return resolveAliases(template, componentTemplates, templateName);
+        return resolveAliases(template, componentTemplates);
     }
 
     /**
      * Resolve the given v2 template and component templates into an ordered list of aliases
      */
     static List<Map<String, AliasMetadata>> resolveAliases(final ComposableIndexTemplate template,
-                                                          final Map<String, ComponentTemplate> componentTemplates,
-                                                          @Nullable String templateName) {
+                                                           final Map<String, ComponentTemplate> componentTemplates) {
         Objects.requireNonNull(template, "attempted to resolve aliases for a null template");
         Objects.requireNonNull(componentTemplates, "attempted to resolve aliases with null component templates");
         List<Map<String, AliasMetadata>> aliases = template.composedOf().stream()

+ 80 - 7
server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateDataStreamServiceTests.java

@@ -14,6 +14,7 @@ import org.elasticsearch.cluster.ClusterName;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.metadata.ComposableIndexTemplate.DataStreamTemplate;
 import org.elasticsearch.cluster.metadata.MetadataCreateDataStreamService.CreateDataStreamClusterStateUpdateRequest;
+import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.core.TimeValue;
 import org.elasticsearch.indices.ExecutorNames;
@@ -75,13 +76,8 @@ public class MetadataCreateDataStreamServiceTests extends ESTestCase {
         final int aliasCount = randomIntBetween(0, 3);
         Map<String, AliasMetadata> aliases = new HashMap<>(aliasCount);
         for (int k = 0; k < aliasCount; k++) {
-            final String aliasName = randomAlphaOfLength(6);
-            var builder = AliasMetadata.newAliasMetadataBuilder(aliasName);
-            if (randomBoolean()) {
-                builder.filter(Map.of("term", Map.of("user", Map.of("value", randomAlphaOfLength(5)))));
-            }
-            builder.writeIndex(randomBoolean());
-            aliases.put(aliasName, builder.build());
+            final AliasMetadata am = randomAlias(null);
+            aliases.put(am.alias(), am);
         }
         ComposableIndexTemplate template = new ComposableIndexTemplate.Builder()
             .indexPatterns(List.of(dataStreamName + "*"))
@@ -118,6 +114,83 @@ public class MetadataCreateDataStreamServiceTests extends ESTestCase {
         assertThat(newState.metadata().index(DataStream.getDefaultBackingIndexName(dataStreamName, 1)).isSystem(), is(false));
     }
 
+    public void testCreateDataStreamWithAliasFromComponentTemplate() throws Exception {
+        final MetadataCreateIndexService metadataCreateIndexService = getMetadataCreateIndexService();
+        final String dataStreamName = "my-data-stream";
+        final int componentTemplateCount = randomIntBetween(0, 3);
+        final int aliasCount = randomIntBetween(0, 3);
+        int totalAliasCount = aliasCount;
+        Map<String, AliasMetadata> aliases = new HashMap<>();
+        for (int k = 0; k < aliasCount; k++) {
+            final AliasMetadata am = randomAlias(null);
+            aliases.put(am.alias(), am);
+        }
+
+        List<String> ctNames = new ArrayList<>();
+        List<Map<String, AliasMetadata>> allAliases = new ArrayList<>();
+        var metadataBuilder = Metadata.builder();
+        final List<ComponentTemplate> componentTemplates = new ArrayList<>(componentTemplateCount);
+        for (int k = 0; k < componentTemplateCount; k++) {
+            final String ctName = randomAlphaOfLength(5);
+            ctNames.add(ctName);
+            final int ctAliasCount = randomIntBetween(0, 3);
+            totalAliasCount += ctAliasCount;
+            final var ctAliasMap = new HashMap<String, AliasMetadata>(ctAliasCount);
+            allAliases.add(ctAliasMap);
+            for (int m = 0; m < ctAliasCount; m++) {
+                final AliasMetadata am = randomAlias(ctName);
+                ctAliasMap.put(am.alias(), am);
+            }
+            metadataBuilder.put(ctName, new ComponentTemplate(new Template(null, null, ctAliasMap), null, null));
+        }
+        allAliases.add(aliases);
+
+        ComposableIndexTemplate template = new ComposableIndexTemplate.Builder()
+            .indexPatterns(List.of(dataStreamName + "*"))
+            .dataStreamTemplate(new DataStreamTemplate())
+            .template(new Template(null, null, aliases))
+            .componentTemplates(ctNames)
+            .build();
+
+        ClusterState cs = ClusterState.builder(new ClusterName("_name"))
+            .metadata(metadataBuilder.put("template", template).build())
+            .build();
+        CreateDataStreamClusterStateUpdateRequest req =
+            new CreateDataStreamClusterStateUpdateRequest(dataStreamName, TimeValue.ZERO, TimeValue.ZERO);
+        ClusterState newState = MetadataCreateDataStreamService.createDataStream(metadataCreateIndexService, cs, req);
+        assertThat(newState.metadata().dataStreams().size(), equalTo(1));
+        assertThat(newState.metadata().dataStreams().get(dataStreamName).getName(), equalTo(dataStreamName));
+        assertThat(newState.metadata().dataStreams().get(dataStreamName).isSystem(), is(false));
+        assertThat(newState.metadata().dataStreams().get(dataStreamName).isHidden(), is(false));
+        assertThat(newState.metadata().dataStreams().get(dataStreamName).isReplicated(), is(false));
+        assertThat(newState.metadata().dataStreamAliases().size(), is(totalAliasCount));
+        for (var aliasMap : allAliases) {
+            for (var alias : aliasMap.values()) {
+                var actualAlias = newState.metadata().dataStreamAliases().get(alias.alias());
+                assertThat(actualAlias, is(notNullValue()));
+                assertThat(actualAlias.getName(), equalTo(alias.alias()));
+                assertThat(actualAlias.getFilter(), equalTo(alias.filter()));
+                assertThat(actualAlias.getWriteDataStream(), equalTo(alias.writeIndex() ? dataStreamName : null));
+            }
+        }
+
+        assertThat(newState.metadata().index(DataStream.getDefaultBackingIndexName(dataStreamName, 1)), notNullValue());
+        assertThat(newState.metadata().index(DataStream.getDefaultBackingIndexName(dataStreamName, 1)).getAliases().size(), is(0));
+        assertThat(newState.metadata().index(DataStream.getDefaultBackingIndexName(dataStreamName, 1)).getSettings().get("index.hidden"),
+            equalTo("true"));
+        assertThat(newState.metadata().index(DataStream.getDefaultBackingIndexName(dataStreamName, 1)).isSystem(), is(false));
+    }
+
+    private static AliasMetadata randomAlias(String prefix) {
+        final String aliasName = (Strings.isNullOrEmpty(prefix) ? "" : prefix + "-") + randomAlphaOfLength(6);
+        var builder = AliasMetadata.newAliasMetadataBuilder(aliasName);
+        if (randomBoolean()) {
+            builder.filter(Map.of("term", Map.of("user", Map.of("value", randomAlphaOfLength(5)))));
+        }
+        builder.writeIndex(randomBoolean());
+        return builder.build();
+    }
+
     public void testCreateSystemDataStream() throws Exception {
         final MetadataCreateIndexService metadataCreateIndexService = getMetadataCreateIndexService();
         final String dataStreamName = ".system-data-stream";