Skip to content

Commit 3720bf0

Browse files
committed
Updating TransportSimulateIndexTemplateAction.resolveTemplate() to account for data stream overrides
1 parent a2aea7e commit 3720bf0

File tree

6 files changed

+164
-3
lines changed

6 files changed

+164
-3
lines changed

qa/smoke-test-ingest-with-all-dependencies/src/yamlRestTest/resources/rest-api-spec/test/ingest/80_ingest_simulate.yml

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,3 +1740,100 @@ setup:
17401740
- match: { docs.0.doc._source.abc: "sfdsfsfdsfsfdsfsfdsfsfdsfsfdsf" }
17411741
- match: { docs.0.doc.ignored_fields: [ {"field": "abc"} ] }
17421742
- not_exists: docs.0.doc.error
1743+
1744+
---
1745+
"Simulate ingest with data stream with mapping and setting overrides":
1746+
- skip:
1747+
features: headers
1748+
1749+
- do:
1750+
indices.put_index_template:
1751+
name: test
1752+
body:
1753+
index_patterns: test*
1754+
template:
1755+
lifecycle:
1756+
data_retention: "7d"
1757+
data_stream: {}
1758+
1759+
- do:
1760+
indices.create_data_stream:
1761+
name: test
1762+
- is_true: acknowledged
1763+
1764+
- do:
1765+
cluster.health:
1766+
wait_for_status: yellow
1767+
1768+
- do:
1769+
indices.put_data_stream_mappings:
1770+
name: test
1771+
body:
1772+
properties:
1773+
foo:
1774+
type: boolean
1775+
1776+
- match: { data_streams.0.applied_to_data_stream: true }
1777+
1778+
# For an ordinary simulate request with no overrides, we fetch the mapping from the write index, and do not take the
1779+
# data stream mapping override into account. So the foo field is unmapped, and we can write text to it.
1780+
- do:
1781+
headers:
1782+
Content-Type: application/json
1783+
simulate.ingest:
1784+
index: test
1785+
body: >
1786+
{
1787+
"docs": [
1788+
{
1789+
"_id": "asdf",
1790+
"_source": {
1791+
"@timestamp": 1234,
1792+
"foo": "bar"
1793+
}
1794+
}
1795+
]
1796+
}
1797+
- length: { docs: 1 }
1798+
- match: { docs.0.doc._index: "test" }
1799+
- match: { docs.0.doc._source.foo: "bar" }
1800+
- not_exists: docs.0.doc.error
1801+
1802+
# If template overrides are given, we go to the data stream's template and mapping override (even if the given
1803+
# template overrides are irrelevant as is the case in this test). Now we see that the foo field is mapped as a
1804+
# boolean, so we get a validation error when trying to write text to that field.
1805+
- do:
1806+
headers:
1807+
Content-Type: application/json
1808+
simulate.ingest:
1809+
index: test
1810+
body: >
1811+
{
1812+
"docs": [
1813+
{
1814+
"_id": "asdf",
1815+
"_source": {
1816+
"@timestamp": 1234,
1817+
"foo": "bar"
1818+
}
1819+
}
1820+
],
1821+
"component_template_substitutions": {
1822+
"mappings_template": {
1823+
"template": {
1824+
"mappings": {
1825+
"dynamic": "true",
1826+
"properties": {
1827+
"foo": {
1828+
"type": "keyword"
1829+
}
1830+
}
1831+
}
1832+
}
1833+
}
1834+
}
1835+
}
1836+
- length: { docs: 1 }
1837+
- match: { docs.0.doc._index: "test" }
1838+
- match: { docs.0.doc._source.foo: "bar" }
1839+
- match: { docs.0.doc.error.type: "document_parsing_exception" }

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/indices.simulate_index_template/10_basic.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,51 @@
250250
- match: {template.lifecycle.data_retention: "7d"}
251251
- is_true: template.lifecycle.rollover
252252
- match: {overlapping: []}
253+
254+
---
255+
"Simulate index template with data stream with mapping and setting overrides":
256+
- do:
257+
indices.put_index_template:
258+
name: test
259+
body:
260+
index_patterns: test*
261+
template:
262+
lifecycle:
263+
data_retention: "7d"
264+
data_stream: {}
265+
266+
- do:
267+
indices.create_data_stream:
268+
name: test
269+
- is_true: acknowledged
270+
271+
- do:
272+
cluster.health:
273+
wait_for_status: yellow
274+
275+
- do:
276+
indices.put_data_stream_mappings:
277+
name: test
278+
body:
279+
properties:
280+
foo:
281+
type: keyword
282+
283+
- match: { data_streams.0.applied_to_data_stream: true }
284+
285+
- do:
286+
indices.put_data_stream_settings:
287+
name: test
288+
body:
289+
index:
290+
refresh_interval: "47s"
291+
292+
- match: { data_streams.0.applied_to_data_stream: true }
293+
294+
- do:
295+
indices.simulate_index_template:
296+
name: test
297+
include_defaults: true
298+
299+
- match: {template.mappings.properties.foo.type: "keyword"}
300+
- match: {template.settings.index.refresh_interval: "47s"}

