Add get stored script and delete stored script to high level REST API (#31355)

Add get stored script and delete stored script to high level REST API

Relates to #27205
This commit is contained in:
Vladimir Dolzhenko 2018-06-19 14:21:11 +02:00 committed by GitHub
parent e67aa96c81
commit 04e4e44409
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 790 additions and 47 deletions

View File

@ -37,6 +37,8 @@ import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRe
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;
@ -892,6 +894,23 @@ final class RequestConverters {
return request;
}
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;
}
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));

View File

@ -26,6 +26,10 @@ import org.elasticsearch.ElasticsearchStatusException;
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 class RestHighLevelClient implements Closeable {
FieldCapabilitiesResponse::fromXContent, emptySet());
}
/**
* Get stored script by id.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html">
* How to use scripts on elastic.co</a>
* @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 getScript(GetStoredScriptRequest request, RequestOptions options) throws IOException {
return performRequestAndParseEntity(request, RequestConverters::getScript, options,
GetStoredScriptResponse::fromXContent, emptySet());
}
/**
* Asynchronously get stored script by id.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html">
* How to use scripts on elastic.co</a>
* @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 getScriptAsync(GetStoredScriptRequest request, RequestOptions options,
ActionListener<GetStoredScriptResponse> listener) {
performRequestAsyncAndParseEntity(request, RequestConverters::getScript, options,
GetStoredScriptResponse::fromXContent, listener, emptySet());
}
/**
* Delete stored script by id.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html">
* How to use scripts on elastic.co</a>
* @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 deleteScript(DeleteStoredScriptRequest request, RequestOptions options) throws IOException {
return performRequestAndParseEntity(request, RequestConverters::deleteScript, options,
DeleteStoredScriptResponse::fromXContent, emptySet());
}
/**
* Asynchronously delete stored script by id.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html">
* How to use scripts on elastic.co</a>
* @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 deleteScriptAsync(DeleteStoredScriptRequest request, RequestOptions options,
ActionListener<DeleteStoredScriptResponse> listener) {
performRequestAsyncAndParseEntity(request, RequestConverters::deleteScript, options,
DeleteStoredScriptResponse::fromXContent, listener, emptySet());
}
/**
* Asynchronously executes a request using the Field Capabilities API.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-field-caps.html">Field Capabilities API

View File

@ -37,6 +37,8 @@ import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRe
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;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions;
@ -1948,6 +1950,32 @@ public class RequestConvertersTests extends ESTestCase {
assertThat(request.getEntity(), nullValue());
}
public void testGetScriptRequest() {
GetStoredScriptRequest getStoredScriptRequest = new GetStoredScriptRequest("x-script");
Map<String, String> expectedParams = new HashMap<>();
setRandomMasterTimeout(getStoredScriptRequest, expectedParams);
Request request = RequestConverters.getScript(getStoredScriptRequest);
assertThat(request.getEndpoint(), equalTo("/_scripts/" + getStoredScriptRequest.id()));
assertThat(request.getMethod(), equalTo(HttpGet.METHOD_NAME));
assertThat(request.getParameters(), equalTo(expectedParams));
assertThat(request.getEntity(), nullValue());
}
public void testDeleteScriptRequest() {
DeleteStoredScriptRequest deleteStoredScriptRequest = new DeleteStoredScriptRequest("x-script");
Map<String, String> expectedParams = new HashMap<>();
setRandomTimeout(deleteStoredScriptRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams);
setRandomMasterTimeout(deleteStoredScriptRequest, expectedParams);
Request request = RequestConverters.deleteScript(deleteStoredScriptRequest);
assertThat(request.getEndpoint(), equalTo("/_scripts/" + deleteStoredScriptRequest.id()));
assertThat(request.getMethod(), equalTo(HttpDelete.METHOD_NAME));
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());

View File

@ -0,0 +1,105 @@
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");
getRequest.masterNodeTimeout("50s");
GetStoredScriptResponse getResponse = execute(getRequest, highLevelClient()::getScript,
highLevelClient()::getScriptAsync);
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);
deleteRequest.masterNodeTimeout("50s");
deleteRequest.timeout("50s");
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()::getScript,
highLevelClient()::getScriptAsync));
assertThat(statusException.status(), equalTo(RestStatus.NOT_FOUND));
}
}

View File

@ -0,0 +1,204 @@
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.unit.TimeValue;
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.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static java.util.Collections.emptyMap;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.hamcrest.Matchers.equalTo;
/**
* 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-request-masterTimeout
request.masterNodeTimeout(TimeValue.timeValueSeconds(50)); // <1>
request.masterNodeTimeout("50s"); // <2>
// end::get-stored-script-request-masterTimeout
// tag::get-stored-script-execute
GetStoredScriptResponse getResponse = client.getScript(request, RequestOptions.DEFAULT);
// end::get-stored-script-execute
// tag::get-stored-script-response
StoredScriptSource storedScriptSource = getResponse.getSource(); // <1>
String lang = storedScriptSource.getLang(); // <2>
String source = storedScriptSource.getSource(); // <3>
Map<String, String> options = storedScriptSource.getOptions(); // <4>
// end::get-stored-script-response
assertThat(storedScriptSource, equalTo(scriptSource));
// tag::get-stored-script-execute-listener
ActionListener<GetStoredScriptResponse> listener =
new ActionListener<GetStoredScriptResponse>() {
@Override
public void onResponse(GetStoredScriptResponse 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.getScriptAsync(request, RequestOptions.DEFAULT, listener); // <1>
// end::get-stored-script-execute-async
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
}
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-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
DeleteStoredScriptResponse deleteResponse = client.deleteScript(deleteRequest, RequestOptions.DEFAULT);
// end::delete-stored-script-execute
// tag::delete-stored-script-response
boolean acknowledged = deleteResponse.isAcknowledged();// <1>
// end::delete-stored-script-response
putStoredScript("calculate-score", scriptSource);
// tag::delete-stored-script-execute-listener
ActionListener<DeleteStoredScriptResponse> listener =
new ActionListener<DeleteStoredScriptResponse>() {
@Override
public void onResponse(DeleteStoredScriptResponse 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.deleteScriptAsync(deleteRequest, RequestOptions.DEFAULT, listener); // <1>
// end::delete-stored-script-execute-async
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
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()));
}
}

View File

@ -0,0 +1,81 @@
[[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
==== 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"]
--------------------------------------------------
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[delete-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[delete-stored-script-response]
--------------------------------------------------
<1> Indicates whether all of the nodes have acknowledged the request

View File

@ -0,0 +1,77 @@
[[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
==== 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"]
--------------------------------------------------
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[get-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 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.

View File

@ -151,3 +151,14 @@ The Java High Level REST Client supports the following Tasks APIs:
include::tasks/list_tasks.asciidoc[]
include::tasks/cancel_tasks.asciidoc[]
== Script APIs
The Java High Level REST Client supports the following Scripts APIs:
* <<java-rest-high-get-stored-script>>
* <<java-rest-high-delete-stored-script>>
include::script/get_script.asciidoc[]
include::script/delete_script.asciidoc[]

View File

@ -13,6 +13,10 @@
}
},
"params" : {
"master_timeout": {
"type" : "time",
"description" : "Specify timeout for connection to master"
}
}
},
"body": null

View File

@ -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));
}
}

View File

@ -21,25 +21,63 @@ package org.elasticsearch.action.admin.cluster.storedscripts;
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.ToXContentObject;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ObjectParser;
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;
public class GetStoredScriptResponse extends ActionResponse implements ToXContentObject {
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
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");
private static final ConstructingObjectParser<GetStoredScriptResponse, String> PARSER =
new ConstructingObjectParser<>("GetStoredScriptResponse",
true,
(a, c) -> {
String id = (String) a[0];
boolean found = (Boolean)a[1];
StoredScriptSource scriptSource = (StoredScriptSource)a[2];
return found ? new GetStoredScriptResponse(id, scriptSource) : new GetStoredScriptResponse(id, null);
});
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, StoredScriptSource source) {
this.id = id;
this.source = source;
}
public String getId() {
return id;
}
/**
* @return if a stored script and if not found <code>null</code>
*/
@ -48,12 +86,29 @@ public class GetStoredScriptResponse extends ActionResponse implements ToXConten
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
source.toXContent(builder, params);
public RestStatus status() {
return source != null ? RestStatus.OK : RestStatus.NOT_FOUND;
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(_ID_PARSE_FIELD.getPreferredName(), id);
builder.field(FOUND_PARSE_FIELD.getPreferredName(), source != null);
if (source != null) {
builder.field(StoredScriptSource.SCRIPT_PARSE_FIELD.getPreferredName());
source.toXContent(builder, params);
}
builder.endObject();
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);
@ -67,6 +122,10 @@ public class GetStoredScriptResponse extends ActionResponse implements ToXConten
} else {
source = null;
}
if (in.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) {
id = in.readString();
}
}
@Override
@ -84,5 +143,22 @@ public class GetStoredScriptResponse extends ActionResponse implements ToXConten
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 Objects.equals(id, that.id) &&
Objects.equals(source, that.source);
}
@Override
public int hashCode() {
return Objects.hash(id, source);
}
}

