Skip to content

Commit ad56802

Browse files
[7.x][ML] Refactor ML mappings and templates into JSON resources (#51… (#52353)
ML mappings and index templates have so far been created programmatically. While this had its merits due to static typing, there is consensus it would be clear to maintain those in json files. In addition, we are going to adding ILM policies to these indices and the component for a plugin to register ILM policies is `IndexTemplateRegistry`. It expects the templates to be in resource json files. For the above reasons this commit refactors ML mappings and index templates into json resource files that are registered via `MlIndexTemplateRegistry`. Backport of #51765
1 parent cabc176 commit ad56802

File tree

51 files changed

+1705
-2107
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1705
-2107
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.core.ml;
7+
8+
import org.elasticsearch.Version;
9+
import org.elasticsearch.index.mapper.MapperService;
10+
import org.elasticsearch.xpack.core.template.TemplateUtils;
11+
12+
import java.util.Collections;
13+
14+
public class MlConfigIndex {
15+
16+
private static final String MAPPINGS_VERSION_VARIABLE = "xpack.ml.version";
17+
18+
private MlConfigIndex() {}
19+
20+
public static String mapping() {
21+
return mapping(MapperService.SINGLE_MAPPING_NAME);
22+
}
23+
24+
public static String mapping(String mappingType) {
25+
return TemplateUtils.loadTemplate("/org/elasticsearch/xpack/core/ml/config_index_mappings.json",
26+
Version.CURRENT.toString(), MAPPINGS_VERSION_VARIABLE, Collections.singletonMap("xpack.ml.mapping_type", mappingType));
27+
}
28+
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/MlMetaIndex.java

+1-38
Original file line numberDiff line numberDiff line change
@@ -5,50 +5,13 @@
55
*/
66
package org.elasticsearch.xpack.core.ml;
77

8-
import org.elasticsearch.common.xcontent.XContentBuilder;
9-
import org.elasticsearch.xpack.core.ml.calendars.Calendar;
10-
import org.elasticsearch.xpack.core.ml.calendars.ScheduledEvent;
11-
import org.elasticsearch.xpack.core.ml.job.persistence.ElasticsearchMappings;
12-
13-
import java.io.IOException;
14-
15-
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
16-
import static org.elasticsearch.index.mapper.MapperService.SINGLE_MAPPING_NAME;
17-
188
public final class MlMetaIndex {
199
/**
2010
* Where to store the ml info in Elasticsearch - must match what's
2111
* expected by kibana/engineAPI/app/directives/mlLogUsage.js
2212
*/
2313
public static final String INDEX_NAME = ".ml-meta";
2414

25-
private MlMetaIndex() {}
2615

27-
public static XContentBuilder docMapping() throws IOException {
28-
XContentBuilder builder = jsonBuilder();
29-
builder.startObject();
30-
builder.startObject(SINGLE_MAPPING_NAME);
31-
ElasticsearchMappings.addMetaInformation(builder);
32-
ElasticsearchMappings.addDefaultMapping(builder);
33-
builder.startObject(ElasticsearchMappings.PROPERTIES)
34-
.startObject(Calendar.ID.getPreferredName())
35-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.KEYWORD)
36-
.endObject()
37-
.startObject(Calendar.JOB_IDS.getPreferredName())
38-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.KEYWORD)
39-
.endObject()
40-
.startObject(Calendar.DESCRIPTION.getPreferredName())
41-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.KEYWORD)
42-
.endObject()
43-
.startObject(ScheduledEvent.START_TIME.getPreferredName())
44-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.DATE)
45-
.endObject()
46-
.startObject(ScheduledEvent.END_TIME.getPreferredName())
47-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.DATE)
48-
.endObject()
49-
.endObject()
50-
.endObject()
51-
.endObject();
52-
return builder;
53-
}
16+
private MlMetaIndex() {}
5417
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/annotations/AnnotationIndex.java

+25-75
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package org.elasticsearch.xpack.core.ml.annotations;
77