server/src/main/java/org/elasticsearch/action/admin/indices/template/post/TransportSimulateIndexTemplateAction.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import org.elasticsearch.xcontent.NamedXContentRegistry;
5050

5151
import java.time.Instant;
52+
import java.util.ArrayList;
5253
import java.util.HashMap;
5354
import java.util.HashSet;
5455
import java.util.List;
@@ -158,7 +159,6 @@ protected void localClusterStateOperation(
158159
listener.onResponse(new SimulateIndexTemplateResponse(null, null));
159160
return;
160161
}
161-
162162
final ProjectMetadata tempProjectMetadata = resolveTemporaryState(matchingTemplate, request.getIndexName(), projectWithTemplate);
163163
ComposableIndexTemplate templateV2 = tempProjectMetadata.templatesV2().get(matchingTemplate);
164164
assert templateV2 != null : "the matched template must exist";
@@ -167,6 +167,7 @@ protected void localClusterStateOperation(
167167
matchingTemplate,
168168
request.getIndexName(),
169169
projectWithTemplate,
170+
state.metadata(),
170171
isDslOnlyMode,
171172
xContentRegistry,
172173
indicesService,
@@ -238,14 +239,14 @@ public static Template resolveTemplate(
238239
final String matchingTemplate,
239240
final String indexName,
240241
final ProjectMetadata simulatedProject,
242+
final ProjectMetadata actualProject,
241243
final boolean isDslOnlyMode,
242244
final NamedXContentRegistry xContentRegistry,
243245
final IndicesService indicesService,
244246
final SystemIndices systemIndices,
245247
Set<IndexSettingProvider> indexSettingProviders
246248
) throws Exception {
247249
Settings templateSettings = resolveSettings(simulatedProject, matchingTemplate);
248-
249250
List<Map<String, AliasMetadata>> resolvedAliases = MetadataIndexTemplateService.resolveAliases(simulatedProject, matchingTemplate);
250251

251252
ComposableIndexTemplate template = simulatedProject.templatesV2().get(matchingTemplate);
@@ -271,6 +272,18 @@ public static Template resolveTemplate(
271272
xContentRegistry,
272273
simulatedIndexName
273274
);
275+
if (template.getDataStreamTemplate() != null) {
276+
DataStream dataStream = actualProject.dataStreams().get(indexName);
277+
if (dataStream != null) {
278+
CompressedXContent dataStreamMappingOverrides = dataStream.getMappings();
279+
if (ComposableIndexTemplate.EMPTY_MAPPINGS.equals(dataStreamMappingOverrides) == false) {
280+
mappings = new ArrayList<>(mappings);
281+
mappings.add(dataStreamMappingOverrides);
282+
}
283+
templateSettings = templateSettings.merge(dataStream.getSettings());
284+
}
285+
}
286+
final List<CompressedXContent> finalMappings = mappings;
274287

275288
// First apply settings sourced from index settings providers
276289
final var now = Instant.now();
@@ -337,7 +350,7 @@ public static Template resolveTemplate(
337350
indexMetadata,
338351
tempIndexService -> {
339352
MapperService mapperService = tempIndexService.mapperService();
340-
mapperService.merge(MapperService.SINGLE_MAPPING_NAME, mappings, MapperService.MergeReason.INDEX_TEMPLATE);
353+
mapperService.merge(MapperService.SINGLE_MAPPING_NAME, finalMappings, MapperService.MergeReason.INDEX_TEMPLATE);
341354

342355
DocumentMapper documentMapper = mapperService.documentMapper();
343356
return documentMapper != null ? documentMapper.mappingSource() : null;

server/src/main/java/org/elasticsearch/action/admin/indices/template/post/TransportSimulateTemplateAction.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ protected void localClusterStateOperation(
179179
matchingTemplate,
180180
temporaryIndexName,
181181
projectWithTemplate,
182+
projectWithTemplate, // this arg does not matter -- we never need data stream overrides because we never match a data stream
182183
isDslOnlyMode,
183184
xContentRegistry,
184185
indicesService,

server/src/main/java/org/elasticsearch/action/bulk/TransportSimulateBulkAction.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ private Tuple<Collection<String>, Exception> validateMappings(
273273
matchingTemplate,
274274
request.index(),
275275
simulatedProjectMetadata,
276+
project,
276277
isDataStreamsLifecycleOnlyMode(clusterService.getSettings()),
277278
xContentRegistry,
278279
indicesService,

server/src/test/java/org/elasticsearch/action/admin/indices/template/post/TransportSimulateIndexTemplateActionTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ public boolean overrulesTemplateAndRequestSettings() {
9797
matchingTemplate,
9898
indexName,
9999
simulatedProject,
100+
simulatedProject,
100101
isDslOnlyMode,
101102
xContentRegistry(),
102103
indicesService,

0 commit comments

Comments
 (0)