Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add put stored script support to high-level rest client #31323

Merged
merged 11 commits into from
Sep 9, 2018
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest;
Expand Down Expand Up @@ -887,6 +888,19 @@ static Request getTemplates(GetIndexTemplatesRequest getIndexTemplatesRequest) t
return request;
}

static Request putScript(PutStoredScriptRequest putStoredScriptRequest) throws IOException {
String endpoint = new EndpointBuilder().addPathPartAsIs("_scripts").addPathPart(putStoredScriptRequest.id()).build();
Request request = new Request(HttpPost.METHOD_NAME, endpoint);
Params params = new Params(request);
params.withTimeout(putStoredScriptRequest.timeout());
params.withMasterTimeout(putStoredScriptRequest.masterNodeTimeout());
if (Strings.hasText(putStoredScriptRequest.context())) {
params.putParam("context", putStoredScriptRequest.context());
}
request.setEntity(createEntity(putStoredScriptRequest, REQUEST_BODY_CONTENT_TYPE));
return request;
}

static Request analyze(AnalyzeRequest request) throws IOException {
EndpointBuilder builder = new EndpointBuilder();
String index = request.index();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse;
import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
Expand Down Expand Up @@ -121,36 +122,36 @@
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedAvg;
import org.elasticsearch.search.aggregations.metrics.CardinalityAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedCardinality;
import org.elasticsearch.search.aggregations.metrics.ExtendedStatsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.GeoBoundsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedGeoBounds;
import org.elasticsearch.search.aggregations.metrics.GeoCentroidAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedGeoCentroid;
import org.elasticsearch.search.aggregations.metrics.MaxAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedMax;
import org.elasticsearch.search.aggregations.metrics.MinAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedMin;
import org.elasticsearch.search.aggregations.metrics.InternalHDRPercentileRanks;
import org.elasticsearch.search.aggregations.metrics.InternalHDRPercentiles;
import org.elasticsearch.search.aggregations.metrics.ParsedHDRPercentileRanks;
import org.elasticsearch.search.aggregations.metrics.ParsedHDRPercentiles;
import org.elasticsearch.search.aggregations.metrics.InternalTDigestPercentileRanks;
import org.elasticsearch.search.aggregations.metrics.InternalTDigestPercentiles;
import org.elasticsearch.search.aggregations.metrics.MaxAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.MinAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedAvg;
import org.elasticsearch.search.aggregations.metrics.ParsedCardinality;
import org.elasticsearch.search.aggregations.metrics.ParsedExtendedStats;
import org.elasticsearch.search.aggregations.metrics.ParsedGeoBounds;
import org.elasticsearch.search.aggregations.metrics.ParsedGeoCentroid;
import org.elasticsearch.search.aggregations.metrics.ParsedHDRPercentileRanks;
import org.elasticsearch.search.aggregations.metrics.ParsedHDRPercentiles;
import org.elasticsearch.search.aggregations.metrics.ParsedMax;
import org.elasticsearch.search.aggregations.metrics.ParsedMin;
import org.elasticsearch.search.aggregations.metrics.ParsedScriptedMetric;
import org.elasticsearch.search.aggregations.metrics.ParsedStats;
import org.elasticsearch.search.aggregations.metrics.ParsedSum;
import org.elasticsearch.search.aggregations.metrics.ParsedTDigestPercentileRanks;
import org.elasticsearch.search.aggregations.metrics.ParsedTDigestPercentiles;
import org.elasticsearch.search.aggregations.metrics.ParsedScriptedMetric;
import org.elasticsearch.search.aggregations.metrics.ParsedTopHits;
import org.elasticsearch.search.aggregations.metrics.ParsedValueCount;
import org.elasticsearch.search.aggregations.metrics.ScriptedMetricAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedStats;
import org.elasticsearch.search.aggregations.metrics.StatsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ExtendedStatsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedExtendedStats;
import org.elasticsearch.search.aggregations.metrics.ParsedSum;
import org.elasticsearch.search.aggregations.metrics.SumAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedTopHits;
import org.elasticsearch.search.aggregations.metrics.TopHitsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.ParsedValueCount;
import org.elasticsearch.search.aggregations.metrics.ValueCountAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.InternalSimpleValue;
import org.elasticsearch.search.aggregations.pipeline.ParsedSimpleValue;
Expand Down Expand Up @@ -1050,6 +1051,35 @@ public void deleteScriptAsync(DeleteStoredScriptRequest request, RequestOptions
AcknowledgedResponse::fromXContent, listener, emptySet());
}

