diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/cluster/state/ClusterStateRequest.java b/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/cluster/state/ClusterStateRequest.java index e535f1d22a5..54da446048b 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/cluster/state/ClusterStateRequest.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/cluster/state/ClusterStateRequest.java @@ -21,16 +21,25 @@ package org.elasticsearch.action.admin.cluster.state; import org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.action.support.master.MasterNodeOperationRequest; +import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import java.io.IOException; /** - * @author kimchy (Shay Banon) + * @author kimchy (shay.banon) */ public class ClusterStateRequest extends MasterNodeOperationRequest { + private boolean filterRoutingTable = false; + + private boolean filterNodes = false; + + private boolean filterMetaData = false; + + private String[] filteredIndices = Strings.EMPTY_ARRAY; + public ClusterStateRequest() { } @@ -38,9 +47,62 @@ public class ClusterStateRequest extends MasterNodeOperationRequest { return null; } + public boolean filterRoutingTable() { + return filterRoutingTable; + } + + public ClusterStateRequest filterRoutingTable(boolean filterRoutingTable) { + this.filterRoutingTable = filterRoutingTable; + return this; + } + + public boolean filterNodes() { + return filterNodes; + } + + public ClusterStateRequest filterNodes(boolean filterNodes) { + this.filterNodes = filterNodes; + return this; + } + + public boolean filterMetaData() { + return filterMetaData; + } + + public ClusterStateRequest filterMetaData(boolean filterMetaData) { + this.filterMetaData = filterMetaData; + return this; + } + + public String[] filteredIndices() { + return filteredIndices; + } + + public ClusterStateRequest filteredIndices(String... filteredIndices) { + this.filteredIndices = filteredIndices; + return this; + } + @Override public void readFrom(StreamInput in) throws IOException { + filterRoutingTable = in.readBoolean(); + filterNodes = in.readBoolean(); + filterMetaData = in.readBoolean(); + int size = in.readVInt(); + if (size > 0) { + filteredIndices = new String[size]; + for (int i = 0; i < filteredIndices.length; i++) { + filteredIndices[i] = in.readUTF(); + } + } } @Override public void writeTo(StreamOutput out) throws IOException { + out.writeBoolean(filterRoutingTable); + out.writeBoolean(filterNodes); + out.writeBoolean(filterMetaData); + out.writeVInt(filteredIndices.length); + for (String filteredIndex : filteredIndices) { + out.writeUTF(filteredIndex); + } } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java b/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java index a0ba98c4022..1c975aa04ab 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java @@ -24,13 +24,21 @@ import org.elasticsearch.action.TransportActions; import org.elasticsearch.action.support.master.TransportMasterNodeOperationAction; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.Index; +import org.elasticsearch.indices.IndexMissingException; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportService; +import static org.elasticsearch.cluster.ClusterState.*; +import static org.elasticsearch.cluster.metadata.MetaData.*; + /** - * @author kimchy (Shay Banon) + * @author kimchy (shay.banon) */ public class TransportClusterStateAction extends TransportMasterNodeOperationAction { @@ -55,6 +63,30 @@ public class TransportClusterStateAction extends TransportMasterNodeOperationAct } @Override protected ClusterStateResponse masterOperation(ClusterStateRequest request) throws ElasticSearchException { - return new ClusterStateResponse(clusterName, clusterService.state()); + ClusterState currentState = clusterService.state(); + ClusterState.Builder builder = newClusterStateBuilder(); + if (!request.filterNodes()) { + builder.nodes(currentState.nodes()); + } + if (!request.filterRoutingTable()) { + builder.routingTable(currentState.routingTable()); + } + if (!request.filterMetaData()) { + if (request.filteredIndices().length > 0) { + MetaData.Builder mdBuilder = newMetaDataBuilder(); + String[] indices = currentState.metaData().concreteIndices(request.filteredIndices()); + for (String filteredIndex : indices) { + IndexMetaData indexMetaData = currentState.metaData().index(filteredIndex); + if (indexMetaData == null) { + throw new IndexMissingException(new Index(filteredIndex)); + } + mdBuilder.put(indexMetaData); + } + builder.metaData(mdBuilder); + } else { + builder.metaData(currentState.metaData()); + } + } + return new ClusterStateResponse(clusterName, builder.build()); } } \ No newline at end of file diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/client/action/admin/cluster/state/ClusterStateRequestBuilder.java b/modules/elasticsearch/src/main/java/org/elasticsearch/client/action/admin/cluster/state/ClusterStateRequestBuilder.java index 5aaf61bb913..431706bc0b1 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/client/action/admin/cluster/state/ClusterStateRequestBuilder.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/client/action/admin/cluster/state/ClusterStateRequestBuilder.java @@ -40,6 +40,42 @@ public class ClusterStateRequestBuilder { this.request = new ClusterStateRequest(); } + /** + * Should the cluster state result include the {@link org.elasticsearch.cluster.metadata.MetaData}. Defaults + * to false. + */ + public ClusterStateRequestBuilder setFilterMetaData(boolean filter) { + request.filterMetaData(filter); + return this; + } + + /** + * Should the cluster state result include the {@link org.elasticsearch.cluster.node.DiscoveryNodes}. Defaults + * to false. + */ + public ClusterStateRequestBuilder setFilterNodes(boolean filter) { + request.filterNodes(filter); + return this; + } + + /** + * Should the cluster state result include teh {@link org.elasticsearch.cluster.routing.RoutingTable}. Defaults + * to false. + */ + public ClusterStateRequestBuilder setFilterRoutingTable(boolean filter) { + request.filterRoutingTable(filter); + return this; + } + + /** + * When {@link #setFilterMetaData(boolean)} is not set, which indices to return the {@link org.elasticsearch.cluster.metadata.IndexMetaData} + * for. Defaults to all indices. + */ + public ClusterStateRequestBuilder setFilterIndices(String... indices) { + request.filteredIndices(indices); + return this; + } + /** * Executes the operation asynchronously and returns a future. */ diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/RestActionModule.java b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/RestActionModule.java index 659f5f17632..8c0ac7f3660 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/RestActionModule.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/RestActionModule.java @@ -35,6 +35,7 @@ import org.elasticsearch.rest.action.admin.indices.create.RestCreateIndexAction; import org.elasticsearch.rest.action.admin.indices.delete.RestDeleteIndexAction; import org.elasticsearch.rest.action.admin.indices.flush.RestFlushAction; import org.elasticsearch.rest.action.admin.indices.gateway.snapshot.RestGatewaySnapshotAction; +import org.elasticsearch.rest.action.admin.indices.mapping.get.RestGetMappingAction; import org.elasticsearch.rest.action.admin.indices.mapping.put.RestPutMappingAction; import org.elasticsearch.rest.action.admin.indices.optimize.RestOptimizeAction; import org.elasticsearch.rest.action.admin.indices.refresh.RestRefreshAction; @@ -75,6 +76,7 @@ public class RestActionModule extends AbstractModule { bind(RestDeleteIndexAction.class).asEagerSingleton(); bind(RestPutMappingAction.class).asEagerSingleton(); + bind(RestGetMappingAction.class).asEagerSingleton(); bind(RestGatewaySnapshotAction.class).asEagerSingleton(); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/admin/indices/mapping/get/RestGetMappingAction.java b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/admin/indices/mapping/get/RestGetMappingAction.java new file mode 100644 index 00000000000..1514ef1bc2b --- /dev/null +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/admin/indices/mapping/get/RestGetMappingAction.java @@ -0,0 +1,112 @@ +/* + * Licensed to Elastic Search and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. Elastic Search 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.rest.action.admin.indices.mapping.get; + +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest; +import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.client.Requests; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.common.collect.ImmutableSet; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.builder.XContentBuilder; +import org.elasticsearch.rest.*; +import org.elasticsearch.rest.action.support.RestXContentBuilder; + +import java.io.IOException; +import java.util.Map; +import java.util.Set; + +import static org.elasticsearch.rest.RestRequest.Method.*; +import static org.elasticsearch.rest.RestResponse.Status.*; +import static org.elasticsearch.rest.action.support.RestActions.*; + +/** + * @author kimchy (shay.banon) + */ +public class RestGetMappingAction extends BaseRestHandler { + + @Inject public RestGetMappingAction(Settings settings, Client client, RestController controller) { + super(settings, client); + controller.registerHandler(GET, "/_mapping", this); + controller.registerHandler(GET, "/{index}/_mapping", this); + controller.registerHandler(GET, "/{index}/{type}/_mapping", this); + } + + @Override public void handleRequest(final RestRequest request, final RestChannel channel) { + final String[] indices = splitIndices(request.param("index")); + final Set types = ImmutableSet.copyOf(splitTypes(request.param("type"))); + + ClusterStateRequest clusterStateRequest = Requests.clusterState() + .filterRoutingTable(true) + .filterNodes(true) + .filteredIndices(indices); + + client.admin().cluster().state(clusterStateRequest, new ActionListener() { + @Override public void onResponse(ClusterStateResponse response) { + try { + MetaData metaData = response.state().metaData(); + XContentBuilder builder = RestXContentBuilder.restContentBuilder(request); + builder.startObject(); + + for (IndexMetaData indexMetaData : metaData) { + builder.startObject(indexMetaData.index()); + + for (Map.Entry entry : indexMetaData.mappings().entrySet()) { + if (!types.isEmpty() && !types.contains(entry.getKey())) { + // filter this type out... + continue; + } + XContentParser parser = XContentFactory.xContent(entry.getValue()).createParser(entry.getValue()); + Map mapping = parser.map(); + if (mapping.size() == 1 && mapping.containsKey(entry.getKey())) { + // the type name is the root value, reduce it + mapping = (Map) mapping.get(entry.getKey()); + } + builder.field(entry.getKey()); + builder.map(mapping); + } + + builder.endObject(); + } + + builder.endObject(); + + channel.sendResponse(new XContentRestResponse(request, OK, builder)); + } catch (Exception e) { + onFailure(e); + } + } + + @Override public void onFailure(Throwable e) { + try { + channel.sendResponse(new XContentThrowableRestResponse(request, e)); + } catch (IOException e1) { + logger.error("Failed to send failure response", e1); + } + } + }); + } +} diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/count/RestCountAction.java b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/count/RestCountAction.java index 190750d558a..7e37a9db6c2 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/count/RestCountAction.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/count/RestCountAction.java @@ -77,10 +77,7 @@ public class RestCountAction extends BaseRestHandler { countRequest.queryParserName(request.param("query_parser_name")); countRequest.queryHint(request.param("query_hint")); countRequest.minScore(request.paramAsFloat("min_score", DEFAULT_MIN_SCORE)); - String typesParam = request.param("type"); - if (typesParam != null) { - countRequest.types(splitTypes(typesParam)); - } + countRequest.types(splitTypes(request.param("type"))); } catch (Exception e) { try { XContentBuilder builder = RestXContentBuilder.restContentBuilder(request); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/deletebyquery/RestDeleteByQueryAction.java b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/deletebyquery/RestDeleteByQueryAction.java index cfb06143a14..3466aaeb7a9 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/deletebyquery/RestDeleteByQueryAction.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/deletebyquery/RestDeleteByQueryAction.java @@ -66,10 +66,7 @@ public class RestDeleteByQueryAction extends BaseRestHandler { } } deleteByQueryRequest.queryParserName(request.param("query_parser_name")); - String typesParam = request.param("type"); - if (typesParam != null) { - deleteByQueryRequest.types(RestActions.splitTypes(typesParam)); - } + deleteByQueryRequest.types(splitTypes(request.param("type"))); deleteByQueryRequest.timeout(request.paramAsTime("timeout", ShardDeleteByQueryRequest.DEFAULT_TIMEOUT)); String replicationType = request.param("replication"); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java index 65300105b94..8239f5de608 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java @@ -133,12 +133,7 @@ public class RestSearchAction extends BaseRestHandler { } searchRequest.timeout(request.paramAsTime("timeout", null)); - - String typesParam = request.param("type"); - if (typesParam != null) { - searchRequest.types(RestActions.splitTypes(typesParam)); - } - + searchRequest.types(RestActions.splitTypes(request.param("type"))); searchRequest.queryHint(request.param("query_hint")); return searchRequest; diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/support/RestActions.java b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/support/RestActions.java index 92a7dce3cb2..c28ac3e5230 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/support/RestActions.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/support/RestActions.java @@ -92,6 +92,9 @@ public class RestActions { } public static String[] splitTypes(String typeNames) { + if (typeNames == null) { + return Strings.EMPTY_ARRAY; + } return typesPattern.split(typeNames); }