Skip to content

Commit 1a5845e

Browse files
authored
Add simulate template composition API _index_template/_simulate_index/{name} (elastic#55686)
This adds a new api to simulate matching the given index name against the index templates in the system. The syntax for the new API takes the following form: POST _index_template/_simulate_index/{index_name} { "index_patterns": ["logs-*"], "priority": 15, "template": { "settings": { "number_of_shards": 3 } ... } } Where the body is optional, but we support the entire body used by the PUT _index_template/{name} api. When the body is specified we'll simulate matching the given index against a system that'd have the given index template together with the index templates that exist in the system. The response, in both cases, will return the matching template's resolved settings, mappings and aliases, together with a special field that'll print any overlapping templates and their corresponding index patterns.
1 parent e0f3889 commit 1a5845e

File tree

15 files changed

+851
-27
lines changed

15 files changed

+851
-27
lines changed

client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,7 @@ public void testApiNamingConventions() throws Exception {
861861
"indices.create_data_stream",
862862
"indices.get_data_streams",
863863
"indices.delete_data_stream",
864+
"indices.simulate_index_template"
864865
};
865866
//These API are not required for high-level client feature completeness
866867
String[] notRequiredApi = new String[] {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"indices.simulate_index_template":{
3+
"documentation":{
4+
"url":"https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html",
5+
"description": "Simulate matching the given index name against the index templates in the system"
6+
},
7+
"stability":"stable",
8+
"url":{
9+
"paths":[
10+
{
11+
"path":"/_index_template/_simulate_index/{name}",
12+
"methods":[
13+
"POST"
14+
],
15+
"parts":{
16+
"name":{
17+
"type":"string",
18+
"description":"The name of the index (it must be a concrete index name)"
19+
}
20+
}
21+
}
22+
]
23+
},
24+
"params":{
25+
"master_timeout":{
26+
"type":"time",
27+
"description":"Specify timeout for connection to master"
28+
}
29+
},
30+
"body":{
31+
"description":"New index template definition, which will be included in the simulation, as if it already exists in the system",
32+
"required":false
33+
}
34+
}
35+
}
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
---
2+
"Simulate index template without new template in the body":
3+
- skip:
4+
version: " - 7.99.99"
5+
reason: "simulate index template API has not been backported"
6+
features: allowed_warnings
7+
8+
- do:
9+
allowed_warnings:
10+
- "index template [test] has index patterns [te*] matching patterns from existing older templates [global] with patterns (global => [*]); this template [test] will take precedence during new index creation"
11+
indices.put_index_template:
12+
name: test
13+
body:
14+
index_patterns: te*
15+
template:
16+
settings:
17+
number_of_shards: 1
18+
number_of_replicas: 0
19+
mappings:
20+
properties:
21+
field:
22+
type: keyword
23+
24+
- do:
25+
indices.simulate_index_template:
26+
name: test
27+
28+
- match: {template.settings.index.number_of_shards: "1"}
29+
- match: {template.settings.index.number_of_replicas: "0"}
30+
- match: {template.mappings._doc.properties.field.type: "keyword"}
31+
- match: {overlapping: []}
32+
33+
---
34+
"Simulate index template specifying a new template":
35+
- skip:
36+
version: " - 7.99.99"
37+
reason: "simulate index template API has not been backported"
38+
features: allowed_warnings
39+
40+
- do:
41+
allowed_warnings:
42+
- "index template [test] has index patterns [te*] matching patterns from existing older templates [global] with patterns (global => [*]); this template [test] will take precedence during new index creation"
43+
indices.put_index_template:
44+
name: existing_test
45+
body:
46+
index_patterns: te*
47+
priority: 10
48+
template:
49+
settings:
50+
number_of_shards: 1
51+
number_of_replicas: 0
52+
mappings:
53+
properties:
54+
field:
55+
type: keyword
56+
57+
- do:
58+
cluster.put_component_template:
59+
name: ct
60+
body:
61+
template:
62+
settings:
63+
index.number_of_replicas: 2
64+
mappings:
65+
properties:
66+
ct_field:
67+
type: keyword
68+
69+
- do:
70+
indices.simulate_index_template:
71+
name: test
72+
body:
73+
index_patterns: te*
74+
priority: 15
75+
template:
76+
settings:
77+
index.blocks.write: true
78+
aliases:
79+
test_alias: {}
80+
composed_of: ["ct"]
81+
82+
- match: {template.settings.index.blocks.write: "true"}
83+
- match: {template.settings.index.number_of_replicas: "2"}
84+
- match: {template.mappings._doc.properties.ct_field.type: "keyword"}
85+
- match: {overlapping.0.name: existing_test}
86+
- match: {overlapping.0.index_patterns: ["te*"]}
87+
- length: {template.aliases: 1}
88+
- is_true: template.aliases.test_alias
89+
90+
---
91+
"Simulate index template with index not matching any template":
92+
- skip:
93+
version: " - 7.99.99"
94+
reason: "simulate index template API has not been backported"
95+
features: allowed_warnings
96+
97+
- do:
98+
allowed_warnings:
99+
- "index template [test] has index patterns [te*] matching patterns from existing older templates [global] with patterns (global => [*]); this template [test] will take precedence during new index creation"
100+
indices.put_index_template:
101+
name: test
102+
body:
103+
index_patterns: te*
104+
priority: 10
105+
template:
106+
settings:
107+
number_of_shards: 1
108+
number_of_replicas: 0
109+
mappings:
110+
properties:
111+
field:
112+
type: keyword
113+
114+
- do:
115+
indices.simulate_index_template:
116+
name: will_not_match
117+
118+
- match: {body: null}
119+
120+
---
121+
"Simulate index matches overlapping V1 and V2 templates":
122+
- skip:
123+
version: " - 7.99.99"
124+
reason: "simulate index template API has not been backported"
125+
features: allowed_warnings
126+
127+
- do:
128+
indices.put_template:
129+
name: v1_template
130+
body:
131+
index_patterns: [t*, t1*]
132+
settings:
133+
number_of_shards: 5
134+
135+
- do:
136+
allowed_warnings:
137+
- "index template [v2_template] has index patterns [te*] matching patterns from existing older templates [v1_template] with patterns
138+
(v1_template => [t*, t1*]); this template [v2_template] will take precedence during new index creation"
139+
indices.put_index_template:
140+
name: v2_template
141+
body:
142+
index_patterns: te*
143+
priority: 10
144+
template:
145+
settings:
146+
number_of_shards: 10
147+
number_of_replicas: 2
148+
mappings:
149+
properties:
150+
field:
151+
type: text
152+
153+
- do:
154+
allowed_warnings:
155+
- "index template [winning_v2_template] has index patterns [te*] matching patterns from existing older templates [v1_template] with patterns
156+
(v1_template => [t*, t1*]); this template [winning_v2_template] will take precedence during new index creation"
157+
indices.put_index_template:
158+
name: winning_v2_template
159+
body:
160+
index_patterns: te*
161+
priority: 20
162+
template:
163+
settings:
164+
number_of_shards: 1
165+
number_of_replicas: 0
166+
mappings:
167+
properties:
168+
field:
169+
type: keyword
170+
171+
- do:
172+
indices.simulate_index_template:
173+
name: test
174+
175+
- match: {template.settings.index.number_of_shards: "1"}
176+
- match: {template.settings.index.number_of_replicas: "0"}
177+
- match: {template.mappings._doc.properties.field.type: "keyword"}
178+
- match: {overlapping.0.name: v1_template}
179+
- match: {overlapping.0.index_patterns: ["t*", "t1*"]}
180+
- match: {overlapping.1.name: v2_template}
181+
- match: {overlapping.1.index_patterns: ["te*"]}

server/src/main/java/org/elasticsearch/action/ActionModule.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@
2828
import org.elasticsearch.action.admin.cluster.configuration.ClearVotingConfigExclusionsAction;
2929
import org.elasticsearch.action.admin.cluster.configuration.TransportAddVotingConfigExclusionsAction;
3030
import org.elasticsearch.action.admin.cluster.configuration.TransportClearVotingConfigExclusionsAction;
31-
import org.elasticsearch.action.admin.indices.datastream.DeleteDataStreamAction;
32-
import org.elasticsearch.action.admin.indices.datastream.GetDataStreamsAction;
33-
import org.elasticsearch.action.admin.indices.datastream.CreateDataStreamAction;
3431
import org.elasticsearch.action.admin.cluster.health.ClusterHealthAction;
3532
import org.elasticsearch.action.admin.cluster.health.TransportClusterHealthAction;
3633
import org.elasticsearch.action.admin.cluster.node.hotthreads.NodesHotThreadsAction;
@@ -108,6 +105,9 @@
108105
import org.elasticsearch.action.admin.indices.close.TransportVerifyShardBeforeCloseAction;
109106
import org.elasticsearch.action.admin.indices.create.CreateIndexAction;
110107
import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction;
108+
import org.elasticsearch.action.admin.indices.datastream.CreateDataStreamAction;
109+
import org.elasticsearch.action.admin.indices.datastream.DeleteDataStreamAction;
110+
import org.elasticsearch.action.admin.indices.datastream.GetDataStreamsAction;
111111
import org.elasticsearch.action.admin.indices.delete.DeleteIndexAction;
112112
import org.elasticsearch.action.admin.indices.delete.TransportDeleteIndexAction;
113113
import org.elasticsearch.action.admin.indices.flush.FlushAction;
@@ -158,6 +158,8 @@
158158
import org.elasticsearch.action.admin.indices.template.get.TransportGetComponentTemplateAction;
159159
import org.elasticsearch.action.admin.indices.template.get.TransportGetIndexTemplateV2Action;
160160
import org.elasticsearch.action.admin.indices.template.get.TransportGetIndexTemplatesAction;
161+
import org.elasticsearch.action.admin.indices.template.post.SimulateIndexTemplateAction;
162+
import org.elasticsearch.action.admin.indices.template.post.TransportSimulateIndexTemplateAction;
161163
import org.elasticsearch.action.admin.indices.template.put.PutComponentTemplateAction;
162164
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateAction;
163165
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateV2Action;
@@ -260,11 +262,9 @@
260262
import org.elasticsearch.rest.action.admin.cluster.RestClusterStatsAction;
261263
import org.elasticsearch.rest.action.admin.cluster.RestClusterUpdateSettingsAction;
262264
import org.elasticsearch.rest.action.admin.cluster.RestCreateSnapshotAction;
263-
import org.elasticsearch.rest.action.admin.indices.RestDeleteDataStreamAction;
264265
import org.elasticsearch.rest.action.admin.cluster.RestDeleteRepositoryAction;
265266
import org.elasticsearch.rest.action.admin.cluster.RestDeleteSnapshotAction;
266267
import org.elasticsearch.rest.action.admin.cluster.RestDeleteStoredScriptAction;
267-
import org.elasticsearch.rest.action.admin.indices.RestGetDataStreamsAction;
268268
import org.elasticsearch.rest.action.admin.cluster.RestGetRepositoriesAction;
269269
import org.elasticsearch.rest.action.admin.cluster.RestGetScriptContextAction;
270270
import org.elasticsearch.rest.action.admin.cluster.RestGetScriptLanguageAction;
@@ -277,7 +277,6 @@
277277
import org.elasticsearch.rest.action.admin.cluster.RestNodesStatsAction;
278278
import org.elasticsearch.rest.action.admin.cluster.RestNodesUsageAction;
279279
import org.elasticsearch.rest.action.admin.cluster.RestPendingClusterTasksAction;
280-
import org.elasticsearch.rest.action.admin.indices.RestCreateDataStreamAction;
281280
import org.elasticsearch.rest.action.admin.cluster.RestPutRepositoryAction;
282281
import org.elasticsearch.rest.action.admin.cluster.RestPutStoredScriptAction;
283282
import org.elasticsearch.rest.action.admin.cluster.RestReloadSecureSettingsAction;
@@ -288,15 +287,18 @@
288287
import org.elasticsearch.rest.action.admin.indices.RestAnalyzeAction;
289288
import org.elasticsearch.rest.action.admin.indices.RestClearIndicesCacheAction;
290289
import org.elasticsearch.rest.action.admin.indices.RestCloseIndexAction;
290+
import org.elasticsearch.rest.action.admin.indices.RestCreateDataStreamAction;
291291
import org.elasticsearch.rest.action.admin.indices.RestCreateIndexAction;
292292
import org.elasticsearch.rest.action.admin.indices.RestDeleteComponentTemplateAction;
293+
import org.elasticsearch.rest.action.admin.indices.RestDeleteDataStreamAction;
293294
import org.elasticsearch.rest.action.admin.indices.RestDeleteIndexAction;
294295
import org.elasticsearch.rest.action.admin.indices.RestDeleteIndexTemplateAction;
295296
import org.elasticsearch.rest.action.admin.indices.RestDeleteIndexTemplateV2Action;
296297
import org.elasticsearch.rest.action.admin.indices.RestFlushAction;
297298
import org.elasticsearch.rest.action.admin.indices.RestForceMergeAction;
298299
import org.elasticsearch.rest.action.admin.indices.RestGetAliasesAction;
299300
import org.elasticsearch.rest.action.admin.indices.RestGetComponentTemplateAction;
301+
import org.elasticsearch.rest.action.admin.indices.RestGetDataStreamsAction;
300302
import org.elasticsearch.rest.action.admin.indices.RestGetFieldMappingAction;
301303
import org.elasticsearch.rest.action.admin.indices.RestGetIndexTemplateAction;
302304
import org.elasticsearch.rest.action.admin.indices.RestGetIndexTemplateV2Action;
@@ -310,6 +312,7 @@
310312
import org.elasticsearch.rest.action.admin.indices.RestIndicesShardStoresAction;
311313
import org.elasticsearch.rest.action.admin.indices.RestIndicesStatsAction;
312314
import org.elasticsearch.rest.action.admin.indices.RestOpenIndexAction;
315+
import org.elasticsearch.rest.action.admin.indices.RestSimulateIndexTemplateAction;
313316
import org.elasticsearch.rest.action.admin.indices.RestPutComponentTemplateAction;
314317
import org.elasticsearch.rest.action.admin.indices.RestPutIndexTemplateAction;
315318
import org.elasticsearch.rest.action.admin.indices.RestPutIndexTemplateV2Action;
@@ -550,6 +553,7 @@ public <Request extends ActionRequest, Response extends ActionResponse> void reg
550553
actions.register(PutIndexTemplateV2Action.INSTANCE, TransportPutIndexTemplateV2Action.class);
551554
actions.register(GetIndexTemplateV2Action.INSTANCE, TransportGetIndexTemplateV2Action.class);
552555
actions.register(DeleteIndexTemplateV2Action.INSTANCE, TransportDeleteIndexTemplateV2Action.class);
556+
actions.register(SimulateIndexTemplateAction.INSTANCE, TransportSimulateIndexTemplateAction.class);
553557
}
554558
actions.register(ValidateQueryAction.INSTANCE, TransportValidateQueryAction.class);
555559
actions.register(RefreshAction.INSTANCE, TransportRefreshAction.class);
@@ -700,6 +704,7 @@ public void initRestHandlers(Supplier<DiscoveryNodes> nodesInCluster) {
700704
registerHandler.accept(new RestPutIndexTemplateV2Action());
701705
registerHandler.accept(new RestGetIndexTemplateV2Action());
702706
registerHandler.accept(new RestDeleteIndexTemplateV2Action());
707+
registerHandler.accept(new RestSimulateIndexTemplateAction());
703708
}
704709

705710
registerHandler.accept(new RestPutMappingAction());
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.action.admin.indices.template.post;
21+
22+
import org.elasticsearch.action.ActionType;
23+
24+
public class SimulateIndexTemplateAction extends ActionType<SimulateIndexTemplateResponse> {
25+
26+
public static final SimulateIndexTemplateAction INSTANCE = new SimulateIndexTemplateAction();
27+
public static final String NAME = "indices:admin/index_template/simulate_index";
28+
29+
private SimulateIndexTemplateAction() {
30+
super(NAME, SimulateIndexTemplateResponse::new);
31+
}
32+
33+
}

0 commit comments

Comments
 (0)