A composable index template with no `template` defined in the body is mistakingly always assumed to not be a time series template. Even if it refers to a component template that has the `index.mode` setting set to `time_series` and the component template defines mappings with dimension fields or routing paths.

Incorrectly this causes to create a data stream with a tsdb index *without* time series start and end time settings set. The fact that this can happen is another bug and is being tracked #98833.

What should happen in this case is that a tsdb data stream is created with a valid tsdb backing index (with correctly generated time series start and end time settings).

This bug was found as part investigating #98792 and is the cause of that bug.
server/src/test/java/org/elasticsearch/cluster/metadata/MetadataTests.java
assertThat(index2.getLifecycleExecutionState().asMap(), is(state.asMap()));
        assertThat(index2.getVersion(), is(index1.getVersion() + 1));
        
        IndexMetadata.Builder builder = IndexMetadata.builder(index2);
        builder.version(builder.version() - 1);
        builder.removeCustom(LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY);
        assertThat(index1, equalTo(builder.build()));
        
        Metadata metadata3 = metadata2.withLifecycleState(index2.getIndex(), state);
        assertThat(metadata3, sameInstance(metadata2));
        
        String randomUUID = randomValueOtherThan(indexUUID, () -> randomAlphaOfLength(10));
        expectThrows(IndexNotFoundException.class, () -> metadata1.withLifecycleState(new Index(indexName, randomUUID), state));
    }
    public void testEmptyDiffReturnsSameInstance() throws IOException {
        final Metadata instance = randomMetadata();
        Diff<Metadata> diff = instance.diff(instance);
        assertSame(instance, diff.apply(instance));
        final BytesStreamOutput out = new BytesStreamOutput();
        diff.writeTo(out);
        final Diff<Metadata> deserializedDiff = Metadata.readDiffFrom(out.bytes().streamInput());
        assertSame(instance, deserializedDiff.apply(instance));
    }
    public void testChunkedToXContent() throws IOException {
        final int datastreams = randomInt(10);