diff --git a/docs/reference/migration/migrate_7_0/api.asciidoc b/docs/reference/migration/migrate_7_0/api.asciidoc index 3d824c60064..f7b6f9b2e00 100644 --- a/docs/reference/migration/migrate_7_0/api.asciidoc +++ b/docs/reference/migration/migrate_7_0/api.asciidoc @@ -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. diff --git a/modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/SearchTemplateIT.java b/modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/SearchTemplateIT.java index 884e26e7df8..0fbc3fa16af 100644 --- a/modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/SearchTemplateIT.java +++ b/modules/lang-mustache/src/test/java/org/elasticsearch/script/mustache/SearchTemplateIT.java @@ -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."); } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java index 4cf686b9c28..742fb1a74ea 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java @@ -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); diff --git a/server/src/main/java/org/elasticsearch/script/StoredScriptSource.java b/server/src/main/java/org/elasticsearch/script/StoredScriptSource.java index 885d72bdec6..aabef751fc7 100644 --- a/server/src/main/java/org/elasticsearch/script/StoredScriptSource.java +++ b/server/src/main/java/org/elasticsearch/script/StoredScriptSource.java @@ -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 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 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 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 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 imp } else { throw new ParsingException(parser.getTokenLocation(), "unexpected token [" + token + "], expected [{, ]"); } - } 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 imp private final String source; private final Map 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 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 options = (Map)(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 options = (Map)(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 options = (Map)(Map)this.options; - out.writeMap(options); - } else { - out.writeBytesReference(new BytesArray(source)); - } + out.writeString(lang); + out.writeString(source); + @SuppressWarnings("unchecked") + Map options = (Map)(Map)this.options; + out.writeMap(options); } /** diff --git a/server/src/test/java/org/elasticsearch/script/ScriptMetaDataTests.java b/server/src/test/java/org/elasticsearch/script/ScriptMetaDataTests.java index 6a17556a103..7a856ee13b9 100644 --- a/server/src/test/java/org/elasticsearch/script/ScriptMetaDataTests.java +++ b/server/src/test/java/org/elasticsearch/script/ScriptMetaDataTests.java @@ -77,14 +77,12 @@ public class ScriptMetaDataTests extends AbstractSerializingTestCase 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(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); } diff --git a/server/src/test/java/org/elasticsearch/script/StoredScriptTests.java b/server/src/test/java/org/elasticsearch/script/StoredScriptTests.java index 04483c869d9..627d67dc833 100644 --- a/server/src/test/java/org/elasticsearch/script/StoredScriptTests.java +++ b/server/src/test/java/org/elasticsearch/script/StoredScriptTests.java @@ -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 + 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