Skip to content

Commit b93824b

Browse files
authored
Using index setting providers for data stream setting validation (#136214) (#136308)
1 parent f4e1abf commit b93824b

File tree

7 files changed

+140
-10
lines changed

7 files changed

+140
-10
lines changed

docs/changelog/136214.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 136214
2+
summary: Using index setting providers for data stream setting validation
3+
area: Data streams
4+
type: bug
5+
issues:
6+
- 136166

modules/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/DataStreamSettingsIT.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
2525
import org.elasticsearch.cluster.metadata.IndexMetadata;
2626
import org.elasticsearch.cluster.metadata.Template;
27+
import org.elasticsearch.common.compress.CompressedXContent;
2728
import org.elasticsearch.common.settings.Setting;
2829
import org.elasticsearch.common.settings.Settings;
2930
import org.elasticsearch.core.Nullable;
@@ -323,12 +324,57 @@ public void testIndexBlock() throws Exception {
323324
}
324325
}
325326

327+
public void testPutDataStreamSettingsTSDS() throws Exception {
328+
String dataStreamName = randomAlphaOfLength(20).toLowerCase(Locale.ROOT);
329+
putComposableIndexTemplate(
330+
"my-template",
331+
List.of(dataStreamName),
332+
indexSettings(1, 0).put("index.mode", "time_series").build(),
333+
CompressedXContent.fromJSON("""
334+
{
335+
"properties": {
336+
"host.name": {
337+
"type": "keyword",
338+
"time_series_dimension": true
339+
}
340+
}
341+
}
342+
""")
343+
);
344+
final var createDataStreamRequest = new CreateDataStreamAction.Request(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT, dataStreamName);
345+
assertAcked(client().execute(CreateDataStreamAction.INSTANCE, createDataStreamRequest).actionGet());
346+
final int numberOfShards = randomIntBetween(2, 7);
347+
Settings dataStreamSettings = Settings.builder().put("index.number_of_shards", numberOfShards).build();
348+
UpdateDataStreamSettingsAction.Response putSettingsResponse = client().execute(
349+
UpdateDataStreamSettingsAction.INSTANCE,
350+
new UpdateDataStreamSettingsAction.Request(dataStreamSettings, TimeValue.THIRTY_SECONDS, TimeValue.THIRTY_SECONDS).indices(
351+
dataStreamName
352+
)
353+
).actionGet();
354+
List<UpdateDataStreamSettingsAction.DataStreamSettingsResponse> dataStreamSettingsResponses = putSettingsResponse
355+
.getDataStreamSettingsResponses();
356+
assertThat(dataStreamSettingsResponses.size(), equalTo(1));
357+
UpdateDataStreamSettingsAction.DataStreamSettingsResponse dataStreamSettingsResponse = dataStreamSettingsResponses.get(0);
358+
assertThat(dataStreamSettingsResponse.dataStreamName(), equalTo(dataStreamName));
359+
assertThat(dataStreamSettingsResponse.dataStreamSucceeded(), equalTo(true));
360+
assertThat(dataStreamSettingsResponse.settings().get("index.number_of_shards"), equalTo(Integer.toString(numberOfShards)));
361+
}
362+
326363
static void putComposableIndexTemplate(String id, List<String> patterns, @Nullable Settings settings) throws IOException {
364+
putComposableIndexTemplate(id, patterns, settings, null);
365+
}
366+
367+
static void putComposableIndexTemplate(
368+
String id,
369+
List<String> patterns,
370+
@Nullable Settings settings,
371+
@Nullable CompressedXContent mappings
372+
) throws IOException {
327373
TransportPutComposableIndexTemplateAction.Request request = new TransportPutComposableIndexTemplateAction.Request(id);
328374
request.indexTemplate(
329375
ComposableIndexTemplate.builder()
330376
.indexPatterns(patterns)
331-
.template(Template.builder().settings(settings))
377+
.template(Template.builder().settings(settings).mappings(mappings))
332378
.dataStreamTemplate(new ComposableIndexTemplate.DataStreamTemplate())
333379
.build()
334380
);

server/src/main/java/org/elasticsearch/cluster/metadata/MetadataDataStreamsService.java

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
import org.elasticsearch.core.TimeValue;
3333
import org.elasticsearch.core.Tuple;
3434
import org.elasticsearch.index.Index;
35+
import org.elasticsearch.index.IndexMode;
36+
import org.elasticsearch.index.IndexSettingProviders;
37+
import org.elasticsearch.index.IndexVersion;
3538
import org.elasticsearch.index.mapper.MapperService;
3639
import org.elasticsearch.indices.IndicesService;
3740
import org.elasticsearch.logging.LogManager;
@@ -40,6 +43,7 @@
4043
import org.elasticsearch.snapshots.SnapshotsServiceUtils;
4144

4245
import java.io.IOException;
46+
import java.time.Instant;
4347
import java.util.HashSet;
4448
import java.util.List;
4549
import java.util.Map;
@@ -62,15 +66,18 @@ public class MetadataDataStreamsService {
6266
private final MasterServiceTaskQueue<UpdateOptionsTask> updateOptionsTaskQueue;
6367
private final MasterServiceTaskQueue<UpdateSettingsTask> updateSettingsTaskQueue;
6468
private final MasterServiceTaskQueue<UpdateMappingsTask> updateMappingsTaskQueue;
69+
private final IndexSettingProviders indexSettingProviders;
6570

6671
public MetadataDataStreamsService(
6772
ClusterService clusterService,
6873
IndicesService indicesService,
69-
DataStreamGlobalRetentionSettings globalRetentionSettings
74+
DataStreamGlobalRetentionSettings globalRetentionSettings,
75+
IndexSettingProviders indexSettingProviders
7076
) {
7177
this.clusterService = clusterService;
7278
this.indicesService = indicesService;
7379
this.globalRetentionSettings = globalRetentionSettings;
80+
this.indexSettingProviders = indexSettingProviders;
7481
ClusterStateTaskExecutor<UpdateLifecycleTask> updateLifecycleExecutor = new SimpleBatchedAckListenerTaskExecutor<>() {
7582

7683
@Override
@@ -497,15 +504,56 @@ private DataStream createDataStreamForUpdatedDataStreamSettings(
497504
final ComposableIndexTemplate template = lookupTemplateForDataStream(dataStreamName, projectMetadata);
498505
Settings templateSettings = MetadataIndexTemplateService.resolveSettings(template, projectMetadata.componentTemplates());
499506
Settings mergedEffectiveSettings = templateSettings.merge(mergedDataStreamSettings);
507+
CompressedXContent effectiveMappings = dataStream.getEffectiveMappings(projectMetadata, indicesService);
500508
MetadataIndexTemplateService.validateTemplate(
501-
mergedEffectiveSettings,
502-
dataStream.getEffectiveMappings(projectMetadata, indicesService),
509+
addSettingsFromIndexSettingProviders(dataStreamName, effectiveMappings, projectMetadata, mergedEffectiveSettings),
510+
effectiveMappings,
503511
indicesService
504512
);
505513

506514
return dataStream.copy().setSettings(mergedDataStreamSettings).build();
507515
}
508516

517+
private Settings addSettingsFromIndexSettingProviders(
518+
String dataStreamName,
519+
CompressedXContent effectiveMappings,
520+
ProjectMetadata projectMetadata,
521+
Settings settings
522+
) throws IOException {
523+
Settings.Builder additionalSettings = Settings.builder();
524+
IndexMode indexMode = projectMetadata.dataStreams().get(dataStreamName).getIndexMode();
525+
Set<String> overrulingSettings = new HashSet<>();
526+
indexSettingProviders.getIndexSettingProviders().forEach(indexSettingProvider -> {
527+
Settings.Builder providerSettingsBuilder = Settings.builder();
528+
indexSettingProvider.provideAdditionalSettings(
529+
dataStreamName,
530+
dataStreamName,
531+
indexMode,
532+
projectMetadata,
533+
Instant.now(),
534+
settings,
535+
List.of(effectiveMappings),
536+
IndexVersion.current(),
537+
providerSettingsBuilder
538+
);
539+
Settings providerSettings = providerSettingsBuilder.build();
540+
if (indexSettingProvider.overrulesTemplateAndRequestSettings()) {
541+
overrulingSettings.addAll(providerSettings.keySet());
542+
}
543+
additionalSettings.put(providerSettings);
544+
});
545+
Settings filteredmergedEffectiveSettings = settings;
546+
if (overrulingSettings.isEmpty() == false) {
547+
// Filter any conflicting settings from overruling providers, to avoid overwriting their values from templates.
548+
final Settings.Builder filtered = Settings.builder().put(settings);
549+
for (String setting : overrulingSettings) {
550+
filtered.remove(setting);
551+
}
552+
filteredmergedEffectiveSettings = filtered.build();
553+
}
554+
return additionalSettings.put(filteredmergedEffectiveSettings).build();
555+
}
556+
509557
private DataStream createDataStreamForUpdatedDataStreamMappings(
510558
ProjectId projectId,
511559
String dataStreamName,

server/src/main/java/org/elasticsearch/node/NodeConstruction.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,8 @@ private DataStreamGlobalRetentionSettings createDataStreamServicesAndGlobalReten
646646
ThreadPool threadPool,
647647
ClusterService clusterService,
648648
IndicesService indicesService,
649-
MetadataCreateIndexService metadataCreateIndexService
649+
MetadataCreateIndexService metadataCreateIndexService,
650+
IndexSettingProviders indexSettingProviders
650651
) {
651652
DataStreamGlobalRetentionSettings dataStreamGlobalRetentionSettings = DataStreamGlobalRetentionSettings.create(
652653
clusterService.getClusterSettings()
@@ -662,7 +663,7 @@ private DataStreamGlobalRetentionSettings createDataStreamServicesAndGlobalReten
662663
);
663664
modules.bindToInstance(
664665
MetadataDataStreamsService.class,
665-
new MetadataDataStreamsService(clusterService, indicesService, dataStreamGlobalRetentionSettings)
666+
new MetadataDataStreamsService(clusterService, indicesService, dataStreamGlobalRetentionSettings, indexSettingProviders)
666667
);
667668
return dataStreamGlobalRetentionSettings;
668669
}
@@ -990,7 +991,8 @@ public Map<String, String> queryFields() {
990991
threadPool,
991992
clusterService,
992993
indicesService,
993-
metadataCreateIndexService
994+
metadataCreateIndexService,
995+
indexSettingProviders
994996
);
995997

996998
final MetadataIndexTemplateService metadataIndexTemplateService = new MetadataIndexTemplateService(

server/src/test/java/org/elasticsearch/cluster/metadata/DataStreamLifecycleWithRetentionWarningsTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ public void testUpdatingLifecycleOnADataStream() {
141141
MetadataDataStreamsService metadataDataStreamsService = new MetadataDataStreamsService(
142142
mock(ClusterService.class),
143143
mock(IndicesService.class),
144-
DataStreamGlobalRetentionSettings.create(ClusterSettings.createBuiltInClusterSettings(settingsWithDefaultRetention))
144+
DataStreamGlobalRetentionSettings.create(ClusterSettings.createBuiltInClusterSettings(settingsWithDefaultRetention)),
145+
IndexSettingProviders.EMPTY
145146
);
146147

147148
ProjectMetadata after = metadataDataStreamsService.updateDataLifecycle(

server/src/test/java/org/elasticsearch/cluster/metadata/MetadataDataStreamsServiceTests.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.elasticsearch.common.settings.Settings;
2121
import org.elasticsearch.core.Tuple;
2222
import org.elasticsearch.index.Index;
23+
import org.elasticsearch.index.IndexSettingProviders;
2324
import org.elasticsearch.index.IndexVersion;
2425
import org.elasticsearch.index.mapper.MapperService;
2526
import org.elasticsearch.index.mapper.MapperServiceTestCase;
@@ -472,7 +473,8 @@ public void testUpdateLifecycle() {
472473
MetadataDataStreamsService service = new MetadataDataStreamsService(
473474
mock(ClusterService.class),
474475
mock(IndicesService.class),
475-
DataStreamGlobalRetentionSettings.create(ClusterSettings.createBuiltInClusterSettings())
476+
DataStreamGlobalRetentionSettings.create(ClusterSettings.createBuiltInClusterSettings()),
477+
IndexSettingProviders.EMPTY
476478
);
477479
{
478480
// Remove lifecycle
@@ -503,7 +505,8 @@ public void testUpdateDataStreamOptions() {
503505
MetadataDataStreamsService service = new MetadataDataStreamsService(
504506
mock(ClusterService.class),
505507
mock(IndicesService.class),
506-
DataStreamGlobalRetentionSettings.create(ClusterSettings.createBuiltInClusterSettings())
508+
DataStreamGlobalRetentionSettings.create(ClusterSettings.createBuiltInClusterSettings()),
509+
IndexSettingProviders.EMPTY
507510
);
508511

509512
// Ensure no data stream options are stored

x-pack/plugin/otel-data/src/yamlRestTest/resources/rest-api-spec/test/20_metrics_tests.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,3 +351,27 @@ host.name pass-through:
351351
- length: { hits.hits: 1 }
352352
- match: { hits.hits.0.fields.resource\.attributes\.host\.name: [ "localhost" ] }
353353
- match: { hits.hits.0.fields.host\.name: [ "localhost" ] }
354+
355+
---
356+
data stream settings ilm:
357+
- do:
358+
bulk:
359+
index: metrics-generic.otel-default
360+
refresh: true
361+
body:
362+
- create: {"dynamic_templates":{"metrics.foo.bar":"counter_long"}}
363+
- "@timestamp": 2024-07-18T14:00:00Z
364+
resource:
365+
attributes:
366+
host.name: localhost
367+
metrics:
368+
foo.bar: 42
369+
- is_false: errors
370+
- do:
371+
indices.put_data_stream_settings:
372+
name: metrics-generic.otel-default
373+
body:
374+
index:
375+
number_of_shards: 2
376+
- match: { data_streams.0.name: metrics-generic.otel-default }
377+
- match: { data_streams.0.applied_to_data_stream: true }

0 commit comments

Comments
 (0)