Skip to content

Commit b0f55ce

Browse files
committed
Index Pipelines: Add {created,modified}_date
1 parent 204c496 commit b0f55ce

File tree

8 files changed

+360
-89
lines changed

8 files changed

+360
-89
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
setup:
2+
- requires:
3+
test_runner_features: [capabilities, contains]
4+
capabilities:
5+
- method: PUT
6+
path: /_index_template/{id}
7+
capabilities: [ index_template_tracking_info ]
8+
reason: "Index templates have tracking info: modified_date and created_date"
9+
10+
---
11+
"Test PUT setting created_date":
12+
- do:
13+
catch: bad_request
14+
indices.put_index_template:
15+
name: test_tracking
16+
body:
17+
index_patterns: [ "test-*" ]
18+
template:
19+
settings:
20+
number_of_shards: 1
21+
created_date: "2025-07-04T12:50:48.415Z"
22+
- match: { status: 400 }
23+
- contains: { error.reason: "[index_template] unknown field [created_date] did you mean [created_date_millis]?" }
24+
25+
---
26+
"Test PUT setting created_date_millis":
27+
- do:
28+
catch: bad_request
29+
indices.put_index_template:
30+
name: test_tracking
31+
body:
32+
index_patterns: ["test-*"]
33+
template:
34+
settings:
35+
number_of_shards: 1
36+
created_date_millis: 0
37+
- match: { status: 400 }
38+
- match: { error.reason: "index_template [test_tracking] invalid, cause [provided a template property which is managed by the system: created_date]" }
39+
40+
---
41+
"Test PUT setting modified_date":
42+
- do:
43+
catch: bad_request
44+
indices.put_index_template:
45+
name: test_tracking
46+
body:
47+
index_patterns: ["test-*"]
48+
template:
49+
settings:
50+
number_of_shards: 1
51+
modified_date: "2025-07-04T12:50:48.415Z"
52+
- match: { status: 400 }
53+
- contains: { error.reason: "[index_template] unknown field [modified_date] did you mean [modified_date_millis]?" }
54+
55+
---
56+
"Test PUT setting modified_date_millis":
57+
- do:
58+
catch: bad_request
59+
indices.put_index_template:
60+
name: test_tracking
61+
body:
62+
index_patterns: ["test-*"]
63+
template:
64+
settings:
65+
number_of_shards: 1
66+
modified_date_millis: 0
67+
- match: { status: 400 }
68+
- match: { error.reason: "index_template [test_tracking] invalid, cause [provided a template property which is managed by the system: modified_date]" }
69+
70+
---
71+
"Test update preserves created_date but updates modified_date":
72+
- do:
73+
indices.put_index_template:
74+
human: true
75+
name: test_tracking
76+
body:
77+
index_patterns: ["test-*"]
78+
template:
79+
settings:
80+
number_of_shards: 1
81+
- match: { acknowledged: true }
82+
83+
- do:
84+
indices.get_index_template:
85+
human: true
86+
name: test_tracking
87+
- set: { index_templates.0.index_template.created_date: first_created }
88+
- set: { index_templates.0.index_template.created_date_millis: first_created_millis }
89+
- set: { index_templates.0.index_template.modified_date: first_modified }
90+
- set: { index_templates.0.index_template.modified_date_millis: first_modified_millis }
91+
- match: { $first_created: "/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/" }
92+
- match: { $first_modified: "/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/" }
93+
- match: { $first_created: $first_modified }
94+
- match: { $first_created_millis: $first_modified_millis }
95+
- gte: { $first_created_millis: 0 }
96+
97+
- do:
98+
indices.put_index_template:
99+
name: test_tracking
100+
body:
101+
index_patterns: ["test-*"]
102+
template:
103+
settings:
104+
number_of_shards: 2
105+
106+
- do:
107+
indices.get_index_template:
108+
human: true
109+
name: test_tracking
110+
- set: { index_templates.0.index_template.created_date: second_created }
111+
- set: { index_templates.0.index_template.created_date_millis: second_created_millis }
112+
- match: { $second_created: $first_created }
113+
- match: { $second_created_millis: $first_created_millis }

