From d41b56cad548606772c4c29351452ebaf9165054 Mon Sep 17 00:00:00 2001 From: javanna Date: Wed, 3 Sep 2014 16:50:27 +0200 Subject: [PATCH] Indexed scripts: make sure headers are handed over to internal requests and streamline versioning support The get, put and delete indexed script apis map to get, index and delete api and internally create those corresponding requests. We need to make sure that the original headers are handed over to the new request by passing the original request in the constructor when creating the new one. Also streamlined the support for version and version_type in the REST layer since the parameters were not consistently parsed and set to the internal java API requests. Modified the REST delete template and delete script actions to make use of a client instead of using the `ScriptService` directly. Closes #7569 --- rest-api-spec/api/delete_script.json | 11 ++ rest-api-spec/api/delete_template.json | 11 ++ rest-api-spec/api/get_script.json | 11 ++ rest-api-spec/api/get_template.json | 16 +- rest-api-spec/api/put_script.json | 17 ++ rest-api-spec/api/put_template.json | 17 ++ rest-api-spec/test/script/20_versions.yaml | 112 ++++++++++++ .../action/delete/DeleteRequest.java | 9 + .../action/index/IndexRequest.java | 9 + .../TransportDeleteIndexedScriptAction.java | 11 +- .../get/TransportGetIndexedScriptAction.java | 7 +- .../put/TransportPutIndexedScriptAction.java | 9 +- .../script/RestDeleteIndexedScriptAction.java | 33 ++-- .../script/RestGetIndexedScriptAction.java | 25 ++- .../script/RestPutIndexedScriptAction.java | 17 +- .../RestDeleteSearchTemplateAction.java | 52 +----- .../template/RestGetSearchTemplateAction.java | 46 ++--- .../template/RestPutSearchTemplateAction.java | 67 +------- .../elasticsearch/script/ScriptService.java | 159 +++++++----------- 19 files changed, 355 insertions(+), 284 deletions(-) create mode 100644 rest-api-spec/test/script/20_versions.yaml diff --git a/rest-api-spec/api/delete_script.json b/rest-api-spec/api/delete_script.json index 07dcdbb8b91c4..897f2e20669a0 100644 --- a/rest-api-spec/api/delete_script.json +++ b/rest-api-spec/api/delete_script.json @@ -16,6 +16,17 @@ "description" : "Script language", "required" : true } + }, + "params" : { + "version": { + "type": "number", + "description": "Explicit version number for concurrency control" + }, + "version_type": { + "type": "enum", + "options": ["internal", "external", "external_gte", "force"], + "description": "Specific version type" + } } }, "body": null diff --git a/rest-api-spec/api/delete_template.json b/rest-api-spec/api/delete_template.json index 7c66d787a014d..2f38b204fd0d5 100644 --- a/rest-api-spec/api/delete_template.json +++ b/rest-api-spec/api/delete_template.json @@ -12,6 +12,17 @@ } } }, + "params" : { + "version": { + "type": "number", + "description": "Explicit version number for concurrency control" + }, + "version_type": { + "type": "enum", + "options": ["internal", "external", "external_gte", "force"], + "description": "Specific version type" + } + }, "body": null } } diff --git a/rest-api-spec/api/get_script.json b/rest-api-spec/api/get_script.json index ad913cd27fb69..49e3c8a8540e7 100644 --- a/rest-api-spec/api/get_script.json +++ b/rest-api-spec/api/get_script.json @@ -16,6 +16,17 @@ "description" : "Script language", "required" : true } + }, + "params" : { + "version": { + "type": "number", + "description": "Explicit version number for concurrency control" + }, + "version_type": { + "type": "enum", + "options": ["internal", "external", "external_gte", "force"], + "description": "Specific version type" + } } }, "body": null diff --git a/rest-api-spec/api/get_template.json b/rest-api-spec/api/get_template.json index 42a5b03d68451..c4d292455c242 100644 --- a/rest-api-spec/api/get_template.json +++ b/rest-api-spec/api/get_template.json @@ -11,11 +11,19 @@ "description" : "Template ID", "required" : true } + }, + "params" : { + "version": { + "type": "number", + "description": "Explicit version number for concurrency control" + }, + "version_type": { + "type": "enum", + "options": ["internal", "external", "external_gte", "force"], + "description": "Specific version type" + } } }, - "body": { - "description" : "The document", - "required" : false - } + "body": null } } \ No newline at end of file diff --git a/rest-api-spec/api/put_script.json b/rest-api-spec/api/put_script.json index c7ae9510eca94..e7c27fa0dc404 100644 --- a/rest-api-spec/api/put_script.json +++ b/rest-api-spec/api/put_script.json @@ -16,6 +16,23 @@ "description" : "Script language", "required" : true } + }, + "params" : { + "op_type": { + "type" : "enum", + "options" : ["index", "create"], + "default" : "index", + "description" : "Explicit operation type" + }, + "version": { + "type": "number", + "description": "Explicit version number for concurrency control" + }, + "version_type": { + "type": "enum", + "options": ["internal", "external", "external_gte", "force"], + "description": "Specific version type" + } } }, "body": { diff --git a/rest-api-spec/api/put_template.json b/rest-api-spec/api/put_template.json index e3daf88bcb1b2..994635616bcfc 100644 --- a/rest-api-spec/api/put_template.json +++ b/rest-api-spec/api/put_template.json @@ -13,6 +13,23 @@ } } }, + "params" : { + "op_type": { + "type" : "enum", + "options" : ["index", "create"], + "default" : "index", + "description" : "Explicit operation type" + }, + "version": { + "type": "number", + "description": "Explicit version number for concurrency control" + }, + "version_type": { + "type": "enum", + "options": ["internal", "external", "external_gte", "force"], + "description": "Specific version type" + } + }, "body": { "description" : "The document", "required" : true diff --git a/rest-api-spec/test/script/20_versions.yaml b/rest-api-spec/test/script/20_versions.yaml new file mode 100644 index 0000000000000..11b4716a9c2d9 --- /dev/null +++ b/rest-api-spec/test/script/20_versions.yaml @@ -0,0 +1,112 @@ +--- +"External version": + + - do: + put_script: + lang: groovy + id: 1 + body: { "script": "_score * doc[\"myParent.weight\"].value" } + version_type: external + version: 0 + + - match: { _version: 0 } + + - do: + put_script: + lang: groovy + id: 1 + body: { "script": "_score * doc[\"myParent.weight\"].value" } + version_type: external + version: 5 + + - match: { _version: 5 } + + - do: + catch: conflict + get_script: + lang: groovy + id: 1 + version: 3 + + - do: + catch: conflict + delete_script: + lang: groovy + id: 1 + version: 3 + + - do: + get_script: + lang: groovy + id: 1 + version: 5 + version_type: external + - is_true: script + + - do: + get_script: + lang: groovy + id: 1 + version: 5 + version_type: external_gte + - is_true: script + + - do: + catch: conflict + get_script: + lang: groovy + id: 1 + version: 10 + version_type: external_gte + + - do: + catch: conflict + delete_script: + lang: groovy + id: 1 + version: 3 + version_type: external + + - do: + get_script: + lang: groovy + id: 1 + version: 5 + version_type: force + - is_true: script + + - do: + get_script: + lang: groovy + id: 1 + version: 10 + version_type: force + - is_true: script + + - do: + catch: conflict + put_script: + lang: groovy + id: 1 + body: { "script": "_score * doc[\"myParent.weight\"].value" } + version_type: external + version: 5 + + - do: + catch: conflict + put_script: + lang: groovy + id: 1 + body: { "script": "_score * doc[\"myParent.weight\"].value" } + version_type: external + version: 0 + + - do: + put_script: + lang: groovy + id: 1 + body: { "script": "_score * doc[\"myParent.weight\"].value" } + version_type: external + version: 6 + + - match: { _version: 6} diff --git a/src/main/java/org/elasticsearch/action/delete/DeleteRequest.java b/src/main/java/org/elasticsearch/action/delete/DeleteRequest.java index dd898de61e45a..104575f874bdb 100644 --- a/src/main/java/org/elasticsearch/action/delete/DeleteRequest.java +++ b/src/main/java/org/elasticsearch/action/delete/DeleteRequest.java @@ -19,6 +19,7 @@ package org.elasticsearch.action.delete; +import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.action.support.replication.ShardReplicationOperationRequest; import org.elasticsearch.common.Nullable; @@ -86,6 +87,14 @@ public DeleteRequest(DeleteRequest request) { public DeleteRequest() { } + /** + * Creates a delete request caused by some other request, which is provided as an + * argument so that its headers and context can be copied to the new request + */ + public DeleteRequest(ActionRequest request) { + super(request); + } + @Override public ActionRequestValidationException validate() { ActionRequestValidationException validationException = super.validate(); diff --git a/src/main/java/org/elasticsearch/action/index/IndexRequest.java b/src/main/java/org/elasticsearch/action/index/IndexRequest.java index 5602397c79150..b21b5105a07e0 100644 --- a/src/main/java/org/elasticsearch/action/index/IndexRequest.java +++ b/src/main/java/org/elasticsearch/action/index/IndexRequest.java @@ -21,6 +21,7 @@ import com.google.common.base.Charsets; import org.elasticsearch.*; +import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.action.RoutingMissingException; import org.elasticsearch.action.TimestampParsingException; @@ -151,6 +152,14 @@ public static OpType fromString(String sOpType) throws ElasticsearchIllegalArgum public IndexRequest() { } + /** + * Creates an index request caused by some other request, which is provided as an + * argument so that its headers and context can be copied to the new request + */ + public IndexRequest(ActionRequest request) { + super(request); + } + /** * Constructs a new index request against the specific index. The {@link #type(String)} * {@link #source(byte[])} must be set. diff --git a/src/main/java/org/elasticsearch/action/indexedscripts/delete/TransportDeleteIndexedScriptAction.java b/src/main/java/org/elasticsearch/action/indexedscripts/delete/TransportDeleteIndexedScriptAction.java index 0e78358ad78ff..f8c14d6d97acd 100644 --- a/src/main/java/org/elasticsearch/action/indexedscripts/delete/TransportDeleteIndexedScriptAction.java +++ b/src/main/java/org/elasticsearch/action/indexedscripts/delete/TransportDeleteIndexedScriptAction.java @@ -20,11 +20,10 @@ package org.elasticsearch.action.indexedscripts.delete; import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.DelegatingActionListener; -import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.script.ScriptService; @@ -37,14 +36,12 @@ public class TransportDeleteIndexedScriptAction extends HandledTransportAction { private final ScriptService scriptService; - private final Client client; @Inject public TransportDeleteIndexedScriptAction(Settings settings, ThreadPool threadPool, ScriptService scriptService, - Client client, TransportService transportService, ActionFilters actionFilters) { + TransportService transportService, ActionFilters actionFilters) { super(settings, DeleteIndexedScriptAction.NAME, threadPool, transportService, actionFilters); this.scriptService = scriptService; - this.client = client; } @Override @@ -54,10 +51,10 @@ public DeleteIndexedScriptRequest newRequestInstance(){ @Override protected void doExecute(final DeleteIndexedScriptRequest request, final ActionListener listener) { - scriptService.deleteScriptFromIndex(client, request.scriptLang(), request.id(), request.version(), new DelegatingActionListener(listener) { + scriptService.deleteScriptFromIndex(request, new DelegatingActionListener(listener) { @Override public DeleteIndexedScriptResponse getDelegatedFromInstigator(DeleteResponse deleteResponse){ - return new DeleteIndexedScriptResponse(deleteResponse.getIndex(),deleteResponse.getType(),deleteResponse.getType(),deleteResponse.getVersion(), deleteResponse.isFound()); + return new DeleteIndexedScriptResponse(deleteResponse.getIndex(), deleteResponse.getType(), deleteResponse.getId(), deleteResponse.getVersion(), deleteResponse.isFound()); } }); } diff --git a/src/main/java/org/elasticsearch/action/indexedscripts/get/TransportGetIndexedScriptAction.java b/src/main/java/org/elasticsearch/action/indexedscripts/get/TransportGetIndexedScriptAction.java index 99b980a37ca61..d48a55b707206 100644 --- a/src/main/java/org/elasticsearch/action/indexedscripts/get/TransportGetIndexedScriptAction.java +++ b/src/main/java/org/elasticsearch/action/indexedscripts/get/TransportGetIndexedScriptAction.java @@ -23,7 +23,6 @@ import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.script.ScriptService; @@ -36,14 +35,12 @@ public class TransportGetIndexedScriptAction extends HandledTransportAction { private final ScriptService scriptService; - private final Client client; @Inject public TransportGetIndexedScriptAction(Settings settings, ThreadPool threadPool, ScriptService scriptService, - TransportService transportService, Client client, ActionFilters actionFilters) { + TransportService transportService, ActionFilters actionFilters) { super(settings, GetIndexedScriptAction.NAME, threadPool,transportService, actionFilters); this.scriptService = scriptService; - this.client = client; } @Override @@ -53,7 +50,7 @@ public GetIndexedScriptRequest newRequestInstance(){ @Override public void doExecute(GetIndexedScriptRequest request, ActionListener listener){ - GetResponse scriptResponse = scriptService.queryScriptIndex(client, request.scriptLang(), request.id(), request.version(), request.versionType()); + GetResponse scriptResponse = scriptService.queryScriptIndex(request); listener.onResponse(new GetIndexedScriptResponse(scriptResponse)); } } diff --git a/src/main/java/org/elasticsearch/action/indexedscripts/put/TransportPutIndexedScriptAction.java b/src/main/java/org/elasticsearch/action/indexedscripts/put/TransportPutIndexedScriptAction.java index 3c9a432566159..3fcb60992f5de 100644 --- a/src/main/java/org/elasticsearch/action/indexedscripts/put/TransportPutIndexedScriptAction.java +++ b/src/main/java/org/elasticsearch/action/indexedscripts/put/TransportPutIndexedScriptAction.java @@ -24,7 +24,6 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.DelegatingActionListener; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.script.ScriptService; @@ -37,14 +36,11 @@ public class TransportPutIndexedScriptAction extends HandledTransportAction { private final ScriptService scriptService; - private final Client client; @Inject public TransportPutIndexedScriptAction(Settings settings, ThreadPool threadPool, - ScriptService scriptService, Client client, - TransportService transportService, ActionFilters actionFilters) { + ScriptService scriptService, TransportService transportService, ActionFilters actionFilters) { super(settings, PutIndexedScriptAction.NAME, threadPool, transportService, actionFilters); - this.client = client; this.scriptService = scriptService; } @@ -55,12 +51,11 @@ public PutIndexedScriptRequest newRequestInstance(){ @Override protected void doExecute(final PutIndexedScriptRequest request, final ActionListener listener) { - scriptService.putScriptToIndex(client, request.safeSource(), request.scriptLang(), request.id(), null, request.opType().toString(), request.version(), request.versionType(), new DelegatingActionListener(listener) { + scriptService.putScriptToIndex(request, new DelegatingActionListener(listener) { @Override public PutIndexedScriptResponse getDelegatedFromInstigator(IndexResponse indexResponse){ return new PutIndexedScriptResponse(indexResponse.getType(),indexResponse.getId(),indexResponse.getVersion(),indexResponse.isCreated()); } }); } - } diff --git a/src/main/java/org/elasticsearch/rest/action/script/RestDeleteIndexedScriptAction.java b/src/main/java/org/elasticsearch/rest/action/script/RestDeleteIndexedScriptAction.java index 8a48bfba13ca8..e9cc789d07587 100644 --- a/src/main/java/org/elasticsearch/rest/action/script/RestDeleteIndexedScriptAction.java +++ b/src/main/java/org/elasticsearch/rest/action/script/RestDeleteIndexedScriptAction.java @@ -18,17 +18,16 @@ */ package org.elasticsearch.rest.action.script; -import org.elasticsearch.action.delete.DeleteRequest; -import org.elasticsearch.action.delete.DeleteResponse; +import org.elasticsearch.action.indexedscripts.delete.DeleteIndexedScriptRequest; +import org.elasticsearch.action.indexedscripts.delete.DeleteIndexedScriptResponse; import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.lucene.uid.Versions; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilderString; +import org.elasticsearch.index.VersionType; import org.elasticsearch.rest.*; import org.elasticsearch.rest.action.support.RestBuilderListener; -import org.elasticsearch.script.ScriptService; import static org.elasticsearch.rest.RestRequest.Method.DELETE; import static org.elasticsearch.rest.RestStatus.NOT_FOUND; @@ -36,24 +35,28 @@ public class RestDeleteIndexedScriptAction extends BaseRestHandler { - private ScriptService scriptService; - @Inject - public RestDeleteIndexedScriptAction(Settings settings, Client client, - ScriptService scriptService, RestController controller) { + public RestDeleteIndexedScriptAction(Settings settings, Client client, RestController controller) { super(settings, client); controller.registerHandler(DELETE, "/_scripts/{lang}/{id}", this); - this.scriptService = scriptService; + } + + protected RestDeleteIndexedScriptAction(Settings settings, Client client) { + super(settings, client); + } + + protected String getScriptLang(RestRequest request) { + return request.param("lang"); } @Override public void handleRequest(final RestRequest request, final RestChannel channel, Client client) { - - final String id = request.param("id"); - final long version = request.paramAsLong("version", Versions.MATCH_ANY); - scriptService.deleteScriptFromIndex(client,request.param("lang"), id, version, new RestBuilderListener(channel) { + DeleteIndexedScriptRequest deleteIndexedScriptRequest = new DeleteIndexedScriptRequest(getScriptLang(request), request.param("id")); + deleteIndexedScriptRequest.version(request.paramAsLong("version", deleteIndexedScriptRequest.version())); + deleteIndexedScriptRequest.versionType(VersionType.fromString(request.param("version_type"), deleteIndexedScriptRequest.versionType())); + client.deleteIndexedScript(deleteIndexedScriptRequest, new RestBuilderListener(channel) { @Override - public RestResponse buildResponse(DeleteResponse result, XContentBuilder builder) throws Exception { + public RestResponse buildResponse(DeleteIndexedScriptResponse result, XContentBuilder builder) throws Exception { builder.startObject() .field(Fields.FOUND, result.isFound()) .field(Fields._INDEX, result.getIndex()) @@ -77,6 +80,4 @@ static final class Fields { static final XContentBuilderString _ID = new XContentBuilderString("_id"); static final XContentBuilderString _VERSION = new XContentBuilderString("_version"); } - - } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/rest/action/script/RestGetIndexedScriptAction.java b/src/main/java/org/elasticsearch/rest/action/script/RestGetIndexedScriptAction.java index b1ce78cb25a66..38e4e59ab6ba7 100644 --- a/src/main/java/org/elasticsearch/rest/action/script/RestGetIndexedScriptAction.java +++ b/src/main/java/org/elasticsearch/rest/action/script/RestGetIndexedScriptAction.java @@ -27,6 +27,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.VersionType; import org.elasticsearch.rest.*; import org.elasticsearch.rest.action.support.RestResponseListener; @@ -47,11 +48,24 @@ public RestGetIndexedScriptAction(Settings settings, Client client, RestControll controller.registerHandler(GET, "/_scripts/{lang}/{id}", this); } + protected RestGetIndexedScriptAction(Settings settings, Client client) { + super(settings, client); + } + + protected String getScriptLang(RestRequest request) { + return request.param("lang"); + } + + protected String getScriptFieldName() { + return "script"; + } + @Override public void handleRequest(final RestRequest request, final RestChannel channel, Client client) { - - final GetIndexedScriptRequest getRequest = new GetIndexedScriptRequest(request.param("lang"), request.param("id")); - RestResponseListener responseListener = new RestResponseListener(channel) { + final GetIndexedScriptRequest getRequest = new GetIndexedScriptRequest(getScriptLang(request), request.param("id")); + getRequest.version(request.paramAsLong("version", getRequest.version())); + getRequest.versionType(VersionType.fromString(request.param("version_type"), getRequest.versionType())); + client.getIndexedScript(getRequest, new RestResponseListener(channel) { @Override public RestResponse buildResponse(GetIndexedScriptResponse response) throws Exception { XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); @@ -61,7 +75,7 @@ public RestResponse buildResponse(GetIndexedScriptResponse response) throws Exce try{ String script = response.getScript(); builder.startObject(); - builder.field("script",script); + builder.field(getScriptFieldName(), script); builder.endObject(); return new BytesRestResponse(OK, builder); } catch( IOException|ClassCastException e ){ @@ -69,7 +83,6 @@ public RestResponse buildResponse(GetIndexedScriptResponse response) throws Exce } } } - }; - client.getIndexedScript(getRequest, responseListener); + }); } } diff --git a/src/main/java/org/elasticsearch/rest/action/script/RestPutIndexedScriptAction.java b/src/main/java/org/elasticsearch/rest/action/script/RestPutIndexedScriptAction.java index 09ed78a5999df..5f7e9046c0db9 100644 --- a/src/main/java/org/elasticsearch/rest/action/script/RestPutIndexedScriptAction.java +++ b/src/main/java/org/elasticsearch/rest/action/script/RestPutIndexedScriptAction.java @@ -27,6 +27,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilderString; +import org.elasticsearch.index.VersionType; import org.elasticsearch.rest.*; import org.elasticsearch.rest.action.support.RestBuilderListener; @@ -52,6 +53,10 @@ public RestPutIndexedScriptAction(Settings settings, Client client, RestControll controller.registerHandler(POST, "/_scripts/{lang}/{id}/_create", new CreateHandler(settings, client)); } + protected RestPutIndexedScriptAction(Settings settings, Client client) { + super(settings, client); + } + final class CreateHandler extends BaseRestHandler { protected CreateHandler(Settings settings, final Client client) { super(settings, client); @@ -64,12 +69,15 @@ public void handleRequest(RestRequest request, RestChannel channel, final Client } } + protected String getScriptLang(RestRequest request) { + return request.param("lang"); + } + @Override public void handleRequest(final RestRequest request, final RestChannel channel, Client client) { - - PutIndexedScriptRequest putRequest = new PutIndexedScriptRequest(request.param("lang"), request.param("id")); - putRequest.listenerThreaded(false); - + PutIndexedScriptRequest putRequest = new PutIndexedScriptRequest(getScriptLang(request), request.param("id")).listenerThreaded(false); + putRequest.version(request.paramAsLong("version", putRequest.version())); + putRequest.versionType(VersionType.fromString(request.param("version_type"), putRequest.versionType())); putRequest.source(request.content(), request.contentUnsafe()); String sOpType = request.param("op_type"); if (sOpType != null) { @@ -109,5 +117,4 @@ static final class Fields { static final XContentBuilderString _ID = new XContentBuilderString("_id"); static final XContentBuilderString CREATED = new XContentBuilderString("created"); } - } diff --git a/src/main/java/org/elasticsearch/rest/action/template/RestDeleteSearchTemplateAction.java b/src/main/java/org/elasticsearch/rest/action/template/RestDeleteSearchTemplateAction.java index 91b136e678973..0bc5489b5f2b2 100644 --- a/src/main/java/org/elasticsearch/rest/action/template/RestDeleteSearchTemplateAction.java +++ b/src/main/java/org/elasticsearch/rest/action/template/RestDeleteSearchTemplateAction.java @@ -18,63 +18,25 @@ */ package org.elasticsearch.rest.action.template; -import org.elasticsearch.action.delete.DeleteRequest; -import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.lucene.uid.Versions; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentBuilderString; -import org.elasticsearch.rest.*; -import org.elasticsearch.rest.action.support.RestBuilderListener; -import org.elasticsearch.script.ScriptService; +import org.elasticsearch.rest.RestController; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.rest.action.script.RestDeleteIndexedScriptAction; import static org.elasticsearch.rest.RestRequest.Method.DELETE; -import static org.elasticsearch.rest.RestStatus.OK; -import static org.elasticsearch.rest.RestStatus.NOT_FOUND; -public class RestDeleteSearchTemplateAction extends BaseRestHandler { - - private ScriptService scriptService; +public class RestDeleteSearchTemplateAction extends RestDeleteIndexedScriptAction { @Inject - public RestDeleteSearchTemplateAction(Settings settings, Client client, RestController controller, ScriptService scriptService) { + public RestDeleteSearchTemplateAction(Settings settings, Client client, RestController controller) { super(settings, client); controller.registerHandler(DELETE, "/_search/template/{id}", this); - this.scriptService = scriptService; } @Override - public void handleRequest(final RestRequest request, final RestChannel channel, Client client) { - final String id = request.param("id"); - final long version = request.paramAsLong("version", Versions.MATCH_ANY); - scriptService.deleteScriptFromIndex(client,"mustache", id, version, new RestBuilderListener(channel) { - @Override - public RestResponse buildResponse(DeleteResponse result, XContentBuilder builder) throws Exception { - builder.startObject() - .field(Fields.FOUND, result.isFound()) - .field(Fields._INDEX, result.getIndex()) - .field(Fields._TYPE, result.getType()) - .field(Fields._ID, result.getId()) - .field(Fields._VERSION, result.getVersion()) - .endObject(); - RestStatus status = OK; - if (!result.isFound()) { - status = NOT_FOUND; - } - return new BytesRestResponse(status, builder); - } - }); - } - - static final class Fields { - static final XContentBuilderString FOUND = new XContentBuilderString("found"); - static final XContentBuilderString _INDEX = new XContentBuilderString("_index"); - static final XContentBuilderString _TYPE = new XContentBuilderString("_type"); - static final XContentBuilderString _ID = new XContentBuilderString("_id"); - static final XContentBuilderString _VERSION = new XContentBuilderString("_version"); + protected String getScriptLang(RestRequest request) { + return "mustache"; } - - } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/rest/action/template/RestGetSearchTemplateAction.java b/src/main/java/org/elasticsearch/rest/action/template/RestGetSearchTemplateAction.java index 326e5813104b8..4a638869848df 100644 --- a/src/main/java/org/elasticsearch/rest/action/template/RestGetSearchTemplateAction.java +++ b/src/main/java/org/elasticsearch/rest/action/template/RestGetSearchTemplateAction.java @@ -18,28 +18,19 @@ */ package org.elasticsearch.rest.action.template; -import org.elasticsearch.ElasticsearchIllegalStateException; -import org.elasticsearch.action.indexedscripts.get.GetIndexedScriptRequest; -import org.elasticsearch.action.indexedscripts.get.GetIndexedScriptResponse; import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.rest.*; -import org.elasticsearch.rest.action.support.RestResponseListener; - -import java.io.IOException; +import org.elasticsearch.rest.RestController; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.rest.action.script.RestGetIndexedScriptAction; import static org.elasticsearch.rest.RestRequest.Method.GET; -import static org.elasticsearch.rest.RestStatus.NOT_FOUND; -import static org.elasticsearch.rest.RestStatus.OK; /** * */ -public class RestGetSearchTemplateAction extends BaseRestHandler { +public class RestGetSearchTemplateAction extends RestGetIndexedScriptAction { @Inject public RestGetSearchTemplateAction(Settings settings, Client client, RestController controller) { @@ -48,27 +39,12 @@ public RestGetSearchTemplateAction(Settings settings, Client client, RestControl } @Override - public void handleRequest(final RestRequest request, final RestChannel channel, Client client) { - final GetIndexedScriptRequest getRequest = new GetIndexedScriptRequest("mustache", request.param("id")); - RestResponseListener responseListener = new RestResponseListener(channel) { - @Override - public RestResponse buildResponse(GetIndexedScriptResponse response) throws Exception { - XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); - if (!response.isExists()) { - return new BytesRestResponse(NOT_FOUND, builder); - } else { - try{ - String templateString = response.getScript(); - builder.startObject(); - builder.field("template",templateString); - builder.endObject(); - return new BytesRestResponse(OK, builder); - } catch( IOException|ClassCastException e ){ - throw new ElasticsearchIllegalStateException("Unable to parse " + response.getScript() + " as json",e); - } - } - } - }; - client.getIndexedScript(getRequest, responseListener); + protected String getScriptLang(RestRequest request) { + return "mustache"; + } + + @Override + protected String getScriptFieldName() { + return "template"; } } diff --git a/src/main/java/org/elasticsearch/rest/action/template/RestPutSearchTemplateAction.java b/src/main/java/org/elasticsearch/rest/action/template/RestPutSearchTemplateAction.java index b748c14872e9a..632138508f4f2 100644 --- a/src/main/java/org/elasticsearch/rest/action/template/RestPutSearchTemplateAction.java +++ b/src/main/java/org/elasticsearch/rest/action/template/RestPutSearchTemplateAction.java @@ -18,30 +18,22 @@ */ package org.elasticsearch.rest.action.template; -import org.elasticsearch.ElasticsearchIllegalArgumentException; -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.action.indexedscripts.put.PutIndexedScriptRequest; -import org.elasticsearch.action.indexedscripts.put.PutIndexedScriptResponse; import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentBuilderString; -import org.elasticsearch.rest.*; -import org.elasticsearch.rest.action.support.RestBuilderListener; - -import java.io.IOException; +import org.elasticsearch.rest.BaseRestHandler; +import org.elasticsearch.rest.RestChannel; +import org.elasticsearch.rest.RestController; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.rest.action.script.RestPutIndexedScriptAction; import static org.elasticsearch.rest.RestRequest.Method.POST; import static org.elasticsearch.rest.RestRequest.Method.PUT; -import static org.elasticsearch.rest.RestStatus.CREATED; -import static org.elasticsearch.rest.RestStatus.OK; -import static org.elasticsearch.rest.RestStatus.BAD_REQUEST; /** * */ -public class RestPutSearchTemplateAction extends BaseRestHandler { +public class RestPutSearchTemplateAction extends RestPutIndexedScriptAction { @Inject public RestPutSearchTemplateAction(Settings settings, Client client, RestController controller) { @@ -67,51 +59,8 @@ public void handleRequest(RestRequest request, RestChannel channel, final Client } } - - @Override - public void handleRequest(final RestRequest request, final RestChannel channel, Client client) { - PutIndexedScriptRequest putRequest = new PutIndexedScriptRequest("mustache", request.param("id")); - putRequest.listenerThreaded(false); - - putRequest.source(request.content(), request.contentUnsafe()); - String sOpType = request.param("op_type"); - if (sOpType != null) { - try { - putRequest.opType(IndexRequest.OpType.fromString(sOpType)); - } catch (ElasticsearchIllegalArgumentException eia){ - try { - XContentBuilder builder = channel.newBuilder(); - channel.sendResponse(new BytesRestResponse(BAD_REQUEST, builder.startObject().field("error", eia.getMessage()).endObject())); - return; - } catch (IOException e1) { - logger.warn("Failed to send response", e1); - return; - } - } - } - - client.putIndexedScript(putRequest, new RestBuilderListener(channel) { - @Override - public RestResponse buildResponse(PutIndexedScriptResponse response, XContentBuilder builder) throws Exception { - builder.startObject() - .field(Fields._ID, response.getId()) - .field(Fields._VERSION, response.getVersion()) - .field(Fields.CREATED, response.isCreated()); - builder.endObject(); - RestStatus status = OK; - if (response.isCreated()) { - status = CREATED; - } - return new BytesRestResponse(status, builder); - } - }); - } - - static final class Fields { - static final XContentBuilderString _VERSION = new XContentBuilderString("_version"); - static final XContentBuilderString _ID = new XContentBuilderString("_id"); - static final XContentBuilderString CREATED = new XContentBuilderString("created"); + protected String getScriptLang(RestRequest request) { + return "mustache"; } - } diff --git a/src/main/java/org/elasticsearch/script/ScriptService.java b/src/main/java/org/elasticsearch/script/ScriptService.java index 7eba26ab551af..8d538b38b55c0 100644 --- a/src/main/java/org/elasticsearch/script/ScriptService.java +++ b/src/main/java/org/elasticsearch/script/ScriptService.java @@ -26,13 +26,15 @@ import org.elasticsearch.ElasticsearchIllegalArgumentException; import org.elasticsearch.ElasticsearchIllegalStateException; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.ListenableActionFuture; import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexResponse; +import org.elasticsearch.action.indexedscripts.delete.DeleteIndexedScriptRequest; +import org.elasticsearch.action.indexedscripts.get.GetIndexedScriptRequest; +import org.elasticsearch.action.indexedscripts.put.PutIndexedScriptRequest; import org.elasticsearch.client.Client; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.ParseField; @@ -44,7 +46,6 @@ import org.elasticsearch.common.io.Streams; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.lucene.uid.Versions; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.util.concurrent.ConcurrentCollections; @@ -53,7 +54,6 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.env.Environment; -import org.elasticsearch.index.VersionType; import org.elasticsearch.index.query.TemplateQueryParser; import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.watcher.FileChangesListener; @@ -81,10 +81,9 @@ public class ScriptService extends AbstractComponent { public static final String SCRIPT_CACHE_EXPIRE_SETTING = "script.cache.expire"; public static final String DISABLE_DYNAMIC_SCRIPTING_DEFAULT = "sandbox"; public static final String SCRIPT_INDEX = ".scripts"; + public static final String DEFAULT_LANG = "groovy"; - //Make static so that it has visibility in IndexedScript - //Looked up from settings in ctor - private static String defaultLang = "groovy"; + private final String defaultLang; private final ImmutableMap scriptEngines; @@ -108,7 +107,7 @@ enum DynamicScriptDisabling { ONLY_DISK_ALLOWED, SANDBOXED_ONLY; - public static final DynamicScriptDisabling parse(String s) { + static DynamicScriptDisabling parse(String s) { switch (s.toLowerCase(Locale.ROOT)) { // true for "disable_dynamic" means only on-disk scripts are enabled case "true": @@ -129,19 +128,16 @@ public static final DynamicScriptDisabling parse(String s) { } public static final ParseField SCRIPT_LANG = new ParseField("lang","script_lang"); - + public static final ParseField SCRIPT_FILE = new ParseField("script_file","file"); + public static final ParseField SCRIPT_ID = new ParseField("script_id", "id"); + public static final ParseField SCRIPT_INLINE = new ParseField("script","scriptField"); public static final ParseField VALUE_SCRIPT_FILE = new ParseField("value_script_file"); public static final ParseField VALUE_SCRIPT_ID = new ParseField("value_script_id"); public static final ParseField VALUE_SCRIPT_INLINE = new ParseField("value_script"); - public static final ParseField KEY_SCRIPT_FILE = new ParseField("key_script_file"); public static final ParseField KEY_SCRIPT_ID = new ParseField("key_script_id"); public static final ParseField KEY_SCRIPT_INLINE = new ParseField("key_script"); - public static final ParseField SCRIPT_FILE = new ParseField("script_file","file"); - public static final ParseField SCRIPT_ID = new ParseField("script_id", "id"); - public static final ParseField SCRIPT_INLINE = new ParseField("script","scriptField"); - public static enum ScriptType { INLINE, @@ -165,8 +161,7 @@ public static ScriptType readFrom(StreamInput in) throws IOException { throw new ElasticsearchIllegalArgumentException("Unexpected value read for ScriptType got [" + scriptTypeVal + "] expected one of ["+INLINE_VAL +"," + INDEXED_VAL + "," + FILE_VAL+"]"); } - - } + } public static void writeTo(ScriptType scriptType, StreamOutput out) throws IOException{ if (scriptType != null) { @@ -190,17 +185,14 @@ public static void writeTo(ScriptType scriptType, StreamOutput out) throws IOExc } static class IndexedScript { - String lang; - String id; + private final String lang; + private final String id; IndexedScript(String lang, String script) { this.lang = lang; final String[] parts = script.split("/"); if (parts.length == 1) { this.id = script; - if (this.lang == null){ - this.lang = defaultLang; - } } else { if (parts.length != 3) { throw new ElasticsearchIllegalArgumentException("Illegal index script format [" + script + "]" + @@ -224,7 +216,7 @@ public ScriptService(Settings settings, Environment env, Set listener) { - try { - scriptLang = validateScriptLanguage(scriptLang); - - //verify that the script compiles - validate(scriptBytes, scriptLang); - - IndexRequest indexRequest = new IndexRequest(SCRIPT_INDEX, scriptLang, id); - indexRequest.listenerThreaded(false); - indexRequest.operationThreaded(false); - indexRequest.version(version); - indexRequest.versionType(versionType); - indexRequest.refresh(true); //Always refresh after indexing a template - - indexRequest.source(scriptBytes, true); - if (timeout != null) { - indexRequest.timeout(timeout); - } + public void putScriptToIndex(PutIndexedScriptRequest request, ActionListener listener) { + String scriptLang = validateScriptLanguage(request.scriptLang()); + //verify that the script compiles + validate(request.safeSource(), scriptLang); - if (sOpType != null) { - indexRequest.opType(IndexRequest.OpType.fromString(sOpType)); - } - - client.index(indexRequest, listener); - } catch (Throwable t){ - listener.onFailure(t); - } + IndexRequest indexRequest = new IndexRequest(request).index(SCRIPT_INDEX).type(scriptLang).id(request.id()) + .listenerThreaded(false).operationThreaded(false).version(request.version()).versionType(request.versionType()) + .source(request.safeSource(), true).opType(request.opType()).refresh(true); //Always refresh after indexing a template + client.index(indexRequest, listener); } - public void deleteScriptFromIndex(Client client, @Nullable String scriptLang, String id, - long version, ActionListener listener) { - scriptLang = validateScriptLanguage(scriptLang); - client.delete((new DeleteRequest(SCRIPT_INDEX,scriptLang,id)).refresh(true).version(version), listener); + public void deleteScriptFromIndex(DeleteIndexedScriptRequest request, ActionListener listener) { + String scriptLang = validateScriptLanguage(request.scriptLang()); + DeleteRequest deleteRequest = new DeleteRequest(request).index(SCRIPT_INDEX).type(scriptLang).id(request.id()) + .refresh(true).version(request.version()).versionType(request.versionType()); + client.delete(deleteRequest, listener); } public static String getScriptFromResponse(GetResponse responseFields) { @@ -602,6 +568,9 @@ public CacheKey(String lang, String script) { @Override public boolean equals(Object o) { + if (! (o instanceof CacheKey)) { + return false; + } CacheKey other = (CacheKey) o; return lang.equals(other.lang) && script.equals(other.script); }