From fae58be6db3e851011e2d10a1744bddad5085edf Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Thu, 14 Jun 2018 19:23:57 +0200 Subject: [PATCH 1/6] get and delete stored script high level REST API Relates to #27205 --- .../client/RequestConverters.java | 14 ++ .../client/RestHighLevelClient.java | 60 ++++++ .../client/RequestConvertersTests.java | 11 + .../elasticsearch/client/StoredScriptsIT.java | 102 +++++++++ .../StoredScriptsDocumentationIT.java | 194 ++++++++++++++++++ .../high-level/scripts/delete_script.asciidoc | 64 ++++++ .../high-level/scripts/get_script.asciidoc | 64 ++++++ .../high-level/supported-apis.asciidoc | 10 + .../DeleteStoredScriptResponse.java | 5 + .../GetStoredScriptResponse.java | 57 ++++- .../cluster/RestGetStoredScriptAction.java | 14 +- .../script/StoredScriptSource.java | 6 +- .../DeleteStoredScriptResponseTests.java | 46 +++++ .../GetStoredScriptResponseTests.java | 56 +++++ 14 files changed, 686 insertions(+), 17 deletions(-) create mode 100644 client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java create mode 100644 client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java create mode 100644 docs/java-rest/high-level/scripts/delete_script.asciidoc create mode 100644 docs/java-rest/high-level/scripts/get_script.asciidoc create mode 100644 server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponseTests.java create mode 100644 server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponseTests.java diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java index 93bf6a1a19881..a3c69e98b6cc1 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java @@ -37,6 +37,8 @@ import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest; import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; +import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest; +import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest; import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest; @@ -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(); + Request request = new Request(HttpGet.METHOD_NAME, endpoint); + return request; + } + + static Request deleteStoredScript(DeleteStoredScriptRequest deleteStoredScriptRequest) { + String endpoint = new EndpointBuilder().addPathPart("_scripts").addPathPart(deleteStoredScriptRequest.id()).build(); + Request request = new Request(HttpDelete.METHOD_NAME, endpoint); + return request; + } + private static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) throws IOException { BytesRef source = XContentHelper.toXContent(toXContent, xContentType, false).toBytesRef(); return new ByteArrayEntity(source.bytes, source.offset, source.length, createContentType(xContentType)); diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java index 536b85925a4ba..5c6cc90afbfc8 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java @@ -26,6 +26,10 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionRequestValidationException; +import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest; +import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptResponse; +import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest; +import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.delete.DeleteRequest; @@ -652,6 +656,62 @@ public final FieldCapabilitiesResponse fieldCaps(FieldCapabilitiesRequest fieldC FieldCapabilitiesResponse::fromXContent, emptySet()); } + /** + * Get stored script by id. + * See + * How to use scripts on elastic.co + * @param request the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @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 { + return performRequestAndParseEntity(request, RequestConverters::getStoredScript, options, + GetStoredScriptResponse::fromXContent, emptySet()); + } + + /** + * Asynchronously get stored script by id. + * See + * How to use scripts on elastic.co + * @param request the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @param listener the listener to be notified upon request completion + */ + public void getStoredScriptAsync(GetStoredScriptRequest request, RequestOptions options, + ActionListener listener) { + performRequestAsyncAndParseEntity(request, RequestConverters::getStoredScript, options, + GetStoredScriptResponse::fromXContent, listener, emptySet()); + } + + /** + * Delete stored script by id. + * See + * How to use scripts on elastic.co + * @param request the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @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 { + return performRequestAndParseEntity(request, RequestConverters::deleteStoredScript, options, + DeleteStoredScriptResponse::fromXContent, emptySet()); + } + + /** + * Asynchronously delete stored script by id. + * See + * How to use scripts on elastic.co + * @param request the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @param listener the listener to be notified upon request completion + */ + public void deleteStoredScriptAsync(DeleteStoredScriptRequest request, RequestOptions options, + ActionListener listener) { + performRequestAsyncAndParseEntity(request, RequestConverters::deleteStoredScript, options, + DeleteStoredScriptResponse::fromXContent, listener, emptySet()); + } + /** * Asynchronously executes a request using the Field Capabilities API. * See Field Capabilities API diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java index aa8221f30991e..39cfea7dc7c84 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java @@ -37,6 +37,7 @@ import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest; import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; +import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest; import org.elasticsearch.action.admin.indices.alias.Alias; import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions; @@ -1913,6 +1914,16 @@ public void testGetTemplateRequest() throws Exception { assertThat(request.getEntity(), nullValue()); } + public void testGetStoredScriptRequest() { + GetStoredScriptRequest storedScriptRequest = new GetStoredScriptRequest("x-script"); + Map expectedParams = new HashMap<>(); + + Request request = RequestConverters.getStoredScript(storedScriptRequest); + assertThat(request.getEndpoint(), equalTo("/_scripts/" + storedScriptRequest.id())); + assertThat(request.getParameters(), equalTo(expectedParams)); + assertThat(request.getEntity(), nullValue()); + } + private static void assertToXContentBody(ToXContent expectedBody, HttpEntity actualEntity) throws IOException { BytesReference expectedBytes = XContentHelper.toXContent(expectedBody, REQUEST_BODY_CONTENT_TYPE, false); assertEquals(XContentType.JSON.mediaTypeWithoutParameters(), actualEntity.getContentType().getValue()); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java new file mode 100644 index 0000000000000..28ade1e8b1d77 --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java @@ -0,0 +1,102 @@ +package org.elasticsearch.client;/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.util.EntityUtils; +import org.elasticsearch.ElasticsearchStatusException; +import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest; +import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptResponse; +import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest; +import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.rest.RestStatus; +import org.elasticsearch.script.Script; +import org.elasticsearch.script.StoredScriptSource; + +import java.util.Collections; + +import static java.util.Collections.emptyMap; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.hamcrest.Matchers.equalTo; + +public class StoredScriptsIT extends ESRestHighLevelClientTestCase { + + final String id = "calculate-score"; + + public void testGetStoredScript() throws Exception { + final StoredScriptSource scriptSource = + new StoredScriptSource("painless", + "Math.log(_score * 2) + params.my_modifier", + Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); + + final String script = Strings.toString(scriptSource.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)); + // TODO: change to HighLevel PutStoredScriptRequest when it will be ready + // so far - using low-level REST API + Response putResponse = + adminClient() + .performRequest("PUT", "/_scripts/calculate-score", emptyMap(), + new StringEntity("{\"script\":" + script + "}", + ContentType.APPLICATION_JSON)); + assertEquals(putResponse.getStatusLine().getReasonPhrase(), 200, putResponse.getStatusLine().getStatusCode()); + assertEquals("{\"acknowledged\":true}", EntityUtils.toString(putResponse.getEntity())); + + GetStoredScriptRequest getRequest = new GetStoredScriptRequest("calculate-score"); + + GetStoredScriptResponse getResponse = execute(getRequest, highLevelClient()::getStoredScript, + highLevelClient()::getStoredScriptAsync); + + assertThat(getResponse.getSource(), equalTo(scriptSource)); + } + + public void testDeleteStoredScript() throws Exception { + final StoredScriptSource scriptSource = + new StoredScriptSource("painless", + "Math.log(_score * 2) + params.my_modifier", + Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); + + final String script = Strings.toString(scriptSource.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)); + // TODO: change to HighLevel PutStoredScriptRequest when it will be ready + // so far - using low-level REST API + Response putResponse = + adminClient() + .performRequest("PUT", "/_scripts/" + id, emptyMap(), + new StringEntity("{\"script\":" + script + "}", + ContentType.APPLICATION_JSON)); + assertEquals(putResponse.getStatusLine().getReasonPhrase(), 200, putResponse.getStatusLine().getStatusCode()); + assertEquals("{\"acknowledged\":true}", EntityUtils.toString(putResponse.getEntity())); + + DeleteStoredScriptRequest deleteRequest = new DeleteStoredScriptRequest(id); + + DeleteStoredScriptResponse deleteResponse = execute(deleteRequest, highLevelClient()::deleteStoredScript, + highLevelClient()::deleteStoredScriptAsync); + + assertThat(deleteResponse.isAcknowledged(), equalTo(true)); + + GetStoredScriptRequest getRequest = new GetStoredScriptRequest(id); + + final ElasticsearchStatusException statusException = expectThrows(ElasticsearchStatusException.class, + () -> execute(getRequest, highLevelClient()::getStoredScript, + highLevelClient()::getStoredScriptAsync)); + assertThat(statusException.status(), equalTo(RestStatus.NOT_FOUND)); + } +} diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java new file mode 100644 index 0000000000000..f24e60ad6420f --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java @@ -0,0 +1,194 @@ +package org.elasticsearch.client.documentation;/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.util.EntityUtils; +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.LatchedActionListener; +import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest; +import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptResponse; +import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest; +import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse; +import org.elasticsearch.client.ESRestHighLevelClientTestCase; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.RestHighLevelClient; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.script.Script; +import org.elasticsearch.script.StoredScriptSource; + +import java.io.IOException; +import java.util.Collections; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import static java.util.Collections.emptyMap; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.notNullValue; + + +/** + * This class is used to generate the Java Stored Scripts API documentation. + * You need to wrap your code between two tags like: + * // tag::example + * // end::example + * + * Where example is your tag name. + * + * Then in the documentation, you can extract what is between tag and end tags with + * ["source","java",subs="attributes,callouts,macros"] + * -------------------------------------------------- + * include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[example] + * -------------------------------------------------- + * + * The column width of the code block is 84. If the code contains a line longer + * than 84, the line will be cut and a horizontal scroll bar will be displayed. + * (the code indentation of the tag is not included in the width) + */ +public class StoredScriptsDocumentationIT extends ESRestHighLevelClientTestCase { + + public void testGetStoredScript() throws Exception { + RestHighLevelClient client = highLevelClient(); + + final StoredScriptSource scriptSource = + new StoredScriptSource("painless", + "Math.log(_score * 2) + params.my_modifier", + Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); + + putStoredScript("calculate-score", scriptSource); + + { + // tag::get-stored-script-request + GetStoredScriptRequest request = new GetStoredScriptRequest("calculate-score"); // <1> + // end::get-stored-script-request + + // tag::get-stored-script-execute + final GetStoredScriptResponse getResponse = client.getStoredScript(request, RequestOptions.DEFAULT); + // end::get-stored-script-execute + + // tag::get-stored-script-response + final StoredScriptSource source = getResponse.getSource(); // <1> + // end::get-stored-script-response + + assertThat(source, equalTo(scriptSource)); + + AtomicReference getResponseRef = new AtomicReference<>(); + // tag::get-stored-script-execute-listener + ActionListener listener = + new ActionListener() { + @Override + public void onResponse(GetStoredScriptResponse response) { + getResponseRef.set(response); // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }; + // end::get-stored-script-execute-listener + + // Replace the empty listener by a blocking listener in test + final CountDownLatch latch = new CountDownLatch(1); + listener = new LatchedActionListener<>(listener, latch); + + // tag::get-stored-script-execute-async + client.getStoredScriptAsync(request, RequestOptions.DEFAULT, listener); // <1> + // end::get-stored-script-execute-async + + assertTrue(latch.await(30L, TimeUnit.SECONDS)); + assertThat(getResponseRef.get(), notNullValue()); + assertThat(getResponseRef.get().getSource(), equalTo(scriptSource)); + } + + } + + public void testDeleteStoredScript() throws Exception { + RestHighLevelClient client = highLevelClient(); + + final StoredScriptSource scriptSource = + new StoredScriptSource("painless", + "Math.log(_score * 2) + params.my_modifier", + Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); + + putStoredScript("calculate-score", scriptSource); + + // tag::delete-stored-script-request + DeleteStoredScriptRequest deleteRequest = new DeleteStoredScriptRequest("calculate-score"); // <1> + // end::delete-stored-script-request + + // tag::delete-stored-script-execute + final DeleteStoredScriptResponse deleteResponse = client.deleteStoredScript(deleteRequest, RequestOptions.DEFAULT); + // end::delete-stored-script-execute + + // tag::delete-stored-script-response + assertThat(deleteResponse.isAcknowledged(), equalTo(true)); + // end::delete-stored-script-response + + putStoredScript("calculate-score", scriptSource); + + final AtomicReference deleteResponseRef = new AtomicReference<>(); + // tag::delete-stored-script-execute-listener + ActionListener listener = + new ActionListener() { + @Override + public void onResponse(DeleteStoredScriptResponse response) { + deleteResponseRef.set(response);// <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }; + // end::delete-stored-script-execute-listener + + // Replace the empty listener by a blocking listener in test + final CountDownLatch latch = new CountDownLatch(1); + listener = new LatchedActionListener<>(listener, latch); + + // tag::delete-stored-script-execute-async + client.deleteStoredScriptAsync(deleteRequest, RequestOptions.DEFAULT, listener); // <1> + // end::delete-stored-script-execute-async + + assertTrue(latch.await(30L, TimeUnit.SECONDS)); + assertThat(deleteResponseRef.get(), notNullValue()); + assertThat(deleteResponseRef.get().isAcknowledged(), equalTo(true)); + + + } + + private void putStoredScript(String id, StoredScriptSource scriptSource) throws IOException { + final String script = Strings.toString(scriptSource.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS)); + // TODO: change to HighLevel PutStoredScriptRequest when it will be ready + // so far - using low-level REST API + Response putResponse = + adminClient() + .performRequest("PUT", "/_scripts/" + id, emptyMap(), + new StringEntity("{\"script\":" + script + "}", + ContentType.APPLICATION_JSON)); + assertEquals(putResponse.getStatusLine().getReasonPhrase(), 200, putResponse.getStatusLine().getStatusCode()); + assertEquals("{\"acknowledged\":true}", EntityUtils.toString(putResponse.getEntity())); + } +} diff --git a/docs/java-rest/high-level/scripts/delete_script.asciidoc b/docs/java-rest/high-level/scripts/delete_script.asciidoc new file mode 100644 index 0000000000000..e949d502c8756 --- /dev/null +++ b/docs/java-rest/high-level/scripts/delete_script.asciidoc @@ -0,0 +1,64 @@ +[[java-rest-high-delete-stored-script]] + +=== Delete Stored Script API + +[[java-rest-high-delete-stored-script-request]] +==== Delete Stored Script Request + +A `DeleteStoredScriptRequest` requires an `id`: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[delete-stored-script-request] +-------------------------------------------------- +<1> The id of the script + +[[java-rest-high-delete-stored-script-sync]] +==== Synchronous Execution +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[delete-stored-script-execute] +-------------------------------------------------- + +[[java-rest-high-delete-stored-script-async]] +==== Asynchronous Execution + +The asynchronous execution of a delete stored script request requires both the `DeleteStoredScriptRequest` +instance and an `ActionListener` instance to be passed to the asynchronous method: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[put-stored-script-execute-async] +-------------------------------------------------- +<1> The `DeleteStoredScriptRequest` to execute and the `ActionListener` to use when +the execution completes + +[[java-rest-high-delete-stored-script-listener]] +===== Action Listener + +The asynchronous method does not block and returns immediately. Once it is +completed the `ActionListener` is called back using the `onResponse` method +if the execution successfully completed or using the `onFailure` method if +it failed. + +A typical listener for `DeleteStoredScriptResponse` looks like: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[delete-stored-script-execute-listener] +-------------------------------------------------- +<1> Called when the execution is successfully completed. The response is +provided as an argument +<2> Called in case of failure. The raised exception is provided as an argument + +[[java-rest-high-delete-stored-script-response]] +==== Delete Stored Script Response + +The returned `DeleteStoredScriptResponse` allows to retrieve information about the +executed operation as follows: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[`] +-------------------------------------------------- +<1> Indicates whether all of the nodes have acknowledged the request \ No newline at end of file diff --git a/docs/java-rest/high-level/scripts/get_script.asciidoc b/docs/java-rest/high-level/scripts/get_script.asciidoc new file mode 100644 index 0000000000000..b9033a95d0b37 --- /dev/null +++ b/docs/java-rest/high-level/scripts/get_script.asciidoc @@ -0,0 +1,64 @@ +[[java-rest-high-get-stored-script]] + +=== Get Stored Script API + +[[java-rest-high-get-stored-script-request]] +==== Get Stored Script Request + +A `GetStoredScriptRequest` requires an `id`: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[get-stored-script-request] +-------------------------------------------------- +<1> The id of the script + +[[java-rest-high-get-stored-script-sync]] +==== Synchronous Execution +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[get-stored-script-execute] +-------------------------------------------------- + +[[java-rest-high-get-stored-script-async]] +==== Asynchronous Execution + +The asynchronous execution of a get stored script request requires both the `GetStoredScriptRequest` +instance and an `ActionListener` instance to be passed to the asynchronous method: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[put-stored-script-execute-async] +-------------------------------------------------- +<1> The `GetStoredScriptRequest` to execute and the `ActionListener` to use when +the execution completes + +[[java-rest-high-get-stored-script-listener]] +===== Action Listener + +The asynchronous method does not block and returns immediately. Once it is +completed the `ActionListener` is called back using the `onResponse` method +if the execution successfully completed or using the `onFailure` method if +it failed. + +A typical listener for `GetStoredScriptResponse` looks like: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[get-stored-script-execute-listener] +-------------------------------------------------- +<1> Called when the execution is successfully completed. The response is +provided as an argument +<2> Called in case of failure. The raised exception is provided as an argument + +[[java-rest-high-get-stored-script-response]] +==== Get Stored Script Response + +The returned `GetStoredScriptResponse` allows to retrieve information about the +executed operation as follows: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[get-stored-script-response] +-------------------------------------------------- +<1> The content of the script \ No newline at end of file diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index b33c2421b06d3..d259b42192b08 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -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 + +The Java High Level REST Client supports the following Scripts APIs: +* <> +* <> + +include::scripts/get_script.asciidoc[] +include::scripts/delete_script.asciidoc[] + diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponse.java index 42f08ae73e06d..741c105866f46 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponse.java @@ -20,6 +20,7 @@ package org.elasticsearch.action.admin.cluster.storedscripts; import org.elasticsearch.action.support.master.AcknowledgedResponse; +import org.elasticsearch.common.xcontent.XContentParser; public class DeleteStoredScriptResponse extends AcknowledgedResponse { @@ -29,4 +30,8 @@ public class DeleteStoredScriptResponse extends AcknowledgedResponse { public DeleteStoredScriptResponse(boolean acknowledged) { super(acknowledged); } + + public static DeleteStoredScriptResponse fromXContent(XContentParser parser) { + return new DeleteStoredScriptResponse(parseAcknowledged(parser)); + } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java index a394fe17f217f..8ce15597e75e0 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java @@ -21,16 +21,42 @@ import org.elasticsearch.Version; import org.elasticsearch.action.ActionResponse; +import org.elasticsearch.common.ParseField; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ObjectParser; import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.script.StoredScriptSource; import java.io.IOException; +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg; + public class GetStoredScriptResponse extends ActionResponse implements ToXContentObject { + public static final ParseField FOUND_PARSE_FIELD = new ParseField("found"); + public static final ParseField SCRIPT = new ParseField("script"); + + private static final ConstructingObjectParser PARSER = + new ConstructingObjectParser<>("GetStoredScriptResponse", + true, + (a, c) -> { + boolean found = (Boolean)a[0]; + StoredScriptSource scriptSource = (StoredScriptSource)a[1]; + return found ? new GetStoredScriptResponse(scriptSource) : new GetStoredScriptResponse(); + }); + + static { + PARSER.declareField(constructorArg(), (p, c) -> p.booleanValue(), + FOUND_PARSE_FIELD, ObjectParser.ValueType.BOOLEAN); + PARSER.declareField(optionalConstructorArg(), (p, c) -> StoredScriptSource.fromXContent(p, true), + SCRIPT, ObjectParser.ValueType.OBJECT); + } + private StoredScriptSource source; GetStoredScriptResponse() { @@ -48,12 +74,24 @@ public StoredScriptSource getSource() { } @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - source.toXContent(builder, params); + public boolean isFragment() { + return true; + } + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.field(FOUND_PARSE_FIELD.getPreferredName(), source != null); + if (source != null) { + builder.field(StoredScriptSource.SCRIPT_PARSE_FIELD.getPreferredName()); + source.toXContent(builder, params); + } return builder; } + public static GetStoredScriptResponse fromXContent(XContentParser parser) throws IOException { + return PARSER.parse(parser, null); + } + @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); @@ -85,4 +123,19 @@ public void writeTo(StreamOutput out) throws IOException { } } } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + GetStoredScriptResponse that = (GetStoredScriptResponse) o; + + return source != null ? source.equals(that.source) : that.source == null; + } + + @Override + public int hashCode() { + return source != null ? source.hashCode() : 0; + } } diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java index 10050dda88235..56edd0f75f4b9 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java @@ -40,7 +40,6 @@ public class RestGetStoredScriptAction extends BaseRestHandler { public static final ParseField _ID_PARSE_FIELD = new ParseField("_id"); - public static final ParseField FOUND_PARSE_FIELD = new ParseField("found"); public RestGetStoredScriptAction(Settings settings, RestController controller) { super(settings); @@ -66,19 +65,8 @@ public RestResponse buildResponse(GetStoredScriptResponse response, XContentBuil StoredScriptSource source = response.getSource(); boolean found = source != null; - builder.field(FOUND_PARSE_FIELD.getPreferredName(), found); - if (found) { - builder.startObject(StoredScriptSource.SCRIPT_PARSE_FIELD.getPreferredName()); - builder.field(StoredScriptSource.LANG_PARSE_FIELD.getPreferredName(), source.getLang()); - builder.field(StoredScriptSource.SOURCE_PARSE_FIELD.getPreferredName(), source.getSource()); - - if (source.getOptions().isEmpty() == false) { - builder.field(StoredScriptSource.OPTIONS_PARSE_FIELD.getPreferredName(), source.getOptions()); - } - - builder.endObject(); - } + response.toXContent(builder, channel.request()); builder.endObject(); diff --git a/server/src/main/java/org/elasticsearch/script/StoredScriptSource.java b/server/src/main/java/org/elasticsearch/script/StoredScriptSource.java index 11f8769c86b1f..885d72bdec6f5 100644 --- a/server/src/main/java/org/elasticsearch/script/StoredScriptSource.java +++ b/server/src/main/java/org/elasticsearch/script/StoredScriptSource.java @@ -185,7 +185,7 @@ private StoredScriptSource build(boolean ignoreEmpty) { } } - private static final ObjectParser PARSER = new ObjectParser<>("stored script source", Builder::new); + private static final ObjectParser PARSER = new ObjectParser<>("stored script source", true, Builder::new); static { // Defines the fields necessary to parse a Script as XContent using an ObjectParser. @@ -481,7 +481,9 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.startObject(); builder.field(LANG_PARSE_FIELD.getPreferredName(), lang); builder.field(SOURCE_PARSE_FIELD.getPreferredName(), source); - builder.field(OPTIONS_PARSE_FIELD.getPreferredName(), options); + if (options.isEmpty() == false) { + builder.field(OPTIONS_PARSE_FIELD.getPreferredName(), options); + } builder.endObject(); return builder; diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponseTests.java new file mode 100644 index 0000000000000..375a672263060 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/DeleteStoredScriptResponseTests.java @@ -0,0 +1,46 @@ +package org.elasticsearch.action.admin.cluster.storedscripts;/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractStreamableXContentTestCase; + +import java.io.IOException; + +public class DeleteStoredScriptResponseTests extends AbstractStreamableXContentTestCase { + + @Override + protected DeleteStoredScriptResponse doParseInstance(XContentParser parser) throws IOException { + return DeleteStoredScriptResponse.fromXContent(parser); + } + + @Override + protected DeleteStoredScriptResponse createBlankInstance() { + return new DeleteStoredScriptResponse(); + } + + @Override + protected DeleteStoredScriptResponse createTestInstance() { + return new DeleteStoredScriptResponse(randomBoolean()); + } + + @Override + protected DeleteStoredScriptResponse mutateInstance(DeleteStoredScriptResponse instance) throws IOException { + return new DeleteStoredScriptResponse(instance.isAcknowledged() == false); + } +} diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponseTests.java new file mode 100644 index 0000000000000..eb26f5562b566 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponseTests.java @@ -0,0 +1,56 @@ +package org.elasticsearch.action.admin.cluster.storedscripts;/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.script.Script; +import org.elasticsearch.script.StoredScriptSource; +import org.elasticsearch.test.AbstractStreamableXContentTestCase; + +import java.io.IOException; +import java.util.Collections; +import java.util.function.Predicate; + +public class GetStoredScriptResponseTests extends AbstractStreamableXContentTestCase { + + @Override + protected GetStoredScriptResponse doParseInstance(XContentParser parser) throws IOException { + return GetStoredScriptResponse.fromXContent(parser); + } + + @Override + protected GetStoredScriptResponse createBlankInstance() { + return new GetStoredScriptResponse(); + } + + @Override + protected GetStoredScriptResponse createTestInstance() { + return new GetStoredScriptResponse(scriptSource()); + } + + @Override + protected Predicate getRandomFieldsExcludeFilter() { + return s -> "script.options".equals(s); + } + + private StoredScriptSource scriptSource() { + return new StoredScriptSource("lang", "code", + Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); + } +} From e8ded37657d217a2db0d690c3df971dc9f84edbc Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Fri, 15 Jun 2018 21:52:18 +0200 Subject: [PATCH 2/6] fixed broken tags in docs; REST api method names aligned with rest-api-spec; cleaned RestGetStoredScriptAction up and GetStoredScriptResponse.toXContent --- .../client/RequestConverters.java | 8 +-- .../client/RestHighLevelClient.java | 8 +-- .../client/RequestConvertersTests.java | 19 +++++-- .../StoredScriptsDocumentationIT.java | 17 +----- .../{scripts => }/delete_script.asciidoc | 4 +- .../{scripts => }/get_script.asciidoc | 2 +- .../high-level/supported-apis.asciidoc | 5 +- .../common/xcontent/XContentBuilder.java | 17 ++++++ .../GetStoredScriptResponse.java | 55 ++++++++++++++----- .../TransportGetStoredScriptAction.java | 2 +- .../cluster/RestGetStoredScriptAction.java | 28 +--------- .../GetStoredScriptResponseTests.java | 11 +++- .../common/xcontent/BaseXContentTestCase.java | 2 +- 13 files changed, 102 insertions(+), 76 deletions(-) rename docs/java-rest/high-level/{scripts => }/delete_script.asciidoc (93%) rename docs/java-rest/high-level/{scripts => }/get_script.asciidoc (97%) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java index a3c69e98b6cc1..0d75f4833bd94 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java @@ -879,14 +879,14 @@ static Request getTemplates(GetIndexTemplatesRequest getIndexTemplatesRequest) t return request; } - static Request getStoredScript(GetStoredScriptRequest getStoredScriptRequest) { - String endpoint = new EndpointBuilder().addPathPart("_scripts").addPathPart(getStoredScriptRequest.id()).build(); + static Request getScript(GetStoredScriptRequest getStoredScriptRequest) { + String endpoint = new EndpointBuilder().addPathPartAsIs("_scripts").addPathPart(getStoredScriptRequest.id()).build(); Request request = new Request(HttpGet.METHOD_NAME, endpoint); return request; } - static Request deleteStoredScript(DeleteStoredScriptRequest deleteStoredScriptRequest) { - String endpoint = new EndpointBuilder().addPathPart("_scripts").addPathPart(deleteStoredScriptRequest.id()).build(); + static Request deleteScript(DeleteStoredScriptRequest deleteStoredScriptRequest) { + String endpoint = new EndpointBuilder().addPathPartAsIs("_scripts").addPathPart(deleteStoredScriptRequest.id()).build(); Request request = new Request(HttpDelete.METHOD_NAME, endpoint); return request; } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java index 5c6cc90afbfc8..dd0ab0fe190c1 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java @@ -666,7 +666,7 @@ public final FieldCapabilitiesResponse fieldCaps(FieldCapabilitiesRequest fieldC * @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 { - return performRequestAndParseEntity(request, RequestConverters::getStoredScript, options, + return performRequestAndParseEntity(request, RequestConverters::getScript, options, GetStoredScriptResponse::fromXContent, emptySet()); } @@ -680,7 +680,7 @@ public GetStoredScriptResponse getStoredScript(GetStoredScriptRequest request, R */ public void getStoredScriptAsync(GetStoredScriptRequest request, RequestOptions options, ActionListener listener) { - performRequestAsyncAndParseEntity(request, RequestConverters::getStoredScript, options, + performRequestAsyncAndParseEntity(request, RequestConverters::getScript, options, GetStoredScriptResponse::fromXContent, listener, emptySet()); } @@ -694,7 +694,7 @@ public void getStoredScriptAsync(GetStoredScriptRequest request, RequestOptions * @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 { - return performRequestAndParseEntity(request, RequestConverters::deleteStoredScript, options, + return performRequestAndParseEntity(request, RequestConverters::deleteScript, options, DeleteStoredScriptResponse::fromXContent, emptySet()); } @@ -708,7 +708,7 @@ public DeleteStoredScriptResponse deleteStoredScript(DeleteStoredScriptRequest r */ public void deleteStoredScriptAsync(DeleteStoredScriptRequest request, RequestOptions options, ActionListener listener) { - performRequestAsyncAndParseEntity(request, RequestConverters::deleteStoredScript, options, + performRequestAsyncAndParseEntity(request, RequestConverters::deleteScript, options, DeleteStoredScriptResponse::fromXContent, listener, emptySet()); } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java index 39cfea7dc7c84..17497dc9dd92e 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java @@ -37,6 +37,7 @@ import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest; import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; +import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest; import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest; import org.elasticsearch.action.admin.indices.alias.Alias; import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; @@ -1914,13 +1915,23 @@ public void testGetTemplateRequest() throws Exception { assertThat(request.getEntity(), nullValue()); } - public void testGetStoredScriptRequest() { + public void testGetScriptRequest() { GetStoredScriptRequest storedScriptRequest = new GetStoredScriptRequest("x-script"); - Map expectedParams = new HashMap<>(); - Request request = RequestConverters.getStoredScript(storedScriptRequest); + Request request = RequestConverters.getScript(storedScriptRequest); assertThat(request.getEndpoint(), equalTo("/_scripts/" + storedScriptRequest.id())); - assertThat(request.getParameters(), equalTo(expectedParams)); + assertThat(request.getMethod(), equalTo(HttpGet.METHOD_NAME)); + assertThat(request.getParameters().isEmpty(), equalTo(true)); + assertThat(request.getEntity(), nullValue()); + } + + public void testDeleteScriptRequest() { + DeleteStoredScriptRequest storedScriptRequest = new DeleteStoredScriptRequest("x-script"); + + Request request = RequestConverters.deleteScript(storedScriptRequest); + assertThat(request.getEndpoint(), equalTo("/_scripts/" + storedScriptRequest.id())); + assertThat(request.getMethod(), equalTo(HttpDelete.METHOD_NAME)); + assertThat(request.getParameters().isEmpty(), equalTo(true)); assertThat(request.getEntity(), nullValue()); } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java index f24e60ad6420f..40183ea8c67fc 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java @@ -40,13 +40,10 @@ import java.util.Collections; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; import static java.util.Collections.emptyMap; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.notNullValue; - /** * This class is used to generate the Java Stored Scripts API documentation. @@ -93,13 +90,12 @@ public void testGetStoredScript() throws Exception { assertThat(source, equalTo(scriptSource)); - AtomicReference getResponseRef = new AtomicReference<>(); // tag::get-stored-script-execute-listener ActionListener listener = new ActionListener() { @Override public void onResponse(GetStoredScriptResponse response) { - getResponseRef.set(response); // <1> + // <1> } @Override @@ -118,8 +114,6 @@ public void onFailure(Exception e) { // end::get-stored-script-execute-async assertTrue(latch.await(30L, TimeUnit.SECONDS)); - assertThat(getResponseRef.get(), notNullValue()); - assertThat(getResponseRef.get().getSource(), equalTo(scriptSource)); } } @@ -143,18 +137,17 @@ public void testDeleteStoredScript() throws Exception { // end::delete-stored-script-execute // tag::delete-stored-script-response - assertThat(deleteResponse.isAcknowledged(), equalTo(true)); + assertThat(deleteResponse.isAcknowledged(), equalTo(true)); // <1> // end::delete-stored-script-response putStoredScript("calculate-score", scriptSource); - final AtomicReference deleteResponseRef = new AtomicReference<>(); // tag::delete-stored-script-execute-listener ActionListener listener = new ActionListener() { @Override public void onResponse(DeleteStoredScriptResponse response) { - deleteResponseRef.set(response);// <1> + // <1> } @Override @@ -173,10 +166,6 @@ public void onFailure(Exception e) { // end::delete-stored-script-execute-async assertTrue(latch.await(30L, TimeUnit.SECONDS)); - assertThat(deleteResponseRef.get(), notNullValue()); - assertThat(deleteResponseRef.get().isAcknowledged(), equalTo(true)); - - } private void putStoredScript(String id, StoredScriptSource scriptSource) throws IOException { diff --git a/docs/java-rest/high-level/scripts/delete_script.asciidoc b/docs/java-rest/high-level/delete_script.asciidoc similarity index 93% rename from docs/java-rest/high-level/scripts/delete_script.asciidoc rename to docs/java-rest/high-level/delete_script.asciidoc index e949d502c8756..dca7743c04b12 100644 --- a/docs/java-rest/high-level/scripts/delete_script.asciidoc +++ b/docs/java-rest/high-level/delete_script.asciidoc @@ -28,7 +28,7 @@ instance and an `ActionListener` instance to be passed to the asynchronous metho ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[put-stored-script-execute-async] +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[delete-stored-script-execute-async] -------------------------------------------------- <1> The `DeleteStoredScriptRequest` to execute and the `ActionListener` to use when the execution completes @@ -59,6 +59,6 @@ executed operation as follows: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[`] +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[delete-stored-script-response] -------------------------------------------------- <1> Indicates whether all of the nodes have acknowledged the request \ No newline at end of file diff --git a/docs/java-rest/high-level/scripts/get_script.asciidoc b/docs/java-rest/high-level/get_script.asciidoc similarity index 97% rename from docs/java-rest/high-level/scripts/get_script.asciidoc rename to docs/java-rest/high-level/get_script.asciidoc index b9033a95d0b37..65986f0d817f5 100644 --- a/docs/java-rest/high-level/scripts/get_script.asciidoc +++ b/docs/java-rest/high-level/get_script.asciidoc @@ -28,7 +28,7 @@ instance and an `ActionListener` instance to be passed to the asynchronous metho ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[put-stored-script-execute-async] +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[get-stored-script-execute-async] -------------------------------------------------- <1> The `GetStoredScriptRequest` to execute and the `ActionListener` to use when the execution completes diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index d259b42192b08..2968dd8246060 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -153,9 +153,10 @@ include::tasks/cancel_tasks.asciidoc[] == Scripts The Java High Level REST Client supports the following Scripts APIs: + * <> * <> -include::scripts/get_script.asciidoc[] -include::scripts/delete_script.asciidoc[] +include::get_script.asciidoc[] +include::delete_script.asciidoc[] diff --git a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java index eae5e48a557f3..ef83510b3d36a 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java +++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java @@ -19,6 +19,8 @@ package org.elasticsearch.common.xcontent; +import org.elasticsearch.common.ParseField; + import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.Flushable; @@ -276,6 +278,10 @@ public XContentBuilder endArray() throws IOException { return this; } + public XContentBuilder field(ParseField field) throws IOException { + return field(field.getPreferredName()); + } + public XContentBuilder field(String name) throws IOException { ensureNameNotNull(name); generator.writeFieldName(name); @@ -296,11 +302,18 @@ public XContentBuilder nullValue() throws IOException { //////////////////////////////////////////////////////////////////////////// // Boolean ////////////////////////////////// + public XContentBuilder field(ParseField field, Boolean value) throws IOException { + return field(field.getPreferredName(), value); + } public XContentBuilder field(String name, Boolean value) throws IOException { return (value == null) ? nullField(name) : field(name, value.booleanValue()); } + public XContentBuilder field(ParseField field, boolean value) throws IOException { + return field(field.getPreferredName(), value); + } + public XContentBuilder field(String name, boolean value) throws IOException { ensureNameNotNull(name); generator.writeBooleanField(name, value); @@ -550,6 +563,10 @@ public XContentBuilder value(short value) throws IOException { // String ////////////////////////////////// + public XContentBuilder field(ParseField field, String value) throws IOException { + return field(field.getPreferredName(), value); + } + public XContentBuilder field(String name, String value) throws IOException { if (value == null) { return nullField(name); diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java index 8ce15597e75e0..8fad38556ec9c 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java @@ -26,18 +26,21 @@ import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.ConstructingObjectParser; import org.elasticsearch.common.xcontent.ObjectParser; -import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.StatusToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.rest.RestStatus; import org.elasticsearch.script.StoredScriptSource; import java.io.IOException; +import java.util.Objects; import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg; -public class GetStoredScriptResponse extends ActionResponse implements ToXContentObject { +public class GetStoredScriptResponse extends ActionResponse implements StatusToXContentObject { + public static final ParseField _ID_PARSE_FIELD = new ParseField("_id"); public static final ParseField FOUND_PARSE_FIELD = new ParseField("found"); public static final ParseField SCRIPT = new ParseField("script"); @@ -45,27 +48,40 @@ public class GetStoredScriptResponse extends ActionResponse implements ToXConten new ConstructingObjectParser<>("GetStoredScriptResponse", true, (a, c) -> { - boolean found = (Boolean)a[0]; - StoredScriptSource scriptSource = (StoredScriptSource)a[1]; - return found ? new GetStoredScriptResponse(scriptSource) : new GetStoredScriptResponse(); + String id = (String) a[0]; + boolean found = (Boolean)a[1]; + StoredScriptSource scriptSource = (StoredScriptSource)a[2]; + return found ? new GetStoredScriptResponse(id, scriptSource) : new GetStoredScriptResponse(id); }); static { + PARSER.declareField(constructorArg(), (p, c) -> p.text(), + _ID_PARSE_FIELD, ObjectParser.ValueType.STRING); PARSER.declareField(constructorArg(), (p, c) -> p.booleanValue(), FOUND_PARSE_FIELD, ObjectParser.ValueType.BOOLEAN); PARSER.declareField(optionalConstructorArg(), (p, c) -> StoredScriptSource.fromXContent(p, true), SCRIPT, ObjectParser.ValueType.OBJECT); } + private String id; private StoredScriptSource source; GetStoredScriptResponse() { } - GetStoredScriptResponse(StoredScriptSource source) { + GetStoredScriptResponse(String id) { + this.id = id; + } + + GetStoredScriptResponse(String id, StoredScriptSource source) { + this(id); this.source = source; } + public String getId() { + return id; + } + /** * @return if a stored script and if not found null */ @@ -74,17 +90,22 @@ public StoredScriptSource getSource() { } @Override - public boolean isFragment() { - return true; + public RestStatus status() { + return source != null ? RestStatus.OK : RestStatus.NOT_FOUND; } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.field(FOUND_PARSE_FIELD.getPreferredName(), source != null); + builder.startObject(); + + builder.field(_ID_PARSE_FIELD, id); + builder.field(FOUND_PARSE_FIELD, source != null); if (source != null) { - builder.field(StoredScriptSource.SCRIPT_PARSE_FIELD.getPreferredName()); + builder.field(StoredScriptSource.SCRIPT_PARSE_FIELD); source.toXContent(builder, params); } + + builder.endObject(); return builder; } @@ -105,6 +126,10 @@ public void readFrom(StreamInput in) throws IOException { } else { source = null; } + + if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { + id = in.readString(); + } } @Override @@ -122,20 +147,22 @@ public void writeTo(StreamOutput out) throws IOException { out.writeString(source.getSource()); } } + if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { + out.writeString(id); + } } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - GetStoredScriptResponse that = (GetStoredScriptResponse) o; - - return source != null ? source.equals(that.source) : that.source == null; + return Objects.equals(id, that.id) && + Objects.equals(source, that.source); } @Override public int hashCode() { - return source != null ? source.hashCode() : 0; + return Objects.hash(id, source); } } diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportGetStoredScriptAction.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportGetStoredScriptAction.java index 63f24f31f59bd..368e40b96b7b3 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportGetStoredScriptAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/TransportGetStoredScriptAction.java @@ -60,7 +60,7 @@ protected GetStoredScriptResponse newResponse() { @Override protected void masterOperation(GetStoredScriptRequest request, ClusterState state, ActionListener listener) throws Exception { - listener.onResponse(new GetStoredScriptResponse(scriptService.getStoredScript(state, request))); + listener.onResponse(new GetStoredScriptResponse(request.id(), scriptService.getStoredScript(state, request))); } @Override diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java index 56edd0f75f4b9..79179a9f5275d 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java @@ -19,19 +19,12 @@ package org.elasticsearch.rest.action.admin.cluster; import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest; -import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse; import org.elasticsearch.client.node.NodeClient; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.rest.BaseRestHandler; -import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestRequest; -import org.elasticsearch.rest.RestResponse; -import org.elasticsearch.rest.RestStatus; -import org.elasticsearch.rest.action.RestBuilderListener; -import org.elasticsearch.script.StoredScriptSource; +import org.elasticsearch.rest.action.RestStatusToXContentListener; import java.io.IOException; @@ -39,8 +32,6 @@ public class RestGetStoredScriptAction extends BaseRestHandler { - public static final ParseField _ID_PARSE_FIELD = new ParseField("_id"); - public RestGetStoredScriptAction(Settings settings, RestController controller) { super(settings); @@ -57,21 +48,6 @@ public RestChannelConsumer prepareRequest(final RestRequest request, NodeClient String id = request.param("id"); GetStoredScriptRequest getRequest = new GetStoredScriptRequest(id); - return channel -> client.admin().cluster().getStoredScript(getRequest, new RestBuilderListener(channel) { - @Override - public RestResponse buildResponse(GetStoredScriptResponse response, XContentBuilder builder) throws Exception { - builder.startObject(); - builder.field(_ID_PARSE_FIELD.getPreferredName(), id); - - StoredScriptSource source = response.getSource(); - boolean found = source != null; - - response.toXContent(builder, channel.request()); - - builder.endObject(); - - return new BytesRestResponse(found ? RestStatus.OK : RestStatus.NOT_FOUND, builder); - } - }); + return channel -> client.admin().cluster().getStoredScript(getRequest, new RestStatusToXContentListener<>(channel)); } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponseTests.java index eb26f5562b566..cb0b7fd86e998 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponseTests.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.util.Collections; +import java.util.Map; import java.util.function.Predicate; public class GetStoredScriptResponseTests extends AbstractStreamableXContentTestCase { @@ -41,7 +42,7 @@ protected GetStoredScriptResponse createBlankInstance() { @Override protected GetStoredScriptResponse createTestInstance() { - return new GetStoredScriptResponse(scriptSource()); + return new GetStoredScriptResponse(randomAlphaOfLengthBetween(1, 10), scriptSource()); } @Override @@ -50,7 +51,11 @@ protected Predicate getRandomFieldsExcludeFilter() { } private StoredScriptSource scriptSource() { - return new StoredScriptSource("lang", "code", - Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())); + final String lang = randomFrom("lang", "painless", "mustache"); + final String source = randomAlphaOfLengthBetween(1, 10); + final Map options = randomBoolean() + ? Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType()) + : Collections.emptyMap(); + return new StoredScriptSource(lang, source, options); } } diff --git a/server/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java b/server/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java index 86e55c1ab6a91..b7ca255c48dac 100644 --- a/server/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java +++ b/server/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java @@ -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))); expectUnclosedException(() -> BytesReference.bytes(builder().startObject().field("foo"))); assertResult("{'foo':'bar'}", () -> builder().startObject().field("foo").value("bar").endObject()); From 48af52f47f1a857491cb49d4c171e6bcce8b1a97 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Mon, 18 Jun 2018 18:32:18 +0200 Subject: [PATCH 3/6] added missed timeout doc sections; added missed master-timeout handling at REST level; code style adjustments --- .../client/RequestConverters.java | 5 +++ .../client/RestHighLevelClient.java | 12 +++---- .../elasticsearch/client/StoredScriptsIT.java | 15 ++++---- .../StoredScriptsDocumentationIT.java | 35 +++++++++++++++---- .../{ => script}/delete_script.asciidoc | 17 +++++++++ .../{ => script}/get_script.asciidoc | 15 +++++++- .../high-level/supported-apis.asciidoc | 6 ++-- .../common/xcontent/XContentBuilder.java | 17 --------- .../GetStoredScriptResponse.java | 18 ++++------ .../cluster/RestGetStoredScriptAction.java | 2 +- .../GetStoredScriptResponseTests.java | 4 +-- 11 files changed, 92 insertions(+), 54 deletions(-) rename docs/java-rest/high-level/{ => script}/delete_script.asciidoc (75%) rename docs/java-rest/high-level/{ => script}/get_script.asciidoc (79%) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java index 0d75f4833bd94..8d472a3d438d9 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java @@ -882,12 +882,17 @@ static Request getTemplates(GetIndexTemplatesRequest getIndexTemplatesRequest) t static Request getScript(GetStoredScriptRequest getStoredScriptRequest) { String endpoint = new EndpointBuilder().addPathPartAsIs("_scripts").addPathPart(getStoredScriptRequest.id()).build(); Request request = new Request(HttpGet.METHOD_NAME, endpoint); + Params params = new Params(request); + params.withMasterTimeout(getStoredScriptRequest.masterNodeTimeout()); 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()); return request; } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java index dd0ab0fe190c1..6905cfdb8f714 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java @@ -665,7 +665,7 @@ public final FieldCapabilitiesResponse fieldCaps(FieldCapabilitiesRequest fieldC * @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 { + public GetStoredScriptResponse getScript(GetStoredScriptRequest request, RequestOptions options) throws IOException { return performRequestAndParseEntity(request, RequestConverters::getScript, options, GetStoredScriptResponse::fromXContent, emptySet()); } @@ -678,8 +678,8 @@ public GetStoredScriptResponse getStoredScript(GetStoredScriptRequest request, R * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized * @param listener the listener to be notified upon request completion */ - public void getStoredScriptAsync(GetStoredScriptRequest request, RequestOptions options, - ActionListener listener) { + public void getScriptAsync(GetStoredScriptRequest request, RequestOptions options, + ActionListener listener) { performRequestAsyncAndParseEntity(request, RequestConverters::getScript, options, GetStoredScriptResponse::fromXContent, listener, emptySet()); } @@ -693,7 +693,7 @@ public void getStoredScriptAsync(GetStoredScriptRequest request, RequestOptions * @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 { + public DeleteStoredScriptResponse deleteScript(DeleteStoredScriptRequest request, RequestOptions options) throws IOException { return performRequestAndParseEntity(request, RequestConverters::deleteScript, options, DeleteStoredScriptResponse::fromXContent, emptySet()); } @@ -706,8 +706,8 @@ public DeleteStoredScriptResponse deleteStoredScript(DeleteStoredScriptRequest r * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized * @param listener the listener to be notified upon request completion */ - public void deleteStoredScriptAsync(DeleteStoredScriptRequest request, RequestOptions options, - ActionListener listener) { + public void deleteScriptAsync(DeleteStoredScriptRequest request, RequestOptions options, + ActionListener listener) { performRequestAsyncAndParseEntity(request, RequestConverters::deleteScript, options, DeleteStoredScriptResponse::fromXContent, listener, emptySet()); } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java index 28ade1e8b1d77..e6d380a4cc0e1 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/StoredScriptsIT.java @@ -61,9 +61,10 @@ public void testGetStoredScript() throws Exception { assertEquals("{\"acknowledged\":true}", EntityUtils.toString(putResponse.getEntity())); GetStoredScriptRequest getRequest = new GetStoredScriptRequest("calculate-score"); + getRequest.masterNodeTimeout("50s"); - GetStoredScriptResponse getResponse = execute(getRequest, highLevelClient()::getStoredScript, - highLevelClient()::getStoredScriptAsync); + GetStoredScriptResponse getResponse = execute(getRequest, highLevelClient()::getScript, + highLevelClient()::getScriptAsync); assertThat(getResponse.getSource(), equalTo(scriptSource)); } @@ -86,17 +87,19 @@ public void testDeleteStoredScript() throws Exception { assertEquals("{\"acknowledged\":true}", EntityUtils.toString(putResponse.getEntity())); DeleteStoredScriptRequest deleteRequest = new DeleteStoredScriptRequest(id); + deleteRequest.masterNodeTimeout("50s"); + deleteRequest.timeout("50s"); - DeleteStoredScriptResponse deleteResponse = execute(deleteRequest, highLevelClient()::deleteStoredScript, - highLevelClient()::deleteStoredScriptAsync); + DeleteStoredScriptResponse deleteResponse = execute(deleteRequest, highLevelClient()::deleteScript, + highLevelClient()::deleteScriptAsync); assertThat(deleteResponse.isAcknowledged(), equalTo(true)); GetStoredScriptRequest getRequest = new GetStoredScriptRequest(id); final ElasticsearchStatusException statusException = expectThrows(ElasticsearchStatusException.class, - () -> execute(getRequest, highLevelClient()::getStoredScript, - highLevelClient()::getStoredScriptAsync)); + () -> execute(getRequest, highLevelClient()::getScript, + highLevelClient()::getScriptAsync)); assertThat(statusException.status(), equalTo(RestStatus.NOT_FOUND)); } } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java index 40183ea8c67fc..0aadae73ce66d 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/StoredScriptsDocumentationIT.java @@ -31,6 +31,7 @@ import org.elasticsearch.client.Response; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.script.Script; @@ -38,6 +39,7 @@ import java.io.IOException; import java.util.Collections; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -80,15 +82,24 @@ public void testGetStoredScript() throws Exception { GetStoredScriptRequest request = new GetStoredScriptRequest("calculate-score"); // <1> // end::get-stored-script-request + // tag::get-stored-script-request-masterTimeout + request.masterNodeTimeout(TimeValue.timeValueSeconds(50)); // <1> + request.masterNodeTimeout("50s"); // <2> + // end::get-stored-script-request-masterTimeout + // tag::get-stored-script-execute - final GetStoredScriptResponse getResponse = client.getStoredScript(request, RequestOptions.DEFAULT); + GetStoredScriptResponse getResponse = client.getScript(request, RequestOptions.DEFAULT); // end::get-stored-script-execute // tag::get-stored-script-response - final StoredScriptSource source = getResponse.getSource(); // <1> + StoredScriptSource storedScriptSource = getResponse.getSource(); // <1> + + String lang = storedScriptSource.getLang(); // <2> + String source = storedScriptSource.getSource(); // <3> + Map options = storedScriptSource.getOptions(); // <4> // end::get-stored-script-response - assertThat(source, equalTo(scriptSource)); + assertThat(storedScriptSource, equalTo(scriptSource)); // tag::get-stored-script-execute-listener ActionListener listener = @@ -110,7 +121,7 @@ public void onFailure(Exception e) { listener = new LatchedActionListener<>(listener, latch); // tag::get-stored-script-execute-async - client.getStoredScriptAsync(request, RequestOptions.DEFAULT, listener); // <1> + client.getScriptAsync(request, RequestOptions.DEFAULT, listener); // <1> // end::get-stored-script-execute-async assertTrue(latch.await(30L, TimeUnit.SECONDS)); @@ -132,12 +143,22 @@ public void testDeleteStoredScript() throws Exception { DeleteStoredScriptRequest deleteRequest = new DeleteStoredScriptRequest("calculate-score"); // <1> // end::delete-stored-script-request + // tag::delete-stored-script-request-masterTimeout + deleteRequest.masterNodeTimeout(TimeValue.timeValueSeconds(50)); // <1> + deleteRequest.masterNodeTimeout("50s"); // <2> + // end::delete-stored-script-request-masterTimeout + + // tag::delete-stored-script-request-timeout + deleteRequest.timeout(TimeValue.timeValueSeconds(60)); // <1> + deleteRequest.timeout("60s"); // <2> + // end::delete-stored-script-request-timeout + // tag::delete-stored-script-execute - final DeleteStoredScriptResponse deleteResponse = client.deleteStoredScript(deleteRequest, RequestOptions.DEFAULT); + DeleteStoredScriptResponse deleteResponse = client.deleteScript(deleteRequest, RequestOptions.DEFAULT); // end::delete-stored-script-execute // tag::delete-stored-script-response - assertThat(deleteResponse.isAcknowledged(), equalTo(true)); // <1> + boolean acknowledged = deleteResponse.isAcknowledged();// <1> // end::delete-stored-script-response putStoredScript("calculate-score", scriptSource); @@ -162,7 +183,7 @@ public void onFailure(Exception e) { listener = new LatchedActionListener<>(listener, latch); // tag::delete-stored-script-execute-async - client.deleteStoredScriptAsync(deleteRequest, RequestOptions.DEFAULT, listener); // <1> + client.deleteScriptAsync(deleteRequest, RequestOptions.DEFAULT, listener); // <1> // end::delete-stored-script-execute-async assertTrue(latch.await(30L, TimeUnit.SECONDS)); diff --git a/docs/java-rest/high-level/delete_script.asciidoc b/docs/java-rest/high-level/script/delete_script.asciidoc similarity index 75% rename from docs/java-rest/high-level/delete_script.asciidoc rename to docs/java-rest/high-level/script/delete_script.asciidoc index dca7743c04b12..79b3b0b324715 100644 --- a/docs/java-rest/high-level/delete_script.asciidoc +++ b/docs/java-rest/high-level/script/delete_script.asciidoc @@ -13,6 +13,23 @@ include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[delete-stored-scri -------------------------------------------------- <1> The id of the script +==== Optional arguments +The following arguments can optionally be provided: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[delete-stored-script-request-timeout] +-------------------------------------------------- +<1> Timeout to wait for the all the nodes to acknowledge the stored script is deleted as a `TimeValue` +<2> Timeout to wait for the all the nodes to acknowledge the stored script is deleted as a `String` + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[delete-stored-script-request-masterTimeout] +-------------------------------------------------- +<1> Timeout to connect to the master node as a `TimeValue` +<2> Timeout to connect to the master node as a `String` + [[java-rest-high-delete-stored-script-sync]] ==== Synchronous Execution ["source","java",subs="attributes,callouts,macros"] diff --git a/docs/java-rest/high-level/get_script.asciidoc b/docs/java-rest/high-level/script/get_script.asciidoc similarity index 79% rename from docs/java-rest/high-level/get_script.asciidoc rename to docs/java-rest/high-level/script/get_script.asciidoc index 65986f0d817f5..a38bdad2bd6af 100644 --- a/docs/java-rest/high-level/get_script.asciidoc +++ b/docs/java-rest/high-level/script/get_script.asciidoc @@ -13,6 +13,16 @@ include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[get-stored-script- -------------------------------------------------- <1> The id of the script +==== Optional arguments +The following arguments can optionally be provided: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[get-stored-script-request-masterTimeout] +-------------------------------------------------- +<1> Timeout to connect to the master node as a `TimeValue` +<2> Timeout to connect to the master node as a `String` + [[java-rest-high-get-stored-script-sync]] ==== Synchronous Execution ["source","java",subs="attributes,callouts,macros"] @@ -61,4 +71,7 @@ executed operation as follows: -------------------------------------------------- include-tagged::{doc-tests}/StoredScriptsDocumentationIT.java[get-stored-script-response] -------------------------------------------------- -<1> The content of the script \ No newline at end of file +<1> The script object consists of a content and a metadata +<2> The language the script is written in, which defaults to `painless`. +<3> The content of the script +<4> Any named options that should be passed into the script. \ No newline at end of file diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index 2968dd8246060..f5c662a8204ca 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -150,13 +150,13 @@ The Java High Level REST Client supports the following Tasks APIs: include::tasks/list_tasks.asciidoc[] include::tasks/cancel_tasks.asciidoc[] -== Scripts +== Script APIs The Java High Level REST Client supports the following Scripts APIs: * <> * <> -include::get_script.asciidoc[] -include::delete_script.asciidoc[] +include::script/get_script.asciidoc[] +include::script/delete_script.asciidoc[] diff --git a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java index ef83510b3d36a..eae5e48a557f3 100644 --- a/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java +++ b/libs/x-content/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java @@ -19,8 +19,6 @@ package org.elasticsearch.common.xcontent; -import org.elasticsearch.common.ParseField; - import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.Flushable; @@ -278,10 +276,6 @@ public XContentBuilder endArray() throws IOException { return this; } - public XContentBuilder field(ParseField field) throws IOException { - return field(field.getPreferredName()); - } - public XContentBuilder field(String name) throws IOException { ensureNameNotNull(name); generator.writeFieldName(name); @@ -302,18 +296,11 @@ public XContentBuilder nullValue() throws IOException { //////////////////////////////////////////////////////////////////////////// // Boolean ////////////////////////////////// - public XContentBuilder field(ParseField field, Boolean value) throws IOException { - return field(field.getPreferredName(), value); - } public XContentBuilder field(String name, Boolean value) throws IOException { return (value == null) ? nullField(name) : field(name, value.booleanValue()); } - public XContentBuilder field(ParseField field, boolean value) throws IOException { - return field(field.getPreferredName(), value); - } - public XContentBuilder field(String name, boolean value) throws IOException { ensureNameNotNull(name); generator.writeBooleanField(name, value); @@ -563,10 +550,6 @@ public XContentBuilder value(short value) throws IOException { // String ////////////////////////////////// - public XContentBuilder field(ParseField field, String value) throws IOException { - return field(field.getPreferredName(), value); - } - public XContentBuilder field(String name, String value) throws IOException { if (value == null) { return nullField(name); diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java index 8fad38556ec9c..e27fa0a69b971 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java @@ -51,7 +51,7 @@ public class GetStoredScriptResponse extends ActionResponse implements StatusToX 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(); }); static { @@ -69,12 +69,8 @@ public class GetStoredScriptResponse extends ActionResponse implements StatusToX GetStoredScriptResponse() { } - GetStoredScriptResponse(String id) { - this.id = id; - } - GetStoredScriptResponse(String id, StoredScriptSource source) { - this(id); + this.id = id; this.source = source; } @@ -98,10 +94,10 @@ public RestStatus status() { public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); - builder.field(_ID_PARSE_FIELD, id); - builder.field(FOUND_PARSE_FIELD, source != null); + builder.field(_ID_PARSE_FIELD.getPreferredName(), id); + builder.field(FOUND_PARSE_FIELD.getPreferredName(), source != null); if (source != null) { - builder.field(StoredScriptSource.SCRIPT_PARSE_FIELD); + builder.field(StoredScriptSource.SCRIPT_PARSE_FIELD.getPreferredName()); source.toXContent(builder, params); } @@ -128,7 +124,7 @@ public void readFrom(StreamInput in) throws IOException { } if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { - id = in.readString(); + id = in.readOptionalString(); } } @@ -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); } } diff --git a/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java b/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java index 79179a9f5275d..1a14d50538237 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java @@ -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())); return channel -> client.admin().cluster().getStoredScript(getRequest, new RestStatusToXContentListener<>(channel)); } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponseTests.java index cb0b7fd86e998..1c92c0c8c2bf7 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponseTests.java @@ -42,7 +42,7 @@ protected GetStoredScriptResponse createBlankInstance() { @Override protected GetStoredScriptResponse createTestInstance() { - return new GetStoredScriptResponse(randomAlphaOfLengthBetween(1, 10), scriptSource()); + return new GetStoredScriptResponse(randomAlphaOfLengthBetween(1, 10), randomScriptSource()); } @Override @@ -50,7 +50,7 @@ protected Predicate getRandomFieldsExcludeFilter() { return s -> "script.options".equals(s); } - private StoredScriptSource scriptSource() { + private static StoredScriptSource randomScriptSource() { final String lang = randomFrom("lang", "painless", "mustache"); final String source = randomAlphaOfLengthBetween(1, 10); final Map options = randomBoolean() From 00f3689b82efb2b91e18b0721eaf53915531a2c4 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Mon, 18 Jun 2018 20:17:45 +0200 Subject: [PATCH 4/6] fixed broken test due to handling timeouts --- .../client/RequestConvertersTests.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java index 17497dc9dd92e..798c1edf37c42 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java @@ -1916,22 +1916,28 @@ public void testGetTemplateRequest() throws Exception { } public void testGetScriptRequest() { - GetStoredScriptRequest storedScriptRequest = new GetStoredScriptRequest("x-script"); + GetStoredScriptRequest getStoredScriptRequest = new GetStoredScriptRequest("x-script"); + Map expectedParams = new HashMap<>(); + setRandomMasterTimeout(getStoredScriptRequest, expectedParams); - Request request = RequestConverters.getScript(storedScriptRequest); - assertThat(request.getEndpoint(), equalTo("/_scripts/" + storedScriptRequest.id())); + Request request = RequestConverters.getScript(getStoredScriptRequest); + assertThat(request.getEndpoint(), equalTo("/_scripts/" + getStoredScriptRequest.id())); assertThat(request.getMethod(), equalTo(HttpGet.METHOD_NAME)); - assertThat(request.getParameters().isEmpty(), equalTo(true)); + assertThat(request.getParameters(), equalTo(expectedParams)); assertThat(request.getEntity(), nullValue()); } public void testDeleteScriptRequest() { - DeleteStoredScriptRequest storedScriptRequest = new DeleteStoredScriptRequest("x-script"); + DeleteStoredScriptRequest deleteStoredScriptRequest = new DeleteStoredScriptRequest("x-script"); - Request request = RequestConverters.deleteScript(storedScriptRequest); - assertThat(request.getEndpoint(), equalTo("/_scripts/" + storedScriptRequest.id())); + Map expectedParams = new HashMap<>(); + setRandomMasterTimeout(deleteStoredScriptRequest, expectedParams); + setRandomTimeout(deleteStoredScriptRequest::timeout, ReplicationRequest.DEFAULT_TIMEOUT, expectedParams); + + Request request = RequestConverters.deleteScript(deleteStoredScriptRequest); + assertThat(request.getEndpoint(), equalTo("/_scripts/" + deleteStoredScriptRequest.id())); assertThat(request.getMethod(), equalTo(HttpDelete.METHOD_NAME)); - assertThat(request.getParameters().isEmpty(), equalTo(true)); + assertThat(request.getParameters(), equalTo(expectedParams)); assertThat(request.getEntity(), nullValue()); } From 8c34d9e1b965f13653f9bfc0778e801ee1e52240 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Mon, 18 Jun 2018 22:43:14 +0200 Subject: [PATCH 5/6] fixed broken test due to handling timeouts --- .../java/org/elasticsearch/client/RequestConvertersTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java index 798c1edf37c42..d47f450a5f34a 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java @@ -1931,8 +1931,8 @@ public void testDeleteScriptRequest() { DeleteStoredScriptRequest deleteStoredScriptRequest = new DeleteStoredScriptRequest("x-script"); Map expectedParams = new HashMap<>(); + setRandomTimeout(deleteStoredScriptRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams); setRandomMasterTimeout(deleteStoredScriptRequest, expectedParams); - setRandomTimeout(deleteStoredScriptRequest::timeout, ReplicationRequest.DEFAULT_TIMEOUT, expectedParams); Request request = RequestConverters.deleteScript(deleteStoredScriptRequest); assertThat(request.getEndpoint(), equalTo("/_scripts/" + deleteStoredScriptRequest.id())); From 3dadad89d3380c78c7e5fb5e05ff35e23db1dd43 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Tue, 19 Jun 2018 11:33:06 +0200 Subject: [PATCH 6/6] couple more touches - update get_script rest api spec; minor clean ups --- .../src/main/resources/rest-api-spec/api/get_script.json | 4 ++++ .../cluster/storedscripts/GetStoredScriptResponse.java | 6 +++--- .../elasticsearch/common/xcontent/BaseXContentTestCase.java | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/get_script.json b/rest-api-spec/src/main/resources/rest-api-spec/api/get_script.json index 2240f0e1a0b75..0b2d6c5a5b9c2 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/get_script.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/get_script.json @@ -13,6 +13,10 @@ } }, "params" : { + "master_timeout": { + "type" : "time", + "description" : "Specify timeout for connection to master" + } } }, "body": null diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java index e27fa0a69b971..7bfbbe7ad4d7f 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/GetStoredScriptResponse.java @@ -51,7 +51,7 @@ public class GetStoredScriptResponse extends ActionResponse implements StatusToX String id = (String) a[0]; boolean found = (Boolean)a[1]; StoredScriptSource scriptSource = (StoredScriptSource)a[2]; - return found ? new GetStoredScriptResponse(id, scriptSource) : new GetStoredScriptResponse(); + return found ? new GetStoredScriptResponse(id, scriptSource) : new GetStoredScriptResponse(id, null); }); static { @@ -124,7 +124,7 @@ public void readFrom(StreamInput in) throws IOException { } if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { - id = in.readOptionalString(); + id = in.readString(); } } @@ -144,7 +144,7 @@ public void writeTo(StreamOutput out) throws IOException { } } if (out.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { - out.writeOptionalString(id); + out.writeString(id); } } diff --git a/server/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java b/server/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java index b7ca255c48dac..86e55c1ab6a91 100644 --- a/server/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java +++ b/server/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java @@ -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((String)null))); + expectNonNullFieldException(() -> BytesReference.bytes(builder().field(null))); expectUnclosedException(() -> BytesReference.bytes(builder().startObject().field("foo"))); assertResult("{'foo':'bar'}", () -> builder().startObject().field("foo").value("bar").endObject());