88
import org.elasticsearch.ResourceAlreadyExistsException;
9+
import org.elasticsearch.Version;
910
import org.elasticsearch.action.ActionListener;
1011
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
1112
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
@@ -15,19 +16,13 @@
1516
import org.elasticsearch.cluster.ClusterState;
1617
import org.elasticsearch.cluster.metadata.AliasOrIndex;
1718
import org.elasticsearch.cluster.metadata.IndexMetaData;
18-
import org.elasticsearch.cluster.routing.UnassignedInfo;
1919
import org.elasticsearch.common.settings.Settings;
20-
import org.elasticsearch.common.unit.TimeValue;
21-
import org.elasticsearch.common.xcontent.XContentBuilder;
22-
import org.elasticsearch.xpack.core.ml.MachineLearningField;
23-
import org.elasticsearch.xpack.core.ml.job.config.Job;
24-
import org.elasticsearch.xpack.core.ml.job.persistence.ElasticsearchMappings;
20+
import org.elasticsearch.common.xcontent.XContentType;
2521
import org.elasticsearch.xpack.core.ml.utils.ExceptionsHelper;
22+
import org.elasticsearch.xpack.core.template.TemplateUtils;
2623

27-
import java.io.IOException;
2824
import java.util.SortedMap;
2925

30-
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
3126
import static org.elasticsearch.index.mapper.MapperService.SINGLE_MAPPING_NAME;
3227
import static org.elasticsearch.xpack.core.ClientHelper.ML_ORIGIN;
3328
import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
@@ -40,6 +35,8 @@ public class AnnotationIndex {
4035
public static final String INDEX_NAME = ".ml-annotations-6";
4136
public static final String INDEX_PATTERN = ".ml-annotations*";
4237

38+
private static final String MAPPINGS_VERSION_VARIABLE = "xpack.ml.version";
39+
4340
/**
4441
* Create the .ml-annotations index with correct mappings if it does not already
4542
* exist. This index is read and written by the UI results views, so needs to
@@ -64,39 +61,26 @@ public static void createAnnotationsIndexIfNecessary(Settings settings, Client c
6461
// Create the annotations index if it doesn't exist already.
6562
if (mlLookup.containsKey(INDEX_NAME) == false) {
6663

67-
final TimeValue delayedNodeTimeOutSetting;
68-
// Whether we are using native process is a good way to detect whether we are in dev / test mode:
69-
if (MachineLearningField.AUTODETECT_PROCESS.get(settings)) {
70-
delayedNodeTimeOutSetting = UnassignedInfo.INDEX_DELAYED_NODE_LEFT_TIMEOUT_SETTING.get(settings);
71-
} else {
72-
delayedNodeTimeOutSetting = TimeValue.ZERO;
73-
}
74-
7564
CreateIndexRequest createIndexRequest = new CreateIndexRequest(INDEX_NAME);
76-
try (XContentBuilder annotationsMapping = AnnotationIndex.annotationsMapping()) {
77-
createIndexRequest.mapping(SINGLE_MAPPING_NAME, annotationsMapping);
78-
createIndexRequest.settings(Settings.builder()
79-
.put(IndexMetaData.SETTING_AUTO_EXPAND_REPLICAS, "0-1")
80-
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, "1")
81-
.put(UnassignedInfo.INDEX_DELAYED_NODE_LEFT_TIMEOUT_SETTING.getKey(), delayedNodeTimeOutSetting));
65+
createIndexRequest.mapping(SINGLE_MAPPING_NAME, annotationsMapping(), XContentType.JSON);
66+
createIndexRequest.settings(Settings.builder()
67+
.put(IndexMetaData.SETTING_AUTO_EXPAND_REPLICAS, "0-1")
68+
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, "1"));
8269

83-
executeAsyncWithOrigin(client.threadPool().getThreadContext(), ML_ORIGIN, createIndexRequest,
84-
ActionListener.<CreateIndexResponse>wrap(
85-
r -> createAliasListener.onResponse(r.isAcknowledged()),
86-
e -> {
87-
// Possible that the index was created while the request was executing,
88-
// so we need to handle that possibility
89-
if (ExceptionsHelper.unwrapCause(e) instanceof ResourceAlreadyExistsException) {
90-
// Create the alias
91-
createAliasListener.onResponse(true);
92-
} else {
93-
finalListener.onFailure(e);
94-
}
70+
executeAsyncWithOrigin(client.threadPool().getThreadContext(), ML_ORIGIN, createIndexRequest,
71+
ActionListener.<CreateIndexResponse>wrap(
72+
r -> createAliasListener.onResponse(r.isAcknowledged()),
73+
e -> {
74+
// Possible that the index was created while the request was executing,
75+
// so we need to handle that possibility
76+
if (ExceptionsHelper.unwrapCause(e) instanceof ResourceAlreadyExistsException) {
77+
// Create the alias
78+
createAliasListener.onResponse(true);
79+
} else {
80+
finalListener.onFailure(e);
9581
}
96-
), client.admin().indices()::create);
97-
} catch (IOException e) {
98-
finalListener.onFailure(e);
99-
}
82+
}
83+
), client.admin().indices()::create);
10084
return;
10185
}
10286

@@ -111,42 +95,8 @@ public static void createAnnotationsIndexIfNecessary(Settings settings, Client c
11195
finalListener.onResponse(false);
11296
}
11397

114-
public static XContentBuilder annotationsMapping() throws IOException {
115-
XContentBuilder builder = jsonBuilder()
116-
.startObject()
117-
.startObject(SINGLE_MAPPING_NAME);
118-
ElasticsearchMappings.addMetaInformation(builder);
119-
builder.startObject(ElasticsearchMappings.PROPERTIES)
120-
.startObject(Annotation.ANNOTATION.getPreferredName())
121-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.TEXT)
122-
.endObject()
123-
.startObject(Annotation.CREATE_TIME.getPreferredName())
124-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.DATE)
125-
.endObject()
126-
.startObject(Annotation.CREATE_USERNAME.getPreferredName())
127-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.KEYWORD)
128-
.endObject()
129-
.startObject(Annotation.TIMESTAMP.getPreferredName())
130-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.DATE)
131-
.endObject()
132-
.startObject(Annotation.END_TIMESTAMP.getPreferredName())
133-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.DATE)
134-
.endObject()
135-
.startObject(Job.ID.getPreferredName())
136-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.KEYWORD)
137-
.endObject()
138-
.startObject(Annotation.MODIFIED_TIME.getPreferredName())
139-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.DATE)
140-
.endObject()
141-
.startObject(Annotation.MODIFIED_USERNAME.getPreferredName())
142-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.KEYWORD)
143-
.endObject()
144-
.startObject(Annotation.TYPE.getPreferredName())
145-
.field(ElasticsearchMappings.TYPE, ElasticsearchMappings.KEYWORD)
146-
.endObject()
147-
.endObject()
148-
.endObject()
149-
.endObject();
150-
return builder;
98+
public static String annotationsMapping() {
99+
return TemplateUtils.loadTemplate("/org/elasticsearch/xpack/core/ml/annotations_index_mappings.json",
100+
Version.CURRENT.toString(), MAPPINGS_VERSION_VARIABLE);
151101
}
152102
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/job/persistence/AnomalyDetectorsIndex.java

+14
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package org.elasticsearch.xpack.core.ml.job.persistence;
77

88
import org.elasticsearch.ResourceAlreadyExistsException;
9+
import org.elasticsearch.Version;
910
import org.elasticsearch.action.ActionListener;
1011
import org.elasticsearch.action.admin.indices.alias.Alias;
1112
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
@@ -16,7 +17,9 @@
1617
import org.elasticsearch.client.Client;
1718
import org.elasticsearch.cluster.ClusterState;
1819
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
20+
import org.elasticsearch.index.mapper.MapperService;
1921
import org.elasticsearch.xpack.core.ml.utils.ExceptionsHelper;
22+
import org.elasticsearch.xpack.core.template.TemplateUtils;
2023

2124
import java.util.Arrays;
2225
import java.util.Collections;
@@ -31,6 +34,9 @@ public final class AnomalyDetectorsIndex {
3134

3235
public static final int CONFIG_INDEX_MAX_RESULTS_WINDOW = 10_000;
3336

37+
private static final String RESULTS_MAPPINGS_VERSION_VARIABLE = "xpack.ml.version";
38+
private static final String RESOURCE_PATH = "/org/elasticsearch/xpack/core/ml/anomalydetection/";
39+
3440
private AnomalyDetectorsIndex() {
3541
}
3642

@@ -144,4 +150,12 @@ public static void createStateIndexAndAliasIfNecessary(Client client, ClusterSta
144150
}
145151
}
146152

153+
public static String resultsMapping() {
154+
return resultsMapping(MapperService.SINGLE_MAPPING_NAME);
155+
}
156+
157+
public static String resultsMapping(String mappingType) {
158+
return TemplateUtils.loadTemplate(RESOURCE_PATH + "results_index_mappings.json",
159+
Version.CURRENT.toString(), RESULTS_MAPPINGS_VERSION_VARIABLE, Collections.singletonMap("xpack.ml.mapping_type", mappingType));
160+
}
147161
}

0 commit comments

Comments
 (0)