Add get stored script and delete stored script to high level REST API#31355
Conversation
|
Pinging @elastic/es-core-infra |
javanna
left a comment
There was a problem hiding this comment.
left some comments, thanks @vladimirdolzhenko
| } | ||
|
|
||
| static Request getStoredScript(GetStoredScriptRequest getStoredScriptRequest) { | ||
| String endpoint = new EndpointBuilder().addPathPart("_scripts").addPathPart(getStoredScriptRequest.id()).build(); |
There was a problem hiding this comment.
the first one should be addPathPartAsIs
| } | ||
|
|
||
| static Request deleteStoredScript(DeleteStoredScriptRequest deleteStoredScriptRequest) { | ||
| String endpoint = new EndpointBuilder().addPathPart("_scripts").addPathPart(deleteStoredScriptRequest.id()).build(); |
There was a problem hiding this comment.
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.
the SPEC have get_script, can we call these methods getScript ?
There was a problem hiding this comment.
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.
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.
no need to create a new map right? you can just assert that parameters is empty.
| include::tasks/list_tasks.asciidoc[] | ||
| include::tasks/cancel_tasks.asciidoc[] | ||
|
|
||
| == Scripts |
There was a problem hiding this comment.
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.
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.
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.
I think you can make the response a StatusToXContentObject and then use RestStatusToXContentListener here.
There was a problem hiding this comment.
StatusToXContentObject starts to conflict with ToXContentFragment
There was a problem hiding this comment.
and RestStatusToXContentListener does not work with fragment - RestGetStoredScriptAction as well adds id into response
There was a problem hiding this comment.
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.
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.
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.
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.
|
|
||
| private StoredScriptSource scriptSource() { | ||
| return new StoredScriptSource("lang", "code", | ||
| Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); |
There was a problem hiding this comment.
can we randomize how this instance gets created?
|
one more thing @vladimirdolzhenko the docs don't seem to build, can you check that please? |
…i-spec; cleaned RestGetStoredScriptAction up and GetStoredScriptResponse.toXContent
javanna
left a comment
There was a problem hiding this comment.
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.
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.
is it worth expanding on how to interact with StoredScriptSource?
| ["source","java",subs="attributes,callouts,macros"] | ||
| -------------------------------------------------- | ||
| include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[delete-stored-script-execute] | ||
| -------------------------------------------------- |
There was a problem hiding this comment.
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.
remove stored from all methods names?
| include::tasks/list_tasks.asciidoc[] | ||
| include::tasks/cancel_tasks.asciidoc[] | ||
|
|
||
| == Scripts |
There was a problem hiding this comment.
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.
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.
| source.toXContent(builder, params); | ||
| builder.startObject(); | ||
|
|
||
| builder.field(_ID_PARSE_FIELD, id); |
There was a problem hiding this comment.
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.
nope, actually RestGetStoredScriptAction adds that _id manually (out of GetStoredScriptRequest.toXContent)
There was a problem hiding this comment.
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.
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.
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.
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.
thanks for checking, that is fine then
| } | ||
|
|
||
| GetStoredScriptResponse(StoredScriptSource source) { | ||
| GetStoredScriptResponse(String id) { |
There was a problem hiding this comment.
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); | ||
| } |
| return s -> "script.options".equals(s); | ||
| } | ||
|
|
||
| private StoredScriptSource scriptSource() { |
There was a problem hiding this comment.
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 ? |
javanna
left a comment
There was a problem hiding this comment.
thanks @vladimirdolzhenko I left a couple of things but LGTM, feel free to push once those are addressed.
| 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.
also set them to some value?
| 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.
I thought that you wanted to set the id in both cases and that the else block should become new GetStoredScriptResponse(id, null)
| } | ||
| if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { | ||
| out.writeString(id); | ||
| out.writeOptionalString(id); |
There was a problem hiding this comment.
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.
| 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.
can you also add this to the SPEC if it's supported?
| 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.
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.
@javanna I guess you mean some value like this
* 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