Scripting: Add optional context parameter to put stored script requests (#25014)

This commit adds an optional `context` url parameter to the put stored
script request. When a context is specified, the script is compiled
against that context before storing, as a validation the script will
work when used in that context.
This commit is contained in:
Ryan Ernst 2017-06-01 17:53:48 -07:00 committed by GitHub
parent 39e59b49b1
commit 8d88b94372
7 changed files with 37 additions and 11 deletions

View File

@ -38,6 +38,7 @@ public class PutStoredScriptRequest extends AcknowledgedRequest<PutStoredScriptR
private String id;
private String lang;
private String context;
private BytesReference content;
private XContentType xContentType;
@ -45,10 +46,11 @@ public class PutStoredScriptRequest extends AcknowledgedRequest<PutStoredScriptR
super();
}
public PutStoredScriptRequest(String id, String lang, BytesReference content, XContentType xContentType) {
public PutStoredScriptRequest(String id, String lang, String context, BytesReference content, XContentType xContentType) {
super();
this.id = id;
this.lang = lang;
this.context = context;
this.content = content;
this.xContentType = Objects.requireNonNull(xContentType);
}
@ -94,6 +96,15 @@ public class PutStoredScriptRequest extends AcknowledgedRequest<PutStoredScriptR
return this;
}
public String context() {
return context;
}
public PutStoredScriptRequest context(String context) {
this.context = context;
return this;
}
public BytesReference content() {
return content;
}
@ -128,6 +139,9 @@ public class PutStoredScriptRequest extends AcknowledgedRequest<PutStoredScriptR
} else {
xContentType = XContentFactory.xContentType(content);
}
if (in.getVersion().onOrAfter(Version.V_6_0_0_alpha2)) {
context = in.readOptionalString();
}
}
@Override
@ -140,6 +154,9 @@ public class PutStoredScriptRequest extends AcknowledgedRequest<PutStoredScriptR
if (out.getVersion().onOrAfter(Version.V_5_3_0)) {
xContentType.writeTo(out);
}
if (out.getVersion().onOrAfter(Version.V_6_0_0_alpha2)) {
out.writeOptionalString(context);
}
}
@Override

View File

@ -50,6 +50,7 @@ public class RestPutStoredScriptAction extends BaseRestHandler {
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {
String id = request.param("id");
String lang = request.param("lang");
String context = request.param("context");
// In the case where only {lang} is not null, we make it {id} because of
// name ordering issues in the handlers' paths.
@ -65,7 +66,7 @@ public class RestPutStoredScriptAction extends BaseRestHandler {
"specifying lang [" + lang + "] as part of the url path is deprecated, use request content instead");
}
PutStoredScriptRequest putRequest = new PutStoredScriptRequest(id, lang, content, request.getXContentType());
PutStoredScriptRequest putRequest = new PutStoredScriptRequest(id, lang, context, content, request.getXContentType());
return channel -> client.admin().cluster().putStoredScript(putRequest, new AcknowledgedRestListener<>(channel));
}
}

View File

@ -431,14 +431,12 @@ public class ScriptService extends AbstractComponent implements Closeable, Clust
} else if (isAnyContextEnabled() == false) {
throw new IllegalArgumentException(
"cannot put [" + ScriptType.STORED + "] script, no script contexts are enabled");
} else {
// TODO: executable context here is just a placeholder, replace with optional context name passed into PUT stored script req
Object compiled = scriptEngine.compile(request.id(), source.getCode(), ExecutableScript.CONTEXT, Collections.emptyMap());
if (compiled == null) {
throw new IllegalArgumentException("failed to parse/compile stored script [" + request.id() + "]" +
(source.getCode() == null ? "" : " using code [" + source.getCode() + "]"));
} else if (request.context() != null) {
ScriptContext<?> context = contexts.get(request.context());
if (context == null) {
throw new IllegalArgumentException("Unknown context [" + request.context() + "]");
}
scriptEngine.compile(request.id(), source.getCode(), context, Collections.emptyMap());
}
} catch (ScriptException good) {
throw good;

View File

@ -32,7 +32,8 @@ import java.util.Base64;
public class PutStoredScriptRequestTests extends ESTestCase {
public void testSerialization() throws IOException {
PutStoredScriptRequest storedScriptRequest = new PutStoredScriptRequest("foo", "bar", new BytesArray("{}"), XContentType.JSON);
PutStoredScriptRequest storedScriptRequest =
new PutStoredScriptRequest("foo", "bar", "context", new BytesArray("{}"), XContentType.JSON);
assertEquals(XContentType.JSON, storedScriptRequest.xContentType());
try (BytesStreamOutput output = new BytesStreamOutput()) {
@ -44,6 +45,7 @@ public class PutStoredScriptRequestTests extends ESTestCase {
assertEquals(XContentType.JSON, serialized.xContentType());
assertEquals(storedScriptRequest.lang(), serialized.lang());
assertEquals(storedScriptRequest.id(), serialized.id());
assertEquals(storedScriptRequest.context(), serialized.context());
}
}
}

View File

@ -26,6 +26,7 @@ import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.AcknowledgedRestListener;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.Script;
import java.io.IOException;
@ -47,7 +48,8 @@ public class RestPutSearchTemplateAction extends BaseRestHandler {
String id = request.param("id");
BytesReference content = request.content();
PutStoredScriptRequest put = new PutStoredScriptRequest(id, Script.DEFAULT_TEMPLATE_LANG, content, request.getXContentType());
PutStoredScriptRequest put = new PutStoredScriptRequest(id, Script.DEFAULT_TEMPLATE_LANG, ExecutableScript.CONTEXT.name,
content, request.getXContentType());
return channel -> client.admin().cluster().putStoredScript(put, new AcknowledgedRestListener<>(channel));
}
}

View File

@ -38,10 +38,12 @@
catch: request
put_script:
id: "1"
context: "search"
body: { "script": {"lang": "painless", "code": "_score * foo bar + doc['myParent.weight'].value"} }
- do:
catch: /compile error/
put_script:
id: "1"
context: "search"
body: { "script": {"lang": "painless", "code": "_score * foo bar + doc['myParent.weight'].value"} }

View File

@ -18,6 +18,10 @@
}
},
"params" : {
"context": {
"type" : "string",
"description" : "Context name to compile script against"
}
}
},
"body": {