Skip to content

Commit 6b886b0

Browse files
authored
[7.x] Add simulate template composition API _index_template/_simulate_index/{name} (#55686) (#55922)
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. (cherry picked from commit 1a5845e) Signed-off-by: Andrei Dan <[email protected]>
1 parent 337dc45 commit 6b886b0

File tree

14 files changed

+851
-23
lines changed

14 files changed

+851
-23
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;
@@ -109,6 +106,9 @@
109106
import org.elasticsearch.action.admin.indices.close.TransportCloseIndexAction;
110107
import org.elasticsearch.action.admin.indices.create.CreateIndexAction;
111108
import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction;
109+
import org.elasticsearch.action.admin.indices.datastream.CreateDataStreamAction;
110+
import org.elasticsearch.action.admin.indices.datastream.DeleteDataStreamAction;
111+
import org.elasticsearch.action.admin.indices.datastream.GetDataStreamsAction;
112112
import org.elasticsearch.action.admin.indices.delete.DeleteIndexAction;
113113
import org.elasticsearch.action.admin.indices.delete.TransportDeleteIndexAction;
114114
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsAction;
@@ -163,6 +163,8 @@
163163
import org.elasticsearch.action.admin.indices.template.get.TransportGetComponentTemplateAction;
164164
import org.elasticsearch.action.admin.indices.template.get.TransportGetIndexTemplateV2Action;
165165
import org.elasticsearch.action.admin.indices.template.get.TransportGetIndexTemplatesAction;
166+
import org.elasticsearch.action.admin.indices.template.post.SimulateIndexTemplateAction;
167+
import org.elasticsearch.action.admin.indices.template.post.TransportSimulateIndexTemplateAction;
166168
import org.elasticsearch.action.admin.indices.template.put.PutComponentTemplateAction;
167169
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateAction;
168170
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateV2Action;
@@ -261,11 +263,9 @@
261263
import org.elasticsearch.rest.action.admin.cluster.RestClusterStatsAction;
262264
import org.elasticsearch.rest.action.admin.cluster.RestClusterUpdateSettingsAction;
263265
import org.elasticsearch.rest.action.admin.cluster.RestCreateSnapshotAction;
264-
import org.elasticsearch.rest.action.admin.indices.RestDeleteDataStreamAction;
265266
import org.elasticsearch.rest.action.admin.cluster.RestDeleteRepositoryAction;
266267
import org.elasticsearch.rest.action.admin.cluster.RestDeleteSnapshotAction;
267268
import org.elasticsearch.rest.action.admin.cluster.RestDeleteStoredScriptAction;
268-
import org.elasticsearch.rest.action.admin.indices.RestGetDataStreamsAction;
269269
import org.elasticsearch.rest.action.admin.cluster.RestGetRepositoriesAction;
270270
import org.elasticsearch.rest.action.admin.cluster.RestGetScriptContextAction;
271271
import org.elasticsearch.rest.action.admin.cluster.RestGetScriptLanguageAction;
@@ -278,7 +278,6 @@
278278
import org.elasticsearch.rest.action.admin.cluster.RestNodesStatsAction;
279279
import org.elasticsearch.rest.action.admin.cluster.RestNodesUsageAction;
280280
import org.elasticsearch.rest.action.admin.cluster.RestPendingClusterTasksAction;
281-
import org.elasticsearch.rest.action.admin.indices.RestCreateDataStreamAction;
282281
import org.elasticsearch.rest.action.admin.cluster.RestPutRepositoryAction;
283282
import org.elasticsearch.rest.action.admin.cluster.RestPutStoredScriptAction;
284283
import org.elasticsearch.rest.action.admin.cluster.RestReloadSecureSettingsAction;
@@ -289,15 +288,18 @@
289288
import org.elasticsearch.rest.action.admin.indices.RestAnalyzeAction;
290289
import org.elasticsearch.rest.action.admin.indices.RestClearIndicesCacheAction;
291290
import org.elasticsearch.rest.action.admin.indices.RestCloseIndexAction;
291+
import org.elasticsearch.rest.action.admin.indices.RestCreateDataStreamAction;
292292
import org.elasticsearch.rest.action.admin.indices.RestCreateIndexAction;
293293
import org.elasticsearch.rest.action.admin.indices.RestDeleteComponentTemplateAction;
294+
import org.elasticsearch.rest.action.admin.indices.RestDeleteDataStreamAction;
294295
import org.elasticsearch.rest.action.admin.indices.RestDeleteIndexAction;
295296
import org.elasticsearch.rest.action.admin.indices.RestDeleteIndexTemplateAction;
296297
import org.elasticsearch.rest.action.admin.indices.RestDeleteIndexTemplateV2Action;
297298
import org.elasticsearch.rest.action.admin.indices.RestFlushAction;
298299
import org.elasticsearch.rest.action.admin.indices.RestForceMergeAction;
299300
import org.elasticsearch.rest.action.admin.indices.RestGetAliasesAction;
300301
import org.elasticsearch.rest.action.admin.indices.RestGetComponentTemplateAction;
302+
import org.elasticsearch.rest.action.admin.indices.RestGetDataStreamsAction;
301303
import org.elasticsearch.rest.action.admin.indices.RestGetFieldMappingAction;
302304
import org.elasticsearch.rest.action.admin.indices.RestGetIndexTemplateAction;
303305
import org.elasticsearch.rest.action.admin.indices.RestGetIndexTemplateV2Action;
@@ -311,6 +313,7 @@
311313
import org.elasticsearch.rest.action.admin.indices.RestIndicesShardStoresAction;
312314
import org.elasticsearch.rest.action.admin.indices.RestIndicesStatsAction;
313315
import org.elasticsearch.rest.action.admin.indices.RestOpenIndexAction;
316+
import org.elasticsearch.rest.action.admin.indices.RestSimulateIndexTemplateAction;
314317
import org.elasticsearch.rest.action.admin.indices.RestPutComponentTemplateAction;
315318
import org.elasticsearch.rest.action.admin.indices.RestPutIndexTemplateAction;
316319
import org.elasticsearch.rest.action.admin.indices.RestPutIndexTemplateV2Action;
@@ -561,6 +564,7 @@ public <Request extends ActionRequest, Response extends ActionResponse> void reg
561564
actions.register(PutIndexTemplateV2Action.INSTANCE, TransportPutIndexTemplateV2Action.class);
562565
actions.register(GetIndexTemplateV2Action.INSTANCE, TransportGetIndexTemplateV2Action.class);
563566
actions.register(DeleteIndexTemplateV2Action.INSTANCE, TransportDeleteIndexTemplateV2Action.class);
567+
actions.register(SimulateIndexTemplateAction.INSTANCE, TransportSimulateIndexTemplateAction.class);
564568
}
565569
actions.register(ValidateQueryAction.INSTANCE, TransportValidateQueryAction.class);
566570
actions.register(RefreshAction.INSTANCE, TransportRefreshAction.class);
@@ -703,6 +707,7 @@ public void initRestHandlers(Supplier<DiscoveryNodes> nodesInCluster) {
703707
registerHandler.accept(new RestPutIndexTemplateV2Action());
704708
registerHandler.accept(new RestGetIndexTemplateV2Action());
705709
registerHandler.accept(new RestDeleteIndexTemplateV2Action());
710+
registerHandler.accept(new RestSimulateIndexTemplateAction());
706711
}
707712

708713
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)