5.0.0 Using Painless in ESIntegTestCase

Hi together,

we are currently updating our application from Elasticsearch 2.4.1 to Elasticsearch 5.0.0
and in the same process we are updating our integration tests to use the ESIntegTestCase as foundation.

Everything works fine, except for one groovy script function:
IllegalArgumentException[script_lang not supported [groovy]];

Ok, who want's groovy if he can have painless, which is builtin and also the default scripting option.
So I converted the script from groovy to painless, but I still get the same error:
IllegalArgumentException[script_lang not supported [painless]];

What do I have to do to use Painless or Groovy in an ESIntegTestCase?

Regards,
Daniel

Add

    @Override
    protected Collection<Class<? extends Plugin>> nodePlugins() {
        return Collections.singleton(PainlessPlugin.class);
    }

and make sure the painless plugin and its dependencies are on the classpath.

I should warn you that we are slowly moving away from ESIntegTestCase, towards unit tests and fully stood up integration tests against REST. ESIntegTestCase won't go away, but slowly it'll see less use in our code base and be concentrated on cluster testing tasks. It used to be that we would test everything with ESIntegTestCase (or its previous name, which I'm forgetting now) because we didn't have anything else.

Thank you for your fast and very informative answer.

Regarding Painless:
As far as I can see painless is not published to maven central, or am I missing something?
This would complicate the build process since we have to manage the dependency for ourself.

Regarding ESIntegTestCase:
We previously had an own base class for integration tests which used the NodeBuilder.nodeBuilder().
Since NodeBuilder was removed in 5.0.0 we decided to give ESIntegTestCase a try and it works out really well.
What I really like about ESIntegTestCase is that I don't have to manage an external Elasticsearch Installation for the integration tests.
But if I understand you correctly, I don't have to consider it deprecated, at least for some time, right?

Regards,
Daniel

Looks like it isn't.... Sorry about that! I'm just now remembering a conversation where "only the plugins that are needed for the transport client are in central". I believe the reasoning is along the same lines as to why we use fully stood up integration tests for these sorts of tests. You can work around it by stuffing all the modules/lang-painless/lang-painless-*.jar files in a local repo and adding dependencies for all of the other jars in that directory as test dependencies. That ought to work. It might have trouble with security, I'm not 100% clear on the hoops we jump through in our build for this.

This is more fuel for the argument that it is probably a better idea to test against a distribution rather than ESIntegTestCase. It is less likely that we'll break it but I admit it is more work to set up. There is a maven plugin that does this but I don't believe it has been upgraded for 5.0.0. Also, I proposed

so we'd maintain a Maven and Gradle plugin that'd do that. Sorry for the messy state....

It is complicated :frowning: . We're not really fully in agreement on where it'll go when. If I were you I'd bit the bullet and set up an ES instance as part of your build. Or go poke that issue I linked so we know we should get to it....

Ok, thanks again for the clarification.

My conclusion from this is, that I will test our application against a standalone elasticsearch installation using the transport client. This is also a much more realistic setup than using an embedded elasticsearch.
We are testing against an external database, so why should we do otherwise for elasticsearch.

Regards,
Daniel

I've made that argument before. I think it is a good one.

Personally I'd try to get Elasticsearch to start as part of your build script, but it might make sense to go +1 that issue I linked and run it on your own for now. That way we'll maintain the maven/gradle plugin. That only works if you use maven or gradle the build though.

I think you are mentioning this issue: Plugins jars are not published to maven central · Issue #18131 · elastic/elasticsearch · GitHub

In case you are using Maven, this can help you: https://david.pilato.fr/blog/2016-07-29-elasticsearch-real-integration-tests/

I keep forgetting that!

This looks indeed promising. Thanks for the info. :slight_smile:

Getting the following exception when trying to run a simple script with ESIntegTestCase. Am I missing something?

Failed to execute phase [query], all shards failed; shardFailures {[HkQYG3qkRkK5v2eutHfqgg][test][0]: RemoteTransportException[[node_sm0][local[1]][indices:data/read/search[phase/query]]]; nested: QueryShardException[script_score: the script could not be loaded]; nested: GeneralScriptException[Failed to compile inline script [return 1;] using lang [painless]]; nested: SecurityException[access denied ("java.lang.RuntimePermission" "createClassLoader")]; }{[znhhDCm_QjCQ8EH7Z4FO0A][test][1]: RemoteTransportException[[node_sm0][local[1]][indices:data/read/search[phase/query]]]; nested: QueryShardException[script_score: the script could not be loaded]; nested: GeneralScriptException[Failed to compile inline script [return 1;] using lang [painless]]; nested: SecurityException[access denied ("java.lang.RuntimePermission" "createClassLoader")]; }{[4abErMiHRwGWSxUvDg9O_Q][test][2]: RemoteTransportException[[node_sm0][local[1]][indices:data/read/search[phase/query]]]; nested: QueryShardException[script_score: the script could not be loaded]; nested: GeneralScriptException[Failed to compile inline script [return 1;] using lang [painless]]; nested: SecurityException[access denied ("java.lang.RuntimePermission" "createClassLoader")]; }{[HkQYG3qkRkK5v2eutHfqgg][test][3]: RemoteTransportException[[node_sm0][local[1]][indices:data/read/search[phase/query]]]; nested: QueryShardException[script_score: the script could not be loaded]; nested: GeneralScriptException[Failed to compile inline script [return 1;] using lang [painless]]; nested: SecurityException[access denied ("java.lang.RuntimePermission" "createClassLoader")]; }{[znhhDCm_QjCQ8EH7Z4FO0A][test][4]: RemoteTransportException[[node_sm0][local[1]][indices:data/read/search[phase/query]]]; nested: QueryShardException[script_score: the script could not be loaded]; nested: GeneralScriptException[Failed to compile inline script [return 1;] using lang [painless]]; nested: SecurityException[access denied ("java.lang.RuntimePermission" "createClassLoader")]; }{[4abErMiHRwGWSxUvDg9O_Q][test][5]: RemoteTransportException[[node_sm0][local[1]][indices:data/read/search[phase/query]]]; nested: QueryShardException[script_score: the script could not be loaded]; nested: GeneralScriptException[Failed to compile inline script [return 1;] using lang [painless]]; nested: SecurityException[access denied ("java.lang.RuntimePermission" "createClassLoader")]; }
        at __randomizedtesting.SeedInfo.seed([7AD536286B2A9DBA:C85041F1742D6D3B]:0)
        at org.elasticsearch.action.search.AbstractSearchAsyncAction.onFirstPhaseResult(AbstractSearchAsyncAction.java:235)
        at org.elasticsearch.action.search.AbstractSearchAsyncAction$1.onFailure(AbstractSearchAsyncAction.java:170)
        at org.elasticsearch.action.ActionListenerResponseHandler.handleException(ActionListenerResponseHandler.java:51)
        at org.elasticsearch.transport.TransportService$ContextRestoreResponseHandler.handleException(TransportService.java:954)
        at org.elasticsearch.transport.local.LocalTransport.handleException(LocalTransport.java:418)
        at org.elasticsearch.transport.local.LocalTransport.handleResponseError(LocalTransport.java:409)
        at org.elasticsearch.transport.local.LocalTransport.processReceivedMessage(LocalTransport.java:289)
        at org.elasticsearch.transport.local.LocalTransport.lambda$receiveMessage$0(LocalTransport.java:251)
        at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:444)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: RemoteTransportException[[node_sm0][local[1]][indices:data/read/search[phase/query]]]; nested: QueryShardException[script_score: the script could not be loaded]; nested: GeneralScriptException[Failed to compile inline script [return 1;] using lang [painless]]; nested: SecurityException[access denied ("java.lang.RuntimePermission" "createClassLoader")];
Caused by: [test/wON6u3wRSmqkTJEPv97OAw] QueryShardException[script_score: the script could not be loaded]; nested: GeneralScriptException[Failed to compile inline script [return 1;] using lang [painless]]; nested: SecurityException[access denied ("java.lang.RuntimePermission" "createClassLoader")];
        at org.elasticsearch.index.query.functionscore.ScriptScoreFunctionBuilder.doToFunction(ScriptScoreFunctionBuilder.java:102)
        at org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder.toFunction(ScoreFunctionBuilder.java:137)

I don't think ESIntegTest case is really the way to go - @dadoonet's comment about about running Elasticsearch as part of your build is much more likely to work. ESIntegTestCase is really for testing Elasticsearch or your own plugins. The painless plugin jars aren't available in central to install to test against, iirc. You can get them from the zip/tar/rpm/deb distributions and extract them and use them, but that is brittle and a lot of work so it is probably better to test against an Elasticsearch outside of the test process, hopefully started by the build using the instructions in @dadoonet's post.

It's strange because the documentation states that's the way to go.

I've filed

so we'll fix it.