diff --git a/modules/aggregations/build.gradle b/modules/aggregations/build.gradle index ae639be3db4af..ab826456613c2 100644 --- a/modules/aggregations/build.gradle +++ b/modules/aggregations/build.gradle @@ -12,11 +12,12 @@ apply plugin: 'elasticsearch.internal-cluster-test' esplugin { description 'Adds "built in" aggregations to Elasticsearch.' classname 'org.elasticsearch.aggregations.AggregationsPlugin' + extendedPlugins = ['lang-painless'] } restResources { restApi { - include '_common', 'indices', 'cluster', 'index', 'search', 'nodes', 'bulk' + include '_common', 'indices', 'cluster', 'index', 'search', 'nodes', 'bulk', 'scripts_painless_execute' } restTests { // Pulls in all aggregation tests from core AND the forwards v7's core for forwards compatibility @@ -38,3 +39,11 @@ tasks.named("yamlRestTestV7CompatTransform").configure { task -> artifacts { restTests(new File(projectDir, "src/yamlRestTest/resources/rest-api-spec/test")) } + +testClusters.configureEach { + module ':modules:lang-painless' +} + +dependencies { + compileOnly(project(':modules:lang-painless:spi')) +} diff --git a/modules/aggregations/src/main/java/module-info.java b/modules/aggregations/src/main/java/module-info.java index a41affa5ba4b6..5c3acfcc3beeb 100644 --- a/modules/aggregations/src/main/java/module-info.java +++ b/modules/aggregations/src/main/java/module-info.java @@ -8,11 +8,16 @@ module org.elasticsearch.aggs { requires org.elasticsearch.base; + requires org.elasticsearch.painless.spi; requires org.elasticsearch.server; requires org.elasticsearch.xcontent; requires org.apache.lucene.core; exports org.elasticsearch.aggregations.bucket.histogram; exports org.elasticsearch.aggregations.bucket.adjacency; + exports org.elasticsearch.aggregations.pipeline; + opens org.elasticsearch.aggregations to org.elasticsearch.painless.spi; // whitelist resource access + + provides org.elasticsearch.painless.spi.PainlessExtension with org.elasticsearch.aggregations.AggregationsPainlessExtension; } diff --git a/modules/aggregations/src/main/java/org/elasticsearch/aggregations/AggregationsPainlessExtension.java b/modules/aggregations/src/main/java/org/elasticsearch/aggregations/AggregationsPainlessExtension.java new file mode 100644 index 0000000000000..e181bb0018015 --- /dev/null +++ b/modules/aggregations/src/main/java/org/elasticsearch/aggregations/AggregationsPainlessExtension.java @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch.aggregations; + +import org.elasticsearch.aggregations.pipeline.MovingFunctionScript; +import org.elasticsearch.painless.spi.PainlessExtension; +import org.elasticsearch.painless.spi.PainlessTestScript; +import org.elasticsearch.painless.spi.Whitelist; +import org.elasticsearch.painless.spi.WhitelistLoader; +import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.search.aggregations.pipeline.MovingFunctions; + +import java.util.List; +import java.util.Map; + +/** + * Extends the painless whitelist for the {@link MovingFunctionScript} to include {@link MovingFunctions}. + */ +public class AggregationsPainlessExtension implements PainlessExtension { + private static final Whitelist MOVING_FUNCTION_ALLOWLIST = WhitelistLoader.loadFromResourceFiles( + AggregationsPainlessExtension.class, + "moving_function_whitelist.txt" + ); + + @Override + public Map, List> getContextWhitelists() { + return Map.ofEntries( + Map.entry(MovingFunctionScript.CONTEXT, List.of(MOVING_FUNCTION_ALLOWLIST)), + Map.entry(PainlessTestScript.CONTEXT, List.of(MOVING_FUNCTION_ALLOWLIST)) + ); + } +} diff --git a/modules/aggregations/src/main/java/org/elasticsearch/aggregations/AggregationsPlugin.java b/modules/aggregations/src/main/java/org/elasticsearch/aggregations/AggregationsPlugin.java index d13cc20cb2d2d..1553470a47403 100644 --- a/modules/aggregations/src/main/java/org/elasticsearch/aggregations/AggregationsPlugin.java +++ b/modules/aggregations/src/main/java/org/elasticsearch/aggregations/AggregationsPlugin.java @@ -12,13 +12,16 @@ import org.elasticsearch.aggregations.bucket.adjacency.InternalAdjacencyMatrix; import org.elasticsearch.aggregations.bucket.histogram.AutoDateHistogramAggregationBuilder; import org.elasticsearch.aggregations.bucket.histogram.InternalAutoDateHistogram; +import org.elasticsearch.aggregations.pipeline.MovFnPipelineAggregationBuilder; +import org.elasticsearch.aggregations.pipeline.MovingFunctionScript; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.plugins.ScriptPlugin; import org.elasticsearch.plugins.SearchPlugin; +import org.elasticsearch.script.ScriptContext; import java.util.List; -public class AggregationsPlugin extends Plugin implements SearchPlugin { - +public class AggregationsPlugin extends Plugin implements SearchPlugin, ScriptPlugin { @Override public List getAggregations() { return List.of( @@ -35,4 +38,20 @@ public List getAggregations() { .setAggregatorRegistrar(AutoDateHistogramAggregationBuilder::registerAggregators) ); } + + @Override + public List getPipelineAggregations() { + return List.of( + new PipelineAggregationSpec( + MovFnPipelineAggregationBuilder.NAME, + MovFnPipelineAggregationBuilder::new, + MovFnPipelineAggregationBuilder.PARSER + ) + ); + } + + @Override + public List> getContexts() { + return List.of(MovingFunctionScript.CONTEXT); + } } diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovFnPipelineAggregationBuilder.java b/modules/aggregations/src/main/java/org/elasticsearch/aggregations/pipeline/MovFnPipelineAggregationBuilder.java similarity index 97% rename from server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovFnPipelineAggregationBuilder.java rename to modules/aggregations/src/main/java/org/elasticsearch/aggregations/pipeline/MovFnPipelineAggregationBuilder.java index 1208e7661c81f..8c721ae2e1797 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovFnPipelineAggregationBuilder.java +++ b/modules/aggregations/src/main/java/org/elasticsearch/aggregations/pipeline/MovFnPipelineAggregationBuilder.java @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -package org.elasticsearch.search.aggregations.pipeline; +package org.elasticsearch.aggregations.pipeline; import org.elasticsearch.Version; import org.elasticsearch.common.Strings; @@ -14,7 +14,9 @@ import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.script.Script; import org.elasticsearch.search.DocValueFormat; +import org.elasticsearch.search.aggregations.pipeline.AbstractPipelineAggregationBuilder; import org.elasticsearch.search.aggregations.pipeline.BucketHelpers.GapPolicy; +import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; import org.elasticsearch.xcontent.ConstructingObjectParser; import org.elasticsearch.xcontent.ObjectParser; import org.elasticsearch.xcontent.ParseField; diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovFnPipelineAggregator.java b/modules/aggregations/src/main/java/org/elasticsearch/aggregations/pipeline/MovFnPipelineAggregator.java similarity index 95% rename from server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovFnPipelineAggregator.java rename to modules/aggregations/src/main/java/org/elasticsearch/aggregations/pipeline/MovFnPipelineAggregator.java index f4995762cc789..7431e806d96e4 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovFnPipelineAggregator.java +++ b/modules/aggregations/src/main/java/org/elasticsearch/aggregations/pipeline/MovFnPipelineAggregator.java @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -package org.elasticsearch.search.aggregations.pipeline; +package org.elasticsearch.aggregations.pipeline; import org.elasticsearch.script.Script; import org.elasticsearch.search.DocValueFormat; @@ -16,6 +16,9 @@ import org.elasticsearch.search.aggregations.InternalMultiBucketAggregation; import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation; import org.elasticsearch.search.aggregations.bucket.histogram.HistogramFactory; +import org.elasticsearch.search.aggregations.pipeline.BucketHelpers; +import org.elasticsearch.search.aggregations.pipeline.InternalSimpleValue; +import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator; import java.util.ArrayList; import java.util.HashMap; diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovingFunctionScript.java b/modules/aggregations/src/main/java/org/elasticsearch/aggregations/pipeline/MovingFunctionScript.java similarity index 95% rename from server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovingFunctionScript.java rename to modules/aggregations/src/main/java/org/elasticsearch/aggregations/pipeline/MovingFunctionScript.java index af9ef625e4808..2a6dc1107ad67 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovingFunctionScript.java +++ b/modules/aggregations/src/main/java/org/elasticsearch/aggregations/pipeline/MovingFunctionScript.java @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -package org.elasticsearch.search.aggregations.pipeline; +package org.elasticsearch.aggregations.pipeline; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptFactory; diff --git a/modules/aggregations/src/main/resources/META-INF/services/org.elasticsearch.painless.spi.PainlessExtension b/modules/aggregations/src/main/resources/META-INF/services/org.elasticsearch.painless.spi.PainlessExtension new file mode 100644 index 0000000000000..49fffefd631dc --- /dev/null +++ b/modules/aggregations/src/main/resources/META-INF/services/org.elasticsearch.painless.spi.PainlessExtension @@ -0,0 +1,9 @@ +# +# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +# or more contributor license agreements. Licensed under the Elastic License +# 2.0 and the Server Side Public License, v 1; you may not use this file except +# in compliance with, at your election, the Elastic License 2.0 or the Server +# Side Public License, v 1. +# + +org.elasticsearch.aggregations.AggregationsPainlessExtension diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.moving_function.txt b/modules/aggregations/src/main/resources/org/elasticsearch/aggregations/moving_function_whitelist.txt similarity index 89% rename from modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.moving_function.txt rename to modules/aggregations/src/main/resources/org/elasticsearch/aggregations/moving_function_whitelist.txt index 634c47f738486..0575734988063 100644 --- a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.moving_function.txt +++ b/modules/aggregations/src/main/resources/org/elasticsearch/aggregations/moving_function_whitelist.txt @@ -6,7 +6,7 @@ # Side Public License, v 1. # -# This file contains a whitelist for the Moving Function pipeline aggregator in core +# This file contains a allowlist for the Moving Function pipeline aggregator class org.elasticsearch.search.aggregations.pipeline.MovingFunctions { double max(double[]) diff --git a/server/src/test/java/org/elasticsearch/search/aggregations/pipeline/MovFnAggrgatorTests.java b/modules/aggregations/src/test/java/org/elasticsearch/aggregations/pipeline/MovFnAggregatorTests.java similarity index 78% rename from server/src/test/java/org/elasticsearch/search/aggregations/pipeline/MovFnAggrgatorTests.java rename to modules/aggregations/src/test/java/org/elasticsearch/aggregations/pipeline/MovFnAggregatorTests.java index 6c673cd837e39..acb30ca23ec8d 100644 --- a/server/src/test/java/org/elasticsearch/search/aggregations/pipeline/MovFnAggrgatorTests.java +++ b/modules/aggregations/src/test/java/org/elasticsearch/aggregations/pipeline/MovFnAggregatorTests.java @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -package org.elasticsearch.search.aggregations.pipeline; +package org.elasticsearch.aggregations.pipeline; import org.apache.lucene.document.Document; import org.apache.lucene.document.LongPoint; @@ -24,10 +24,9 @@ import org.elasticsearch.index.mapper.DateFieldMapper; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.NumberFieldMapper; -import org.elasticsearch.script.MockScriptEngine; import org.elasticsearch.script.Script; +import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptEngine; -import org.elasticsearch.script.ScriptModule; import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptType; import org.elasticsearch.search.aggregations.AggregatorTestCase; @@ -36,17 +35,20 @@ import org.elasticsearch.search.aggregations.bucket.histogram.Histogram; import org.elasticsearch.search.aggregations.bucket.histogram.InternalDateHistogram; import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder; +import org.elasticsearch.search.aggregations.pipeline.InternalSimpleValue; +import org.elasticsearch.search.aggregations.pipeline.MovingFunctions; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Consumer; import static org.hamcrest.Matchers.equalTo; -public class MovFnAggrgatorTests extends AggregatorTestCase { +public class MovFnAggregatorTests extends AggregatorTestCase { private static final String DATE_FIELD = "date"; private static final String INSTANT_FIELD = "instant"; @@ -69,14 +71,44 @@ public class MovFnAggrgatorTests extends AggregatorTestCase { @Override protected ScriptService getMockScriptService() { - MockScriptEngine scriptEngine = new MockScriptEngine( - MockScriptEngine.NAME, - Collections.singletonMap("test", script -> MovingFunctions.max((double[]) script.get("_values"))), - Collections.emptyMap() - ); + ScriptEngine scriptEngine = new ScriptEngine() { + @Override + public String getType() { + return "test"; + } + + @Override + public FactoryType compile( + String name, + String code, + ScriptContext context, + Map params + ) { + if (getSupportedContexts().contains(context) == false) { + return null; + } + MovingFunctionScript.Factory factory = () -> new MovingFunctionScript() { + @Override + public double execute(Map params, double[] values) { + return MovingFunctions.max(values); + } + }; + return context.factoryClazz.cast(factory); + } + + @Override + public Set> getSupportedContexts() { + return Set.of(MovingFunctionScript.CONTEXT); + } + }; Map engines = Collections.singletonMap(scriptEngine.getType(), scriptEngine); - return new ScriptService(Settings.EMPTY, engines, ScriptModule.CORE_CONTEXTS, () -> 1L); + return new ScriptService( + Settings.EMPTY, + engines, + Map.of(MovingFunctionScript.CONTEXT.name, MovingFunctionScript.CONTEXT), + () -> 1L + ); } public void testMatchAllDocs() throws IOException { @@ -94,7 +126,7 @@ public void testWideWindow() throws IOException { } private void check(int shift, int window, List expected) throws IOException { - Script script = new Script(ScriptType.INLINE, MockScriptEngine.NAME, "test", Collections.emptyMap()); + Script script = new Script(ScriptType.INLINE, "test", "test", Collections.emptyMap()); MovFnPipelineAggregationBuilder builder = new MovFnPipelineAggregationBuilder("mov_fn", "avg", script, window); builder.setShift(shift); diff --git a/modules/aggregations/src/test/java/org/elasticsearch/aggregations/pipeline/MovFnPipelineAggregationBuilderSerializationTests.java b/modules/aggregations/src/test/java/org/elasticsearch/aggregations/pipeline/MovFnPipelineAggregationBuilderSerializationTests.java index 5149570d1f7af..88c8a54232310 100644 --- a/modules/aggregations/src/test/java/org/elasticsearch/aggregations/pipeline/MovFnPipelineAggregationBuilderSerializationTests.java +++ b/modules/aggregations/src/test/java/org/elasticsearch/aggregations/pipeline/MovFnPipelineAggregationBuilderSerializationTests.java @@ -8,14 +8,16 @@ package org.elasticsearch.aggregations.pipeline; +import org.elasticsearch.aggregations.AggregationsPlugin; +import org.elasticsearch.plugins.SearchPlugin; import org.elasticsearch.script.Script; import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.BasePipelineAggregationTestCase; import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder; -import org.elasticsearch.search.aggregations.pipeline.MovFnPipelineAggregationBuilder; import java.io.IOException; import java.util.Collections; +import java.util.List; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; @@ -23,6 +25,11 @@ import static org.hamcrest.Matchers.nullValue; public class MovFnPipelineAggregationBuilderSerializationTests extends BasePipelineAggregationTestCase { + @Override + protected List plugins() { + return List.of(new AggregationsPlugin()); + } + @Override protected MovFnPipelineAggregationBuilder createTestAggregatorFactory() { MovFnPipelineAggregationBuilder builder = new MovFnPipelineAggregationBuilder( diff --git a/modules/aggregations/src/test/java/org/elasticsearch/aggregations/pipeline/PipelineAggregationHelperTests.java b/modules/aggregations/src/test/java/org/elasticsearch/aggregations/pipeline/PipelineAggregationHelperTests.java index 71f2ec284f8c2..94ad4e4bc657a 100644 --- a/modules/aggregations/src/test/java/org/elasticsearch/aggregations/pipeline/PipelineAggregationHelperTests.java +++ b/modules/aggregations/src/test/java/org/elasticsearch/aggregations/pipeline/PipelineAggregationHelperTests.java @@ -134,7 +134,7 @@ public static double calculateMetric(double[] values, ValuesSourceAggregationBui return 0.0; } - static AggregationBuilder getRandomSequentiallyOrderedParentAgg() throws IOException { + public static AggregationBuilder getRandomSequentiallyOrderedParentAgg() throws IOException { @SuppressWarnings("unchecked") Function builder = randomFrom( HistogramAggregationBuilder::new, diff --git a/modules/aggregations/src/yamlRestTest/resources/rest-api-spec/test/aggregations/70_adjacency_matrix.yml b/modules/aggregations/src/yamlRestTest/resources/rest-api-spec/test/aggregations/adjacency_matrix.yml similarity index 100% rename from modules/aggregations/src/yamlRestTest/resources/rest-api-spec/test/aggregations/70_adjacency_matrix.yml rename to modules/aggregations/src/yamlRestTest/resources/rest-api-spec/test/aggregations/adjacency_matrix.yml diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/70_moving_fn_agg.yml b/modules/aggregations/src/yamlRestTest/resources/rest-api-spec/test/aggregations/moving_fn.yml similarity index 95% rename from modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/70_moving_fn_agg.yml rename to modules/aggregations/src/yamlRestTest/resources/rest-api-spec/test/aggregations/moving_fn.yml index d2ff73ab16b1c..177bafaa07adf 100644 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/70_moving_fn_agg.yml +++ b/modules/aggregations/src/yamlRestTest/resources/rest-api-spec/test/aggregations/moving_fn.yml @@ -765,3 +765,50 @@ bad path: buckets_path: "missing" window: 2 script: "MovingFunctions.min(values)" + +--- +"Bad window": + + - skip: + version: " - 7.1.99" + reason: "calendar_interval added in 7.2" + + - do: + catch: /\[window\] must be a positive, non-zero integer\./ + search: + rest_total_hits_as_int: true + body: + size: 0 + aggs: + the_histo: + date_histogram: + field: "date" + calendar_interval: "1d" + aggs: + the_avg: + avg: + field: "value_field" + the_mov_fn: + moving_fn: + buckets_path: "the_avg" + window: -1 + script: "MovingFunctions.max(values)" + +--- +"Not under date_histo": + + - do: + catch: /moving_fn aggregation \[the_mov_fn\] must have a histogram, date_histogram or auto_date_histogram as parent but doesn't have a parent/ + search: + rest_total_hits_as_int: true + body: + size: 0 + aggs: + the_avg: + avg: + field: "value_field" + the_mov_fn: + moving_fn: + buckets_path: "the_avg" + window: 1 + script: "MovingFunctions.max(values)" diff --git a/modules/aggregations/src/yamlRestTest/resources/rest-api-spec/test/aggregations/painless_execute.yml b/modules/aggregations/src/yamlRestTest/resources/rest-api-spec/test/aggregations/painless_execute.yml new file mode 100644 index 0000000000000..9ee544f7a10fb --- /dev/null +++ b/modules/aggregations/src/yamlRestTest/resources/rest-api-spec/test/aggregations/painless_execute.yml @@ -0,0 +1,8 @@ +--- +MovingFunctions are available in the default context: + - do: + scripts_painless_execute: + body: + script: + source: "MovingFunctions.max(new double[] {1.0, 2.0, -1234})" + - match: { result: "2.0" } diff --git a/modules/lang-painless/build.gradle b/modules/lang-painless/build.gradle index 31c2955c38751..17e43a755bedd 100644 --- a/modules/lang-painless/build.gradle +++ b/modules/lang-painless/build.gradle @@ -96,7 +96,8 @@ tasks.named("yamlRestTestV7CompatTest").configure { 'painless/40_fields_api/script fields api for dates', 'painless/70_execute_painless_scripts/Execute with double field context (multi-value, fields api)', 'painless/40_fields_api/filter script fields api', - 'painless/40_fields_api/script score fields api' + 'painless/40_fields_api/script score fields api', + 'painless/70_mov_fn_agg/*' // Agg moved to a module. ].join(',') } diff --git a/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/PainlessTestScript.java b/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/PainlessTestScript.java new file mode 100644 index 0000000000000..6f2f49233242f --- /dev/null +++ b/modules/lang-painless/spi/src/main/java/org/elasticsearch/painless/spi/PainlessTestScript.java @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch.painless.spi; + +import org.elasticsearch.script.ScriptContext; + +import java.util.Map; + +/** + * Generic "test" context used by the painless execute REST API + * for testing painless scripts. + */ +public abstract class PainlessTestScript { + private final Map params; + + public PainlessTestScript(Map params) { + this.params = params; + } + + /** Return the parameters for this script. */ + public Map getParams() { + return params; + } + + public abstract Object execute(); + + public interface Factory { + PainlessTestScript newInstance(Map params); + } + + public static final String[] PARAMETERS = {}; + public static final ScriptContext CONTEXT = new ScriptContext<>("painless_test", Factory.class); +} diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java index 490d3899962f8..dfb547cbff0c4 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessPlugin.java @@ -27,6 +27,7 @@ import org.elasticsearch.painless.action.PainlessContextAction; import org.elasticsearch.painless.action.PainlessExecuteAction; import org.elasticsearch.painless.spi.PainlessExtension; +import org.elasticsearch.painless.spi.PainlessTestScript; import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.painless.spi.WhitelistLoader; import org.elasticsearch.painless.spi.annotation.WhitelistAnnotationParser; @@ -111,7 +112,7 @@ public final class PainlessPlugin extends Plugin implements ScriptPlugin, Extens } } testWhitelists.add(WhitelistLoader.loadFromResourceFiles(PainlessPlugin.class, "org.elasticsearch.json.txt")); - whitelists.put(PainlessExecuteAction.PainlessTestScript.CONTEXT, testWhitelists); + whitelists.put(PainlessTestScript.CONTEXT, testWhitelists); } private final SetOnce painlessScriptEngine = new SetOnce<>(); @@ -171,7 +172,7 @@ public void loadExtensions(ExtensionLoader loader) { @Override public List> getContexts() { - return Collections.singletonList(PainlessExecuteAction.PainlessTestScript.CONTEXT); + return Collections.singletonList(PainlessTestScript.CONTEXT); } @Override diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java index e2468506b4013..6a3d54e734975 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java @@ -56,6 +56,7 @@ import org.elasticsearch.index.query.SearchExecutionContext; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.indices.IndicesService; +import org.elasticsearch.painless.spi.PainlessTestScript; import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.action.RestToXContentListener; @@ -433,32 +434,6 @@ public int hashCode() { } } - public abstract static class PainlessTestScript { - - private final Map params; - - public PainlessTestScript(Map params) { - this.params = params; - } - - /** Return the parameters for this script. */ - public Map getParams() { - return params; - } - - public abstract Object execute(); - - public interface Factory { - - PainlessTestScript newInstance(Map params); - - } - - public static final String[] PARAMETERS = {}; - public static final ScriptContext CONTEXT = new ScriptContext<>("painless_test", Factory.class); - - } - public static class TransportAction extends TransportSingleShardAction { private final ScriptService scriptService; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AliasTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AliasTests.java index 0825fb98c2c4e..f9d87f5ce46b8 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/AliasTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/AliasTests.java @@ -8,8 +8,8 @@ package org.elasticsearch.painless; -import org.elasticsearch.painless.action.PainlessExecuteAction.PainlessTestScript; import org.elasticsearch.painless.lookup.PainlessLookupBuilder; +import org.elasticsearch.painless.spi.PainlessTestScript; import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.painless.spi.WhitelistLoader; import org.elasticsearch.script.ScriptContext; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/Debugger.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/Debugger.java index d20ac3cf31bea..04577d8ca9d81 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/Debugger.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/Debugger.java @@ -8,10 +8,10 @@ package org.elasticsearch.painless; -import org.elasticsearch.painless.action.PainlessExecuteAction.PainlessTestScript; import org.elasticsearch.painless.lookup.PainlessLookupBuilder; import org.elasticsearch.painless.phase.IRTreeVisitor; import org.elasticsearch.painless.phase.UserTreeVisitor; +import org.elasticsearch.painless.spi.PainlessTestScript; import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.painless.symbol.ScriptScope; import org.elasticsearch.painless.symbol.WriteScope; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DynamicTypeTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DynamicTypeTests.java index cdeea943782fe..ffbb7a17137d9 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/DynamicTypeTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/DynamicTypeTests.java @@ -8,7 +8,7 @@ package org.elasticsearch.painless; -import org.elasticsearch.painless.action.PainlessExecuteAction.PainlessTestScript; +import org.elasticsearch.painless.spi.PainlessTestScript; import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.painless.spi.WhitelistLoader; import org.elasticsearch.script.ScriptContext; diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java index 0cab58ae95504..ec5973a2d8371 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java @@ -12,6 +12,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.painless.antlr.Walker; +import org.elasticsearch.painless.spi.PainlessTestScript; import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.painless.spi.WhitelistLoader; import org.elasticsearch.script.ScriptContext; @@ -25,7 +26,6 @@ import java.util.List; import java.util.Map; -import static org.elasticsearch.painless.action.PainlessExecuteAction.PainlessTestScript; import static org.hamcrest.Matchers.hasSize; /** diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/action/PainlessExecuteApiTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/action/PainlessExecuteApiTests.java index f0cd8fbf60b44..63eb067a7a103 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/action/PainlessExecuteApiTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/action/PainlessExecuteApiTests.java @@ -390,11 +390,6 @@ public void testContextWhitelists() throws IOException { response = innerShardOperation(request, scriptService, null); assertEquals("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33", response.getResult()); - // movfn - request = new Request(new Script("MovingFunctions.max(new double[]{1, 3, 2})"), null, null); - response = innerShardOperation(request, scriptService, null); - assertEquals(3.0, Double.parseDouble((String) response.getResult()), .1); - // json request = new Request(new Script("Json.load('{\"a\": 1, \"b\": 2}')['b']"), null, null); response = innerShardOperation(request, scriptService, null); diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/action/SuggestTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/action/SuggestTests.java index c930d38675a26..f3e10ac0d1162 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/action/SuggestTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/action/SuggestTests.java @@ -11,9 +11,9 @@ import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.Token; import org.elasticsearch.painless.ScriptTestCase; -import org.elasticsearch.painless.action.PainlessExecuteAction.PainlessTestScript; import org.elasticsearch.painless.antlr.EnhancedSuggestLexer; import org.elasticsearch.painless.antlr.SuggestLexer; +import org.elasticsearch.painless.spi.PainlessTestScript; import java.util.List; diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.aggregation/250_moving_fn.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.aggregation/250_moving_fn.yml deleted file mode 100644 index 4e977468927f9..0000000000000 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search.aggregation/250_moving_fn.yml +++ /dev/null @@ -1,47 +0,0 @@ -# There are many more tests under modules/lang-painless/...moving_fn.yml so they can use painless ---- -"Bad window": - - - skip: - version: " - 7.1.99" - reason: "calendar_interval added in 7.2" - - - do: - catch: /\[window\] must be a positive, non-zero integer\./ - search: - rest_total_hits_as_int: true - body: - size: 0 - aggs: - the_histo: - date_histogram: - field: "date" - calendar_interval: "1d" - aggs: - the_avg: - avg: - field: "value_field" - the_mov_fn: - moving_fn: - buckets_path: "the_avg" - window: -1 - script: "MovingFunctions.max(values)" - ---- -"Not under date_histo": - - - do: - catch: /moving_fn aggregation \[the_mov_fn\] must have a histogram, date_histogram or auto_date_histogram as parent but doesn't have a parent/ - search: - rest_total_hits_as_int: true - body: - size: 0 - aggs: - the_avg: - avg: - field: "value_field" - the_mov_fn: - moving_fn: - buckets_path: "the_avg" - window: 1 - script: "MovingFunctions.max(values)" diff --git a/server/src/main/java/org/elasticsearch/script/ScriptModule.java b/server/src/main/java/org/elasticsearch/script/ScriptModule.java index 996d6815aa433..85afb96225254 100644 --- a/server/src/main/java/org/elasticsearch/script/ScriptModule.java +++ b/server/src/main/java/org/elasticsearch/script/ScriptModule.java @@ -12,7 +12,6 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.query.IntervalFilterScript; import org.elasticsearch.plugins.ScriptPlugin; -import org.elasticsearch.search.aggregations.pipeline.MovingFunctionScript; import java.util.Collections; import java.util.HashMap; @@ -63,7 +62,6 @@ public class ScriptModule { SimilarityWeightScript.CONTEXT, TemplateScript.CONTEXT, TemplateScript.INGEST_CONTEXT, - MovingFunctionScript.CONTEXT, ScriptedMetricAggContexts.InitScript.CONTEXT, ScriptedMetricAggContexts.MapScript.CONTEXT, ScriptedMetricAggContexts.CombineScript.CONTEXT, diff --git a/server/src/main/java/org/elasticsearch/search/SearchModule.java b/server/src/main/java/org/elasticsearch/search/SearchModule.java index 11e903ba989d1..628ff8fbe1b52 100644 --- a/server/src/main/java/org/elasticsearch/search/SearchModule.java +++ b/server/src/main/java/org/elasticsearch/search/SearchModule.java @@ -204,7 +204,6 @@ import org.elasticsearch.search.aggregations.pipeline.MaxBucketPipelineAggregationBuilder; import org.elasticsearch.search.aggregations.pipeline.MinBucketPipelineAggregationBuilder; import org.elasticsearch.search.aggregations.pipeline.MovAvgPipelineAggregationBuilder; -import org.elasticsearch.search.aggregations.pipeline.MovFnPipelineAggregationBuilder; import org.elasticsearch.search.aggregations.pipeline.PercentilesBucketPipelineAggregationBuilder; import org.elasticsearch.search.aggregations.pipeline.SerialDiffPipelineAggregationBuilder; import org.elasticsearch.search.aggregations.pipeline.StatsBucketPipelineAggregationBuilder; @@ -791,13 +790,6 @@ private void registerPipelineAggregations(List plugins) { SerialDiffPipelineAggregationBuilder::parse ) ); - registerPipelineAggregation( - new PipelineAggregationSpec( - MovFnPipelineAggregationBuilder.NAME, - MovFnPipelineAggregationBuilder::new, - MovFnPipelineAggregationBuilder.PARSER - ) - ); if (RestApiVersion.minimumSupported() == RestApiVersion.V_7) { registerPipelineAggregation( new PipelineAggregationSpec( diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/PipelineAggregatorBuilders.java b/server/src/main/java/org/elasticsearch/search/aggregations/PipelineAggregatorBuilders.java index 1409ec94009a5..e5988ced78516 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/PipelineAggregatorBuilders.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/PipelineAggregatorBuilders.java @@ -18,7 +18,6 @@ import org.elasticsearch.search.aggregations.pipeline.ExtendedStatsBucketPipelineAggregationBuilder; import org.elasticsearch.search.aggregations.pipeline.MaxBucketPipelineAggregationBuilder; import org.elasticsearch.search.aggregations.pipeline.MinBucketPipelineAggregationBuilder; -import org.elasticsearch.search.aggregations.pipeline.MovFnPipelineAggregationBuilder; import org.elasticsearch.search.aggregations.pipeline.PercentilesBucketPipelineAggregationBuilder; import org.elasticsearch.search.aggregations.pipeline.SerialDiffPipelineAggregationBuilder; import org.elasticsearch.search.aggregations.pipeline.StatsBucketPipelineAggregationBuilder; @@ -91,8 +90,4 @@ public static CumulativeSumPipelineAggregationBuilder cumulativeSum(String name, public static SerialDiffPipelineAggregationBuilder diff(String name, String bucketsPath) { return new SerialDiffPipelineAggregationBuilder(name, bucketsPath); } - - public static MovFnPipelineAggregationBuilder movingFunction(String name, Script script, String bucketsPaths, int window) { - return new MovFnPipelineAggregationBuilder(name, bucketsPaths, script, window); - } } diff --git a/server/src/test/java/org/elasticsearch/script/ScriptLanguagesInfoTests.java b/server/src/test/java/org/elasticsearch/script/ScriptLanguagesInfoTests.java index 22cf6d5aef36a..ca6d8930eb7b9 100644 --- a/server/src/test/java/org/elasticsearch/script/ScriptLanguagesInfoTests.java +++ b/server/src/test/java/org/elasticsearch/script/ScriptLanguagesInfoTests.java @@ -106,7 +106,7 @@ public void testContextsAllowedSettingRespected() { .collect(Collectors.toMap(c -> c.name, Function.identity())); List allContexts = new ArrayList<>(mockContexts.keySet()); - List allowed = allContexts.subList(0, allContexts.size() / 2); + List allowed = new ArrayList<>(allContexts.subList(0, allContexts.size() / 2)); String miscContext = "misc_context"; allowed.add(miscContext); // check that allowing more than available doesn't pollute the returned contexts diff --git a/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java b/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java index b1cc863835314..ea02011459784 100644 --- a/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java +++ b/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java @@ -20,7 +20,6 @@ import org.elasticsearch.index.similarity.ScriptedSimilarity.Field; import org.elasticsearch.index.similarity.ScriptedSimilarity.Query; import org.elasticsearch.index.similarity.ScriptedSimilarity.Term; -import org.elasticsearch.search.aggregations.pipeline.MovingFunctionScript; import org.elasticsearch.search.lookup.SearchLookup; import java.io.IOException; @@ -251,15 +250,6 @@ public String execute() { } else if (context.instanceClazz.equals(SimilarityWeightScript.class)) { SimilarityWeightScript.Factory factory = mockCompiled::createSimilarityWeightScript; return context.factoryClazz.cast(factory); - } else if (context.instanceClazz.equals(MovingFunctionScript.class)) { - MovingFunctionScript.Factory factory = () -> new MovingFunctionScript() { - @Override - public double execute(Map params1, double[] values) { - params1.put("_values", values); - return (double) script.apply(params1); - } - }; - return context.factoryClazz.cast(factory); } else if (context.instanceClazz.equals(ScoreScript.class)) { ScoreScript.Factory factory = new MockScoreScript(script); return context.factoryClazz.cast(factory); @@ -372,7 +362,6 @@ public Set> getSupportedContexts() { FilterScript.CONTEXT, SimilarityScript.CONTEXT, SimilarityWeightScript.CONTEXT, - MovingFunctionScript.CONTEXT, ScoreScript.CONTEXT, ScriptedMetricAggContexts.InitScript.CONTEXT, ScriptedMetricAggContexts.MapScript.CONTEXT,