21
21
import com .carrotsearch .hppc .cursors .ObjectCursor ;
22
22
import com .google .common .collect .Maps ;
23
23
import com .google .common .collect .Sets ;
24
+ import org .elasticsearch .Version ;
24
25
import org .elasticsearch .action .admin .indices .alias .Alias ;
25
26
import org .elasticsearch .action .support .master .MasterNodeRequest ;
26
27
import org .elasticsearch .cluster .ClusterService ;
34
35
import org .elasticsearch .common .regex .Regex ;
35
36
import org .elasticsearch .common .settings .Settings ;
36
37
import org .elasticsearch .common .unit .TimeValue ;
38
+ import org .elasticsearch .index .Index ;
39
+ import org .elasticsearch .index .IndexService ;
40
+ import org .elasticsearch .index .mapper .MapperParsingException ;
41
+ import org .elasticsearch .index .mapper .MapperService ;
37
42
import org .elasticsearch .indices .IndexTemplateAlreadyExistsException ;
38
43
import org .elasticsearch .indices .IndexTemplateMissingException ;
44
+ import org .elasticsearch .indices .IndicesService ;
39
45
import org .elasticsearch .indices .InvalidIndexTemplateException ;
40
46
41
47
import java .util .ArrayList ;
48
+ import java .util .HashMap ;
42
49
import java .util .List ;
43
50
import java .util .Locale ;
44
51
import java .util .Map ;
@@ -51,13 +58,15 @@ public class MetaDataIndexTemplateService extends AbstractComponent {
51
58
52
59
private final ClusterService clusterService ;
53
60
private final AliasValidator aliasValidator ;
61
+ private final IndicesService indicesService ;
54
62
private final MetaDataCreateIndexService metaDataCreateIndexService ;
55
63
56
64
@ Inject
57
- public MetaDataIndexTemplateService (Settings settings , ClusterService clusterService , MetaDataCreateIndexService metaDataCreateIndexService , AliasValidator aliasValidator ) {
65
+ public MetaDataIndexTemplateService (Settings settings , ClusterService clusterService , MetaDataCreateIndexService metaDataCreateIndexService , AliasValidator aliasValidator , IndicesService indicesService ) {
58
66
super (settings );
59
67
this .clusterService = clusterService ;
60
68
this .aliasValidator = aliasValidator ;
69
+ this .indicesService = indicesService ;
61
70
this .metaDataCreateIndexService = metaDataCreateIndexService ;
62
71
}
63
72
@@ -125,28 +134,7 @@ public void putTemplate(final PutRequest request, final PutListener listener) {
125
134
return ;
126
135
}
127
136
128
- IndexTemplateMetaData .Builder templateBuilder ;
129
- try {
130
- templateBuilder = IndexTemplateMetaData .builder (request .name );
131
- templateBuilder .order (request .order );
132
- templateBuilder .template (request .template );
133
- templateBuilder .settings (request .settings );
134
- for (Map .Entry <String , String > entry : request .mappings .entrySet ()) {
135
- templateBuilder .putMapping (entry .getKey (), entry .getValue ());
136
- }
137
- for (Alias alias : request .aliases ) {
138
- AliasMetaData aliasMetaData = AliasMetaData .builder (alias .name ()).filter (alias .filter ())
139
- .indexRouting (alias .indexRouting ()).searchRouting (alias .searchRouting ()).build ();
140
- templateBuilder .putAlias (aliasMetaData );
141
- }
142
- for (Map .Entry <String , IndexMetaData .Custom > entry : request .customs .entrySet ()) {
143
- templateBuilder .putCustom (entry .getKey (), entry .getValue ());
144
- }
145
- } catch (Throwable e ) {
146
- listener .onFailure (e );
147
- return ;
148
- }
149
- final IndexTemplateMetaData template = templateBuilder .build ();
137
+ final IndexTemplateMetaData .Builder templateBuilder = IndexTemplateMetaData .builder (request .name );
150
138
151
139
clusterService .submitStateUpdateTask ("create-index-template [" + request .name + "], cause [" + request .cause + "]" ,
152
140
new ClusterStateUpdateTask (Priority .URGENT ) {
@@ -161,22 +149,76 @@ public void onFailure(String source, Throwable t) {
161
149
}
162
150
163
151
@ Override
164
- public ClusterState execute (ClusterState currentState ) {
152
+ public ClusterState execute (ClusterState currentState ) throws Exception {
165
153
if (request .create && currentState .metaData ().templates ().containsKey (request .name )) {
166
154
throw new IndexTemplateAlreadyExistsException (request .name );
167
155
}
156
+
157
+ validateAndAddTemplate (request , templateBuilder , indicesService , metaDataCreateIndexService );
158
+
159
+ for (Alias alias : request .aliases ) {
160
+ AliasMetaData aliasMetaData = AliasMetaData .builder (alias .name ()).filter (alias .filter ())
161
+ .indexRouting (alias .indexRouting ()).searchRouting (alias .searchRouting ()).build ();
162
+ templateBuilder .putAlias (aliasMetaData );
163
+ }
164
+ for (Map .Entry <String , IndexMetaData .Custom > entry : request .customs .entrySet ()) {
165
+ templateBuilder .putCustom (entry .getKey (), entry .getValue ());
166
+ }
167
+ IndexTemplateMetaData template = templateBuilder .build ();
168
+
168
169
MetaData .Builder builder = MetaData .builder (currentState .metaData ()).put (template );
169
170
170
171
return ClusterState .builder (currentState ).metaData (builder ).build ();
171
172
}
172
173
173
174
@ Override
174
175
public void clusterStateProcessed (String source , ClusterState oldState , ClusterState newState ) {
175
- listener .onResponse (new PutResponse (true , template ));
176
+ listener .onResponse (new PutResponse (true , templateBuilder . build () ));
176
177
}
177
178
});
178
179
}
179
180
181
+ private void validateAndAddTemplate (final PutRequest request , IndexTemplateMetaData .Builder templateBuilder , IndicesService indicesService ,
182
+ MetaDataCreateIndexService metaDataCreateIndexService ) throws Exception {
183
+ Index createdIndex = null ;
184
+ final String temporaryIndexName = Strings .randomBase64UUID ();
185
+ try {
186
+
187
+ //create index service for parsing and validating "mappings"
188
+ Settings dummySettings = Settings .builder ()
189
+ .put (IndexMetaData .SETTING_VERSION_CREATED , Version .CURRENT )
190
+ .put (request .settings )
191
+ .put (IndexMetaData .SETTING_NUMBER_OF_SHARDS , 1 )
192
+ .put (IndexMetaData .SETTING_NUMBER_OF_REPLICAS , 0 )
193
+ .put (IndexMetaData .SETTING_INDEX_UUID , Strings .randomBase64UUID ())
194
+ .build ();
195
+
196
+ IndexService dummyIndexService = indicesService .createIndex (temporaryIndexName , dummySettings , clusterService .localNode ().id ());
197
+ createdIndex = dummyIndexService .index ();
198
+
199
+ templateBuilder .order (request .order );
200
+ templateBuilder .template (request .template );
201
+ templateBuilder .settings (request .settings );
202
+
203
+ Map <String , Map <String , Object >> mappingsForValidation = new HashMap <>();
204
+ for (Map .Entry <String , String > entry : request .mappings .entrySet ()) {
205
+ try {
206
+ templateBuilder .putMapping (entry .getKey (), entry .getValue ());
207
+ } catch (Exception e ) {
208
+ throw new MapperParsingException ("Failed to parse mapping [{}]: {}" , e , entry .getKey (), e .getMessage ());
209
+ }
210
+ mappingsForValidation .put (entry .getKey (), MapperService .parseMapping (entry .getValue ()));
211
+ }
212
+
213
+ dummyIndexService .mapperService ().merge (mappingsForValidation , false );
214
+
215
+ } finally {
216
+ if (createdIndex != null ) {
217
+ indicesService .removeIndex (temporaryIndexName , " created for parsing template mapping" );
218
+ }
219
+ }
220
+ }
221
+
180
222
private void validate (PutRequest request ) {
181
223
List <String > validationErrors = new ArrayList <>();
182
224
if (request .name .contains (" " )) {
0 commit comments