/**
* Puts an stored script using the Scripting API.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html"> Scripting API
* on elastic.co</a>
* @param putStoredScriptRequest 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 AcknowledgedResponse putScript(PutStoredScriptRequest putStoredScriptRequest,
RequestOptions options) throws IOException {
return performRequestAndParseEntity(putStoredScriptRequest, RequestConverters::putScript, options,
AcknowledgedResponse::fromXContent, emptySet());
}

/**
* Asynchronously puts an stored script using the Scripting API.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html"> Scripting API
* on elastic.co</a>
* @param putStoredScriptRequest 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 putScriptAsync(PutStoredScriptRequest putStoredScriptRequest, RequestOptions options,
ActionListener<AcknowledgedResponse> listener) {
performRequestAsyncAndParseEntity(putStoredScriptRequest, RequestConverters::putScript, options,
AcknowledgedResponse::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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptRequest;
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;
Expand Down Expand Up @@ -1991,6 +1992,42 @@ public void testGetTemplateRequest() throws Exception {
assertThat(request.getEntity(), nullValue());
}

public void testPutScript() throws Exception {
PutStoredScriptRequest putStoredScriptRequest = new PutStoredScriptRequest();

String id = randomAlphaOfLengthBetween(5, 10);
putStoredScriptRequest.id(id);

XContentType xContentType = randomFrom(XContentType.values());
try (XContentBuilder builder = XContentBuilder.builder(xContentType.xContent())) {
builder.startObject();
builder.startObject("script")
.field("lang", "painless")
.field("source", "Math.log(_score * 2) + params.multiplier")
.endObject();
builder.endObject();

putStoredScriptRequest.content(BytesReference.bytes(builder), xContentType);
}

Map<String, String> expectedParams = new HashMap<>();
setRandomMasterTimeout(putStoredScriptRequest, expectedParams);
setRandomTimeout(putStoredScriptRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here we should test the context param too?


if (randomBoolean()) {
String context = randomAlphaOfLengthBetween(5, 10);
putStoredScriptRequest.context(context);
expectedParams.put("context", context);
}

Request request = RequestConverters.putScript(putStoredScriptRequest);

assertThat(request.getEndpoint(), equalTo("/_scripts/" + id));
assertThat(request.getParameters(), equalTo(expectedParams));
assertNotNull(request.getEntity());
assertToXContentBody(putStoredScriptRequest, request.getEntity());
}

public void testAnalyzeRequest() throws Exception {
AnalyzeRequest indexAnalyzeRequest = new AnalyzeRequest()
.text("Here is some text")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,6 @@ public void testApiNamingConventions() throws Exception {
"indices.get_upgrade",
"indices.put_alias",
"mtermvectors",
"put_script",
"reindex_rethrottle",
"render_search_template",
"scripts_painless_execute",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package org.elasticsearch.client;/*
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
Expand All @@ -17,41 +18,37 @@
* under the License.
*/

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.GetStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptRequest;
import org.elasticsearch.common.bytes.BytesArray;
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 java.util.Map;

import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractValue;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.equalTo;

public class StoredScriptsIT extends ESRestHighLevelClientTestCase {

final String id = "calculate-score";
private static 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
Request putRequest = new Request("PUT", "/_scripts/calculate-score");
putRequest.setJsonEntity("{\"script\":" + script + "}");
Response putResponse = adminClient().performRequest(putRequest);
assertEquals("{\"acknowledged\":true}", EntityUtils.toString(putResponse.getEntity()));
PutStoredScriptRequest request =
new PutStoredScriptRequest(id, "search", new BytesArray("{}"), XContentType.JSON, scriptSource);
assertAcked(execute(request, highLevelClient()::putScript, highLevelClient()::putScriptAsync));

GetStoredScriptRequest getRequest = new GetStoredScriptRequest("calculate-score");
getRequest.masterNodeTimeout("50s");
Expand All @@ -68,22 +65,14 @@ public void testDeleteStoredScript() throws Exception {
"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
Request putRequest = new Request("PUT", "/_scripts/" + id);
putRequest.setJsonEntity("{\"script\":" + script + "}");
Response putResponse = adminClient().performRequest(putRequest);
assertEquals("{\"acknowledged\":true}", EntityUtils.toString(putResponse.getEntity()));
PutStoredScriptRequest request =
new PutStoredScriptRequest(id, "search", new BytesArray("{}"), XContentType.JSON, scriptSource);
assertAcked(execute(request, highLevelClient()::putScript, highLevelClient()::putScriptAsync));

DeleteStoredScriptRequest deleteRequest = new DeleteStoredScriptRequest(id);
deleteRequest.masterNodeTimeout("50s");
deleteRequest.timeout("50s");

AcknowledgedResponse deleteResponse = execute(deleteRequest, highLevelClient()::deleteScript,
highLevelClient()::deleteScriptAsync);

assertThat(deleteResponse.isAcknowledged(), equalTo(true));
assertAcked(execute(deleteRequest, highLevelClient()::deleteScript, highLevelClient()::deleteScriptAsync));

GetStoredScriptRequest getRequest = new GetStoredScriptRequest(id);

Expand All @@ -92,4 +81,21 @@ public void testDeleteStoredScript() throws Exception {
highLevelClient()::getScriptAsync));
assertThat(statusException.status(), equalTo(RestStatus.NOT_FOUND));
}

public void testPutScript() throws Exception {
final StoredScriptSource scriptSource =
new StoredScriptSource("painless",
"Math.log(_score * 2) + params.my_modifier",
Collections.singletonMap(Script.CONTENT_TYPE_OPTION, XContentType.JSON.mediaType()));

PutStoredScriptRequest request =
new PutStoredScriptRequest(id, "search", new BytesArray("{}"), XContentType.JSON, scriptSource);
assertAcked(execute(request, highLevelClient()::putScript, highLevelClient()::putScriptAsync));

Map<String, Object> script = getAsMap("/_scripts/" + id);
assertThat(extractValue("_id", script), equalTo(id));
assertThat(extractValue("found", script), equalTo(true));
assertThat(extractValue("script.lang", script), equalTo("painless"));
assertThat(extractValue("script.source", script), equalTo("Math.log(_score * 2) + params.my_modifier"));
}
}
Loading