Skip to content

Commit 04e4e44

Browse files
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
1 parent e67aa96 commit 04e4e44

File tree

16 files changed

+789
-46
lines changed

16 files changed

+789
-46
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
3838
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
3939
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
40+
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
41+
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
4042
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
4143
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
4244
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheRequest;
@@ -892,6 +894,23 @@ static Request getTemplates(GetIndexTemplatesRequest getIndexTemplatesRequest) t
892894
return request;
893895
}
894896

897+
static Request getScript(GetStoredScriptRequest getStoredScriptRequest) {
898+
String endpoint = new EndpointBuilder().addPathPartAsIs("_scripts").addPathPart(getStoredScriptRequest.id()).build();
899+
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
900+
Params params = new Params(request);
901+
params.withMasterTimeout(getStoredScriptRequest.masterNodeTimeout());
902+
return request;
903+
}
904+
905+
static Request deleteScript(DeleteStoredScriptRequest deleteStoredScriptRequest) {
906+
String endpoint = new EndpointBuilder().addPathPartAsIs("_scripts").addPathPart(deleteStoredScriptRequest.id()).build();
907+
Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
908+
Params params = new Params(request);
909+
params.withTimeout(deleteStoredScriptRequest.timeout());
910+
params.withMasterTimeout(deleteStoredScriptRequest.masterNodeTimeout());
911+
return request;
912+
}
913+
895914
private static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) throws IOException {
896915
BytesRef source = XContentHelper.toXContent(toXContent, xContentType, false).toBytesRef();
897916
return new ByteArrayEntity(source.bytes, source.offset, source.length, createContentType(xContentType));

client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
import org.elasticsearch.action.ActionListener;
2727
import org.elasticsearch.action.ActionRequest;
2828
import org.elasticsearch.action.ActionRequestValidationException;
29+
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
30+
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptResponse;
31+
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
32+
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse;
2933
import org.elasticsearch.action.bulk.BulkRequest;
3034
import org.elasticsearch.action.bulk.BulkResponse;
3135
import org.elasticsearch.action.delete.DeleteRequest;
@@ -652,6 +656,62 @@ public final FieldCapabilitiesResponse fieldCaps(FieldCapabilitiesRequest fieldC
652656
FieldCapabilitiesResponse::fromXContent, emptySet());
653657
}
654658

