Skip to content

Commit 79375d3

Browse files
Scripting: Replace Update Context (#32096)
* SCRIPTING: Move Update Scripts to their own context * Added system property for backwards compatibility of change to `ctx.params`
1 parent 823d40e commit 79375d3

File tree

14 files changed

+116
-28
lines changed

14 files changed

+116
-28
lines changed

buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,9 +782,12 @@ class BuildPlugin implements Plugin<Project> {
782782
}
783783
}
784784

785-
// TODO: remove this once joda time is removed from scriptin in 7.0
785+
// TODO: remove this once joda time is removed from scripting in 7.0
786786
systemProperty 'es.scripting.use_java_time', 'true'
787787

788+
// TODO: remove this once ctx isn't added to update script params in 7.0
789+
systemProperty 'es.scripting.update.ctx_in_params', 'false'
790+
788791
// Set the system keystore/truststore password if we're running tests in a FIPS-140 JVM
789792
if (project.inFipsJvm) {
790793
systemProperty 'javax.net.ssl.trustStorePassword', 'password'

docs/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ integTestCluster {
4040

4141
// TODO: remove this for 7.0, this exists to allow the doc examples in 6.x to continue using the defaults
4242
systemProperty 'es.scripting.use_java_time', 'false'
43+
systemProperty 'es.scripting.update.ctx_in_params', 'false'
4344
}
4445

4546
// remove when https://github.com/elastic/elasticsearch/issues/31305 is fixed

modules/lang-painless/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ esplugin {
2525
integTestCluster {
2626
module project.project(':modules:mapper-extras')
2727
systemProperty 'es.scripting.use_java_time', 'true'
28+
systemProperty 'es.scripting.update.ctx_in_params', 'false'
2829
}
2930

3031
dependencies {

modules/lang-painless/src/test/resources/rest-api-spec/test/painless/15_update.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@
132132
body:
133133
script:
134134
lang: painless
135-
source: "for (def key : params.keySet()) { ctx._source[key] = params[key]}"
135+
source: "ctx._source.ctx = ctx"
136136
params: { bar: 'xxx' }
137137

138138
- match: { error.root_cause.0.type: "remote_transport_exception" }

modules/reindex/src/main/java/org/elasticsearch/index/reindex/AbstractAsyncBulkByScrollAction.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@
4848
import org.elasticsearch.index.mapper.TypeFieldMapper;
4949
import org.elasticsearch.index.mapper.VersionFieldMapper;
5050
import org.elasticsearch.index.reindex.ScrollableHitSource.SearchFailure;
51-
import org.elasticsearch.script.ExecutableScript;
5251
import org.elasticsearch.script.Script;
5352
import org.elasticsearch.script.ScriptService;
53+
import org.elasticsearch.script.UpdateScript;
5454
import org.elasticsearch.search.sort.SortBuilder;
5555
import org.elasticsearch.threadpool.ThreadPool;
5656

@@ -746,7 +746,7 @@ public abstract static class ScriptApplier implements BiFunction<RequestWrapper<
746746
private final Script script;
747747
private final Map<String, Object> params;
748748

749-
private ExecutableScript executable;
749+
private UpdateScript executable;
750750
private Map<String, Object> context;
751751

752752
public ScriptApplier(WorkerBulkByScrollTaskState taskWorker,
@@ -766,7 +766,7 @@ public RequestWrapper<?> apply(RequestWrapper<?> request, ScrollableHitSource.Hi
766766
return request;
767767
}
768768
if (executable == null) {
769-
ExecutableScript.Factory factory = scriptService.compile(script, ExecutableScript.UPDATE_CONTEXT);
769+
UpdateScript.Factory factory = scriptService.compile(script, UpdateScript.CONTEXT);
770770
executable = factory.newInstance(params);
771771
}
772772
if (context == null) {
@@ -787,8 +787,7 @@ public RequestWrapper<?> apply(RequestWrapper<?> request, ScrollableHitSource.Hi
787787
OpType oldOpType = OpType.INDEX;
788788
context.put("op", oldOpType.toString());
789789

790-
executable.setNextVar("ctx", context);
791-
executable.run();
790+
executable.execute(context);
792791

793792
String newOp = (String) context.remove("op");
794793
if (newOp == null) {

modules/reindex/src/test/java/org/elasticsearch/index/reindex/AbstractAsyncBulkByScrollActionScriptTestCase.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
import org.elasticsearch.action.index.IndexRequest;
2727
import org.elasticsearch.script.ExecutableScript;
2828
import org.elasticsearch.script.ScriptService;
29+
import org.elasticsearch.script.UpdateScript;
2930
import org.junit.Before;
3031

32+
import java.util.Collections;
3133
import java.util.Map;
3234
import java.util.function.Consumer;
3335

@@ -54,10 +56,16 @@ public void setupScriptService() {
5456
protected <T extends ActionRequest> T applyScript(Consumer<Map<String, Object>> scriptBody) {
5557
IndexRequest index = new IndexRequest("index", "type", "1").source(singletonMap("foo", "bar"));
5658
ScrollableHitSource.Hit doc = new ScrollableHitSource.BasicHit("test", "type", "id", 0);
57-
ExecutableScript executableScript = new SimpleExecutableScript(scriptBody);
58-
ExecutableScript.Factory factory = params -> executableScript;
59-
when(scriptService.compile(any(), eq(ExecutableScript.CONTEXT))).thenReturn(factory);
60-
when(scriptService.compile(any(), eq(ExecutableScript.UPDATE_CONTEXT))).thenReturn(factory);
59+
UpdateScript updateScript = new UpdateScript(Collections.emptyMap()) {
60+
@Override
61+
public void execute(Map<String, Object> ctx) {
62+
scriptBody.accept(ctx);
63+
}
64+
};
65+
UpdateScript.Factory factory = params -> updateScript;
66+
ExecutableScript simpleExecutableScript = new SimpleExecutableScript(scriptBody);
67+
when(scriptService.compile(any(), eq(ExecutableScript.CONTEXT))).thenReturn(params -> simpleExecutableScript);
68+
when(scriptService.compile(any(), eq(UpdateScript.CONTEXT))).thenReturn(factory);
6169
AbstractAsyncBulkByScrollAction<Request> action = action(scriptService, request().setScript(mockScript("")));
6270
RequestWrapper<?> result = action.buildScriptApplier().apply(AbstractAsyncBulkByScrollAction.wrap(index), doc);
6371
return (result != null) ? (T) result.self() : null;

server/src/main/java/org/elasticsearch/action/update/UpdateHelper.java

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919

2020
package org.elasticsearch.action.update;
2121

22+
import java.io.IOException;
23+
import java.util.Collections;
24+
import java.util.HashMap;
25+
import java.util.Map;
26+
import java.util.function.LongSupplier;
2227
import org.apache.logging.log4j.Logger;
2328
import org.elasticsearch.ElasticsearchException;
2429
import org.elasticsearch.action.DocWriteResponse;
@@ -42,21 +47,22 @@
4247
import org.elasticsearch.index.mapper.RoutingFieldMapper;
4348
import org.elasticsearch.index.shard.IndexShard;
4449
import org.elasticsearch.index.shard.ShardId;
45-
import org.elasticsearch.script.ExecutableScript;
4650
import org.elasticsearch.script.Script;
4751
import org.elasticsearch.script.ScriptService;
52+
import org.elasticsearch.script.UpdateScript;
4853
import org.elasticsearch.search.lookup.SourceLookup;
4954

50-
import java.io.IOException;
51-
import java.util.Collections;
52-
import java.util.HashMap;
53-
import java.util.Map;
54-
import java.util.function.LongSupplier;
55+
import static org.elasticsearch.common.Booleans.parseBoolean;
5556

5657
/**
5758
* Helper for translating an update request to an index, delete request or update response.
5859
*/
5960
public class UpdateHelper extends AbstractComponent {
61+
62+
/** Whether scripts should add the ctx variable to the params map. */
63+
private static final boolean CTX_IN_PARAMS =
64+
parseBoolean(System.getProperty("es.scripting.update.ctx_in_params"), true);
65+
6066
private final ScriptService scriptService;
6167

6268
public UpdateHelper(Settings settings, ScriptService scriptService) {
@@ -279,10 +285,18 @@ Result prepareUpdateScriptRequest(ShardId shardId, UpdateRequest request, GetRes
279285
private Map<String, Object> executeScript(Script script, Map<String, Object> ctx) {
280286
try {
281287
if (scriptService != null) {
282-
ExecutableScript.Factory factory = scriptService.compile(script, ExecutableScript.UPDATE_CONTEXT);
283-
ExecutableScript executableScript = factory.newInstance(script.getParams());
284-
executableScript.setNextVar(ContextFields.CTX, ctx);
285-
executableScript.run();
288+
UpdateScript.Factory factory = scriptService.compile(script, UpdateScript.CONTEXT);
289+
final Map<String, Object> params;
290+
if (CTX_IN_PARAMS) {
291+
params = new HashMap<>(script.getParams());
292+
params.put(ContextFields.CTX, ctx);
293+
deprecationLogger.deprecated("Using `ctx` via `params.ctx` is deprecated. " +
294+
"Use -Des.scripting.update.ctx_in_params=false to enforce non-deprecated usage.");
295+
} else {
296+
params = script.getParams();
297+
}
298+
UpdateScript executableScript = factory.newInstance(params);
299+
executableScript.execute(ctx);
286300
}
287301
} catch (Exception e) {
288302
throw new IllegalArgumentException("failed to execute script", e);

server/src/main/java/org/elasticsearch/script/ExecutableScript.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,4 @@ interface Factory {
4646
}
4747

4848
ScriptContext<Factory> CONTEXT = new ScriptContext<>("executable", Factory.class);
49-
50-
// TODO: remove these once each has its own script interface
51-
ScriptContext<Factory> UPDATE_CONTEXT = new ScriptContext<>("update", Factory.class);
5249
}

server/src/main/java/org/elasticsearch/script/ScriptModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ public class ScriptModule {
4646
SearchScript.SCRIPT_SORT_CONTEXT,
4747
SearchScript.TERMS_SET_QUERY_CONTEXT,
4848
ExecutableScript.CONTEXT,
49+
UpdateScript.CONTEXT,
4950
BucketAggregationScript.CONTEXT,
5051
BucketAggregationSelectorScript.CONTEXT,
5152
SignificantTermsHeuristicScoreScript.CONTEXT,
52-
ExecutableScript.UPDATE_CONTEXT,
5353
IngestScript.CONTEXT,
5454
FilterScript.CONTEXT,
5555
SimilarityScript.CONTEXT,

server/src/main/java/org/elasticsearch/script/ScriptService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ public <FactoryType> FactoryType compile(Script script, ScriptContext<FactoryTyp
285285
// TODO: fix this through some API or something, that's wrong
286286
// special exception to prevent expressions from compiling as update or mapping scripts
287287
boolean expression = "expression".equals(lang);
288-
boolean notSupported = context.name.equals(ExecutableScript.UPDATE_CONTEXT.name);
288+
boolean notSupported = context.name.equals(UpdateScript.CONTEXT.name);
289289
if (expression && notSupported) {
290290
throw new UnsupportedOperationException("scripts of type [" + script.getType() + "]," +
291291
" operation [" + context.name + "] and lang [" + lang + "] are not supported");

0 commit comments

Comments
 (0)