Skip to content

Commit 1e61059

Browse files
authored
Move runtime fields to server (#69223)
This commit makes a start on moving runtime fields to server. The runtime field types are now built-in. The dynamic fields builder extension (needed to make dynamic:runtime work) is removed: further simplifications are needed but are left for a follow-up. It is still possible to plug in custom runtime field types through the same extension point that the xpack plugin used to use. The runtime fields script contexts are now also moved to server, and the corresponding whitelists are part of painless-lang with the exception of grok and dissect which will require additional work. The runtime fields xpack plugin still exists to hold the grok and dissect extensions needed, which depend on grok and dissect lib and we will address as a follow-up. Also, the qa tests and yaml tests are yet to be moved. Despite the need for additional work, runtime fields are fully functional and users should not be impacted by this change.
1 parent ae94701 commit 1e61059

File tree

161 files changed

+996
-1087
lines changed

Some content is hidden

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

161 files changed

+996
-1087
lines changed

modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@
3737
import org.elasticsearch.repositories.RepositoriesService;
3838
import org.elasticsearch.rest.RestController;
3939
import org.elasticsearch.rest.RestHandler;
40+
import org.elasticsearch.runtimefields.mapper.BooleanFieldScript;
41+
import org.elasticsearch.runtimefields.mapper.DateFieldScript;
42+
import org.elasticsearch.runtimefields.mapper.DoubleFieldScript;
43+
import org.elasticsearch.runtimefields.mapper.GeoPointFieldScript;
44+
import org.elasticsearch.runtimefields.mapper.IpFieldScript;
45+
import org.elasticsearch.runtimefields.mapper.LongFieldScript;
46+
import org.elasticsearch.runtimefields.mapper.StringFieldScript;
4047
import org.elasticsearch.script.IngestScript;
4148
import org.elasticsearch.script.ScoreScript;
4249
import org.elasticsearch.script.ScriptContext;
@@ -88,6 +95,15 @@ public final class PainlessPlugin extends Plugin implements ScriptPlugin, Extens
8895
ingest.add(ingestWhitelist);
8996
map.put(IngestScript.CONTEXT, ingest);
9097

98+
// Functions available to runtime fields
99+
map.put(BooleanFieldScript.CONTEXT, getRuntimeFieldWhitelist("boolean"));
100+
map.put(DateFieldScript.CONTEXT, getRuntimeFieldWhitelist("date"));
101+
map.put(DoubleFieldScript.CONTEXT, getRuntimeFieldWhitelist("double"));
102+
map.put(LongFieldScript.CONTEXT, getRuntimeFieldWhitelist("long"));
103+
map.put(StringFieldScript.CONTEXT, getRuntimeFieldWhitelist("string"));
104+
map.put(GeoPointFieldScript.CONTEXT, getRuntimeFieldWhitelist("geopoint"));
105+
map.put(IpFieldScript.CONTEXT, getRuntimeFieldWhitelist("ip"));
106+
91107
// Execute context gets everything
92108
List<Whitelist> test = new ArrayList<>(Whitelist.BASE_WHITELISTS);
93109
test.add(movFnWhitelist);
@@ -99,6 +115,14 @@ public final class PainlessPlugin extends Plugin implements ScriptPlugin, Extens
99115
whitelists = map;
100116
}
101117

118+
private static List<Whitelist> getRuntimeFieldWhitelist(String fieldType) {
119+
List<Whitelist> scriptField = new ArrayList<>(Whitelist.BASE_WHITELISTS);
120+
Whitelist whitelist = WhitelistLoader.loadFromResourceFiles(Whitelist.class,
121+
"org.elasticsearch.runtimefields." + fieldType + ".txt");
122+
scriptField.add(whitelist);
123+
return scriptField;
124+
}
125+
102126
private final SetOnce<PainlessScriptEngine> painlessScriptEngine = new SetOnce<>();
103127

104128
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
# 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
# in compliance with, at your election, the Elastic License 2.0 or the Server
6+
# Side Public License, v 1.
7+
#
8+
9+
# The whitelist for boolean-valued runtime fields
10+
11+
# These two whitelists are required for painless to find the classes
12+
class org.elasticsearch.runtimefields.mapper.BooleanFieldScript @no_import {
13+
}
14+
class org.elasticsearch.runtimefields.mapper.BooleanFieldScript$Factory @no_import {
15+
}
16+
17+
static_import {
18+
# The `emit` callback to collect values for the field
19+
void emit(org.elasticsearch.runtimefields.mapper.BooleanFieldScript, boolean) bound_to org.elasticsearch.runtimefields.mapper.BooleanFieldScript$Emit
20+
}
21+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
# 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
# in compliance with, at your election, the Elastic License 2.0 or the Server
6+
# Side Public License, v 1.
7+
#
8+
9+
# The whitelist for date-valued runtime fields
10+
11+
# These two whitelists are required for painless to find the classes
12+
class org.elasticsearch.runtimefields.mapper.DateFieldScript @no_import {
13+
}
14+
class org.elasticsearch.runtimefields.mapper.DateFieldScript$Factory @no_import {
15+
}
16+
17+
static_import {
18+
# The `emit` callback to collect values for the field
19+
void emit(org.elasticsearch.runtimefields.mapper.DateFieldScript, long) bound_to org.elasticsearch.runtimefields.mapper.DateFieldScript$Emit
20+
# Parse a value from the source to millis since epoch
21+
long parse(org.elasticsearch.runtimefields.mapper.DateFieldScript, def) bound_to org.elasticsearch.runtimefields.mapper.DateFieldScript$Parse
22+
}
23+
24+
25+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
# 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
# in compliance with, at your election, the Elastic License 2.0 or the Server
6+
# Side Public License, v 1.
7+
#
8+
9+
# The whitelist for double-valued runtime fields
10+
11+
# These two whitelists are required for painless to find the classes
12+
class org.elasticsearch.runtimefields.mapper.DoubleFieldScript @no_import {
13+
}
14+
class org.elasticsearch.runtimefields.mapper.DoubleFieldScript$Factory @no_import {
15+
}
16+
17+
static_import {
18+
# The `emit` callback to collect values for the field
19+
void emit(org.elasticsearch.runtimefields.mapper.DoubleFieldScript, double) bound_to org.elasticsearch.runtimefields.mapper.DoubleFieldScript$Emit
20+
}
21+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
# 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
# in compliance with, at your election, the Elastic License 2.0 or the Server
6+
# Side Public License, v 1.
7+
#
8+
9+
# The whitelist for ip-valued runtime fields
10+
11+
# These two whitelists are required for painless to find the classes
12+
class org.elasticsearch.runtimefields.mapper.GeoPointFieldScript @no_import {
13+
}
14+
class org.elasticsearch.runtimefields.mapper.GeoPointFieldScript$Factory @no_import {
15+
}
16+
17+
static_import {
18+
# The `emit` callback to collect values for the field
19+
void emit(org.elasticsearch.runtimefields.mapper.GeoPointFieldScript, double, double) bound_to org.elasticsearch.runtimefields.mapper.GeoPointFieldScript$Emit
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
# 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
# in compliance with, at your election, the Elastic License 2.0 or the Server
6+
# Side Public License, v 1.
7+
#
8+
9+
# The whitelist for ip-valued runtime fields
10+
11+
# These two whitelists are required for painless to find the classes
12+
class org.elasticsearch.runtimefields.mapper.IpFieldScript @no_import {
13+
}
14+
class org.elasticsearch.runtimefields.mapper.IpFieldScript$Factory @no_import {
15+
}
16+
17+
static_import {
18+
# The `emit` callback to collect values for the field
19+
void emit(org.elasticsearch.runtimefields.mapper.IpFieldScript, String) bound_to org.elasticsearch.runtimefields.mapper.IpFieldScript$Emit
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
# 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
# in compliance with, at your election, the Elastic License 2.0 or the Server
6+
# Side Public License, v 1.
7+
#
8+
9+
# The whitelist for long-valued runtime fields
10+
11+
# These two whitelists are required for painless to find the classes
12+
class org.elasticsearch.runtimefields.mapper.LongFieldScript @no_import {
13+
}
14+
class org.elasticsearch.runtimefields.mapper.LongFieldScript$Factory @no_import {
15+
}
16+
17+
static_import {
18+
# The `emit` callback to collect values for the field
19+
void emit(org.elasticsearch.runtimefields.mapper.LongFieldScript, long) bound_to org.elasticsearch.runtimefields.mapper.LongFieldScript$Emit
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
# 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
# in compliance with, at your election, the Elastic License 2.0 or the Server
6+
# Side Public License, v 1.
7+
#
8+
9+
# The whitelist for string-valued runtime fields
10+
11+
# These two whitelists are required for painless to find the classes
12+
class org.elasticsearch.runtimefields.mapper.StringFieldScript @no_import {
13+
}
14+
class org.elasticsearch.runtimefields.mapper.StringFieldScript$Factory @no_import {
15+
}
16+
17+
static_import {
18+
# The `emit` callback to collect values for the field
19+
void emit(org.elasticsearch.runtimefields.mapper.StringFieldScript, String) bound_to org.elasticsearch.runtimefields.mapper.StringFieldScript$Emit
20+
}

server/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,6 @@
88

99
package org.elasticsearch.index.mapper;
1010

11-
import java.io.IOException;
12-
import java.util.ArrayList;
13-
import java.util.Collections;
14-
import java.util.Comparator;
15-
import java.util.Iterator;
16-
import java.util.List;
17-
import java.util.function.Function;
18-
1911
import org.apache.lucene.document.Field;
2012
import org.apache.lucene.index.IndexableField;
2113
import org.apache.lucene.search.Query;
@@ -31,6 +23,14 @@
3123
import org.elasticsearch.common.xcontent.XContentType;
3224
import org.elasticsearch.index.query.SearchExecutionContext;
3325

26+
import java.io.IOException;
27+
import java.util.ArrayList;
28+
import java.util.Collections;
29+
import java.util.Comparator;
30+
import java.util.Iterator;
31+
import java.util.List;
32+
import java.util.function.Function;
33+
3434
/** A parser for documents, given mappings from a DocumentMapper */
3535
final class DocumentParser {
3636

@@ -39,11 +39,10 @@ final class DocumentParser {
3939
private final DynamicRuntimeFieldsBuilder dynamicRuntimeFieldsBuilder;
4040

4141
DocumentParser(NamedXContentRegistry xContentRegistry,
42-
Function<DateFormatter, Mapper.TypeParser.ParserContext> dateParserContext,
43-
DynamicRuntimeFieldsBuilder dynamicRuntimeFieldsBuilder) {
42+
Function<DateFormatter, Mapper.TypeParser.ParserContext> dateParserContext) {
4443
this.xContentRegistry = xContentRegistry;
4544
this.dateParserContext = dateParserContext;
46-
this.dynamicRuntimeFieldsBuilder = dynamicRuntimeFieldsBuilder;
45+
this.dynamicRuntimeFieldsBuilder = org.elasticsearch.runtimefields.mapper.DynamicRuntimeFieldsBuilder.INSTANCE;
4746
}
4847

4948
ParsedDocument parseDocument(SourceToParse source,

server/src/main/java/org/elasticsearch/index/mapper/DynamicRuntimeFieldsBuilder.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
package org.elasticsearch.index.mapper;
1010

1111
import org.elasticsearch.common.time.DateFormatter;
12-
import org.elasticsearch.plugins.MapperPlugin;
1312

1413
import static org.elasticsearch.index.mapper.ObjectMapper.Dynamic;
1514

@@ -18,7 +17,6 @@
1817
* Plugins that provide runtime field implementations can also plug in their implementation of this interface
1918
* to define how leaf fields of each supported type can be dynamically created in dynamic runtime mode.
2019
*
21-
* @see MapperPlugin#getDynamicRuntimeFieldsBuilder()
2220
* @see Dynamic
2321
*/
2422
public interface DynamicRuntimeFieldsBuilder {

server/src/main/java/org/elasticsearch/index/mapper/Mapper.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ class ParserContext {
4949
private final Function<String, SimilarityProvider> similarityLookupService;
5050
private final Function<String, TypeParser> typeParsers;
5151
private final Function<String, RuntimeFieldType.Parser> runtimeTypeParsers;
52-
private final boolean supportsDynamicRuntimeMappings;
5352
private final Version indexVersionCreated;
5453
private final Supplier<SearchExecutionContext> searchExecutionContextSupplier;
5554
private final DateFormatter dateFormatter;
@@ -67,8 +66,7 @@ public ParserContext(Function<String, SimilarityProvider> similarityLookupServic
6766
ScriptService scriptService,
6867
IndexAnalyzers indexAnalyzers,
6968
IndexSettings indexSettings,
70-
BooleanSupplier idFieldDataEnabled,
71-
boolean supportsDynamicRuntimeMappings) {
69+
BooleanSupplier idFieldDataEnabled) {
7270
this.similarityLookupService = similarityLookupService;
7371
this.typeParsers = typeParsers;
7472
this.runtimeTypeParsers = runtimeTypeParsers;
@@ -79,7 +77,6 @@ public ParserContext(Function<String, SimilarityProvider> similarityLookupServic
7977
this.indexAnalyzers = indexAnalyzers;
8078
this.indexSettings = indexSettings;
8179
this.idFieldDataEnabled = idFieldDataEnabled;
82-
this.supportsDynamicRuntimeMappings = supportsDynamicRuntimeMappings;
8380
}
8481

8582
public IndexAnalyzers getIndexAnalyzers() {
@@ -110,10 +107,6 @@ public RuntimeFieldType.Parser runtimeFieldTypeParser(String type) {
110107
return runtimeTypeParsers.apply(type);
111108
}
112109

113-
public boolean supportsDynamicRuntimeMappings() {
114-
return supportsDynamicRuntimeMappings;
115-
}
116-
117110
public Version indexVersionCreated() {
118111
return indexVersionCreated;
119112
}
@@ -159,7 +152,7 @@ private static class MultiFieldParserContext extends ParserContext {
159152
MultiFieldParserContext(ParserContext in) {
160153
super(in.similarityLookupService, in.typeParsers, in.runtimeTypeParsers, in.indexVersionCreated,
161154
in.searchExecutionContextSupplier, in.dateFormatter, in.scriptService, in.indexAnalyzers, in.indexSettings,
162-
in.idFieldDataEnabled, in.supportsDynamicRuntimeMappings);
155+
in.idFieldDataEnabled);
163156
}
164157

165158
@Override
@@ -170,7 +163,7 @@ private static class DynamicTemplateParserContext extends ParserContext {
170163
DynamicTemplateParserContext(ParserContext in) {
171164
super(in.similarityLookupService, in.typeParsers, in.runtimeTypeParsers, in.indexVersionCreated,
172165
in.searchExecutionContextSupplier, in.dateFormatter, in.scriptService, in.indexAnalyzers, in.indexSettings,
173-
in.idFieldDataEnabled, in.supportsDynamicRuntimeMappings);
166+
in.idFieldDataEnabled);
174167
}
175168

176169
@Override

server/src/main/java/org/elasticsearch/index/mapper/MapperService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ public MapperService(IndexSettings indexSettings, IndexAnalyzers indexAnalyzers,
110110
Function<DateFormatter, Mapper.TypeParser.ParserContext> parserContextFunction =
111111
dateFormatter -> new Mapper.TypeParser.ParserContext(similarityService::getSimilarity, mapperRegistry.getMapperParsers()::get,
112112
mapperRegistry.getRuntimeFieldTypeParsers()::get, indexVersionCreated, searchExecutionContextSupplier, dateFormatter,
113-
scriptService, indexAnalyzers, indexSettings, idFieldDataEnabled, mapperRegistry.getDynamicRuntimeFieldsBuilder() != null);
114-
this.documentParser = new DocumentParser(xContentRegistry, parserContextFunction, mapperRegistry.getDynamicRuntimeFieldsBuilder());
113+
scriptService, indexAnalyzers, indexSettings, idFieldDataEnabled);
114+
this.documentParser = new DocumentParser(xContentRegistry, parserContextFunction);
115115
Map<String, MetadataFieldMapper.TypeParser> metadataMapperParsers =
116116
mapperRegistry.getMetadataMapperParsers(indexSettings.getIndexVersionCreated());
117117
this.parserContextSupplier = () -> parserContextFunction.apply(null);

server/src/main/java/org/elasticsearch/index/mapper/ObjectMapper.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,6 @@ protected static boolean parseObjectOrDocumentTypeProperties(String fieldName, O
219219
if (value.equalsIgnoreCase("strict")) {
220220
builder.dynamic(Dynamic.STRICT);
221221
} else if (value.equalsIgnoreCase("runtime")) {
222-
if (parserContext.supportsDynamicRuntimeMappings() == false) {
223-
throw new IllegalArgumentException("unable to set dynamic:runtime as there is " +
224-
"no registered dynamic runtime fields builder");
225-
}
226222
builder.dynamic(Dynamic.RUNTIME);
227223
} else {
228224
boolean dynamic = XContentMapValues.nodeBooleanValue(fieldNode, fieldName + ".dynamic");

server/src/main/java/org/elasticsearch/index/mapper/ParseContext.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import org.elasticsearch.common.xcontent.XContentParser;
1616
import org.elasticsearch.index.IndexSettings;
1717
import org.elasticsearch.index.analysis.IndexAnalyzers;
18-
import org.elasticsearch.plugins.MapperPlugin;
1918

2019
import java.util.ArrayList;
2120
import java.util.Collection;
@@ -685,7 +684,6 @@ public final <T> T parseExternalValue(Class<T> clazz) {
685684

686685
/**
687686
* Retrieve the builder for dynamically created runtime fields
688-
* @see MapperPlugin#getDynamicRuntimeFieldsBuilder()
689687
*/
690688
public abstract DynamicRuntimeFieldsBuilder getDynamicRuntimeFieldsBuilder();
691689
}

0 commit comments

Comments
 (0)