Skip to content

Commit 6f3a3e1

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

File tree

14 files changed

+115
-27
lines changed

14 files changed

+115
-27
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
@@ -820,9 +820,12 @@ class BuildPlugin implements Plugin<Project> {
820820
}
821821
}
822822

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

826+
// TODO: remove this once ctx isn't added to update script params in 7.0
827+
systemProperty 'es.scripting.update.ctx_in_params', 'false'
828+
826829
// Set the system keystore/truststore password if we're running tests in a FIPS-140 JVM
827830
if (project.inFipsJvm) {
828831
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
@@ -49,9 +49,9 @@
4949
import org.elasticsearch.index.mapper.TypeFieldMapper;
5050
import org.elasticsearch.index.mapper.VersionFieldMapper;
5151
import org.elasticsearch.index.reindex.ScrollableHitSource.SearchFailure;
52-
import org.elasticsearch.script.ExecutableScript;
5352
import org.elasticsearch.script.Script;
5453
import org.elasticsearch.script.ScriptService;
54+
import org.elasticsearch.script.UpdateScript;
5555
import org.elasticsearch.search.sort.SortBuilder;
5656
import org.elasticsearch.threadpool.ThreadPool;
5757

@@ -772,7 +772,7 @@ public abstract static class ScriptApplier implements BiFunction<RequestWrapper<
772772
private final Script script;
773773
private final Map<String, Object> params;
774774

775-
private ExecutableScript executable;
775+
private UpdateScript executable;
776776
private Map<String, Object> context;
777777

778778
public ScriptApplier(WorkerBulkByScrollTaskState taskWorker,
@@ -792,7 +792,7 @@ public RequestWrapper<?> apply(RequestWrapper<?> request, ScrollableHitSource.Hi
792792
return request;
793793
}
794794
if (executable == null) {
795-
ExecutableScript.Factory factory = scriptService.compile(script, ExecutableScript.UPDATE_CONTEXT);
795+
UpdateScript.Factory factory = scriptService.compile(script, UpdateScript.CONTEXT);
796796
executable = factory.newInstance(params);
797797
}
798798
if (context == null) {
@@ -815,8 +815,7 @@ public RequestWrapper<?> apply(RequestWrapper<?> request, ScrollableHitSource.Hi
815815
OpType oldOpType = OpType.INDEX;
816816
context.put("op", oldOpType.toString());
817817

818-
executable.setNextVar("ctx", context);
819-
executable.run();
818+
executable.execute(context);
820819

821820
String newOp = (String) context.remove("op");
822821
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: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919

2020
package org.elasticsearch.action.update;
2121

22+
import java.io.IOException;
23+
import java.util.HashMap;
24+
import java.util.Map;
25+
import java.util.function.LongSupplier;
2226
import org.apache.logging.log4j.Logger;
2327
import org.elasticsearch.ElasticsearchException;
2428
import org.elasticsearch.action.DocWriteResponse;
@@ -44,21 +48,23 @@
4448
import org.elasticsearch.index.mapper.RoutingFieldMapper;
4549
import org.elasticsearch.index.shard.IndexShard;
4650
import org.elasticsearch.index.shard.ShardId;
47-
import org.elasticsearch.script.ExecutableScript;
4851
import org.elasticsearch.script.Script;
4952
import org.elasticsearch.script.ScriptService;
53+
import org.elasticsearch.script.UpdateScript;
5054
import org.elasticsearch.search.lookup.SourceLookup;
5155

52-
import java.io.IOException;
5356
import java.util.ArrayList;
54-
import java.util.HashMap;
55-
import java.util.Map;
56-
import java.util.function.LongSupplier;
57+
import static org.elasticsearch.common.Booleans.parseBoolean;
5758

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

6470
public UpdateHelper(Settings settings, ScriptService scriptService) {
@@ -297,10 +303,18 @@ Result prepareUpdateScriptRequest(ShardId shardId, UpdateRequest request, GetRes
297303
private Map<String, Object> executeScript(Script script, Map<String, Object> ctx) {
298304
try {
299305
if (scriptService != null) {
300-
ExecutableScript.Factory factory = scriptService.compile(script, ExecutableScript.UPDATE_CONTEXT);
301-
ExecutableScript executableScript = factory.newInstance(script.getParams());
302-
executableScript.setNextVar(ContextFields.CTX, ctx);
303-
executableScript.run();
306+
UpdateScript.Factory factory = scriptService.compile(script, UpdateScript.CONTEXT);
307+
final Map<String, Object> params;
308+
if (CTX_IN_PARAMS) {
309+
params = new HashMap<>(script.getParams());
310+
params.put(ContextFields.CTX, ctx);
311+
deprecationLogger.deprecated("Using `ctx` via `params.ctx` is deprecated. " +
312+
"Use -Des.scripting.update.ctx_in_params=false to enforce non-deprecated usage.");
313+
} else {
314+
params = script.getParams();
315+
}
316+
UpdateScript executableScript = factory.newInstance(params);
317+
executableScript.execute(ctx);
304318
}
305319
} catch (Exception e) {
306320
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
@@ -49,10 +49,10 @@ public class ScriptModule {
4949
SearchScript.SCRIPT_SORT_CONTEXT,
5050
SearchScript.TERMS_SET_QUERY_CONTEXT,
5151
ExecutableScript.CONTEXT,
52+
UpdateScript.CONTEXT,
5253
BucketAggregationScript.CONTEXT,
5354
BucketAggregationSelectorScript.CONTEXT,
5455
SignificantTermsHeuristicScoreScript.CONTEXT,
55-
ExecutableScript.UPDATE_CONTEXT,
5656
IngestScript.CONTEXT,
5757
FilterScript.CONTEXT,
5858
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)