-
Notifications
You must be signed in to change notification settings - Fork 24.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add get stored script and delete stored script to high level REST API #31355
Add get stored script and delete stored script to high level REST API #31355
Conversation
Pinging @elastic/es-core-infra |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left some comments, thanks @vladimirdolzhenko
@@ -877,6 +879,18 @@ static Request getTemplates(GetIndexTemplatesRequest getIndexTemplatesRequest) t | |||
return request; | |||
} | |||
|
|||
static Request getStoredScript(GetStoredScriptRequest getStoredScriptRequest) { | |||
String endpoint = new EndpointBuilder().addPathPart("_scripts").addPathPart(getStoredScriptRequest.id()).build(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the first one should be addPathPartAsIs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++
} | ||
|
||
static Request deleteStoredScript(DeleteStoredScriptRequest deleteStoredScriptRequest) { | ||
String endpoint = new EndpointBuilder().addPathPart("_scripts").addPathPart(deleteStoredScriptRequest.id()).build(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here too, addPartAsIs for _scripts
* @return the response | ||
* @throws IOException in case there is a problem sending the request or parsing back the response | ||
*/ | ||
public GetStoredScriptResponse getStoredScript(GetStoredScriptRequest request, RequestOptions options) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the SPEC have get_script, can we call these methods getScript ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove stored from all methods names?
* @return the response | ||
* @throws IOException in case there is a problem sending the request or parsing back the response | ||
*/ | ||
public DeleteStoredScriptResponse deleteStoredScript(DeleteStoredScriptRequest request, RequestOptions options) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here too, remove the stored part
|
||
Request request = RequestConverters.getStoredScript(storedScriptRequest); | ||
assertThat(request.getEndpoint(), equalTo("/_scripts/" + storedScriptRequest.id())); | ||
assertThat(request.getParameters(), equalTo(expectedParams)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to create a new map right? you can just assert that parameters is empty.
@@ -149,3 +149,13 @@ The Java High Level REST Client supports the following Tasks APIs: | |||
|
|||
include::tasks/list_tasks.asciidoc[] | |||
include::tasks/cancel_tasks.asciidoc[] | |||
|
|||
== Scripts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move them up with the top-level API? We try to align this with the API categories from the SPEC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking again, I think that it's fine to have them grouped under scripts although the spec puts them in the top-level API. Things are a bit different in the es reference docs. Call it Scripts APIs though .
source.toXContent(builder, params); | ||
public boolean isFragment() { | ||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this method is not meant to be overridden. Please use ToXContentFragment instead of ToXContentObject if needed. Yet normally responses are objects rather than fragments, you sure about this?
|
||
builder.endObject(); | ||
} | ||
response.toXContent(builder, channel.request()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can make the response a StatusToXContentObject
and then use RestStatusToXContentListener
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StatusToXContentObject
starts to conflict with ToXContentFragment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and RestStatusToXContentListener
does not work with fragment - RestGetStoredScriptAction
as well adds id
into response
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said above, this probably should not be a fragment, I don't get why it would need to be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is a manual serialization performed in RestGetStoredScriptAction
- it adds as well id
of script
in front of GetStoredScriptResponse
- agreed to move id
within GetStoredScriptResponse
, make it StatusToXContentObject
and drop fragment
builder.field(OPTIONS_PARSE_FIELD.getPreferredName(), options); | ||
if (options.isEmpty() == false) { | ||
builder.field(OPTIONS_PARSE_FIELD.getPreferredName(), options); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need this change? it seems like it changes the existing StoredScriptSource output, that may be risky to do, not sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is a custom serialization performed in RestGetStoredScriptAction
- I use a standard StoredScriptSource.toXContent
but it violates test rest-api-spec/test/painless/16_update2.yml
- it expects that empty options
are not shows at all. Deserialization of empty options
or no-options are equal - resolves to empty map.
I traced call sites - seems no any other usages of StoredScriptSource.toXContent
+ other tests passes fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok thanks
|
||
private StoredScriptSource scriptSource() { | ||
return new StoredScriptSource("lang", "code", | ||
Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we randomize how this instance gets created?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed
one more thing @vladimirdolzhenko the docs don't seem to build, can you check that please? |
…i-spec; cleaned RestGetStoredScriptAction up and GetStoredScriptResponse.toXContent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left a few more comments, mostly minors.
// end::delete-stored-script-execute | ||
|
||
// tag::delete-stored-script-response | ||
assertThat(deleteResponse.isAcknowledged(), equalTo(true)); // <1> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer that we don't show assertions in the docs output, but rather just assign values to variables, which is more aligned with what users will do in their applications.
// end::get-stored-script-execute | ||
|
||
// tag::get-stored-script-response | ||
final StoredScriptSource source = getResponse.getSource(); // <1> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it worth expanding on how to interact with StoredScriptSource?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed
["source","java",subs="attributes,callouts,macros"] | ||
-------------------------------------------------- | ||
include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[delete-stored-script-execute] | ||
-------------------------------------------------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we are missing the optional parameters section here that describe the two supported timeouts.
* @return the response | ||
* @throws IOException in case there is a problem sending the request or parsing back the response | ||
*/ | ||
public GetStoredScriptResponse getStoredScript(GetStoredScriptRequest request, RequestOptions options) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove stored from all methods names?
@@ -149,3 +149,13 @@ The Java High Level REST Client supports the following Tasks APIs: | |||
|
|||
include::tasks/list_tasks.asciidoc[] | |||
include::tasks/cancel_tasks.asciidoc[] | |||
|
|||
== Scripts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking again, I think that it's fine to have them grouped under scripts although the spec puts them in the top-level API. Things are a bit different in the es reference docs. Call it Scripts APIs though .
public XContentBuilder field(ParseField field, String value) throws IOException { | ||
return field(field.getPreferredName(), value); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I wonder what these method buy us, my concern is that we have already a lot of methods in XContentBuilder. After all callers only have to call the other variant of these methods and pass in field.getPreferredName()
. I am a bit on the fence on this. Maybe let's try and do it separately and see what others think about it.
|
||
builder.field(_ID_PARSE_FIELD, id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we may have a small problem here, when toXContent is called on an object deserialized from a previous version that didn't send the _id .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope, actually RestGetStoredScriptAction
adds that _id
manually (out of GetStoredScriptRequest.toXContent
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you added id as a member, which is great. It is now being serialized over the wire, but nodes on previous versions don't send it. If you are deserializing from a previous version this one will be null, and what will happen when you call toXcontent against such an object? I am not sure whether it will be NPE or the id will be printed out null, maybe just the latter, can you check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed - use writeOptionalString
instead of writeString
(to avoid NPE on serialization) - while I don't see anything more how we can handle this case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if it prints out null it may be ok, if it gives NPE we need a null check, that's what I meant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it prints out null
:
public XContentBuilder field(String name, String value) throws IOException {
if (value == null) {
return nullField(name);
}
ensureNameNotNull(name);
generator.writeStringField(name, value);
return this;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for checking, that is fine then
private StoredScriptSource source; | ||
|
||
GetStoredScriptResponse() { | ||
} | ||
|
||
GetStoredScriptResponse(StoredScriptSource source) { | ||
GetStoredScriptResponse(String id) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we can do without this constructor and always use the other that accepts both id and source? otherwise make this one private at least?
builder.field(OPTIONS_PARSE_FIELD.getPreferredName(), options); | ||
if (options.isEmpty() == false) { | ||
builder.field(OPTIONS_PARSE_FIELD.getPreferredName(), options); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok thanks
return s -> "script.options".equals(s); | ||
} | ||
|
||
private StoredScriptSource scriptSource() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static? and call it randomScriptSource?
…ng at REST level; code style adjustments
thanks @javanna for your comments, could you pls have another look into this ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks @vladimirdolzhenko I left a couple of things but LGTM, feel free to push once those are addressed.
return request; | ||
} | ||
|
||
static Request deleteScript(DeleteStoredScriptRequest deleteStoredScriptRequest) { | ||
String endpoint = new EndpointBuilder().addPathPartAsIs("_scripts").addPathPart(deleteStoredScriptRequest.id()).build(); | ||
Request request = new Request(HttpDelete.METHOD_NAME, endpoint); | ||
Params params = new Params(request); | ||
params.withTimeout(deleteStoredScriptRequest.timeout()); | ||
params.withMasterTimeout(deleteStoredScriptRequest.masterNodeTimeout()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also set them to some value?
@@ -51,7 +51,7 @@ | |||
String id = (String) a[0]; | |||
boolean found = (Boolean)a[1]; | |||
StoredScriptSource scriptSource = (StoredScriptSource)a[2]; | |||
return found ? new GetStoredScriptResponse(id, scriptSource) : new GetStoredScriptResponse(id); | |||
return found ? new GetStoredScriptResponse(id, scriptSource) : new GetStoredScriptResponse(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that you wanted to set the id in both cases and that the else block should become new GetStoredScriptResponse(id, null)
@@ -148,7 +144,7 @@ public void writeTo(StreamOutput out) throws IOException { | |||
} | |||
} | |||
if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { | |||
out.writeString(id); | |||
out.writeOptionalString(id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You already have a conditional based on the version, if a version supports it, it will always send it. Making it optional helps in case something that is deserialized from a previous version is sent back to another node. I am not sure we ever do those multiple roundtrips with this API, hence I don't think we need to make it optional. If this is due to my previous comment on id being potentially null, I didn't mean to make you make this change. I rather meant to protect toXcontent from potential NPEs if they may happen.
@@ -47,7 +47,7 @@ public String getName() { | |||
public RestChannelConsumer prepareRequest(final RestRequest request, NodeClient client) throws IOException { | |||
String id = request.param("id"); | |||
GetStoredScriptRequest getRequest = new GetStoredScriptRequest(id); | |||
|
|||
getRequest.masterNodeTimeout(request.paramAsTime("master_timeout", getRequest.masterNodeTimeout())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you also add this to the SPEC if it's supported?
@@ -134,7 +134,7 @@ public void testStartEndArray() throws IOException { | |||
|
|||
public void testField() throws IOException { | |||
expectValueException(() -> BytesReference.bytes(builder().field("foo"))); | |||
expectNonNullFieldException(() -> BytesReference.bytes(builder().field(null))); | |||
expectNonNullFieldException(() -> BytesReference.bytes(builder().field((String)null))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should not be needed anymore
DeleteStoredScriptRequest deleteStoredScriptRequest = new DeleteStoredScriptRequest("x-script"); | ||
|
||
Map<String, String> expectedParams = new HashMap<>(); | ||
setRandomTimeout(deleteStoredScriptRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@javanna I guess you mean some value
like this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes ;)
* master: Add get stored script and delete stored script to high level REST API - post backport fix Add get stored script and delete stored script to high level REST API (#31355) Core: Combine Action and GenericAction (#31405) Fix reference to XContentBuilder.string() (#31337) Avoid sending duplicate remote failed shard requests (#31313) Fix defaults in GeoShapeFieldMapper output (#31302) RestAPI: Reject forcemerge requests with a body (#30792) Packaging: Remove windows bin files from the tar distribution (#30596) Docs: Use the default distribution to test docs (#31251) [DOCS] Adds testing for security APIs (#31345) Clarify that IP range data can be specified in CIDR notation. (#31374) Use system context for cluster state update tasks (#31241) Percentile/Ranks should return null instead of NaN when empty (#30460) REST high-level client: add validate query API (#31077) Move language analyzers from server to analysis-common module. (#31300) [Test] Fix :example-plugins:rest-handler on Windows Expose lucene's RemoveDuplicatesTokenFilter (#31275) Reload secure settings for plugins (#31383) Remove some cases in FieldTypeLookupTests that are no longer relevant. (#31381) Ensure we don't use a remote profile if cluster name matches (#31331) [TEST] Double write alias fault (#30942) [DOCS] Fix version in SQL JDBC Maven template [DOCS] Improve install and setup section for SQL JDBC SQL: Fix rest endpoint names in node stats (#31371) Support for remote path in reindex api - post backport fix Closes #22913 [ML] Put ML filter API response should contain the filter (#31362) Support for remote path in reindex api (#31290) Add byte array pooling to nio http transport (#31349) Remove trial status info from start trial doc (#31365) [DOCS] Adds links to release notes and highlights add is-write-index flag to aliases (#30942) Add rollover-creation-date setting to rolled over index (#31144) [ML] Hold ML filter items in sorted set (#31338) [Tests] Fix edge case in ScriptedMetricAggregatorTests (#31357)
Add get stored script and delete stored script to High Level REST API Client
Relates to #27205