server/src/main/java/org/elasticsearch/TransportVersions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ static TransportVersion def(int id) {
354354
public static final TransportVersion RERANK_SNIPPETS = def(9_130_0_00);
355355
public static final TransportVersion PIPELINE_TRACKING_INFO = def(9_131_0_00);
356356
public static final TransportVersion COMPONENT_TEMPLATE_TRACKING_INFO = def(9_132_0_00);
357+
public static final TransportVersion INDEX_TEMPLATE_TRACKING_INFO = def(9_133_0_00);
357358

358359
/*
359360
* STOP! READ THIS FIRST! No, really,

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

Lines changed: 93 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@
4040
import java.util.List;
4141
import java.util.Map;
4242
import java.util.Objects;
43+
import java.util.Optional;
4344

4445
/**
4546
* An index template consists of a set of index patterns, an optional template, and a list of
4647
* ids corresponding to component templates that should be composed in order when creating a new
4748
* index.
4849
*/
4950
public class ComposableIndexTemplate implements SimpleDiffable<ComposableIndexTemplate>, ToXContentObject {
51+
5052
private static final ParseField INDEX_PATTERNS = new ParseField("index_patterns");
5153
private static final ParseField TEMPLATE = new ParseField("template");
5254
private static final ParseField PRIORITY = new ParseField("priority");
@@ -57,6 +59,10 @@ public class ComposableIndexTemplate implements SimpleDiffable<ComposableIndexTe
5759
private static final ParseField ALLOW_AUTO_CREATE = new ParseField("allow_auto_create");
5860
private static final ParseField IGNORE_MISSING_COMPONENT_TEMPLATES = new ParseField("ignore_missing_component_templates");
5961
private static final ParseField DEPRECATED = new ParseField("deprecated");
62+
private static final ParseField CREATED_DATE_MILLIS = new ParseField("created_date_millis");
63+
private static final ParseField CREATED_DATE = new ParseField("created_date");
64+
private static final ParseField MODIFIED_DATE_MILLIS = new ParseField("modified_date_millis");
65+
private static final ParseField MODIFIED_DATE = new ParseField("modified_date");
6066
public static final CompressedXContent EMPTY_MAPPINGS;
6167
static {
6268
try {
@@ -70,18 +76,20 @@ public class ComposableIndexTemplate implements SimpleDiffable<ComposableIndexTe
7076
public static final ConstructingObjectParser<ComposableIndexTemplate, Void> PARSER = new ConstructingObjectParser<>(
7177
"index_template",
7278
false,
73-
a -> new ComposableIndexTemplate(
74-
(List<String>) a[0],
75-
(Template) a[1],
76-
(List<String>) a[2],
77-
(Long) a[3],
78-
(Long) a[4],
79-
(Map<String, Object>) a[5],
80-
(DataStreamTemplate) a[6],
81-
(Boolean) a[7],
82-
(List<String>) a[8],
83-
(Boolean) a[9]
84-
)
79+
a -> ComposableIndexTemplate.builder()
80+
.indexPatterns((List<String>) a[0])
81+
.template((Template) a[1])
82+
.componentTemplates((List<String>) a[2])
83+
.priority((Long) a[3])
84+
.version((Long) a[4])
85+
.metadata((Map<String, Object>) a[5])
86+
.dataStreamTemplate((DataStreamTemplate) a[6])
87+
.allowAutoCreate((Boolean) a[7])
88+
.ignoreMissingComponentTemplates((List<String>) a[8])
89+
.deprecated((Boolean) a[9])
90+
.createdDate((Long) a[10])
91+
.modifiedDate((Long) a[11])
92+
.build()
8593
);
8694

8795
static {
@@ -95,6 +103,8 @@ public class ComposableIndexTemplate implements SimpleDiffable<ComposableIndexTe
95103
PARSER.declareBoolean(ConstructingObjectParser.optionalConstructorArg(), ALLOW_AUTO_CREATE);
96104
PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), IGNORE_MISSING_COMPONENT_TEMPLATES);
97105
PARSER.declareBoolean(ConstructingObjectParser.optionalConstructorArg(), DEPRECATED);
106+
PARSER.declareLong(ConstructingObjectParser.optionalConstructorArg(), CREATED_DATE_MILLIS);
107+
PARSER.declareLong(ConstructingObjectParser.optionalConstructorArg(), MODIFIED_DATE_MILLIS);
98108
}
99109

100110
private final List<String> indexPatterns;
@@ -116,6 +126,10 @@ public class ComposableIndexTemplate implements SimpleDiffable<ComposableIndexTe
116126
private final List<String> ignoreMissingComponentTemplates;
117127
@Nullable
118128
private final Boolean deprecated;
129+
@Nullable
130+
private final Long createdDateMillis;
131+
@Nullable
132+
private final Long modifiedDateMillis;
119133

120134
static Diff<ComposableIndexTemplate> readITV2DiffFrom(StreamInput in) throws IOException {
121135
return SimpleDiffable.readDiffFrom(ComposableIndexTemplate::new, in);
@@ -129,28 +143,19 @@ public static Builder builder() {
129143
return new Builder();
130144
}
131145

132-
private ComposableIndexTemplate(
133-
List<String> indexPatterns,
134-
@Nullable Template template,
135-
@Nullable List<String> componentTemplates,
136-
@Nullable Long priority,
137-
@Nullable Long version,
138-
@Nullable Map<String, Object> metadata,
139-
@Nullable DataStreamTemplate dataStreamTemplate,
140-
@Nullable Boolean allowAutoCreate,
141-
@Nullable List<String> ignoreMissingComponentTemplates,
142-
@Nullable Boolean deprecated
143-
) {
144-
this.indexPatterns = indexPatterns;
145-
this.template = template;
146-
this.componentTemplates = componentTemplates == null ? List.of() : componentTemplates;
147-
this.priority = priority;
148-
this.version = version;
149-
this.metadata = metadata;
150-
this.dataStreamTemplate = dataStreamTemplate;
151-
this.allowAutoCreate = allowAutoCreate;
152-
this.ignoreMissingComponentTemplates = ignoreMissingComponentTemplates;
153-
this.deprecated = deprecated;
146+
private ComposableIndexTemplate(final Builder b) {
147+
this.indexPatterns = b.indexPatterns;
148+
this.template = b.template;
149+
this.componentTemplates = b.componentTemplates == null ? List.of() : b.componentTemplates;
150+
this.priority = b.priority;
151+
this.version = b.version;
152+
this.metadata = b.metadata;
153+
this.dataStreamTemplate = b.dataStreamTemplate;
154+
this.allowAutoCreate = b.allowAutoCreate;
155+
this.ignoreMissingComponentTemplates = b.ignoreMissingComponentTemplates;
156+
this.deprecated = b.deprecated;
157+
this.createdDateMillis = b.createdDateMillis;
158+
this.modifiedDateMillis = b.modifiedDateMillis;
154159
}
155160

156161
public ComposableIndexTemplate(StreamInput in) throws IOException {
@@ -176,6 +181,13 @@ public ComposableIndexTemplate(StreamInput in) throws IOException {
176181
} else {
177182
this.deprecated = null;
178183
}
184+
if (in.getTransportVersion().onOrAfter(TransportVersions.INDEX_TEMPLATE_TRACKING_INFO)) {
185+
this.createdDateMillis = in.readOptionalLong();
186+
this.modifiedDateMillis = in.readOptionalLong();
187+
} else {
188+
this.createdDateMillis = null;
189+
this.modifiedDateMillis = null;
190+
}
179191
}
180192

181193
public List<String> indexPatterns() {
@@ -257,6 +269,14 @@ public boolean isDeprecated() {
257269
return Boolean.TRUE.equals(deprecated);
258270
}
259271

272+
public Optional<Long> createdDateMillis() {
273+
return Optional.ofNullable(createdDateMillis);
274+
}
275+
276+
public Optional<Long> modifiedDateMillis() {
277+
return Optional.ofNullable(modifiedDateMillis);
278+
}
279+
260280
@Override
261281
public void writeTo(StreamOutput out) throws IOException {
262282
out.writeStringCollection(this.indexPatterns);
@@ -278,6 +298,10 @@ public void writeTo(StreamOutput out) throws IOException {
278298
if (out.getTransportVersion().onOrAfter(TransportVersions.V_8_12_0)) {
279299
out.writeOptionalBoolean(deprecated);
280300
}
301+
if (out.getTransportVersion().onOrAfter(TransportVersions.INDEX_TEMPLATE_TRACKING_INFO)) {
302+
out.writeOptionalLong(createdDateMillis);
303+
out.writeOptionalLong(modifiedDateMillis);
304+
}
281305
}
282306

283307
@Override
@@ -320,6 +344,20 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params, @Nulla
320344
if (this.deprecated != null) {
321345
builder.field(DEPRECATED.getPreferredName(), deprecated);
322346
}
347+
if (this.createdDateMillis != null) {
348+
builder.timestampFieldsFromUnixEpochMillis(
349+
CREATED_DATE_MILLIS.getPreferredName(),
350+
CREATED_DATE.getPreferredName(),
351+
this.createdDateMillis
352+
);
353+
}
354+
if (this.modifiedDateMillis != null) {
355+
builder.timestampFieldsFromUnixEpochMillis(
356+
MODIFIED_DATE_MILLIS.getPreferredName(),
357+
MODIFIED_DATE.getPreferredName(),
358+
this.modifiedDateMillis
359+
);
360+
}
323361
builder.endObject();
324362
return builder;
325363
}
@@ -422,7 +460,9 @@ public int hashCode() {
422460
this.dataStreamTemplate,
423461
this.allowAutoCreate,
424462
this.ignoreMissingComponentTemplates,
425-
this.deprecated
463+
this.deprecated,
464+
this.createdDateMillis,
465+
this.modifiedDateMillis
426466
);
427467
}
428468

@@ -444,7 +484,9 @@ && componentTemplatesEquals(this.componentTemplates, other.componentTemplates)
444484
&& Objects.equals(this.dataStreamTemplate, other.dataStreamTemplate)
445485
&& Objects.equals(this.allowAutoCreate, other.allowAutoCreate)
446486
&& Objects.equals(this.ignoreMissingComponentTemplates, other.ignoreMissingComponentTemplates)
447-
&& Objects.equals(deprecated, other.deprecated);
487+
&& Objects.equals(deprecated, other.deprecated)
488+
&& Objects.equals(createdDateMillis, other.createdDateMillis)
489+
&& Objects.equals(modifiedDateMillis, other.modifiedDateMillis);
448490
}
449491

450492
static boolean componentTemplatesEquals(List<String> c1, List<String> c2) {
@@ -598,6 +640,8 @@ public static class Builder {
598640
private Boolean allowAutoCreate;
599641
private List<String> ignoreMissingComponentTemplates;
600642
private Boolean deprecated;
643+
private Long createdDateMillis;
644+
private Long modifiedDateMillis;
601645

602646
/**
603647
* @deprecated use {@link ComposableIndexTemplate#builder()}
@@ -616,6 +660,8 @@ private Builder(ComposableIndexTemplate template) {
616660
this.allowAutoCreate = template.allowAutoCreate;
617661
this.ignoreMissingComponentTemplates = template.ignoreMissingComponentTemplates;
618662
this.deprecated = template.deprecated;
663+
this.createdDateMillis = template.createdDateMillis;
664+
this.modifiedDateMillis = template.modifiedDateMillis;
619665
}
620666

621667
public Builder indexPatterns(List<String> indexPatterns) {
@@ -673,19 +719,18 @@ public Builder deprecated(@Nullable Boolean deprecated) {
673719
return this;
674720
}
675721

722+
public Builder createdDate(@Nullable Long createdDate) {
723+
this.createdDateMillis = createdDate;
724+
return this;
725+
}
726+
727+
public Builder modifiedDate(@Nullable Long modifiedDate) {
728+
this.modifiedDateMillis = modifiedDate;
729+
return this;
730+
}
731+
676732
public ComposableIndexTemplate build() {
677-
return new ComposableIndexTemplate(
678-
this.indexPatterns,
679-
this.template,
680-
this.componentTemplates,
681-
this.priority,
682-
this.version,
683-
this.metadata,
684-
this.dataStreamTemplate,
685-
this.allowAutoCreate,
686-
this.ignoreMissingComponentTemplates,
687-
this.deprecated
688-
);
733+
return new ComposableIndexTemplate(this);
689734
}
690735
}
691736
}

0 commit comments

Comments
 (0)