Scripting: Remove support for deprecated StoredScript contexts (#31394)

Removes support for storing scripts without the usual json around the
script. So You can no longer do:
```
POST _scripts/<templatename>
{
    "query": {
        "match": {
            "title": "{{query_string}}"
        }
    }
}
```

and must instead do:
```
POST _scripts/<templatename>
{
    "script": {
        "lang": "mustache",
        "source": {
            "query": {
                "match": {
                    "title": "{{query_string}}"
                }
            }
        }
    }
}
```

This improves error reporting when you attempt to store a script but don't
quite get the syntax right. Before, there was a good chance that we'd
think of it as a "raw" template and just store it. Now we won't do that.
Nice.
This commit is contained in:
Sohaib Iftikhar 2018-07-05 15:30:08 +02:00 committed by Nik Everett
parent 894fb97ad7
commit 40b822c878
8 changed files with 141 additions and 271 deletions

View File

@ -75,3 +75,7 @@ will be for such settings to be copied on such operations. To enable users in
`copy_settings` parameter was added on the REST layer. As this behavior will be
the only behavior in 8.0.0, this parameter is deprecated in 7.0.0 for removal in
8.0.0.
==== The deprecated stored script contexts have now been removed
When putting stored scripts, support for storing them with the deprecated `template` context or without a context is
now removed. Scripts must be stored using the `script` context as mentioned in the documentation.

View File

@ -23,7 +23,6 @@ import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRespo
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.plugins.Plugin;
@ -152,25 +151,22 @@ public class SearchTemplateIT extends ESSingleNodeTestCase {
public void testIndexedTemplateClient() throws Exception {
assertAcked(client().admin().cluster().preparePutStoredScript()
.setId("testTemplate")
.setContent(new BytesArray("{" +
"\"template\":{" +
" \"query\":{" +
" \"match\":{" +
" \"theField\" : \"{{fieldParam}}\"}" +
" }" +
"}" +
"}"), XContentType.JSON));
assertAcked(client().admin().cluster().preparePutStoredScript()
.setId("testTemplate").setContent(new BytesArray("{" +
"\"template\":{" +
" \"query\":{" +
" \"match\":{" +
" \"theField\" : \"{{fieldParam}}\"}" +
" }" +
"}" +
"}"), XContentType.JSON));
.setContent(
new BytesArray(
"{" +
" \"script\": {" +
" \"lang\": \"mustache\"," +
" \"source\": {" +
" \"query\": {" +
" \"match\": {" +
" \"theField\": \"{{fieldParam}}\"" +
" }" +
" }" +
" }" +
" }" +
"}"
),
XContentType.JSON));
GetStoredScriptResponse getResponse = client().admin().cluster()
.prepareGetStoredScript("testTemplate").get();
@ -198,41 +194,32 @@ public class SearchTemplateIT extends ESSingleNodeTestCase {
getResponse = client().admin().cluster().prepareGetStoredScript("testTemplate").get();
assertNull(getResponse.getSource());
assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
}
public void testIndexedTemplate() throws Exception {
assertAcked(client().admin().cluster().preparePutStoredScript()
.setId("1a")
.setContent(new BytesArray("{" +
"\"template\":{" +
" \"query\":{" +
" \"match\":{" +
" \"theField\" : \"{{fieldParam}}\"}" +
" }" +
"}" +
"}"
), XContentType.JSON)
String script =
"{" +
" \"script\": {" +
" \"lang\": \"mustache\"," +
" \"source\": {" +
" \"query\": {" +
" \"match\": {" +
" \"theField\": \"{{fieldParam}}\"" +
" }" +
" }" +
" }" +
" }" +
"}";
assertAcked(
client().admin().cluster().preparePutStoredScript().setId("1a").setContent(new BytesArray(script), XContentType.JSON)
);
assertAcked(client().admin().cluster().preparePutStoredScript()
.setId("2")
.setContent(new BytesArray("{" +
"\"template\":{" +
" \"query\":{" +
" \"match\":{" +
" \"theField\" : \"{{fieldParam}}\"}" +
" }" +
"}" +
"}"), XContentType.JSON)
assertAcked(
client().admin().cluster().preparePutStoredScript().setId("2").setContent(new BytesArray(script), XContentType.JSON)
);
assertAcked(client().admin().cluster().preparePutStoredScript()
.setId("3")
.setContent(new BytesArray("{" +
"\"template\":{" +
" \"match\":{" +
" \"theField\" : \"{{fieldParam}}\"}" +
" }" +
"}"), XContentType.JSON)
assertAcked(
client().admin().cluster().preparePutStoredScript().setId("3").setContent(new BytesArray(script), XContentType.JSON)
);
BulkRequestBuilder bulkRequestBuilder = client().prepareBulk();
@ -268,7 +255,6 @@ public class SearchTemplateIT extends ESSingleNodeTestCase {
.setScript("2").setScriptType(ScriptType.STORED).setScriptParams(templateParams)
.get();
assertHitCount(searchResponse.getResponse(), 1);
assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
}
// Relates to #10397
@ -282,13 +268,27 @@ public class SearchTemplateIT extends ESSingleNodeTestCase {
client().admin().indices().prepareRefresh().get();
int iterations = randomIntBetween(2, 11);
String query =
"{" +
" \"script\": {" +
" \"lang\": \"mustache\"," +
" \"source\": {" +
" \"query\": {" +
" \"match_phrase_prefix\": {" +
" \"searchtext\": {" +
" \"query\": \"{{P_Keyword1}}\"," +
" \"slop\": {{slop}}" +
" }" +
" }" +
" }" +
" }" +
" }" +
"}";
for (int i = 1; i < iterations; i++) {
assertAcked(client().admin().cluster().preparePutStoredScript()
.setId("git01")
.setContent(new BytesArray(
"{\"template\":{\"query\": {\"match_phrase_prefix\": {\"searchtext\": {\"query\": \"{{P_Keyword1}}\","
+ "\"slop\": -1}}}}}"),
XContentType.JSON));
.setContent(new BytesArray(query.replace("{{slop}}", Integer.toString(-1))), XContentType.JSON)
);
GetStoredScriptResponse getResponse = client().admin().cluster().prepareGetStoredScript("git01").get();
assertNotNull(getResponse.getSource());
@ -304,8 +304,8 @@ public class SearchTemplateIT extends ESSingleNodeTestCase {
assertAcked(client().admin().cluster().preparePutStoredScript()
.setId("git01")
.setContent(new BytesArray("{\"query\": {\"match_phrase_prefix\": {\"searchtext\": {\"query\": \"{{P_Keyword1}}\"," +
"\"slop\": 0}}}}"), XContentType.JSON));
.setContent(new BytesArray(query.replace("{{slop}}", Integer.toString(0))), XContentType.JSON)
);
SearchTemplateResponse searchResponse = new SearchTemplateRequestBuilder(client())
.setRequest(new SearchRequest("testindex").types("test"))
@ -313,16 +313,30 @@ public class SearchTemplateIT extends ESSingleNodeTestCase {
.get();
assertHitCount(searchResponse.getResponse(), 1);
}
assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
}
public void testIndexedTemplateWithArray() throws Exception {
String multiQuery = "{\"query\":{\"terms\":{\"theField\":[\"{{#fieldParam}}\",\"{{.}}\",\"{{/fieldParam}}\"]}}}";
String multiQuery =
"{\n" +
" \"script\": {\n" +
" \"lang\": \"mustache\",\n" +
" \"source\": {\n" +
" \"query\": {\n" +
" \"terms\": {\n" +
" \"theField\": [\n" +
" \"{{#fieldParam}}\",\n" +
" \"{{.}}\",\n" +
" \"{{/fieldParam}}\"\n" +
" ]\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
assertAcked(
client().admin().cluster().preparePutStoredScript()
.setId("4")
.setContent(BytesReference.bytes(jsonBuilder().startObject().field("template", multiQuery).endObject()),
XContentType.JSON)
.setContent(new BytesArray(multiQuery), XContentType.JSON)
);
BulkRequestBuilder bulkRequestBuilder = client().prepareBulk();
bulkRequestBuilder.add(client().prepareIndex("test", "type", "1").setSource("{\"theField\":\"foo\"}", XContentType.JSON));
@ -342,7 +356,6 @@ public class SearchTemplateIT extends ESSingleNodeTestCase {
.setScript("4").setScriptType(ScriptType.STORED).setScriptParams(arrayTemplateParams)
.get();
assertHitCount(searchResponse.getResponse(), 5);
assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
}
}

View File

@ -114,11 +114,7 @@ public class GetStoredScriptResponse extends ActionResponse implements StatusToX
super.readFrom(in);
if (in.readBoolean()) {
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
source = new StoredScriptSource(in);
} else {
source = new StoredScriptSource(in.readString());
}
source = new StoredScriptSource(in);
} else {
source = null;
}
@ -136,12 +132,7 @@ public class GetStoredScriptResponse extends ActionResponse implements StatusToX
out.writeBoolean(false);
} else {
out.writeBoolean(true);
if (out.getVersion().onOrAfter(Version.V_5_3_0)) {
source.writeTo(out);
} else {
out.writeString(source.getSource());
}
source.writeTo(out);
}
if (out.getVersion().onOrAfter(Version.V_6_4_0)) {
out.writeString(id);

View File

@ -19,15 +19,12 @@
package org.elasticsearch.script;
import org.elasticsearch.Version;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse;
import org.elasticsearch.cluster.AbstractDiffable;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.Diff;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
@ -69,16 +66,6 @@ public class StoredScriptSource extends AbstractDiffable<StoredScriptSource> imp
*/
public static final ParseField SCRIPT_PARSE_FIELD = new ParseField("script");
/**
* Standard {@link ParseField} for outer level of stored script source.
*/
public static final ParseField TEMPLATE_PARSE_FIELD = new ParseField("template");
/**
* Standard {@link ParseField} for query on the inner field.
*/
public static final ParseField TEMPLATE_NO_WRAPPER_PARSE_FIELD = new ParseField("query");
/**
* Standard {@link ParseField} for lang on the inner level.
*/
@ -194,26 +181,6 @@ public class StoredScriptSource extends AbstractDiffable<StoredScriptSource> imp
PARSER.declareField(Builder::setOptions, XContentParser::mapStrings, OPTIONS_PARSE_FIELD, ValueType.OBJECT);
}
private static StoredScriptSource parseRemaining(Token token, XContentParser parser) throws IOException {
try (XContentBuilder builder = XContentFactory.jsonBuilder()) {
if (token != Token.START_OBJECT) {
builder.startObject();
builder.copyCurrentStructure(parser);
builder.endObject();
} else {
builder.copyCurrentStructure(parser);
}
String source = Strings.toString(builder);
if (source == null || source.isEmpty()) {
DEPRECATION_LOGGER.deprecated("empty templates should no longer be used");
}
return new StoredScriptSource(Script.DEFAULT_TEMPLATE_LANG, source, Collections.emptyMap());
}
}
/**
* This will parse XContent into a {@link StoredScriptSource}. The following formats can be parsed:
*
@ -271,27 +238,8 @@ public class StoredScriptSource extends AbstractDiffable<StoredScriptSource> imp
* }
* }
*
* The simple template format:
*
* {@code
* {
* "query" : ...
* }
* }
*
* The complex template format:
*
* {@code
* {
* "template": {
* "query" : ...
* }
* }
* }
*
* Note that templates can be handled as both strings and complex JSON objects.
* Also templates may be part of the 'source' parameter in a script. The Parser
* can handle this case as well.
* Note that the "source" parameter can also handle template parsing including from
* a complex JSON object.
*
* @param content The content from the request to be parsed as described above.
* @return The parsed {@link StoredScriptSource}.
@ -316,7 +264,7 @@ public class StoredScriptSource extends AbstractDiffable<StoredScriptSource> imp
if (token != Token.FIELD_NAME) {
throw new ParsingException(parser.getTokenLocation(), "unexpected token [" + token + ", expected [" +
SCRIPT_PARSE_FIELD.getPreferredName() + ", " + TEMPLATE_PARSE_FIELD.getPreferredName());
SCRIPT_PARSE_FIELD.getPreferredName() + "]");
}
String name = parser.currentName();
@ -329,28 +277,9 @@ public class StoredScriptSource extends AbstractDiffable<StoredScriptSource> imp
} else {
throw new ParsingException(parser.getTokenLocation(), "unexpected token [" + token + "], expected [{, <source>]");
}
} else if (TEMPLATE_PARSE_FIELD.getPreferredName().equals(name)) {
DEPRECATION_LOGGER.deprecated("the template context is now deprecated. Specify templates in a \"script\" element.");
token = parser.nextToken();
if (token == Token.VALUE_STRING) {
String source = parser.text();
if (source == null || source.isEmpty()) {
DEPRECATION_LOGGER.deprecated("empty templates should no longer be used");
}
return new StoredScriptSource(Script.DEFAULT_TEMPLATE_LANG, source, Collections.emptyMap());
} else {
return parseRemaining(token, parser);
}
} else if (TEMPLATE_NO_WRAPPER_PARSE_FIELD.getPreferredName().equals(name)) {
DEPRECATION_LOGGER.deprecated("the template context is now deprecated. Specify templates in a \"script\" element.");
return parseRemaining(token, parser);
} else {
DEPRECATION_LOGGER.deprecated("scripts should not be stored without a context. Specify them in a \"script\" element.");
return parseRemaining(token, parser);
throw new ParsingException(parser.getTokenLocation(), "unexpected field [" + name + "], expected [" +
SCRIPT_PARSE_FIELD.getPreferredName() + "]");
}
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
@ -397,16 +326,6 @@ public class StoredScriptSource extends AbstractDiffable<StoredScriptSource> imp
private final String source;
private final Map<String, String> options;
/**
* Constructor for use with {@link GetStoredScriptResponse}
* to support the deprecated stored script namespace.
*/
public StoredScriptSource(String source) {
this.lang = null;
this.source = Objects.requireNonNull(source);
this.options = null;
}
/**
* Standard StoredScriptSource constructor.
* @param lang The language to compile the script with. Must not be {@code null}.
@ -426,35 +345,24 @@ public class StoredScriptSource extends AbstractDiffable<StoredScriptSource> imp
* only the source parameter will be read in as a bytes reference.
*/
public StoredScriptSource(StreamInput in) throws IOException {
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
this.lang = in.readString();
this.source = in.readString();
@SuppressWarnings("unchecked")
Map<String, String> options = (Map<String, String>)(Map)in.readMap();
this.options = options;
} else {
this.lang = null;
this.source = in.readBytesReference().utf8ToString();
this.options = null;
}
this.lang = in.readString();
this.source = in.readString();
@SuppressWarnings("unchecked")
Map<String, String> options = (Map<String, String>)(Map)in.readMap();
this.options = options;
}
/**
* Writes a {@link StoredScriptSource} to a stream. Version 5.3+ will write
* all of the lang, source, and options parameters. For versions prior to 5.3,
* only the source parameter will be read in as a bytes reference.
* Writes a {@link StoredScriptSource} to a stream. Will write
* all of the lang, source, and options parameters.
*/
@Override
public void writeTo(StreamOutput out) throws IOException {
if (out.getVersion().onOrAfter(Version.V_5_3_0)) {
out.writeString(lang);
out.writeString(source);
@SuppressWarnings("unchecked")
Map<String, Object> options = (Map<String, Object>)(Map)this.options;
out.writeMap(options);
} else {
out.writeBytesReference(new BytesArray(source));
}
out.writeString(lang);
out.writeString(source);
@SuppressWarnings("unchecked")
Map<String, Object> options = (Map<String, Object>)(Map)this.options;
out.writeMap(options);
}
/**

View File

@ -77,14 +77,12 @@ public class ScriptMetaDataTests extends AbstractSerializingTestCase<ScriptMetaD
ScriptMetaData.Builder builder = new ScriptMetaData.Builder(null);
XContentBuilder sourceBuilder = XContentFactory.jsonBuilder();
sourceBuilder.startObject().startObject("template").field("field", "value").endObject().endObject();
builder.storeScript("template", StoredScriptSource.parse(BytesReference.bytes(sourceBuilder), sourceBuilder.contentType()));
assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
sourceBuilder = XContentFactory.jsonBuilder();
sourceBuilder.startObject().field("template", "value").endObject();
builder.storeScript("template_field", StoredScriptSource.parse(BytesReference.bytes(sourceBuilder), sourceBuilder.contentType()));
assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
sourceBuilder.startObject().startObject("script")
.field("lang", "_lang")
.startObject("source").field("field", "value").endObject()
.endObject().endObject();
builder.storeScript("source_template", StoredScriptSource.parse(BytesReference.bytes(sourceBuilder),
sourceBuilder.contentType()));
sourceBuilder = XContentFactory.jsonBuilder();
sourceBuilder.startObject().startObject("script").field("lang", "_lang").field("source", "_source").endObject().endObject();
@ -92,26 +90,25 @@ public class ScriptMetaDataTests extends AbstractSerializingTestCase<ScriptMetaD
ScriptMetaData scriptMetaData = builder.build();
assertEquals("_source", scriptMetaData.getStoredScript("script").getSource());
assertEquals("{\"field\":\"value\"}", scriptMetaData.getStoredScript("template").getSource());
assertEquals("value", scriptMetaData.getStoredScript("template_field").getSource());
assertEquals("{\"field\":\"value\"}", scriptMetaData.getStoredScript("source_template").getSource());
}
public void testDiff() throws Exception {
ScriptMetaData.Builder builder = new ScriptMetaData.Builder(null);
builder.storeScript("1", StoredScriptSource.parse(new BytesArray("{\"foo\":\"abc\"}"), XContentType.JSON));
assertWarnings("scripts should not be stored without a context. Specify them in a \"script\" element.");
builder.storeScript("2", StoredScriptSource.parse(new BytesArray("{\"foo\":\"def\"}"), XContentType.JSON));
assertWarnings("scripts should not be stored without a context. Specify them in a \"script\" element.");
builder.storeScript("3", StoredScriptSource.parse(new BytesArray("{\"foo\":\"ghi\"}"), XContentType.JSON));
assertWarnings("scripts should not be stored without a context. Specify them in a \"script\" element.");
builder.storeScript("1", StoredScriptSource.parse(
new BytesArray("{\"script\":{\"lang\":\"mustache\",\"source\":{\"foo\":\"abc\"}}}"), XContentType.JSON));
builder.storeScript("2", StoredScriptSource.parse(
new BytesArray("{\"script\":{\"lang\":\"mustache\",\"source\":{\"foo\":\"def\"}}}"), XContentType.JSON));
builder.storeScript("3", StoredScriptSource.parse(
new BytesArray("{\"script\":{\"lang\":\"mustache\",\"source\":{\"foo\":\"ghi\"}}}"), XContentType.JSON));
ScriptMetaData scriptMetaData1 = builder.build();
builder = new ScriptMetaData.Builder(scriptMetaData1);
builder.storeScript("2", StoredScriptSource.parse(new BytesArray("{\"foo\":\"changed\"}"), XContentType.JSON));
assertWarnings("scripts should not be stored without a context. Specify them in a \"script\" element.");
builder.storeScript("2", StoredScriptSource.parse(
new BytesArray("{\"script\":{\"lang\":\"mustache\",\"source\":{\"foo\":\"changed\"}}}"), XContentType.JSON));
builder.deleteScript("3");
builder.storeScript("4", StoredScriptSource.parse(new BytesArray("{\"foo\":\"jkl\"}"), XContentType.JSON));
assertWarnings("scripts should not be stored without a context. Specify them in a \"script\" element.");
builder.storeScript("4", StoredScriptSource.parse(
new BytesArray("{\"script\":{\"lang\":\"mustache\",\"source\":{\"foo\":\"jkl\"}}}"), XContentType.JSON));
ScriptMetaData scriptMetaData2 = builder.build();
ScriptMetaData.ScriptMetadataDiff diff = (ScriptMetaData.ScriptMetadataDiff) scriptMetaData2.diff(scriptMetaData1);

View File

@ -40,19 +40,21 @@ public class StoredScriptSourceTests extends AbstractSerializingTestCase<StoredS
try {
XContentBuilder template = XContentBuilder.builder(xContentType.xContent());
template.startObject();
template.startObject("query");
template.startObject("match");
template.field("title", "{{query_string}}");
template.endObject();
template.startObject("script");
{
template.field("lang", "mustache");
template.startObject("source");
template.startObject("query").startObject("match").field("title", "{{query_string}}").endObject();
template.endObject();
template.endObject();
}
template.endObject();
template.endObject();
Map<String, String> options = new HashMap<>();
if (randomBoolean()) {
options.put(Script.CONTENT_TYPE_OPTION, xContentType.mediaType());
}
StoredScriptSource source = StoredScriptSource.parse(BytesReference.bytes(template), xContentType);
assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
return source;
return StoredScriptSource.parse(BytesReference.bytes(template), xContentType);
} catch (IOException e) {
throw new AssertionError("Failed to create test instance", e);
}
@ -84,7 +86,7 @@ public class StoredScriptSourceTests extends AbstractSerializingTestCase<StoredS
newTemplate.endObject();
newTemplate.endObject();
switch (between(0, 3)) {
switch (between(0, 2)) {
case 0:
source = Strings.toString(newTemplate);
break;
@ -92,12 +94,9 @@ public class StoredScriptSourceTests extends AbstractSerializingTestCase<StoredS
lang = randomAlphaOfLengthBetween(1, 20);
break;
case 2:
default:
options = new HashMap<>(options);
options.put(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
break;
case 3:
default:
return new StoredScriptSource(Strings.toString(newTemplate));
}
return new StoredScriptSource(lang, source, options);
}

View File

@ -20,6 +20,7 @@
package org.elasticsearch.script;
import org.elasticsearch.ResourceNotFoundException;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.Writeable;
@ -66,49 +67,6 @@ public class StoredScriptTests extends AbstractSerializingTestCase<StoredScriptS
assertThat(parsed, equalTo(source));
}
// simple template value string
try (XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON)) {
builder.startObject().field("template", "code").endObject();
StoredScriptSource parsed = StoredScriptSource.parse(BytesReference.bytes(builder), XContentType.JSON);
StoredScriptSource source = new StoredScriptSource("mustache", "code", Collections.emptyMap());
assertThat(parsed, equalTo(source));
assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
}
// complex template with wrapper template object
try (XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON)) {
builder.startObject().field("template").startObject().field("query", "code").endObject().endObject();
String code;
try (XContentBuilder cb = XContentFactory.contentBuilder(builder.contentType())) {
code = Strings.toString(cb.startObject().field("query", "code").endObject());
}
StoredScriptSource parsed = StoredScriptSource.parse(BytesReference.bytes(builder), XContentType.JSON);
StoredScriptSource source = new StoredScriptSource("mustache", code, Collections.emptyMap());
assertThat(parsed, equalTo(source));
assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
}
// complex template with no wrapper object
try (XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON)) {
builder.startObject().field("query", "code").endObject();
String code;
try (XContentBuilder cb = XContentFactory.contentBuilder(builder.contentType())) {
code = Strings.toString(cb.startObject().field("query", "code").endObject());
}
StoredScriptSource parsed = StoredScriptSource.parse(BytesReference.bytes(builder), XContentType.JSON);
StoredScriptSource source = new StoredScriptSource("mustache", code, Collections.emptyMap());
assertThat(parsed, equalTo(source));
assertWarnings("the template context is now deprecated. Specify templates in a \"script\" element.");
}
// complex template using script as the field name
try (XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON)) {
builder.startObject().startObject("script").field("lang", "mustache")
@ -206,6 +164,15 @@ public class StoredScriptTests extends AbstractSerializingTestCase<StoredScriptS
StoredScriptSource.parse(BytesReference.bytes(builder), XContentType.JSON));
assertThat(iae.getMessage(), equalTo("illegal compiler options [{option=option}] specified"));
}
// check for unsupported template context
try (XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON)) {
builder.startObject().field("template", "code").endObject();
ParsingException pEx = expectThrows(ParsingException.class, () ->
StoredScriptSource.parse(BytesReference.bytes(builder), XContentType.JSON));
assertThat(pEx.getMessage(), equalTo("unexpected field [template], expected ["+
StoredScriptSource.SCRIPT_PARSE_FIELD.getPreferredName()+ "]"));
}
}
public void testEmptyTemplateDeprecations() throws IOException {
@ -219,19 +186,6 @@ public class StoredScriptTests extends AbstractSerializingTestCase<StoredScriptS
assertWarnings("empty templates should no longer be used");
}
try (XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON)) {
builder.startObject().field("template", "").endObject();
StoredScriptSource parsed = StoredScriptSource.parse(BytesReference.bytes(builder), XContentType.JSON);
StoredScriptSource source = new StoredScriptSource(Script.DEFAULT_TEMPLATE_LANG, "", Collections.emptyMap());
assertThat(parsed, equalTo(source));
assertWarnings(
"the template context is now deprecated. Specify templates in a \"script\" element.",
"empty templates should no longer be used"
);
}
try (XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON)) {
builder.startObject().field("script").startObject().field("lang", "mustache")
.field("source", "").endObject().endObject();

View File

@ -220,7 +220,11 @@ public class BasicWatcherTests extends AbstractWatcherIntegrationTestCase {
SearchSourceBuilder searchSourceBuilder = searchSource().query(matchQuery("level", "a"));
assertAcked(client().admin().cluster().preparePutStoredScript()
.setId("my-template")
.setContent(BytesReference.bytes(jsonBuilder().startObject().field("template").value(searchSourceBuilder).endObject()),
.setContent(BytesReference.bytes(
jsonBuilder().startObject().startObject("script")
.field("lang", "mustache")
.field("source").value(searchSourceBuilder)
.endObject().endObject()),
XContentType.JSON)
.get());