Skip to content

Conversation

@martijnvg
Copy link
Member

@martijnvg martijnvg commented Mar 20, 2018

Adds an api that allows to execute an arbitrary script and a result to be returned.

POST /_scripts/painless/_execute
{
  "script": {
    "source": "params.var1 / params.var2",
    "params": {
      "var1": 1,
      "var2": 1
    }
  }
}

@martijnvg martijnvg added >feature review :Core/Infra/Scripting Scripting abstractions, Painless, and Mustache v7.0.0 v6.3.0 labels Mar 20, 2018
@martijnvg martijnvg requested review from jdconrad and rjernst March 20, 2018 13:25
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-infra

@martijnvg martijnvg force-pushed the painless_execute_api branch 2 times, most recently from f4df137 to 20e9b82 Compare March 27, 2018 05:24
@jasontedor
Copy link
Member

@jdconrad Could you review this PR?

Copy link
Contributor

@jdconrad jdconrad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@martijnvg Thank you so much for a first pass at this! My apologies for taking so long to get to the review. I have some comments mostly related to the documentation, but a few technical points to. I would also like @rjernst to take a look at this as well as I'm hopeful he can better explain the design decisions around the context code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reword this. Maybe something like "allows an arbitrary script to be executed and a result to be returned."

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this follow something more closely to the stored script format?

"script": {
    "code":  "<code>",
    "context": "<context>"
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that makes sense.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After looking at this again. Changing to format to what you suggest does make the request a bit more verbose. Example:

{
  "script": {
    "code": {
      "source": "params.count / params.total",
      "params": {
        "count": 100.0,
        "total": 1000.0
      }
    },
    "context": ...
  }
}

Compared to:

POST /_scripts/painless/_execute
{
  "script": {
    "source": "params.count / params.total",
    "params": {
      "count": 100.0,
      "total": 1000.0
    }
  },
  "context": ...
}

I don't think this adds much? And context is something specific to this api.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My apologies, I don't think I made my request clear. I thought the format was different, what I meant was change "source" to be "code" like we've done for stored scripts, but it looks like we never did that for Script, so it's confusing. Let's just roll with what you had.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please replace "get" with "are"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also consider rewording variables into something like parameters? I realize that's confusing too as params is often used in scripts. Variables seems to imply what can be locally created as well when really we just want to say what external data is allowed to be used.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variables -> Parameters? It's like a hidden method call.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"script parameters" -> "user defined values" ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be a way to possibly return specified parameters as well so they the user can see side-effects? Maybe a follow up.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, whether returning the specified variables makes sense.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it probably doesn't make sense here. I guess I was thinking along the lines of how things get passed around in related to aggs, but that can be simulated anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As commented on before in the documentation, consider changing this field to "code"

Copy link
Contributor

@jdconrad jdconrad Apr 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this rest path potentially limit api additions/changes moving forward given that there is no description of what action is being taken as part of the path? Something like admin/scripts/lang/painless/action/execute may be significantly more flexible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the rest paths are in the RestAction inner class (line 319). This NAME is kind of an unique value that is used to register this action. The reason it is name spaced, is for security, mainly for authorization reasons. I'm ok with the name change you propose here (but it needs to be prefixed with cluster:).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this comment was added to remember the question and should be removed before committing. @rjernst can likely explain the necessity of the design decisions here better than I can, so I'm hopeful he will chime in :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The factory is what holds onto the params, so that they can be passed to the constructor. Think of the factory as the signature for the constructor. It's not boilerplate; it is actually needed based on current uses of scripts throughout the system. Also note that the factory signature is what allows the script instance to have arbitrary objects passed in. If ScriptService.compile were to return an instance directly, instead of a factory, we would need some way to pass in this information in a generic way, which would probably mean duck typing through a String->Object map and then require casts. With the factory, we get static type checking of the arguments a script needs to be constructed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation.

I think I added this after looking at ExecutableScript, but I guess there setNextVar() method is used to provide params to the script engine (so params isn't implicitly provided).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could name the context (and the class) something more descriptive for it's purpose? While the rest api is for executing a script, I think this context is a generic test context? Perhaps it could be "painless_test" (and PainlessTestScript) or something like that? I like having "test" in there because it is clear this is not for production uses, but to test painless code. It would also be more clear for when we do support other contexts in the execute api.

@martijnvg martijnvg force-pushed the painless_execute_api branch from 20e9b82 to 6c03acb Compare April 17, 2018 14:02
Copy link
Contributor

@jdconrad jdconrad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mvg Thanks again for doing this and considering the feeback. Please feel free to commit this whenever you're ready to.

@martijnvg martijnvg force-pushed the painless_execute_api branch from 6c03acb to 7ebcd00 Compare April 19, 2018 05:47
@martijnvg martijnvg merged commit 8afa7c1 into elastic:master Apr 19, 2018
martijnvg added a commit that referenced this pull request Apr 19, 2018
Added an api that allows to execute an arbitrary script and a result to be returned.

```
POST /_scripts/painless/_execute
{
  "script": {
    "source": "params.var1 / params.var2",
    "params": {
      "var1": 1,
      "var2": 1
    }
  }
}
```

Relates to #27875
jasontedor added a commit to jasontedor/elasticsearch that referenced this pull request Apr 19, 2018
* master: (21 commits)
  Remove bulk fallback for write thread pool (elastic#29609)
  Fix an incorrect reference to 'zero_terms_docs' in match_phrase queries.
  Update the version compatibility for zero_terms_query in match_phrase.
  Account translog location to ram usage in version map
  Remove extra spaces from changelog
  Add support to match_phrase query for zero_terms_query. (elastic#29598)
  Fix incorrect references to 'zero_terms_docs' in query parsing error messages. (elastic#29599)
  Build: Move java home checks to pre-execution phase (elastic#29548)
  Avoid side-effect in VersionMap when assertion enabled (elastic#29585)
  [Tests] Remove accidental logger usage
  Add tests for ranking evaluation with aliases (elastic#29452)
  Deprecate use of `htmlStrip` as name for HtmlStripCharFilter (elastic#27429)
  Update plan for the removal of mapping types. (elastic#29586)
  [Docs] Add rankEval method for Jva HL client
  Make ranking evaluation details accessible for client
  Rename the bulk thread pool to write thread pool (elastic#29593)
  [Test] Minor changes to rank_eval tests (elastic#29577)
  Fix missing node id prefix in startup logs (elastic#29534)
  Added painless execute api. (elastic#29164)
  test: also assert deprecation warning after clusters have been closed.
  ...
@simianhacker
Copy link
Member

simianhacker commented Apr 27, 2018

Thank you to @martijnvg @rjernst @jdconrad !

var1: 10
var2: 100
context:
painless_test: {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@martijnvg just wondering whats the reason context takes a map and not a string[]? are we expecting per context settings in the future?

Copy link
Member

@rjernst rjernst Aug 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was improved in a followup PR. context is now just a string (the name of the context to use), not a map. The variables to fill in that context are in context_setup. See https://www.elastic.co/guide/en/elasticsearch/painless/6.4/painless-execute-api.html

@Mpdreamz
Copy link
Member

Thanks for the heads up @rjernst!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:Core/Infra/Scripting Scripting abstractions, Painless, and Mustache >feature v6.3.0 v7.0.0-beta1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants