Skip to content

Commit

Permalink
Scripting: get context names REST API
Browse files Browse the repository at this point in the history
Adds `GET /_script_context`, returning a `contexts` object with each
available context as a key whose value is an empty object. eg.
```
{
  "contexts": {
    "aggregation_selector": {},
    "aggs": {},
    "aggs_combine": {},
...
  }
}
```

refs: elastic#47411
  • Loading branch information
stu-elastic committed Oct 14, 2019
1 parent ef7fdf1 commit 065bade
Show file tree
Hide file tree
Showing 12 changed files with 452 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"get_script_context":{
"documentation":{
"description":"Returns all script contexts."
},
"stability":"experimental",
"url":{
"paths":[
{
"path":"/_script_context",
"methods":[
"GET"
]
}
]
},
"params":{}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"Action to get all contexts":
- do:
get_script_context: {}
- length: { contexts: 22 }
- match: { contexts.aggregation_selector: {} }
- match: { contexts.aggs: {} }
- match: { contexts.aggs_combine: {} }
- match: { contexts.aggs_init: {} }
- match: { contexts.aggs_map: {} }
- match: { contexts.aggs_reduce: {} }
- match: { contexts.bucket_aggregation: {} }
- match: { contexts.field: {} }
- match: { contexts.filter: {} }
- match: { contexts.ingest: {} }
- match: { contexts.interval: {} }
- match: { contexts.number_sort: {} }
- match: { contexts.processor_conditional: {} }
- match: { contexts.score: {} }
- match: { contexts.script_heuristic: {} }
- match: { contexts.similarity: {} }
- match: { contexts.similarity_weight: {} }
- match: { contexts.string_sort: {} }
- match: { contexts.template: {} }
- match: { contexts.terms_set: {} }
- match: { contexts.update: {} }
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsAction;
import org.elasticsearch.action.admin.cluster.stats.TransportClusterStatsAction;
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptAction;
import org.elasticsearch.action.admin.cluster.storedscripts.GetScriptContextAction;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptAction;
import org.elasticsearch.action.admin.cluster.storedscripts.PutStoredScriptAction;
import org.elasticsearch.action.admin.cluster.storedscripts.TransportDeleteStoredScriptAction;
import org.elasticsearch.action.admin.cluster.storedscripts.TransportGetScriptContextAction;
import org.elasticsearch.action.admin.cluster.storedscripts.TransportGetStoredScriptAction;
import org.elasticsearch.action.admin.cluster.storedscripts.TransportPutStoredScriptAction;
import org.elasticsearch.action.admin.cluster.tasks.PendingClusterTasksAction;
Expand Down Expand Up @@ -247,6 +249,7 @@
import org.elasticsearch.rest.action.admin.cluster.RestDeleteSnapshotAction;
import org.elasticsearch.rest.action.admin.cluster.RestDeleteStoredScriptAction;
import org.elasticsearch.rest.action.admin.cluster.RestGetRepositoriesAction;
import org.elasticsearch.rest.action.admin.cluster.RestGetScriptContextAction;
import org.elasticsearch.rest.action.admin.cluster.RestGetSnapshotsAction;
import org.elasticsearch.rest.action.admin.cluster.RestGetStoredScriptAction;
import org.elasticsearch.rest.action.admin.cluster.RestGetTaskAction;
Expand Down Expand Up @@ -519,6 +522,7 @@ public <Request extends ActionRequest, Response extends ActionResponse> void reg
actions.register(PutStoredScriptAction.INSTANCE, TransportPutStoredScriptAction.class);
actions.register(GetStoredScriptAction.INSTANCE, TransportGetStoredScriptAction.class);
actions.register(DeleteStoredScriptAction.INSTANCE, TransportDeleteStoredScriptAction.class);
actions.register(GetScriptContextAction.INSTANCE, TransportGetScriptContextAction.class);

actions.register(FieldCapabilitiesAction.INSTANCE, TransportFieldCapabilitiesAction.class);
actions.register(TransportFieldCapabilitiesIndexAction.TYPE, TransportFieldCapabilitiesIndexAction.class);
Expand Down Expand Up @@ -660,6 +664,7 @@ public void initRestHandlers(Supplier<DiscoveryNodes> nodesInCluster) {
registerHandler.accept(new RestGetStoredScriptAction(restController));
registerHandler.accept(new RestPutStoredScriptAction(restController));
registerHandler.accept(new RestDeleteStoredScriptAction(restController));
registerHandler.accept(new RestGetScriptContextAction(restController));

registerHandler.accept(new RestFieldCapabilitiesAction(restController));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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.
*/

package org.elasticsearch.action.admin.cluster.storedscripts;

import org.elasticsearch.action.ActionType;

public class GetScriptContextAction extends ActionType<GetScriptContextResponse> {

public static final GetScriptContextAction INSTANCE = new GetScriptContextAction();
public static final String NAME = "cluster:admin/script_context/get";

private GetScriptContextAction() {
super(NAME, GetScriptContextResponse::new);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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.
*/
package org.elasticsearch.action.admin.cluster.storedscripts;

import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.support.master.MasterNodeReadRequest;
import org.elasticsearch.common.io.stream.StreamInput;

import java.io.IOException;

public class GetScriptContextRequest extends MasterNodeReadRequest<GetScriptContextRequest> {
public GetScriptContextRequest() {
super();
}

GetScriptContextRequest(StreamInput in) throws IOException {
super(in);
}

@Override
public ActionRequestValidationException validate() {
return null;
}

@Override
public String toString() {
return "get script context";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* 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.
*/

package org.elasticsearch.action.admin.cluster.storedscripts;

import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.StatusToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.rest.RestStatus;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

public class GetScriptContextResponse extends ActionResponse implements StatusToXContentObject {

private static final ParseField CONTEXTS = new ParseField("contexts");
private final List<String> contextNames;

@SuppressWarnings("unchecked")
public static final ConstructingObjectParser<GetScriptContextResponse,Void> PARSER =
new ConstructingObjectParser<>("get_script_context", true,
(a) -> {
Map<String, Object> contexts = ((List<String>) a[0]).stream().collect(Collectors.toMap(
name -> name, name -> new Object()
));
return new GetScriptContextResponse(contexts);
}
);

static {
PARSER.declareNamedObjects(
ConstructingObjectParser.constructorArg(),
(p, c, n) ->
{
// advance empty object
p.nextToken();
p.nextToken();
return n;
},
CONTEXTS
);
}

GetScriptContextResponse(StreamInput in) throws IOException {
super(in);
int size = in.readInt();
ArrayList<String> contextNames = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
contextNames.add(in.readString());
}
this.contextNames = Collections.unmodifiableList(contextNames);
}

GetScriptContextResponse(Map<String,Object> contexts) {
List<String> contextNames = new ArrayList<>(contexts.keySet());
contextNames.sort(String::compareTo);
this.contextNames = Collections.unmodifiableList(contextNames);
}

@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeInt(this.contextNames.size());
for (String context: this.contextNames) {
out.writeString(context);
}
}

@Override
public RestStatus status() {
return RestStatus.OK;
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject().startObject(CONTEXTS.getPreferredName());
for (String contextName: this.contextNames) {
builder.startObject(contextName).endObject();
}
builder.endObject().endObject(); // CONTEXTS
return builder;
}

public static GetScriptContextResponse fromXContent(XContentParser parser) throws IOException {
return PARSER.apply(parser, null);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GetScriptContextResponse that = (GetScriptContextResponse) o;
return new HashSet<>(contextNames).equals(new HashSet<>(that.contextNames));
}

@Override
public int hashCode() {
return Objects.hash(new HashSet<>(contextNames));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* 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.
*/
package org.elasticsearch.action.admin.cluster.storedscripts;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.master.TransportMasterNodeReadAction;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;

import java.io.IOException;
import java.util.Map;
import java.util.stream.Collectors;

public class TransportGetScriptContextAction extends TransportMasterNodeReadAction<GetScriptContextRequest, GetScriptContextResponse> {

private final ScriptService scriptService;

@Inject
public TransportGetScriptContextAction(TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver, ScriptService scriptService) {
super(GetScriptContextAction.NAME, transportService, clusterService, threadPool, actionFilters,
GetScriptContextRequest::new, indexNameExpressionResolver);
this.scriptService = scriptService;
}

@Override
protected String executor() {
return ThreadPool.Names.SAME;
}

@Override
protected GetScriptContextResponse read(StreamInput in) throws IOException {
return new GetScriptContextResponse(in);
}

@Override
protected void masterOperation(Task task, GetScriptContextRequest request, ClusterState state,
ActionListener<GetScriptContextResponse> listener) throws Exception {
Map<String,Object> contexts = scriptService.getContextNames().stream().collect(
Collectors.toMap(name -> name, name -> new Object())
);
listener.onResponse(new GetScriptContextResponse(contexts));
}

@Override
protected ClusterBlockException checkBlock(GetScriptContextRequest request, ClusterState state) {
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_READ);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequestBuilder;
import org.elasticsearch.action.admin.cluster.storedscripts.GetScriptContextRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.GetScriptContextResponse;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptRequestBuilder;
import org.elasticsearch.action.admin.cluster.storedscripts.GetStoredScriptResponse;
Expand Down Expand Up @@ -718,4 +720,9 @@ public interface ClusterAdminClient extends ElasticsearchClient {
* Get a script from the cluster state
*/
ActionFuture<GetStoredScriptResponse> getStoredScript(GetStoredScriptRequest request);

/**
* Get a script from the cluster state
*/
void getScriptContext(GetScriptContextRequest request, ActionListener<GetScriptContextResponse> listener);
}
Loading

0 comments on commit 065bade

Please sign in to comment.