659+
/**
660+
* Get stored script by id.
661+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html">
662+
* How to use scripts on elastic.co</a>
663+
* @param request the request
664+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
665+
* @return the response
666+
* @throws IOException in case there is a problem sending the request or parsing back the response
667+
*/
668+
public GetStoredScriptResponse getScript(GetStoredScriptRequest request, RequestOptions options) throws IOException {
669+
return performRequestAndParseEntity(request, RequestConverters::getScript, options,
670+
GetStoredScriptResponse::fromXContent, emptySet());
671+
}
672+
673+
/**
674+
* Asynchronously get stored script by id.
675+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html">
676+
* How to use scripts on elastic.co</a>
677+
* @param request the request
678+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
679+
* @param listener the listener to be notified upon request completion
680+
*/
681+
public void getScriptAsync(GetStoredScriptRequest request, RequestOptions options,
682+
ActionListener<GetStoredScriptResponse> listener) {
683+
performRequestAsyncAndParseEntity(request, RequestConverters::getScript, options,
684+
GetStoredScriptResponse::fromXContent, listener, emptySet());
685+
}
686+
687+
/**
688+
* Delete stored script by id.
689+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html">
690+
* How to use scripts on elastic.co</a>
691+
* @param request the request
692+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
693+
* @return the response
694+
* @throws IOException in case there is a problem sending the request or parsing back the response
695+
*/
696+
public DeleteStoredScriptResponse deleteScript(DeleteStoredScriptRequest request, RequestOptions options) throws IOException {
697+
return performRequestAndParseEntity(request, RequestConverters::deleteScript, options,
698+
DeleteStoredScriptResponse::fromXContent, emptySet());
699+
}
700+
701+
/**
702+
* Asynchronously delete stored script by id.
703+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html">
704+
* How to use scripts on elastic.co</a>
705+
* @param request the request
706+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
707+
* @param listener the listener to be notified upon request completion
708+
*/
709+
public void deleteScriptAsync(DeleteStoredScriptRequest request, RequestOptions options,
710+
ActionListener<DeleteStoredScriptResponse> listener) {
711+
performRequestAsyncAndParseEntity(request, RequestConverters::deleteScript, options,
712+
DeleteStoredScriptResponse::fromXContent, listener, emptySet());
713+
}
714+
655715
/**
656716
* Asynchronously executes a request using the Field Capabilities API.
657717
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-field-caps.html">Field Capabilities API

client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
3838
import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryRequest;
3939
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
40+
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
41+
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
4042
import org.elasticsearch.action.admin.indices.alias.Alias;
4143
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
4244
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions;
@@ -1948,6 +1950,32 @@ public void testGetTemplateRequest() throws Exception {
19481950
assertThat(request.getEntity(), nullValue());
19491951
}
19501952

1953+
public void testGetScriptRequest() {
1954+
GetStoredScriptRequest getStoredScriptRequest = new GetStoredScriptRequest("x-script");
1955+
Map<String, String> expectedParams = new HashMap<>();
1956+
setRandomMasterTimeout(getStoredScriptRequest, expectedParams);
1957+
1958+
Request request = RequestConverters.getScript(getStoredScriptRequest);
1959+
assertThat(request.getEndpoint(), equalTo("/_scripts/" + getStoredScriptRequest.id()));
1960+
assertThat(request.getMethod(), equalTo(HttpGet.METHOD_NAME));
1961+
assertThat(request.getParameters(), equalTo(expectedParams));
1962+
assertThat(request.getEntity(), nullValue());
1963+
}
1964+
1965+
public void testDeleteScriptRequest() {
1966+
DeleteStoredScriptRequest deleteStoredScriptRequest = new DeleteStoredScriptRequest("x-script");
1967+
1968+
Map<String, String> expectedParams = new HashMap<>();
1969+
setRandomTimeout(deleteStoredScriptRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams);
1970+
setRandomMasterTimeout(deleteStoredScriptRequest, expectedParams);
1971+
1972+
Request request = RequestConverters.deleteScript(deleteStoredScriptRequest);
1973+
assertThat(request.getEndpoint(), equalTo("/_scripts/" + deleteStoredScriptRequest.id()));
1974+
assertThat(request.getMethod(), equalTo(HttpDelete.METHOD_NAME));
1975+
assertThat(request.getParameters(), equalTo(expectedParams));
1976+
assertThat(request.getEntity(), nullValue());
1977+
}
1978+
19511979
private static void assertToXContentBody(ToXContent expectedBody, HttpEntity actualEntity) throws IOException {
19521980
BytesReference expectedBytes = XContentHelper.toXContent(expectedBody, REQUEST_BODY_CONTENT_TYPE, false);
19531981
assertEquals(XContentType.JSON.mediaTypeWithoutParameters(), actualEntity.getContentType().getValue());
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package org.elasticsearch.client;/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
21+
import org.apache.http.entity.ContentType;
22+
import org.apache.http.entity.StringEntity;
23+
import org.apache.http.util.EntityUtils;
24+
import org.elasticsearch.ElasticsearchStatusException;
25+
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
26+
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptResponse;
27+
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
28+
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse;
29+
import org.elasticsearch.common.Strings;
30+
import org.elasticsearch.common.xcontent.ToXContent;
31+
import org.elasticsearch.common.xcontent.XContentType;
32+
import org.elasticsearch.rest.RestStatus;
33+
import org.elasticsearch.script.Script;
34+
import org.elasticsearch.script.StoredScriptSource;
35+
36+
import java.util.Collections;
37+
38+
import static java.util.Collections.emptyMap;
39+
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
40+
import static org.hamcrest.Matchers.equalTo;
41+
42+
public class StoredScriptsIT extends ESRestHighLevelClientTestCase {
43+
44+
final String id = "calculate-score";
45+
46+
public void testGetStoredScript() throws Exception {
47+
final StoredScriptSource scriptSource =
48+
new StoredScriptSource("painless",
49+
"Math.log(_score * 2) + params.my_modifier",
50+
Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType()));
51+
52+
final String script = Strings.toString(scriptSource.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS));
53+
// TODO: change to HighLevel PutStoredScriptRequest when it will be ready
54+
// so far - using low-level REST API
55+
Response putResponse =
56+
adminClient()
57+
.performRequest("PUT", "/_scripts/calculate-score", emptyMap(),
58+
new StringEntity("{\"script\":" + script + "}",
59+
ContentType.APPLICATION_JSON));
60+
assertEquals(putResponse.getStatusLine().getReasonPhrase(), 200, putResponse.getStatusLine().getStatusCode());
61+
assertEquals("{\"acknowledged\":true}", EntityUtils.toString(putResponse.getEntity()));
62+
63+
GetStoredScriptRequest getRequest = new GetStoredScriptRequest("calculate-score");
64+
getRequest.masterNodeTimeout("50s");
65+
66+
GetStoredScriptResponse getResponse = execute(getRequest, highLevelClient()::getScript,
67+
highLevelClient()::getScriptAsync);
68+
69+
assertThat(getResponse.getSource(), equalTo(scriptSource));
70+
}
71+
72+
public void testDeleteStoredScript() throws Exception {
73+
final StoredScriptSource scriptSource =
74+
new StoredScriptSource("painless",
75+
"Math.log(_score * 2) + params.my_modifier",
76+
Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType()));
77+
78+
final String script = Strings.toString(scriptSource.toXContent(jsonBuilder(), ToXContent.EMPTY_PARAMS));
79+
// TODO: change to HighLevel PutStoredScriptRequest when it will be ready
80+
// so far - using low-level REST API
81+
Response putResponse =
82+
adminClient()
83+
.performRequest("PUT", "/_scripts/" + id, emptyMap(),
84+
new StringEntity("{\"script\":" + script + "}",
85+
ContentType.APPLICATION_JSON));
86+
assertEquals(putResponse.getStatusLine().getReasonPhrase(), 200, putResponse.getStatusLine().getStatusCode());
87+
assertEquals("{\"acknowledged\":true}", EntityUtils.toString(putResponse.getEntity()));
88+
89+
DeleteStoredScriptRequest deleteRequest = new DeleteStoredScriptRequest(id);
90+
deleteRequest.masterNodeTimeout("50s");
91+
deleteRequest.timeout("50s");
92+
93+
DeleteStoredScriptResponse deleteResponse = execute(deleteRequest, highLevelClient()::deleteScript,
94+
highLevelClient()::deleteScriptAsync);
95+
96+
assertThat(deleteResponse.isAcknowledged(), equalTo(true));
97+
98+
GetStoredScriptRequest getRequest = new GetStoredScriptRequest(id);
99+
100+
final ElasticsearchStatusException statusException = expectThrows(ElasticsearchStatusException.class,
101+
() -> execute(getRequest, highLevelClient()::getScript,
102+
highLevelClient()::getScriptAsync));
103+
assertThat(statusException.status(), equalTo(RestStatus.NOT_FOUND));
104+
}
105+
}

0 commit comments

Comments
 (0)