From 6940b2b8c72aab8f7c3165010ab7f44dda57d912 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Tue, 22 Nov 2016 19:24:12 -0800 Subject: [PATCH] Remove groovy scripting language (#21607) * Scripting: Remove groovy scripting language Groovy was deprecated in 5.0. This change removes it, along with the legacy default language infrastructure in scripting. --- .../index/query/QueryRewriteContext.java | 9 - .../elasticsearch/script/ScriptSettings.java | 28 -- .../query/QueryDSLDocumentationTests.java | 2 +- .../index/query/QueryRewriteContextTests.java | 64 --- .../script/ScriptServiceTests.java | 4 +- .../script/ScriptSettingsTests.java | 33 -- .../scripted-metric-aggregation.asciidoc | 15 - docs/reference/getting-started.asciidoc | 1 - docs/reference/migration/migrate_6_0.asciidoc | 3 + .../migration/migrate_6_0/scripting.asciidoc | 7 + docs/reference/modules/scripting.asciidoc | 6 - .../modules/scripting/fields.asciidoc | 8 +- .../modules/scripting/groovy.asciidoc | 150 ------- .../modules/scripting/native.asciidoc | 2 +- .../modules/scripting/security.asciidoc | 48 +-- .../modules/scripting/using.asciidoc | 22 +- modules/lang-groovy/build.gradle | 77 ---- .../licenses/groovy-2.4.6-indy.jar.sha1 | 1 - .../lang-groovy/licenses/groovy-LICENSE.txt | 15 - .../lang-groovy/licenses/groovy-NOTICE.txt | 5 - .../script/groovy/GroovyPlugin.java | 35 -- .../groovy/GroovyScriptEngineService.java | 384 ------------------ .../plugin-metadata/plugin-security.policy | 59 --- .../groovy/GroovyIndexedScriptTests.java | 164 -------- .../script/groovy/GroovyScriptTests.java | 156 ------- .../script/groovy/GroovySecurityTests.java | 177 -------- .../LangGroovyClientYamlTestSuiteIT.java | 42 -- .../test/lang_groovy/10_basic.yaml | 13 - .../test/lang_groovy/15_update.yaml | 87 ---- .../test/lang_groovy/16_update2.yaml | 73 ---- .../test/lang_groovy/25_script_upsert.yaml | 69 ---- .../test/lang_groovy/30_compile_limit.yaml | 72 ---- .../test/lang_groovy/90_missing.yaml | 48 --- .../percolator/PercolateQueryBuilder.java | 2 +- ...PercolatorBackwardsCompatibilityTests.java | 173 -------- .../index/reindex/SimpleExecutableScript.java | 2 +- .../plugins/InstallPluginCommandTests.java | 2 +- .../resources/rest-api-spec/api/update.json | 2 +- settings.gradle | 1 - .../test/rest/yaml/Features.java | 1 - 40 files changed, 40 insertions(+), 2022 deletions(-) delete mode 100644 core/src/test/java/org/elasticsearch/index/query/QueryRewriteContextTests.java create mode 100644 docs/reference/migration/migrate_6_0/scripting.asciidoc delete mode 100644 docs/reference/modules/scripting/groovy.asciidoc delete mode 100644 modules/lang-groovy/build.gradle delete mode 100644 modules/lang-groovy/licenses/groovy-2.4.6-indy.jar.sha1 delete mode 100644 modules/lang-groovy/licenses/groovy-LICENSE.txt delete mode 100644 modules/lang-groovy/licenses/groovy-NOTICE.txt delete mode 100644 modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyPlugin.java delete mode 100644 modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyScriptEngineService.java delete mode 100644 modules/lang-groovy/src/main/plugin-metadata/plugin-security.policy delete mode 100644 modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/GroovyIndexedScriptTests.java delete mode 100644 modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/GroovyScriptTests.java delete mode 100644 modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/GroovySecurityTests.java delete mode 100644 modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/LangGroovyClientYamlTestSuiteIT.java delete mode 100644 modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/10_basic.yaml delete mode 100644 modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/15_update.yaml delete mode 100644 modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/16_update2.yaml delete mode 100644 modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/25_script_upsert.yaml delete mode 100644 modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/30_compile_limit.yaml delete mode 100644 modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/90_missing.yaml delete mode 100644 modules/percolator/src/test/java/org/elasticsearch/percolator/PercolatorBackwardsCompatibilityTests.java diff --git a/core/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java b/core/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java index 26c15230279..090a49aa7a6 100644 --- a/core/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java +++ b/core/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java @@ -113,15 +113,6 @@ public class QueryRewriteContext implements ParseFieldMatcherSupplier { return new QueryParseContext(indicesQueriesRegistry, parser, indexSettings.getParseFieldMatcher()); } - /** - * Returns a new {@link QueryParseContext} like {@link #newParseContext(XContentParser)} with the only diffence, that - * the default script language will default to what has been set in the 'script.legacy.default_lang' setting. - */ - public QueryParseContext newParseContextWithLegacyScriptLanguage(XContentParser parser) { - String defaultScriptLanguage = ScriptSettings.getLegacyDefaultLang(indexSettings.getNodeSettings()); - return new QueryParseContext(defaultScriptLanguage, indicesQueriesRegistry, parser, indexSettings.getParseFieldMatcher()); - } - public long nowInMillis() { return nowInMillis.getAsLong(); } diff --git a/core/src/main/java/org/elasticsearch/script/ScriptSettings.java b/core/src/main/java/org/elasticsearch/script/ScriptSettings.java index 27a6ad04a70..447097a4884 100644 --- a/core/src/main/java/org/elasticsearch/script/ScriptSettings.java +++ b/core/src/main/java/org/elasticsearch/script/ScriptSettings.java @@ -32,17 +32,6 @@ import java.util.function.Function; public class ScriptSettings { - static final String LEGACY_DEFAULT_LANG = "groovy"; - - /** - * The default script language to use for scripts that are stored in documents that have no script lang set explicitly. - * This setting is legacy setting and only applies for indices created on ES versions prior to version 5.0 - * - * This constant will be removed in the next major release. - */ - @Deprecated - public static final String LEGACY_SCRIPT_SETTING = "script.legacy.default_lang"; - private static final Map> SCRIPT_TYPE_SETTING_MAP; static { @@ -58,7 +47,6 @@ public class ScriptSettings { private final Map> scriptContextSettingMap; private final List> scriptLanguageSettings; - private final Setting defaultLegacyScriptLanguageSetting; public ScriptSettings(ScriptEngineRegistry scriptEngineRegistry, ScriptContextRegistry scriptContextRegistry) { Map> scriptContextSettingMap = contextSettings(scriptContextRegistry); @@ -66,13 +54,6 @@ public class ScriptSettings { List> scriptLanguageSettings = languageSettings(SCRIPT_TYPE_SETTING_MAP, scriptContextSettingMap, scriptEngineRegistry, scriptContextRegistry); this.scriptLanguageSettings = Collections.unmodifiableList(scriptLanguageSettings); - - this.defaultLegacyScriptLanguageSetting = new Setting<>(LEGACY_SCRIPT_SETTING, LEGACY_DEFAULT_LANG, setting -> { - if (!LEGACY_DEFAULT_LANG.equals(setting) && !scriptEngineRegistry.getRegisteredLanguages().containsKey(setting)) { - throw new IllegalArgumentException("unregistered default language [" + setting + "]"); - } - return setting; - }, Property.NodeScope); } private static Map> contextSettings(ScriptContextRegistry scriptContextRegistry) { @@ -169,19 +150,10 @@ public class ScriptSettings { settings.addAll(SCRIPT_TYPE_SETTING_MAP.values()); settings.addAll(scriptContextSettingMap.values()); settings.addAll(scriptLanguageSettings); - settings.add(defaultLegacyScriptLanguageSetting); return settings; } public Iterable> getScriptLanguageSettings() { return scriptLanguageSettings; } - - public Setting getDefaultLegacyScriptLanguageSetting() { - return defaultLegacyScriptLanguageSetting; - } - - public static String getLegacyDefaultLang(Settings settings) { - return settings.get(LEGACY_SCRIPT_SETTING, ScriptSettings.LEGACY_DEFAULT_LANG); - } } diff --git a/core/src/test/java/org/elasticsearch/index/query/QueryDSLDocumentationTests.java b/core/src/test/java/org/elasticsearch/index/query/QueryDSLDocumentationTests.java index 97adfad95dc..9ea0a3353a6 100644 --- a/core/src/test/java/org/elasticsearch/index/query/QueryDSLDocumentationTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/QueryDSLDocumentationTests.java @@ -297,7 +297,7 @@ public class QueryDSLDocumentationTests extends ESTestCase { parameters.put("param1", 5); scriptQuery( new Script( - ScriptType.FILE, "groovy", "mygroovyscript", + ScriptType.FILE, "coollang", "myscript", parameters) ); diff --git a/core/src/test/java/org/elasticsearch/index/query/QueryRewriteContextTests.java b/core/src/test/java/org/elasticsearch/index/query/QueryRewriteContextTests.java deleted file mode 100644 index 6445ad8e7c6..00000000000 --- a/core/src/test/java/org/elasticsearch/index/query/QueryRewriteContextTests.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.index.query; - -import org.elasticsearch.Version; -import org.elasticsearch.cluster.metadata.IndexMetaData; -import org.elasticsearch.common.bytes.BytesArray; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentHelper; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.index.IndexSettings; -import org.elasticsearch.indices.query.IndicesQueriesRegistry; -import org.elasticsearch.script.ScriptSettings; -import org.elasticsearch.search.SearchModule; -import org.elasticsearch.test.ESTestCase; - -import static java.util.Collections.emptyList; - -public class QueryRewriteContextTests extends ESTestCase { - - public void testNewParseContextWithLegacyScriptLanguage() throws Exception { - String defaultLegacyScriptLanguage = randomAsciiOfLength(4); - IndexMetaData.Builder indexMetadata = new IndexMetaData.Builder("index"); - indexMetadata.settings(Settings.builder().put("index.version.created", Version.CURRENT) - .put("index.number_of_shards", 1) - .put("index.number_of_replicas", 1) - ); - final long nowInMills = randomPositiveLong(); - IndicesQueriesRegistry indicesQueriesRegistry = new SearchModule(Settings.EMPTY, false, emptyList()).getQueryParserRegistry(); - IndexSettings indexSettings = new IndexSettings(indexMetadata.build(), - Settings.builder().put(ScriptSettings.LEGACY_SCRIPT_SETTING, defaultLegacyScriptLanguage).build()); - QueryRewriteContext queryRewriteContext = - new QueryRewriteContext(indexSettings, null, null, indicesQueriesRegistry, null, null, null, () -> nowInMills); - - // verify that the default script language in the query parse context is equal to defaultLegacyScriptLanguage variable: - QueryParseContext queryParseContext = - queryRewriteContext.newParseContextWithLegacyScriptLanguage(XContentHelper.createParser(new BytesArray("{}"))); - assertEquals(defaultLegacyScriptLanguage, queryParseContext.getDefaultScriptLanguage()); - - // verify that the script query's script language is equal to defaultLegacyScriptLanguage variable: - XContentParser parser = XContentHelper.createParser(new BytesArray("{\"script\" : {\"script\": \"return true\"}}")); - queryParseContext = queryRewriteContext.newParseContextWithLegacyScriptLanguage(parser); - ScriptQueryBuilder queryBuilder = (ScriptQueryBuilder) queryParseContext.parseInnerQueryBuilder().get(); - assertEquals(defaultLegacyScriptLanguage, queryBuilder.script().getLang()); - } - -} diff --git a/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java b/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java index fde01e59db2..9d0c5b1867f 100644 --- a/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java +++ b/core/src/test/java/org/elasticsearch/script/ScriptServiceTests.java @@ -221,7 +221,7 @@ public class ScriptServiceTests extends ESTestCase { builder.put("script.file", "true"); } buildScriptService(builder.build()); - createFileScripts("groovy", "mustache", "dtest"); + createFileScripts("mustache", "dtest"); for (ScriptContext scriptContext : scriptContexts) { // only file scripts are accepted by default @@ -292,7 +292,7 @@ public class ScriptServiceTests extends ESTestCase { } buildScriptService(builder.build()); - createFileScripts("groovy", "expression", "mustache", "dtest"); + createFileScripts("expression", "mustache", "dtest"); for (ScriptType scriptType : ScriptType.values()) { //make sure file scripts have a different name than inline ones. diff --git a/core/src/test/java/org/elasticsearch/script/ScriptSettingsTests.java b/core/src/test/java/org/elasticsearch/script/ScriptSettingsTests.java index 917650d36b8..abda0376a2c 100644 --- a/core/src/test/java/org/elasticsearch/script/ScriptSettingsTests.java +++ b/core/src/test/java/org/elasticsearch/script/ScriptSettingsTests.java @@ -34,39 +34,6 @@ import static org.hamcrest.Matchers.equalTo; public class ScriptSettingsTests extends ESTestCase { - public void testDefaultLegacyLanguageIsPainless() { - ScriptEngineRegistry scriptEngineRegistry = - new ScriptEngineRegistry(Collections.singletonList(new CustomScriptEngineService())); - ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList()); - ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); - assertThat(scriptSettings.getDefaultLegacyScriptLanguageSetting().get(Settings.EMPTY), - equalTo(ScriptSettings.LEGACY_DEFAULT_LANG)); - } - - public void testCustomLegacyDefaultLanguage() { - ScriptEngineRegistry scriptEngineRegistry = - new ScriptEngineRegistry(Collections.singletonList(new CustomScriptEngineService())); - ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList()); - ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); - String defaultLanguage = CustomScriptEngineService.NAME; - Settings settings = Settings.builder().put(ScriptSettings.LEGACY_SCRIPT_SETTING, defaultLanguage).build(); - assertThat(scriptSettings.getDefaultLegacyScriptLanguageSetting().get(settings), equalTo(defaultLanguage)); - } - - public void testInvalidLegacyDefaultLanguage() { - ScriptEngineRegistry scriptEngineRegistry = - new ScriptEngineRegistry(Collections.singletonList(new CustomScriptEngineService())); - ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Collections.emptyList()); - ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry); - Settings settings = Settings.builder().put(ScriptSettings.LEGACY_SCRIPT_SETTING, "C++").build(); - try { - scriptSettings.getDefaultLegacyScriptLanguageSetting().get(settings); - fail("should have seen unregistered default language"); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), containsString("unregistered default language [C++]")); - } - } - public void testSettingsAreProperlyPropogated() { ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singletonList(new CustomScriptEngineService())); diff --git a/docs/java-api/aggregations/metrics/scripted-metric-aggregation.asciidoc b/docs/java-api/aggregations/metrics/scripted-metric-aggregation.asciidoc index e9c79ed59d8..6b084c13ea8 100644 --- a/docs/java-api/aggregations/metrics/scripted-metric-aggregation.asciidoc +++ b/docs/java-api/aggregations/metrics/scripted-metric-aggregation.asciidoc @@ -5,21 +5,6 @@ Here is how you can use {ref}/search-aggregations-metrics-scripted-metric-aggregation.html[Scripted Metric Aggregation] with Java API. -Don't forget to add Groovy in your classpath if you want to run Groovy scripts in an embedded data node -(for unit tests for example). -For example, with Maven, add this dependency to your `pom.xml` file: - -[source,xml] --------------------------------------------------- - - org.codehaus.groovy - groovy-all - 2.3.2 - indy - --------------------------------------------------- - - ===== Prepare aggregation request Here is an example on how to create the aggregation request: diff --git a/docs/reference/getting-started.asciidoc b/docs/reference/getting-started.asciidoc index 26d0f6a6f83..a886c6c77df 100755 --- a/docs/reference/getting-started.asciidoc +++ b/docs/reference/getting-started.asciidoc @@ -153,7 +153,6 @@ If everything goes well, you should see a bunch of messages that look like below [2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [aggs-matrix-stats] [2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [ingest-common] [2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [lang-expression] -[2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [lang-groovy] [2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [lang-mustache] [2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [lang-painless] [2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [percolator] diff --git a/docs/reference/migration/migrate_6_0.asciidoc b/docs/reference/migration/migrate_6_0.asciidoc index 48057a8c0cc..5dd7c6d8a20 100644 --- a/docs/reference/migration/migrate_6_0.asciidoc +++ b/docs/reference/migration/migrate_6_0.asciidoc @@ -33,6 +33,7 @@ way to reindex old indices is to use the `reindex` API. * <> * <> * <> +* <> include::migrate_6_0/cat.asciidoc[] @@ -51,3 +52,5 @@ include::migrate_6_0/settings.asciidoc[] include::migrate_6_0/plugins.asciidoc[] include::migrate_6_0/indices.asciidoc[] + +include::migrate_6_0/scripting.asciidoc[] diff --git a/docs/reference/migration/migrate_6_0/scripting.asciidoc b/docs/reference/migration/migrate_6_0/scripting.asciidoc new file mode 100644 index 00000000000..a0cc601490a --- /dev/null +++ b/docs/reference/migration/migrate_6_0/scripting.asciidoc @@ -0,0 +1,7 @@ +[[breaking_60_scripting_changes]] +=== Scripting changes + +==== Groovy language removed + +The groovy scripting language was deprecated in elasticsearch 5.0 and is now removed. +Use painless instead. diff --git a/docs/reference/modules/scripting.asciidoc b/docs/reference/modules/scripting.asciidoc index cab9da7acd3..460b3be461d 100644 --- a/docs/reference/modules/scripting.asciidoc +++ b/docs/reference/modules/scripting.asciidoc @@ -26,10 +26,6 @@ and give the most flexibility. |yes |built-in -|<> - |<> - |built-in - |======================================================================= [float] @@ -79,8 +75,6 @@ include::scripting/fields.asciidoc[] include::scripting/security.asciidoc[] -include::scripting/groovy.asciidoc[] - include::scripting/painless.asciidoc[] include::scripting/painless-syntax.asciidoc[] diff --git a/docs/reference/modules/scripting/fields.asciidoc b/docs/reference/modules/scripting/fields.asciidoc index 35e1488fc28..9b71866d989 100644 --- a/docs/reference/modules/scripting/fields.asciidoc +++ b/docs/reference/modules/scripting/fields.asciidoc @@ -198,14 +198,14 @@ GET my_index/_search "script_fields": { "source": { "script": { - "lang": "groovy", - "inline": "_source.title + ' ' + _source.first_name + ' ' + _source.last_name" <2> + "lang": "painless", + "inline": "params._source.title + ' ' + params._source.first_name + ' ' + params._source.last_name" <2> } }, "stored_fields": { "script": { - "lang": "groovy", - "inline": "_fields['first_name'].value + ' ' + _fields['last_name'].value" + "lang": "painless", + "inline": "params._fields['first_name'].value + ' ' + params._fields['last_name'].value" } } } diff --git a/docs/reference/modules/scripting/groovy.asciidoc b/docs/reference/modules/scripting/groovy.asciidoc deleted file mode 100644 index 24974e5733f..00000000000 --- a/docs/reference/modules/scripting/groovy.asciidoc +++ /dev/null @@ -1,150 +0,0 @@ -[[modules-scripting-groovy]] -=== Groovy Scripting Language - -deprecated[5.0.0,Groovy will be replaced by the new scripting language <>] - -Groovy is available in Elasticsearch by default. Although -limited by the <>, it is not a -sandboxed language and only `file` scripts may be used by default. - -Enabling `inline` or `stored` Groovy scripting is a security risk and should -only be considered if your Elasticsearch cluster is protected from the outside -world. Even a simple `while (true) { }` loop could behave as a denial-of- -service attack on your cluster. - -See <> for details -on security issues with scripts, including how to customize class -whitelisting. - -[float] -=== Doc value properties and methods - -Doc values in Groovy support the following properties and methods (depending -on the underlying field type): - -`doc['field_name'].value`:: - The native value of the field. For example, if its a short type, it will be short. - -`doc['field_name'].values`:: - The native array values of the field. For example, if its a short type, - it will be short[]. Remember, a field can have several values within a - single doc. Returns an empty array if the field has no values. - -`doc['field_name'].empty`:: - A boolean indicating if the field has no values within the doc. - -`doc['field_name'].lat`:: - The latitude of a geo point type, or `null`. - -`doc['field_name'].lon`:: - The longitude of a geo point type, or `null`. - -`doc['field_name'].lats`:: - The latitudes of a geo point type, or an empty array. - -`doc['field_name'].lons`:: - The longitudes of a geo point type, or an empty array. - -`doc['field_name'].arcDistance(lat, lon)`:: - The `arc` distance (in meters) of this geo point field from the provided lat/lon. - -`doc['field_name'].arcDistanceWithDefault(lat, lon, default)`:: - The `arc` distance (in meters) of this geo point field from the provided lat/lon with a default value - for empty fields. - -`doc['field_name'].planeDistance(lat, lon)`:: - The `plane` distance (in meters) of this geo point field from the provided lat/lon. - -`doc['field_name'].planeDistanceWithDefault(lat, lon, default)`:: - The `plane` distance (in meters) of this geo point field from the provided lat/lon with a default value - for empty fields. - -`doc['field_name'].geohashDistance(geohash)`:: - The `arc` distance (in meters) of this geo point field from the provided geohash. - -`doc['field_name'].geohashDistanceWithDefault(geohash, default)`:: - The `arc` distance (in meters) of this geo point field from the provided geohash with a default value - for empty fields. - - -[float] -=== Groovy Built In Functions - -There are several built in functions that can be used within scripts. -They include: - -[cols="<,<",options="header",] -|======================================================================= -|Function |Description -|`sin(a)` |Returns the trigonometric sine of an angle. - -|`cos(a)` |Returns the trigonometric cosine of an angle. - -|`tan(a)` |Returns the trigonometric tangent of an angle. - -|`asin(a)` |Returns the arc sine of a value. - -|`acos(a)` |Returns the arc cosine of a value. - -|`atan(a)` |Returns the arc tangent of a value. - -|`toRadians(angdeg)` |Converts an angle measured in degrees to an -approximately equivalent angle measured in radians - -|`toDegrees(angrad)` |Converts an angle measured in radians to an -approximately equivalent angle measured in degrees. - -|`exp(a)` |Returns Euler's number _e_ raised to the power of value. - -|`log(a)` |Returns the natural logarithm (base _e_) of a value. - -|`log10(a)` |Returns the base 10 logarithm of a value. - -|`sqrt(a)` |Returns the correctly rounded positive square root of a -value. - -|`cbrt(a)` |Returns the cube root of a double value. - -|`IEEEremainder(f1, f2)` |Computes the remainder operation on two -arguments as prescribed by the IEEE 754 standard. - -|`ceil(a)` |Returns the smallest (closest to negative infinity) value -that is greater than or equal to the argument and is equal to a -mathematical integer. - -|`floor(a)` |Returns the largest (closest to positive infinity) value -that is less than or equal to the argument and is equal to a -mathematical integer. - -|`rint(a)` |Returns the value that is closest in value to the argument -and is equal to a mathematical integer. - -|`atan2(y, x)` |Returns the angle _theta_ from the conversion of -rectangular coordinates (_x_, _y_) to polar coordinates (r,_theta_). - -|`pow(a, b)` |Returns the value of the first argument raised to the -power of the second argument. - -|`round(a)` |Returns the closest _int_ to the argument. - -|`random()` |Returns a random _double_ value. - -|`abs(a)` |Returns the absolute value of a value. - -|`max(a, b)` |Returns the greater of two values. - -|`min(a, b)` |Returns the smaller of two values. - -|`ulp(d)` |Returns the size of an ulp of the argument. - -|`signum(d)` |Returns the signum function of the argument. - -|`sinh(x)` |Returns the hyperbolic sine of a value. - -|`cosh(x)` |Returns the hyperbolic cosine of a value. - -|`tanh(x)` |Returns the hyperbolic tangent of a value. - -|`hypot(x, y)` |Returns sqrt(_x2_ + _y2_) without intermediate overflow -or underflow. -|======================================================================= diff --git a/docs/reference/modules/scripting/native.asciidoc b/docs/reference/modules/scripting/native.asciidoc index ed81f44889b..8fb49b03d96 100644 --- a/docs/reference/modules/scripting/native.asciidoc +++ b/docs/reference/modules/scripting/native.asciidoc @@ -1,7 +1,7 @@ [[modules-scripting-native]] === Native (Java) Scripts -Sometimes `groovy` and <> aren't enough. For those times you can +Sometimes `painless` and <> aren't enough. For those times you can implement a native script. The best way to implement a native script is to write a plugin and install it. diff --git a/docs/reference/modules/scripting/security.asciidoc b/docs/reference/modules/scripting/security.asciidoc index cab7561d185..072b954b72f 100644 --- a/docs/reference/modules/scripting/security.asciidoc +++ b/docs/reference/modules/scripting/security.asciidoc @@ -14,16 +14,16 @@ to run scripts on your box or not, and apply the appropriate safety measures. === Enabling dynamic scripting The `script.*` settings allow for <> -control of which script languages (e.g `groovy`, `painless`) are allowed to +control of which script languages (e.g `painless`) are allowed to run in which context ( e.g. `search`, `aggs`, `update`), and where the script source is allowed to come from (i.e. `inline`, `stored`, `file`). For instance, the following setting enables `stored` `update` scripts for -`groovy`: +`painless`: [source,yaml] ---------------- -script.engine.groovy.inline.update: true +script.engine.painless.inline.update: true ---------------- Less fine-grained settings exist which allow you to enable or disable scripts @@ -128,9 +128,9 @@ script.inline: false <1> script.stored: false <1> script.file: false <1> -script.engine.groovy.inline: true <2> -script.engine.groovy.stored.search: true <3> -script.engine.groovy.stored.aggs: true <3> +script.engine.painless.inline: true <2> +script.engine.painless.stored.search: true <3> +script.engine.painless.stored.aggs: true <3> script.engine.mustache.stored.search: true <4> ----------------------------------- @@ -184,7 +184,7 @@ will return the following exception: { "reason": { "type": "script_exception", - "reason": "failed to run inline script [use(java.math.BigInteger); new BigInteger(1)] using lang [groovy]", + "reason": "failed to run inline script [use(java.math.BigInteger); new BigInteger(1)] using lang [painless]", "caused_by": { "type": "no_class_def_found_error", "reason": "java/math/BigInteger", @@ -197,30 +197,6 @@ will return the following exception: } ------------------------------ -However, classloader issues may also result in more difficult to interpret -exceptions. For instance, this script: - -[source,groovy] ------------------------------- -use(groovy.time.TimeCategory); new Date(123456789).format('HH') ------------------------------- - -Returns the following exception: - -[source,js] ------------------------------- -{ - "reason": { - "type": "script_exception", - "reason": "failed to run inline script [use(groovy.time.TimeCategory); new Date(123456789).format('HH')] using lang [groovy]", - "caused_by": { - "type": "missing_property_exception", - "reason": "No such property: groovy for class: 8d45f5c1a07a1ab5dda953234863e283a7586240" - } - } -} ------------------------------- - [float] == Dealing with Java Security Manager issues @@ -262,16 +238,6 @@ grant { }; ---------------------------------- -Here is an example of how to enable the `groovy.time.TimeCategory` class: - -[source,js] ----------------------------------- -grant { - permission org.elasticsearch.script.ClassPermission "java.lang.Class"; - permission org.elasticsearch.script.ClassPermission "groovy.time.TimeCategory"; -}; ----------------------------------- - [TIP] ====================================== diff --git a/docs/reference/modules/scripting/using.asciidoc b/docs/reference/modules/scripting/using.asciidoc index b09a54e5c46..5f2132d142d 100644 --- a/docs/reference/modules/scripting/using.asciidoc +++ b/docs/reference/modules/scripting/using.asciidoc @@ -48,7 +48,7 @@ GET my_index/_search `lang`:: - Specifies the language the script is written in. Defaults to `groovy` but + Specifies the language the script is written in. Defaults to `painless` but may be set to any of languages listed in <>. The default language may be changed in the `elasticsearch.yml` config file by setting `script.default_lang` to the appropriate language. @@ -63,7 +63,7 @@ GET my_index/_search directory (see <>). + While languages like `expression` and `painless` can be used out of the box as -inline or stored scripts, other languages like `groovy` can only be +inline or stored scripts, other languages can only be specified as `file` unless you first adjust the default <>. @@ -134,7 +134,7 @@ the following example creates a Groovy script called `calculate-score`: [source,sh] -------------------------------------------------- -cat "log(_score * 2) + my_modifier" > config/scripts/calculate-score.groovy +cat "Math.log(_score * 2) + my_modifier" > config/scripts/calculate-score.painless -------------------------------------------------- This script can be used as follows: @@ -146,7 +146,7 @@ GET my_index/_search "query": { "script": { "script": { - "lang": "groovy", <1> + "lang": "painless", <1> "file": "calculate-score", <2> "params": { "my_modifier": 2 @@ -161,7 +161,7 @@ GET my_index/_search The `script` directory may contain sub-directories, in which case the hierarchy of directories is flattened and concatenated with underscores. A -script in `group1/group2/my_script.groovy` should use `group1_group2_myscript` +script in `group1/group2/my_script.painless` should use `group1_group2_myscript` as the `file` name. @@ -190,14 +190,14 @@ Scripts may be stored in and retrieved from the cluster state using the <1> The `lang` represents the script language. <2> The `id` is a unique identifier or script name. -This example stores a Groovy script called `calculate-score` in the cluster +This example stores a Painless script called `calculate-score` in the cluster state: [source,js] ----------------------------------- -POST _scripts/groovy/calculate-score +POST _scripts/painless/calculate-score { - "script": "log(_score * 2) + my_modifier" + "script": "Math.log(_score * 2) + params.my_modifier" } ----------------------------------- // CONSOLE @@ -206,7 +206,7 @@ This same script can be retrieved with: [source,js] ----------------------------------- -GET _scripts/groovy/calculate-score +GET _scripts/painless/calculate-score ----------------------------------- // CONSOLE // TEST[continued] @@ -220,7 +220,7 @@ GET _search "query": { "script": { "script": { - "lang": "groovy", + "lang": "painless", "stored": "calculate-score", "params": { "my_modifier": 2 @@ -237,7 +237,7 @@ And deleted with: [source,js] ----------------------------------- -DELETE _scripts/groovy/calculate-score +DELETE _scripts/painless/calculate-score ----------------------------------- // CONSOLE // TEST[continued] diff --git a/modules/lang-groovy/build.gradle b/modules/lang-groovy/build.gradle deleted file mode 100644 index 77e28da7f84..00000000000 --- a/modules/lang-groovy/build.gradle +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -esplugin { - description 'Groovy scripting integration for Elasticsearch' - classname 'org.elasticsearch.script.groovy.GroovyPlugin' -} - -dependencies { - compile 'org.codehaus.groovy:groovy:2.4.6:indy' -} - -integTest { - cluster { - setting 'script.inline', 'true' - setting 'script.stored', 'true' - setting 'script.max_compilations_per_minute', '1000' - } -} - -thirdPartyAudit.excludes = [ - // classes are missing, we bring in a minimal groovy dist - // for example we do not need ivy, scripts arent allowed to download code - 'com.thoughtworks.xstream.XStream', - 'groovyjarjarasm.asm.util.Textifiable', - // commons-cli is referenced by groovy, even though they supposedly - // jarjar it. Since we don't use the cli, we don't need the dep. - 'org.apache.commons.cli.CommandLine', - 'org.apache.commons.cli.CommandLineParser', - 'org.apache.commons.cli.GnuParser', - 'org.apache.commons.cli.HelpFormatter', - 'org.apache.commons.cli.Option', - 'org.apache.commons.cli.OptionBuilder', - 'org.apache.commons.cli.Options', - 'org.apache.commons.cli.Parser', - 'org.apache.commons.cli.PosixParser', - 'org.apache.ivy.Ivy', - 'org.apache.ivy.core.event.IvyListener', - 'org.apache.ivy.core.event.download.PrepareDownloadEvent', - 'org.apache.ivy.core.event.resolve.StartResolveEvent', - 'org.apache.ivy.core.module.descriptor.Configuration', - 'org.apache.ivy.core.module.descriptor.DefaultDependencyArtifactDescriptor', - 'org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor', - 'org.apache.ivy.core.module.descriptor.DefaultExcludeRule', - 'org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor', - 'org.apache.ivy.core.module.id.ArtifactId', - 'org.apache.ivy.core.module.id.ModuleId', - 'org.apache.ivy.core.module.id.ModuleRevisionId', - 'org.apache.ivy.core.report.ResolveReport', - 'org.apache.ivy.core.resolve.ResolveOptions', - 'org.apache.ivy.core.settings.IvySettings', - 'org.apache.ivy.plugins.matcher.ExactPatternMatcher', - 'org.apache.ivy.plugins.matcher.PatternMatcher', - 'org.apache.ivy.plugins.resolver.IBiblioResolver', - 'org.apache.ivy.util.DefaultMessageLogger', - 'org.apache.ivy.util.Message', - 'org.fusesource.jansi.Ansi$Attribute', - 'org.fusesource.jansi.Ansi$Color', - 'org.fusesource.jansi.Ansi', - 'org.fusesource.jansi.AnsiRenderWriter', -] diff --git a/modules/lang-groovy/licenses/groovy-2.4.6-indy.jar.sha1 b/modules/lang-groovy/licenses/groovy-2.4.6-indy.jar.sha1 deleted file mode 100644 index 0cd895b333c..00000000000 --- a/modules/lang-groovy/licenses/groovy-2.4.6-indy.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -af78e80fab591a6dcf2d6ccb8bf34d1e888291be \ No newline at end of file diff --git a/modules/lang-groovy/licenses/groovy-LICENSE.txt b/modules/lang-groovy/licenses/groovy-LICENSE.txt deleted file mode 100644 index e0908d496f6..00000000000 --- a/modules/lang-groovy/licenses/groovy-LICENSE.txt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - \ No newline at end of file diff --git a/modules/lang-groovy/licenses/groovy-NOTICE.txt b/modules/lang-groovy/licenses/groovy-NOTICE.txt deleted file mode 100644 index b863c49d312..00000000000 --- a/modules/lang-groovy/licenses/groovy-NOTICE.txt +++ /dev/null @@ -1,5 +0,0 @@ -Apache Groovy -Copyright 2003-2016 The Apache Software Foundation - -This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). diff --git a/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyPlugin.java b/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyPlugin.java deleted file mode 100644 index c27abefb017..00000000000 --- a/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyPlugin.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.script.groovy; - -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.plugins.ScriptPlugin; -import org.elasticsearch.script.ScriptEngineRegistry; -import org.elasticsearch.script.ScriptEngineService; -import org.elasticsearch.script.ScriptModule; - -public class GroovyPlugin extends Plugin implements ScriptPlugin { - - @Override - public ScriptEngineService getScriptEngineService(Settings settings) { - return new GroovyScriptEngineService(settings); - } -} diff --git a/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyScriptEngineService.java b/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyScriptEngineService.java deleted file mode 100644 index 7ce05f82038..00000000000 --- a/modules/lang-groovy/src/main/java/org/elasticsearch/script/groovy/GroovyScriptEngineService.java +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.script.groovy; - -import groovy.lang.Binding; -import groovy.lang.GroovyClassLoader; -import groovy.lang.GroovyCodeSource; -import groovy.lang.Script; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.message.ParameterizedMessage; -import org.apache.logging.log4j.util.Supplier; -import org.apache.lucene.index.LeafReaderContext; -import org.apache.lucene.search.Scorer; -import org.codehaus.groovy.GroovyBugError; -import org.codehaus.groovy.ast.ClassCodeExpressionTransformer; -import org.codehaus.groovy.ast.ClassNode; -import org.codehaus.groovy.ast.expr.ConstantExpression; -import org.codehaus.groovy.ast.expr.Expression; -import org.codehaus.groovy.classgen.GeneratorContext; -import org.codehaus.groovy.control.CompilationFailedException; -import org.codehaus.groovy.control.CompilePhase; -import org.codehaus.groovy.control.CompilerConfiguration; -import org.codehaus.groovy.control.MultipleCompilationErrorsException; -import org.codehaus.groovy.control.SourceUnit; -import org.codehaus.groovy.control.customizers.CompilationCustomizer; -import org.codehaus.groovy.control.customizers.ImportCustomizer; -import org.codehaus.groovy.control.messages.Message; -import org.elasticsearch.SpecialPermission; -import org.elasticsearch.bootstrap.BootstrapInfo; -import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.component.AbstractComponent; -import org.elasticsearch.common.hash.MessageDigests; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.script.ClassPermission; -import org.elasticsearch.script.CompiledScript; -import org.elasticsearch.script.ExecutableScript; -import org.elasticsearch.script.LeafSearchScript; -import org.elasticsearch.script.ScoreAccessor; -import org.elasticsearch.script.ScriptEngineService; -import org.elasticsearch.script.ScriptException; -import org.elasticsearch.script.SearchScript; -import org.elasticsearch.search.lookup.LeafSearchLookup; -import org.elasticsearch.search.lookup.SearchLookup; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static java.util.Collections.emptyList; - -/** - * Provides the infrastructure for Groovy as a scripting language for Elasticsearch - */ -public class GroovyScriptEngineService extends AbstractComponent implements ScriptEngineService { - - /** - * The name of the scripting engine/language. - */ - public static final String NAME = "groovy"; - - /** - * The name of the Groovy compiler setting to use associated with activating invokedynamic support. - */ - public static final String GROOVY_INDY_SETTING_NAME = "indy"; - - /** - * Classloader used as a parent classloader for all Groovy scripts - */ - private final ClassLoader loader; - - public GroovyScriptEngineService(Settings settings) { - super(settings); - - deprecationLogger.deprecated("[groovy] scripts are deprecated, use [painless] scripts instead"); - - // Creates the classloader here in order to isolate Groovy-land code - final SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new SpecialPermission()); - } - this.loader = AccessController.doPrivileged((PrivilegedAction) () -> { - // snapshot our context (which has permissions for classes), since the script has none - AccessControlContext context = AccessController.getContext(); - return new ClassLoader(getClass().getClassLoader()) { - @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - if (sm != null) { - try { - context.checkPermission(new ClassPermission(name)); - } catch (SecurityException e) { - throw new ClassNotFoundException(name, e); - } - } - return super.loadClass(name, resolve); - } - }; - }); - } - - @Override - public void close() throws IOException { - // Nothing to do here - } - - @Override - public String getType() { - return NAME; - } - - @Override - public String getExtension() { - return NAME; - } - - @Override - public Object compile(String scriptName, String scriptSource, Map params) { - // Create the script class name - String className = MessageDigests.toHexString(MessageDigests.sha1().digest(scriptSource.getBytes(StandardCharsets.UTF_8))); - - final SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new SpecialPermission()); - } - return AccessController.doPrivileged((PrivilegedAction) () -> { - try { - GroovyCodeSource codeSource = new GroovyCodeSource(scriptSource, className, BootstrapInfo.UNTRUSTED_CODEBASE); - codeSource.setCachable(false); - - CompilerConfiguration configuration = new CompilerConfiguration() - .addCompilationCustomizers(new ImportCustomizer().addStarImports("org.joda.time").addStaticStars("java.lang.Math")) - .addCompilationCustomizers(new GroovyBigDecimalTransformer(CompilePhase.CONVERSION)); - - // always enable invokeDynamic, not the crazy softreference-based stuff - configuration.getOptimizationOptions().put(GROOVY_INDY_SETTING_NAME, true); - - GroovyClassLoader groovyClassLoader = new GroovyClassLoader(loader, configuration); - return groovyClassLoader.parseClass(codeSource); - } catch (Exception e) { - if (logger.isTraceEnabled()) { - logger.trace("Exception compiling Groovy script:", e); - } - throw convertToScriptException("Error compiling script " + className, scriptSource, e); - } - }); - } - - /** - * Return a script object with the given vars from the compiled script object - */ - @SuppressWarnings("unchecked") - private Script createScript(Object compiledScript, Map vars) throws ReflectiveOperationException { - Class scriptClass = (Class) compiledScript; - Script scriptObject = (Script) scriptClass.getConstructor().newInstance(); - Binding binding = new Binding(); - binding.getVariables().putAll(vars); - scriptObject.setBinding(binding); - return scriptObject; - } - - @Override - public ExecutableScript executable(CompiledScript compiledScript, Map vars) { - deprecationLogger.deprecated("[groovy] scripts are deprecated, use [painless] scripts instead"); - - try { - Map allVars = new HashMap<>(); - if (vars != null) { - allVars.putAll(vars); - } - return new GroovyScript(compiledScript, createScript(compiledScript.compiled(), allVars), this.logger); - } catch (ReflectiveOperationException e) { - throw convertToScriptException("Failed to build executable script", compiledScript.name(), e); - } - } - - @Override - public SearchScript search(final CompiledScript compiledScript, final SearchLookup lookup, @Nullable final Map vars) { - deprecationLogger.deprecated("[groovy] scripts are deprecated, use [painless] scripts instead"); - - return new SearchScript() { - - @Override - public LeafSearchScript getLeafSearchScript(LeafReaderContext context) throws IOException { - final LeafSearchLookup leafLookup = lookup.getLeafSearchLookup(context); - Map allVars = new HashMap<>(); - allVars.putAll(leafLookup.asMap()); - if (vars != null) { - allVars.putAll(vars); - } - Script scriptObject; - try { - scriptObject = createScript(compiledScript.compiled(), allVars); - } catch (ReflectiveOperationException e) { - throw convertToScriptException("Failed to build search script", compiledScript.name(), e); - } - return new GroovyScript(compiledScript, scriptObject, leafLookup, logger); - } - - @Override - public boolean needsScores() { - // TODO: can we reliably know if a groovy script makes use of _score - return true; - } - }; - } - - /** - * Converts a {@link Throwable} to a {@link ScriptException} - */ - private ScriptException convertToScriptException(String message, String source, Throwable cause) { - List stack = new ArrayList<>(); - if (cause instanceof MultipleCompilationErrorsException) { - @SuppressWarnings({"unchecked"}) - List errors = (List) ((MultipleCompilationErrorsException) cause).getErrorCollector().getErrors(); - for (Message error : errors) { - try (StringWriter writer = new StringWriter()) { - error.write(new PrintWriter(writer)); - stack.add(writer.toString()); - } catch (IOException e1) { - logger.error("failed to write compilation error message to the stack", e1); - } - } - } else if (cause instanceof CompilationFailedException) { - CompilationFailedException error = (CompilationFailedException) cause; - stack.add(error.getMessage()); - } - throw new ScriptException(message, cause, stack, source, NAME); - } - - public static final class GroovyScript implements ExecutableScript, LeafSearchScript { - - private final CompiledScript compiledScript; - private final Script script; - private final LeafSearchLookup lookup; - private final Map variables; - private final Logger logger; - - public GroovyScript(CompiledScript compiledScript, Script script, Logger logger) { - this(compiledScript, script, null, logger); - } - - @SuppressWarnings("unchecked") - public GroovyScript(CompiledScript compiledScript, Script script, @Nullable LeafSearchLookup lookup, Logger logger) { - this.compiledScript = compiledScript; - this.script = script; - this.lookup = lookup; - this.logger = logger; - this.variables = script.getBinding().getVariables(); - } - - @Override - public void setScorer(Scorer scorer) { - this.variables.put("_score", new ScoreAccessor(scorer)); - } - - @Override - public void setDocument(int doc) { - if (lookup != null) { - lookup.setDocument(doc); - } - } - - @Override - public void setNextVar(String name, Object value) { - variables.put(name, value); - } - - @Override - public void setSource(Map source) { - if (lookup != null) { - lookup.source().setSource(source); - } - } - - @Override - public Object run() { - try { - // NOTE: we truncate the stack because IndyInterface has security issue (needs getClassLoader) - // we don't do a security check just as a tradeoff, it cannot really escalate to anything. - return AccessController.doPrivileged((PrivilegedAction) script::run); - } catch (final AssertionError ae) { - if (ae instanceof GroovyBugError) { - // we encountered a bug in Groovy; we wrap this so it does not go to the uncaught exception handler and tear us down - final String message = "encountered bug in Groovy while executing script [" + compiledScript.name() + "]"; - throw new ScriptException(message, ae, Collections.emptyList(), compiledScript.toString(), compiledScript.lang()); - } - // Groovy asserts are not java asserts, and cannot be disabled, so we do a best-effort trying to determine if this is a - // Groovy assert (in which case we wrap it and throw), or a real Java assert, in which case we rethrow it as-is, likely - // resulting in the uncaughtExceptionHandler handling it. - final StackTraceElement[] elements = ae.getStackTrace(); - if (elements.length > 0 && "org.codehaus.groovy.runtime.InvokerHelper".equals(elements[0].getClassName())) { - logger.debug((Supplier) () -> new ParameterizedMessage("failed to run {}", compiledScript), ae); - throw new ScriptException("error evaluating " + compiledScript.name(), ae, emptyList(), "", compiledScript.lang()); - } - throw ae; - } catch (Exception | NoClassDefFoundError e) { - logger.trace((Supplier) () -> new ParameterizedMessage("failed to run {}", compiledScript), e); - throw new ScriptException("error evaluating " + compiledScript.name(), e, emptyList(), "", compiledScript.lang()); - } - } - - @Override - public long runAsLong() { - return ((Number) run()).longValue(); - } - - @Override - public double runAsDouble() { - return ((Number) run()).doubleValue(); - } - } - - /** - * A compilation customizer that is used to transform a number like 1.23, - * which would normally be a BigDecimal, into a double value. - */ - private class GroovyBigDecimalTransformer extends CompilationCustomizer { - - private GroovyBigDecimalTransformer(CompilePhase phase) { - super(phase); - } - - @Override - public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException { - new BigDecimalExpressionTransformer(source).visitClass(classNode); - } - } - - /** - * Groovy expression transformer that converts BigDecimals to doubles - */ - private class BigDecimalExpressionTransformer extends ClassCodeExpressionTransformer { - - private final SourceUnit source; - - private BigDecimalExpressionTransformer(SourceUnit source) { - this.source = source; - } - - @Override - protected SourceUnit getSourceUnit() { - return this.source; - } - - @Override - public Expression transform(Expression expr) { - Expression newExpr = expr; - if (expr instanceof ConstantExpression) { - ConstantExpression constExpr = (ConstantExpression) expr; - Object val = constExpr.getValue(); - if (val != null && val instanceof BigDecimal) { - newExpr = new ConstantExpression(((BigDecimal) val).doubleValue()); - } - } - return super.transform(newExpr); - } - } -} diff --git a/modules/lang-groovy/src/main/plugin-metadata/plugin-security.policy b/modules/lang-groovy/src/main/plugin-metadata/plugin-security.policy deleted file mode 100644 index 13d00d6d17c..00000000000 --- a/modules/lang-groovy/src/main/plugin-metadata/plugin-security.policy +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -grant { - // needed to generate runtime classes - permission java.lang.RuntimePermission "createClassLoader"; - // needed by IndyInterface - permission java.lang.RuntimePermission "getClassLoader"; - // needed by groovy engine - permission java.lang.RuntimePermission "accessDeclaredMembers"; - permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect"; - permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.reflect"; - // Allow executing groovy scripts with codesource of /untrusted - permission groovy.security.GroovyCodeSourcePermission "/untrusted"; - - // Standard set of classes - permission org.elasticsearch.script.ClassPermission "<>"; - // groovy runtime (TODO: clean these up if possible) - permission org.elasticsearch.script.ClassPermission "groovy.grape.GrabAnnotationTransformation"; - permission org.elasticsearch.script.ClassPermission "groovy.lang.Binding"; - permission org.elasticsearch.script.ClassPermission "groovy.lang.GroovyObject"; - permission org.elasticsearch.script.ClassPermission "groovy.lang.GString"; - permission org.elasticsearch.script.ClassPermission "groovy.lang.Script"; - permission org.elasticsearch.script.ClassPermission "groovy.util.GroovyCollections"; - permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.ast.builder.AstBuilderTransformation"; - permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.reflection.ClassInfo"; - permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.GStringImpl"; - permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.powerassert.ValueRecorder"; - permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.powerassert.AssertionRenderer"; - permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.ScriptBytecodeAdapter"; - permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation"; - permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.vmplugin.v7.IndyInterface"; - permission org.elasticsearch.script.ClassPermission "sun.reflect.ConstructorAccessorImpl"; - permission org.elasticsearch.script.ClassPermission "sun.reflect.MethodAccessorImpl"; - permission org.elasticsearch.script.ClassPermission "jdk.internal.reflect.ConstructorAccessorImpl"; - permission org.elasticsearch.script.ClassPermission "jdk.internal.reflect.MethodAccessorImpl"; - - permission org.elasticsearch.script.ClassPermission "groovy.lang.Closure"; - permission org.elasticsearch.script.ClassPermission "org.codehaus.groovy.runtime.GeneratedClosure"; - permission org.elasticsearch.script.ClassPermission "groovy.lang.MetaClass"; - permission org.elasticsearch.script.ClassPermission "groovy.lang.Range"; - permission org.elasticsearch.script.ClassPermission "groovy.lang.Reference"; -}; diff --git a/modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/GroovyIndexedScriptTests.java b/modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/GroovyIndexedScriptTests.java deleted file mode 100644 index ce362e8d78c..00000000000 --- a/modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/GroovyIndexedScriptTests.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -package org.elasticsearch.script.groovy; - -import org.elasticsearch.ExceptionsHelper; -import org.elasticsearch.action.index.IndexRequestBuilder; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.common.bytes.BytesArray; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.script.Script; -import org.elasticsearch.script.ScriptType; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.search.aggregations.AggregationBuilders; -import org.elasticsearch.search.builder.SearchSourceBuilder; -import org.elasticsearch.test.ESIntegTestCase; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; - -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.notNullValue; - -public class GroovyIndexedScriptTests extends ESIntegTestCase { - @Override - protected Collection> nodePlugins() { - return Collections.singleton(GroovyPlugin.class); - } - - @Override - protected Settings nodeSettings(int nodeOrdinal) { - Settings.Builder builder = Settings.builder().put(super.nodeSettings(nodeOrdinal)); - builder.put("script.engine.groovy.stored.update", "false"); - builder.put("script.engine.groovy.stored.search", "true"); - builder.put("script.engine.groovy.stored.aggs", "true"); - builder.put("script.engine.groovy.inline.aggs", "false"); - return builder.build(); - } - - public void testFieldIndexedScript() throws ExecutionException, InterruptedException { - client().admin().cluster().preparePutStoredScript() - .setId("script1") - .setScriptLang(GroovyScriptEngineService.NAME) - .setSource(new BytesArray("{ \"script\" : \"2\"}")) - .get(); - client().admin().cluster().preparePutStoredScript() - .setId("script2") - .setScriptLang(GroovyScriptEngineService.NAME) - .setSource(new BytesArray("{ \"script\" : \"factor * 2\"}")) - .get(); - - List builders = new ArrayList<>(); - builders.add(client().prepareIndex("test", "scriptTest", "1").setSource("{\"theField\":\"foo\"}")); - builders.add(client().prepareIndex("test", "scriptTest", "2").setSource("{\"theField\":\"foo 2\"}")); - builders.add(client().prepareIndex("test", "scriptTest", "3").setSource("{\"theField\":\"foo 3\"}")); - builders.add(client().prepareIndex("test", "scriptTest", "4").setSource("{\"theField\":\"foo 4\"}")); - builders.add(client().prepareIndex("test", "scriptTest", "5").setSource("{\"theField\":\"bar\"}")); - - indexRandom(true, builders); - Map script2Params = new HashMap<>(); - script2Params.put("factor", 3); - SearchResponse searchResponse = client() - .prepareSearch() - .setSource( - new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()).size(1) - .scriptField("test1", - new Script(ScriptType.STORED, GroovyScriptEngineService.NAME, "script1", Collections.emptyMap())) - .scriptField("test2", - new Script(ScriptType.STORED, GroovyScriptEngineService.NAME, "script2", script2Params))) - .setIndices("test").setTypes("scriptTest").get(); - assertHitCount(searchResponse, 5); - assertTrue(searchResponse.getHits().hits().length == 1); - SearchHit sh = searchResponse.getHits().getAt(0); - assertThat(sh.field("test1").getValue(), equalTo(2)); - assertThat(sh.field("test2").getValue(), equalTo(6)); - } - - // Relates to #10397 - public void testUpdateScripts() { - createIndex("test_index"); - ensureGreen("test_index"); - client().prepareIndex("test_index", "test_type", "1").setSource("{\"foo\":\"bar\"}").get(); - flush("test_index"); - - int iterations = randomIntBetween(2, 11); - for (int i = 1; i < iterations; i++) { - assertAcked(client().admin().cluster().preparePutStoredScript() - .setScriptLang(GroovyScriptEngineService.NAME) - .setId("script1") - .setSource(new BytesArray("{\"script\":\"" + i + "\"}"))); - SearchResponse searchResponse = client() - .prepareSearch() - .setSource( - new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()).scriptField("test_field", - new Script(ScriptType.STORED, GroovyScriptEngineService.NAME, "script1", Collections.emptyMap()))) - .setIndices("test_index") - .setTypes("test_type").get(); - assertHitCount(searchResponse, 1); - SearchHit sh = searchResponse.getHits().getAt(0); - assertThat(sh.field("test_field").getValue(), equalTo(i)); - } - } - - public void testDisabledUpdateIndexedScriptsOnly() { - assertAcked(client().admin().cluster().preparePutStoredScript() - .setScriptLang(GroovyScriptEngineService.NAME) - .setId("script1") - .setSource(new BytesArray("{\"script\":\"2\"}"))); - client().prepareIndex("test", "scriptTest", "1").setSource("{\"theField\":\"foo\"}").get(); - try { - client().prepareUpdate("test", "scriptTest", "1") - .setScript(new Script(ScriptType.STORED, GroovyScriptEngineService.NAME, "script1", Collections.emptyMap())).get(); - fail("update script should have been rejected"); - } catch (Exception e) { - assertThat(e.getMessage(), containsString("failed to execute script")); - assertThat(ExceptionsHelper.detailedMessage(e), - containsString("scripts of type [stored], operation [update] and lang [groovy] are disabled")); - } - } - - public void testDisabledAggsDynamicScripts() { - //dynamic scripts don't need to be enabled for an indexed script to be indexed and later on executed - assertAcked(client().admin().cluster().preparePutStoredScript() - .setScriptLang(GroovyScriptEngineService.NAME) - .setId("script1") - .setSource(new BytesArray("{\"script\":\"2\"}"))); - client().prepareIndex("test", "scriptTest", "1").setSource("{\"theField\":\"foo\"}").get(); - refresh(); - SearchResponse searchResponse = client() - .prepareSearch("test") - .setSource( - new SearchSourceBuilder().aggregation(AggregationBuilders.terms("test").script( - new Script(ScriptType.STORED, GroovyScriptEngineService.NAME, "script1", Collections.emptyMap())))).get(); - assertHitCount(searchResponse, 1); - assertThat(searchResponse.getAggregations().get("test"), notNullValue()); - } -} diff --git a/modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/GroovyScriptTests.java b/modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/GroovyScriptTests.java deleted file mode 100644 index 196d878ae66..00000000000 --- a/modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/GroovyScriptTests.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.script.groovy; - -import org.elasticsearch.action.index.IndexRequestBuilder; -import org.elasticsearch.action.search.SearchPhaseExecutionException; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.common.lucene.search.function.CombineFunction; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.script.Script; -import org.elasticsearch.script.ScriptType; -import org.elasticsearch.search.builder.SearchSourceBuilder; -import org.elasticsearch.search.sort.ScriptSortBuilder.ScriptSortType; -import org.elasticsearch.search.sort.SortBuilders; -import org.elasticsearch.test.ESIntegTestCase; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE; -import static org.elasticsearch.index.query.QueryBuilders.constantScoreQuery; -import static org.elasticsearch.index.query.QueryBuilders.functionScoreQuery; -import static org.elasticsearch.index.query.QueryBuilders.matchQuery; -import static org.elasticsearch.index.query.QueryBuilders.scriptQuery; -import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.scriptFunction; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertOrderedSearchHits; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchHits; -import static org.hamcrest.Matchers.equalTo; - -/** - * Various tests for Groovy scripting - */ -// TODO: refactor into unit test or proper rest tests -public class GroovyScriptTests extends ESIntegTestCase { - @Override - protected Collection> nodePlugins() { - return Collections.singleton(GroovyPlugin.class); - } - - public void testGroovyBigDecimalTransformation() { - client().prepareIndex("test", "doc", "1").setSource("foo", 5).setRefreshPolicy(IMMEDIATE).get(); - - // Test that something that would usually be a BigDecimal is transformed into a Double - assertScript("def n = 1.23; assert n instanceof Double; return n;"); - assertScript("def n = 1.23G; assert n instanceof Double; return n;"); - assertScript("def n = BigDecimal.ONE; assert n instanceof BigDecimal; return n;"); - } - - public void assertScript(String scriptString) { - Script script = new Script(ScriptType.INLINE, GroovyScriptEngineService.NAME, scriptString, Collections.emptyMap()); - SearchResponse resp = client().prepareSearch("test") - .setSource(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()).sort(SortBuilders. - scriptSort(script, ScriptSortType.NUMBER))) - .get(); - assertNoFailures(resp); - } - - public void testGroovyExceptionSerialization() throws Exception { - List reqs = new ArrayList<>(); - for (int i = 0; i < randomIntBetween(50, 500); i++) { - reqs.add(client().prepareIndex("test", "doc", "" + i).setSource("foo", "bar")); - } - indexRandom(true, false, reqs); - try { - client().prepareSearch("test") - .setQuery( - constantScoreQuery(scriptQuery(new Script(ScriptType.INLINE, GroovyScriptEngineService.NAME, "1 == not_found", - Collections.emptyMap())))).get(); - fail("should have thrown an exception"); - } catch (SearchPhaseExecutionException e) { - assertThat(e.toString()+ "should not contained NotSerializableTransportException", - e.toString().contains("NotSerializableTransportException"), equalTo(false)); - assertThat(e.toString()+ "should have contained ScriptException", - e.toString().contains("ScriptException"), equalTo(true)); - assertThat(e.toString()+ "should have contained not_found", - e.toString().contains("No such property: not_found"), equalTo(true)); - } - - try { - client().prepareSearch("test") - .setQuery(constantScoreQuery(scriptQuery( - new Script(ScriptType.INLINE, GroovyScriptEngineService.NAME, "null.foo", Collections.emptyMap())))).get(); - fail("should have thrown an exception"); - } catch (SearchPhaseExecutionException e) { - assertThat(e.toString() + "should not contained NotSerializableTransportException", - e.toString().contains("NotSerializableTransportException"), equalTo(false)); - assertThat(e.toString() + "should have contained ScriptException", - e.toString().contains("ScriptException"), equalTo(true)); - assertThat(e.toString()+ "should have contained a NullPointerException", - e.toString().contains("NullPointerException[Cannot get property 'foo' on null object]"), equalTo(true)); - } - } - - public void testGroovyScriptAccess() { - client().prepareIndex("test", "doc", "1").setSource("foo", "quick brow fox jumped over the lazy dog", "bar", 1).get(); - client().prepareIndex("test", "doc", "2").setSource("foo", "fast jumping spiders", "bar", 2).get(); - client().prepareIndex("test", "doc", "3").setSource("foo", "dog spiders that can eat a dog", "bar", 3).get(); - refresh(); - - // doc[] access - SearchResponse resp = client().prepareSearch("test").setQuery(functionScoreQuery(scriptFunction( - new Script(ScriptType.INLINE, GroovyScriptEngineService.NAME, "doc['bar'].value", Collections.emptyMap()))) - .boostMode(CombineFunction.REPLACE)).get(); - - assertNoFailures(resp); - assertOrderedSearchHits(resp, "3", "2", "1"); - } - - public void testScoreAccess() { - client().prepareIndex("test", "doc", "1").setSource("foo", "quick brow fox jumped over the lazy dog", "bar", 1).get(); - client().prepareIndex("test", "doc", "2").setSource("foo", "fast jumping spiders", "bar", 2).get(); - client().prepareIndex("test", "doc", "3").setSource("foo", "dog spiders that can eat a dog", "bar", 3).get(); - refresh(); - - // _score can be accessed - SearchResponse resp = client().prepareSearch("test").setQuery(functionScoreQuery(matchQuery("foo", "dog"), - scriptFunction(new Script(ScriptType.INLINE, GroovyScriptEngineService.NAME, "_score", Collections.emptyMap()))) - .boostMode(CombineFunction.REPLACE)).get(); - assertNoFailures(resp); - assertSearchHits(resp, "3", "1"); - - // _score is comparable - // NOTE: it is important to use 0.0 instead of 0 instead Groovy will do an integer comparison - // and if the score if between 0 and 1 it will be considered equal to 0 due to the cast - resp = client() - .prepareSearch("test") - .setQuery( - functionScoreQuery(matchQuery("foo", "dog"), scriptFunction( - new Script(ScriptType.INLINE, - GroovyScriptEngineService.NAME, "_score > 0.0 ? _score : 0", Collections.emptyMap()))) - .boostMode(CombineFunction.REPLACE)).get(); - assertNoFailures(resp); - assertSearchHits(resp, "3", "1"); - } -} diff --git a/modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/GroovySecurityTests.java b/modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/GroovySecurityTests.java deleted file mode 100644 index ce3f6ea3c88..00000000000 --- a/modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/GroovySecurityTests.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.script.groovy; - -import groovy.lang.MissingPropertyException; -import org.apache.lucene.util.Constants; -import org.codehaus.groovy.control.MultipleCompilationErrorsException; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.script.CompiledScript; -import org.elasticsearch.script.ScriptException; -import org.elasticsearch.script.ScriptType; -import org.elasticsearch.test.ESTestCase; - -import java.nio.file.Path; -import java.security.PrivilegedActionException; -import java.util.AbstractMap; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Tests for the Groovy security permissions - */ -public class GroovySecurityTests extends ESTestCase { - - private GroovyScriptEngineService se; - - @Override - public void setUp() throws Exception { - super.setUp(); - se = new GroovyScriptEngineService(Settings.EMPTY); - // otherwise will exit your VM and other bad stuff - assumeTrue("test requires security manager to be enabled", System.getSecurityManager() != null); - } - - @Override - public void tearDown() throws Exception { - se.close(); - super.tearDown(); - } - - public void testEvilGroovyScripts() throws Exception { - // Plain test - assertSuccess(""); - // field access (via map) - assertSuccess("def foo = doc['foo'].value; if (foo == null) { return 5; }"); - // field access (via list) - assertSuccess("def foo = mylist[0]; if (foo == null) { return 5; }"); - // field access (via array) - assertSuccess("def foo = myarray[0]; if (foo == null) { return 5; }"); - // field access (via object) - assertSuccess("def foo = myobject.primitive.toString(); if (foo == null) { return 5; }"); - assertSuccess("def foo = myobject.object.toString(); if (foo == null) { return 5; }"); - assertSuccess("def foo = myobject.list[0].primitive.toString(); if (foo == null) { return 5; }"); - // List - assertSuccess("def list = [doc['foo'].value, 3, 4]; def v = list.get(1); list.add(10)"); - // Ranges - assertSuccess("def range = 1..doc['foo'].value; def v = range.get(0)"); - // Maps - assertSuccess("def v = doc['foo'].value; def m = [:]; m.put(\"value\", v)"); - // Times - assertSuccess("def t = Instant.now().getMillis()"); - // GroovyCollections - assertSuccess("def n = [1,2,3]; GroovyCollections.max(n)"); - // Groovy closures - assertSuccess("[1, 2, 3, 4].findAll { it % 2 == 0 }"); - assertSuccess("def buckets=[ [2, 4, 6, 8], [10, 12, 16, 14], [18, 22, 20, 24] ]; buckets[-3..-1].every { it.every { i -> i % 2 == 0 } }"); - assertSuccess("def val = \"\"; [1, 2, 3, 4].each { val += it }; val"); - // Groovy uses reflection to invoke closures. These reflective calls are optimized by the JVM after "sun.reflect.inflationThreshold" - // invocations. After the inflation step, access to sun.reflect.MethodAccessorImpl is required from the security manager. This test, - // assuming a inflation threshold below 100 (15 is current value on Oracle JVMs), checks that the relevant permission is available. - assertSuccess("(1..100).collect{ it + 1 }"); - - // Fail cases: - assertFailure("pr = Runtime.getRuntime().exec(\"touch /tmp/gotcha\"); pr.waitFor()", MissingPropertyException.class); - - // infamous: - assertFailure("java.lang.Math.class.forName(\"java.lang.Runtime\")", PrivilegedActionException.class); - // filtered directly by our classloader - assertFailure("getClass().getClassLoader().loadClass(\"java.lang.Runtime\").availableProcessors()", PrivilegedActionException.class); - // unfortunately, we have access to other classloaders (due to indy mechanism needing getClassLoader permission) - // but we can't do much with them directly at least. - assertFailure("myobject.getClass().getClassLoader().loadClass(\"java.lang.Runtime\").availableProcessors()", SecurityException.class); - assertFailure("d = new DateTime(); d.getClass().getDeclaredMethod(\"year\").setAccessible(true)", SecurityException.class); - assertFailure("d = new DateTime(); d.\"${'get' + 'Class'}\"()." + - "\"${'getDeclared' + 'Method'}\"(\"year\").\"${'set' + 'Accessible'}\"(false)", SecurityException.class); - assertFailure("Class.forName(\"org.joda.time.DateTime\").getDeclaredMethod(\"year\").setAccessible(true)", MissingPropertyException.class); - - assertFailure("Eval.me('2 + 2')", MissingPropertyException.class); - assertFailure("Eval.x(5, 'x + 2')", MissingPropertyException.class); - - assertFailure("d = new Date(); java.lang.reflect.Field f = Date.class.getDeclaredField(\"fastTime\");" + - " f.setAccessible(true); f.get(\"fastTime\")", MultipleCompilationErrorsException.class); - - assertFailure("def methodName = 'ex'; Runtime.\"${'get' + 'Runtime'}\"().\"${methodName}ec\"(\"touch /tmp/gotcha2\")", MissingPropertyException.class); - - assertFailure("t = new Thread({ println 3 });", MultipleCompilationErrorsException.class); - - // test a directory we normally have access to, but the groovy script does not. - Path dir = createTempDir(); - // TODO: figure out the necessary escaping for windows paths here :) - if (!Constants.WINDOWS) { - assertFailure("new File(\"" + dir + "\").exists()", MultipleCompilationErrorsException.class); - } - } - - public void testGroovyScriptsThatThrowErrors() throws Exception { - assertFailure("assert false, \"msg\";", AssertionError.class); - assertFailure("def foo=false; assert foo;", AssertionError.class); - // Groovy's asserts require org.codehaus.groovy.runtime.InvokerHelper, so they are denied - assertFailure("def foo=false; assert foo, \"msg2\";", NoClassDefFoundError.class); - } - - public void testGroovyBugError() { - // this script throws a GroovyBugError because our security manager permissions prevent Groovy from accessing this private field - // and Groovy does not handle it gracefully; this test will likely start failing if the bug is fixed upstream so that a - // GroovyBugError no longer surfaces here in which case the script should be replaced with another script that intentionally - // surfaces a GroovyBugError - assertFailure("[1, 2].size", AssertionError.class); - } - - /** runs a script */ - private void doTest(String script) { - Map vars = new HashMap(); - // we add a "mock document" containing a single field "foo" that returns 4 (abusing a jdk class with a getValue() method) - vars.put("doc", Collections.singletonMap("foo", new AbstractMap.SimpleEntry(null, 4))); - vars.put("mylist", Arrays.asList("foo")); - vars.put("myarray", Arrays.asList("foo")); - vars.put("myobject", new MyObject()); - - se.executable(new CompiledScript(ScriptType.INLINE, "test", "js", se.compile(null, script, Collections.emptyMap())), vars).run(); - } - - public static class MyObject { - public int getPrimitive() { return 0; } - public Object getObject() { return "value"; } - public List getList() { return Arrays.asList(new MyObject()); } - } - - /** asserts that a script runs without exception */ - private void assertSuccess(String script) { - doTest(script); - } - - /** asserts that a script triggers the given exceptionclass */ - private void assertFailure(String script, Class exceptionClass) { - try { - doTest(script); - fail("did not get expected exception"); - } catch (ScriptException expected) { - Throwable cause = expected.getCause(); - assertNotNull(cause); - if (exceptionClass.isAssignableFrom(cause.getClass()) == false) { - throw new AssertionError("unexpected exception: " + cause, expected); - } - } - } -} diff --git a/modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/LangGroovyClientYamlTestSuiteIT.java b/modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/LangGroovyClientYamlTestSuiteIT.java deleted file mode 100644 index f407b5b6ce7..00000000000 --- a/modules/lang-groovy/src/test/java/org/elasticsearch/script/groovy/LangGroovyClientYamlTestSuiteIT.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.script.groovy; - -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - -import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; -import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; -import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException; - -import java.io.IOException; - -public class LangGroovyClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase { - - public LangGroovyClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { - super(testCandidate); - } - - @ParametersFactory - public static Iterable parameters() throws IOException, ClientYamlTestParseException { - return ESClientYamlSuiteTestCase.createParameters(); - } -} - diff --git a/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/10_basic.yaml b/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/10_basic.yaml deleted file mode 100644 index d5044bbe422..00000000000 --- a/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/10_basic.yaml +++ /dev/null @@ -1,13 +0,0 @@ -# Integration tests for Groovy scripts -# -"Groovy loaded": - - do: - cluster.state: {} - - # Get master node id - - set: { master_node: master } - - - do: - nodes.info: {} - - - match: { nodes.$master.modules.0.name: lang-groovy } diff --git a/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/15_update.yaml b/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/15_update.yaml deleted file mode 100644 index 683b2c6a2df..00000000000 --- a/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/15_update.yaml +++ /dev/null @@ -1,87 +0,0 @@ ---- -"Update Script": - - - skip: - features: groovy_scripting - - - do: - index: - index: test_1 - type: test - id: 1 - body: - foo: bar - count: 1 - - - do: - update: - index: test_1 - type: test - id: 1 - body: - script: - lang: groovy - inline: "ctx._source.foo = bar" - params: { bar: 'xxx' } - - - match: { _index: test_1 } - - match: { _type: test } - - match: { _id: "1" } - - match: { _version: 2 } - - - do: - get: - index: test_1 - type: test - id: 1 - - - match: { _source.foo: xxx } - - match: { _source.count: 1 } - - - do: - update: - index: test_1 - type: test - id: 1 - body: - script: - lang: groovy - inline: "ctx._source.foo = 'yyy'" - - - match: { _index: test_1 } - - match: { _type: test } - - match: { _id: "1" } - - match: { _version: 3 } - - - do: - get: - index: test_1 - type: test - id: 1 - - - match: { _source.foo: yyy } - - match: { _source.count: 1 } - - - do: - catch: /script_lang not supported \[doesnotexist\]/ - update: - index: test_1 - type: test - id: 1 - body: - script: - inline: "1" - lang: "doesnotexist" - params: { bar: 'xxx' } - - - do: - catch: /script_lang not supported \[doesnotexist\]/ - update: - index: test_1 - type: test - id: 1 - body: - script: - lang: doesnotexist - inline: "1" - diff --git a/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/16_update2.yaml b/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/16_update2.yaml deleted file mode 100644 index 5849874c02e..00000000000 --- a/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/16_update2.yaml +++ /dev/null @@ -1,73 +0,0 @@ ---- -"Indexed script": - - - skip: - features: groovy_scripting - - - do: - put_script: - id: "1" - lang: "groovy" - body: { "script": "_score * doc[\"myParent.weight\"].value" } - - match: { acknowledged: true } - - - do: - get_script: - id: "1" - lang: "groovy" - - match: { found: true } - - match: { lang: groovy } - - match: { _id: "1" } - - match: { "script": "_score * doc[\"myParent.weight\"].value" } - - - do: - catch: missing - get_script: - id: "2" - lang: "groovy" - - match: { found: false } - - match: { lang: groovy } - - match: { _id: "2" } - - is_false: script - - - do: - delete_script: - id: "1" - lang: "groovy" - - match: { acknowledged: true } - - - do: - catch: missing - delete_script: - id: "non_existing" - lang: "groovy" - - - do: - catch: request - put_script: - id: "1" - lang: "groovy" - body: { "script": "_score * foo bar + doc[\"myParent.weight\"].value" } - - - - do: - catch: /script_exception,.+Error.compiling.script.*/ - put_script: - id: "1" - lang: "groovy" - body: { "script": "_score * foo bar + doc[\"myParent.weight\"].value" } - - - do: - catch: request - put_script: - id: "1" - lang: "foobar" - body: { "script" : "_score * doc[\"myParent.weight\"].value" } - - - do: - catch: /script_lang.not.supported/ - put_script: - id: "1" - lang: "foobar" - body: { "script" : "_score * doc[\"myParent.weight\"].value" } - diff --git a/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/25_script_upsert.yaml b/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/25_script_upsert.yaml deleted file mode 100644 index 6ba4d39e71b..00000000000 --- a/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/25_script_upsert.yaml +++ /dev/null @@ -1,69 +0,0 @@ ---- -"Script upsert": - - - skip: - features: groovy_scripting - - - do: - update: - index: test_1 - type: test - id: 1 - body: - script: - inline: "ctx._source.foo = bar" - params: { bar: 'xxx' } - lang: "groovy" - upsert: { foo: baz } - - - do: - get: - index: test_1 - type: test - id: 1 - - - match: { _source.foo: baz } - - - - do: - update: - index: test_1 - type: test - id: 1 - body: - script: - inline: "ctx._source.foo = bar" - params: { bar: 'xxx' } - lang: "groovy" - upsert: { foo: baz } - - - do: - get: - index: test_1 - type: test - id: 1 - - - match: { _source.foo: xxx } - - - do: - update: - index: test_1 - type: test - id: 2 - body: - script: - inline: "ctx._source.foo = bar" - params: { bar: 'xxx' } - lang: "groovy" - upsert: { foo: baz } - scripted_upsert: true - - - do: - get: - index: test_1 - type: test - id: 2 - - - match: { _source.foo: xxx } - - diff --git a/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/30_compile_limit.yaml b/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/30_compile_limit.yaml deleted file mode 100644 index f23cbe22f3b..00000000000 --- a/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/30_compile_limit.yaml +++ /dev/null @@ -1,72 +0,0 @@ -setup: - - do: - indices.create: - index: test - - do: - index: - index: test - type: test - id: 1 - body: { foo: bar } - refresh: wait_for - ---- -teardown: - - do: - cluster.put_settings: - body: - transient: - script.max_compilations_per_minute: null - ---- -"circuit breaking with too many scripts": - - - do: - cluster.put_settings: - body: - transient: - script.max_compilations_per_minute: 1 - - - do: - search: - index: test - type: test - body: - size: 1 - script_fields: - myfield: - script: - inline: "\"aoeu\"" - lang: groovy - - - match: { hits.total: 1 } - - - do: - catch: /Too many dynamic script compilations within one minute/ - search: - index: test - type: test - body: - size: 1 - script_fields: - myfield: - script: - inline: "\"aoeuaoeu\"" - lang: groovy - ---- -"no bad settings": - - - do: - catch: /Failed to parse value \[-1\] for setting \[script.max_compilations_per_minute\] must be >= 0/ - cluster.put_settings: - body: - transient: - script.max_compilations_per_minute: -1 - - - do: - catch: /Failed to parse value \[99999999999\] for setting \[script.max_compilations_per_minute\]/ - cluster.put_settings: - body: - transient: - script.max_compilations_per_minute: 99999999999 diff --git a/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/90_missing.yaml b/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/90_missing.yaml deleted file mode 100644 index 999d9f610ff..00000000000 --- a/modules/lang-groovy/src/test/resources/rest-api-spec/test/lang_groovy/90_missing.yaml +++ /dev/null @@ -1,48 +0,0 @@ ---- -"Missing document (partial doc)": - - - do: - catch: missing - update: - index: test_1 - type: test - id: 1 - body: { doc: { foo: bar } } - - - do: - update: - index: test_1 - type: test - id: 1 - body: { doc: { foo: bar } } - ignore: 404 - ---- -"Missing document (script)": - - - skip: - features: groovy_scripting - - - - do: - catch: missing - update: - index: test_1 - type: test - id: 1 - body: - script: - inline: "ctx._source.foo = bar" - params: { bar: 'xxx' } - lang: "groovy" - - - do: - update: - index: test_1 - type: test - id: 1 - ignore: 404 - body: - script: - inline: "ctx._source.foo = bar" - params: { bar: 'xxx' } diff --git a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java index 4236e9e0c0b..14cb246ae92 100644 --- a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java +++ b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java @@ -521,7 +521,7 @@ public class PercolateQueryBuilder extends AbstractQueryBuilder> nodePlugins() { - return Arrays.asList(PercolatorPlugin.class, FoolMeScriptLang.class); - } - - @Override - protected Collection> transportClientPlugins() { - return Collections.singleton(PercolatorPlugin.class); - } - - public void testOldPercolatorIndex() throws Exception { - setupNode(); - - // verify cluster state: - ClusterState state = client().admin().cluster().prepareState().get().getState(); - assertThat(state.metaData().indices().size(), equalTo(1)); - assertThat(state.metaData().indices().get(INDEX_NAME), notNullValue()); - assertThat(state.metaData().indices().get(INDEX_NAME).getCreationVersion(), equalTo(Version.V_2_0_0)); - assertThat(state.metaData().indices().get(INDEX_NAME).getUpgradedVersion(), equalTo(Version.CURRENT)); - assertThat(state.metaData().indices().get(INDEX_NAME).getMappings().size(), equalTo(2)); - assertThat(state.metaData().indices().get(INDEX_NAME).getMappings().get(".percolator"), notNullValue()); - // important: verify that the query field in the .percolator mapping is of type object (from 5.x this is of type percolator) - MappingMetaData mappingMetaData = state.metaData().indices().get(INDEX_NAME).getMappings().get(".percolator"); - assertThat(XContentMapValues.extractValue("properties.query.type", mappingMetaData.sourceAsMap()), equalTo("object")); - assertThat(state.metaData().indices().get(INDEX_NAME).getMappings().get("message"), notNullValue()); - - // verify existing percolator queries: - SearchResponse searchResponse = client().prepareSearch(INDEX_NAME) - .setTypes(".percolator") - .addSort("_uid", SortOrder.ASC) - .get(); - assertThat(searchResponse.getHits().getTotalHits(), equalTo(4L)); - assertThat(searchResponse.getHits().getAt(0).id(), equalTo("1")); - assertThat(searchResponse.getHits().getAt(1).id(), equalTo("2")); - assertThat(searchResponse.getHits().getAt(2).id(), equalTo("3")); - assertThat(searchResponse.getHits().getAt(3).id(), equalTo("4")); - assertThat(XContentMapValues.extractValue("query.script.script.inline", - searchResponse.getHits().getAt(3).sourceAsMap()), equalTo("return true")); - // we don't upgrade the script definitions so that they include explicitly the lang, - // because we read / parse the query at search time. - assertThat(XContentMapValues.extractValue("query.script.script.lang", - searchResponse.getHits().getAt(3).sourceAsMap()), nullValue()); - - // verify percolate response - PercolateResponse percolateResponse = preparePercolate(client()) - .setIndices(INDEX_NAME) - .setDocumentType("message") - .setPercolateDoc(new PercolateSourceBuilder.DocBuilder().setDoc("{}")) - .get(); - - assertThat(percolateResponse.getCount(), equalTo(1L)); - assertThat(percolateResponse.getMatches().length, equalTo(1)); - assertThat(percolateResponse.getMatches()[0].getId().string(), equalTo("4")); - - percolateResponse = preparePercolate(client()) - .setIndices(INDEX_NAME) - .setDocumentType("message") - .setPercolateDoc(new PercolateSourceBuilder.DocBuilder().setDoc("message", "the quick brown fox jumps over the lazy dog")) - .get(); - - assertThat(percolateResponse.getCount(), equalTo(3L)); - assertThat(percolateResponse.getMatches().length, equalTo(3)); - assertThat(percolateResponse.getMatches()[0].getId().string(), equalTo("1")); - assertThat(percolateResponse.getMatches()[1].getId().string(), equalTo("2")); - assertThat(percolateResponse.getMatches()[2].getId().string(), equalTo("4")); - - // add an extra query and verify the results - client().prepareIndex(INDEX_NAME, ".percolator", "5") - .setSource(jsonBuilder().startObject().field("query", matchQuery("message", "fox jumps")).endObject()) - .get(); - refresh(); - - percolateResponse = preparePercolate(client()) - .setIndices(INDEX_NAME) - .setDocumentType("message") - .setPercolateDoc(new PercolateSourceBuilder.DocBuilder().setDoc("message", "the quick brown fox jumps over the lazy dog")) - .get(); - - assertThat(percolateResponse.getCount(), equalTo(4L)); - assertThat(percolateResponse.getMatches().length, equalTo(4)); - assertThat(percolateResponse.getMatches()[0].getId().string(), equalTo("1")); - assertThat(percolateResponse.getMatches()[1].getId().string(), equalTo("2")); - assertThat(percolateResponse.getMatches()[2].getId().string(), equalTo("4")); - } - - private void setupNode() throws Exception { - Path clusterDir = createTempDir(); - try (InputStream stream = PercolatorBackwardsCompatibilityTests.class. - getResourceAsStream("/indices/percolator/bwc_index_2.0.0.zip")) { - TestUtil.unzip(stream, clusterDir); - } - - Settings.Builder nodeSettings = Settings.builder() - .put(Environment.PATH_DATA_SETTING.getKey(), clusterDir); - internalCluster().startNode(nodeSettings.build()); - ensureGreen(INDEX_NAME); - } - - // Fool the script service that this is the groovy script language, - // so that we can run a script that has no lang defined implicetely against the legacy language: - public static class FoolMeScriptLang extends MockScriptPlugin { - - @Override - protected Map, Object>> pluginScripts() { - return Collections.singletonMap("return true", (vars) -> true); - } - - @Override - public String pluginScriptLang() { - return "groovy"; - } - } - -} diff --git a/modules/reindex/src/test/java/org/elasticsearch/index/reindex/SimpleExecutableScript.java b/modules/reindex/src/test/java/org/elasticsearch/index/reindex/SimpleExecutableScript.java index a4230cab457..af2312da754 100644 --- a/modules/reindex/src/test/java/org/elasticsearch/index/reindex/SimpleExecutableScript.java +++ b/modules/reindex/src/test/java/org/elasticsearch/index/reindex/SimpleExecutableScript.java @@ -59,7 +59,7 @@ public class SimpleExecutableScript implements ExecutableScript { return new HashMap<>((Map) value); } } - // Others just return the objects plain (groovy, painless) + // Others just return the objects plain (painless) return value; } } diff --git a/qa/evil-tests/src/test/java/org/elasticsearch/plugins/InstallPluginCommandTests.java b/qa/evil-tests/src/test/java/org/elasticsearch/plugins/InstallPluginCommandTests.java index 08ce0083ec2..c442032a748 100644 --- a/qa/evil-tests/src/test/java/org/elasticsearch/plugins/InstallPluginCommandTests.java +++ b/qa/evil-tests/src/test/java/org/elasticsearch/plugins/InstallPluginCommandTests.java @@ -372,7 +372,7 @@ public class InstallPluginCommandTests extends ESTestCase { public void testBuiltinModule() throws Exception { Tuple env = createEnv(fs, temp); Path pluginDir = createPluginDir(temp); - String pluginZip = createPlugin("lang-groovy", pluginDir); + String pluginZip = createPlugin("lang-painless", pluginDir); UserException e = expectThrows(UserException.class, () -> installPlugin(pluginZip, env.v1())); assertTrue(e.getMessage(), e.getMessage().contains("is a system module")); assertInstallCleaned(env.v2()); diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/update.json b/rest-api-spec/src/main/resources/rest-api-spec/api/update.json index 7e7fffcee07..7cacda722f5 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/update.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/update.json @@ -45,7 +45,7 @@ }, "lang": { "type": "string", - "description": "The script language (default: groovy)" + "description": "The script language (default: painless)" }, "parent": { "type": "string", diff --git a/settings.gradle b/settings.gradle index 52b3128477c..f3fb14674eb 100644 --- a/settings.gradle +++ b/settings.gradle @@ -24,7 +24,6 @@ List projects = [ 'modules:aggs-matrix-stats', 'modules:ingest-common', 'modules:lang-expression', - 'modules:lang-groovy', 'modules:lang-mustache', 'modules:lang-painless', 'modules:transport-netty4', diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/Features.java b/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/Features.java index 6e47220ec08..850eb802caf 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/Features.java +++ b/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/Features.java @@ -38,7 +38,6 @@ public final class Features { private static final List SUPPORTED = unmodifiableList(Arrays.asList( "catch_unauthorized", "embedded_stash_key", - "groovy_scripting", "headers", "stash_in_path", "warnings",