View File

@ -60,7 +60,7 @@ public class TransportGetStoredScriptAction extends TransportMasterNodeReadActio
@Override
protected void masterOperation(GetStoredScriptRequest request, ClusterState state,
ActionListener<GetStoredScriptResponse> listener) throws Exception {
listener.onResponse(new GetStoredScriptResponse(scriptService.getStoredScript(state, request)));
listener.onResponse(new GetStoredScriptResponse(request.id(), scriptService.getStoredScript(state, request)));
}
@Override

View File

@ -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,9 +32,6 @@ import static org.elasticsearch.rest.RestRequest.Method.GET;
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);
@ -57,33 +47,7 @@ public class RestGetStoredScriptAction extends BaseRestHandler {
public RestChannelConsumer prepareRequest(final RestRequest request, NodeClient client) throws IOException {
String id = request.param("id");
GetStoredScriptRequest getRequest = new GetStoredScriptRequest(id);
return channel -> client.admin().cluster().getStoredScript(getRequest, new RestBuilderListener<GetStoredScriptResponse>(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;
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();
}
builder.endObject();
return new BytesRestResponse(found ? RestStatus.OK : RestStatus.NOT_FOUND, builder);
}
});
getRequest.masterNodeTimeout(request.paramAsTime("master_timeout", getRequest.masterNodeTimeout()));
return channel -> client.admin().cluster().getStoredScript(getRequest, new RestStatusToXContentListener<>(channel));
}
}

View File

@ -185,7 +185,7 @@ public class StoredScriptSource extends AbstractDiffable<StoredScriptSource> imp
}
}
private static final ObjectParser<Builder, Void> PARSER = new ObjectParser<>("stored script source", Builder::new);
private static final ObjectParser<Builder, Void> 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 class StoredScriptSource extends AbstractDiffable<StoredScriptSource> imp
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;

View File

@ -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<DeleteStoredScriptResponse> {
@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);
}
}

View File

@ -0,0 +1,61 @@
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.Map;
import java.util.function.Predicate;
public class GetStoredScriptResponseTests extends AbstractStreamableXContentTestCase<GetStoredScriptResponse> {
@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(randomAlphaOfLengthBetween(1, 10), randomScriptSource());
}
@Override
protected Predicate<String> getRandomFieldsExcludeFilter() {
return s -> "script.options".equals(s);
}
private static StoredScriptSource randomScriptSource() {
final String lang = randomFrom("lang", "painless", "mustache");
final String source = randomAlphaOfLengthBetween(1, 10);
final Map<String, String> options = randomBoolean()
? Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType())
: Collections.emptyMap();
return new StoredScriptSource(lang, source, options);
}
}