diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/cat.segments.json b/rest-api-spec/src/main/resources/rest-api-spec/api/cat.segments.json index 318ae066a7618..719388791b580 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/cat.segments.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/cat.segments.json @@ -93,6 +93,29 @@ "micros", "nanos" ] + }, + "ignore_unavailable": { + "type": "boolean", + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed). Only allowed when providing an index expression." + }, + "ignore_throttled": { + "type": "boolean", + "description": "Whether specified concrete, expanded or aliased indices should be ignored when throttled. Only allowed when providing an index expression." + }, + "allow_no_indices": { + "type": "boolean", + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified). Only allowed when providing an index expression." + }, + "expand_wildcards": { + "type": "enum", + "options": ["open", "closed", "hidden", "none", "all"], + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both." + }, + "allow_closed": { + "type": "boolean", + "description": "If true, allow closed indices to be returned in the response otherwise if false, keep the legacy behaviour of throwing an exception if index pattern matches closed indices", + "default": false } } } diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.segments/10_basic.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.segments/10_basic.yml index 94052cb4fe967..33b4dd83ac01a 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.segments/10_basic.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.segments/10_basic.yml @@ -209,3 +209,77 @@ tsdb: $body: | /^(tsdb \s+ 0 \s+ p \s+ \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} \s+ _\d (\s\d){3} \s+ (\d+|\d+[.]\d+)(kb|b) \s+ \d+ (\s+ (false|true)){2} \s+ \d+\.\d+(\.\d+)? \s+ (false|true) \s? \n?)$/ + +--- +Wildcard Expansion Settings: + - requires: + capabilities: + - method: GET + path: /_cat/segments + capabilities: [ allow_closed ] + test_runner_features: [ capabilities ] + reason: Capability required to run test + + - do: + indices.create: + index: basic-index + body: + settings: + number_of_shards: 1 + number_of_replicas: 0 + + - do: + index: + index: basic-index + id: "1" + body: + field: "basic doc 1" + + - do: + indices.create: + index: hidden-index + body: + settings: + number_of_shards: 1 + number_of_replicas: 0 + index.hidden: true + + - do: + index: + index: hidden-index + id: "1" + body: + field: "hidden doc 1" + + - do: + indices.create: + index: closed-index + body: + settings: + number_of_shards: 1 + number_of_replicas: 0 + + - do: + index: + index: closed-index + id: "1" + body: + field: "closed doc 1" + + - do: + indices.refresh: + index: [ basic-index, closed-index, hidden-index ] + + - do: + indices.close: + index: closed-index + + - do: + cat.segments: + v: true + s: index + expand_wildcards: all + allow_closed: true + - match: + $body: | + /basic-index(\s)+0(\s)+p.*\nclosed-index(\s)+0(\s)+p.*\nhidden-index(\s)+0(\s)+p.*/ diff --git a/server/src/main/java/org/elasticsearch/rest/action/cat/RestSegmentsAction.java b/server/src/main/java/org/elasticsearch/rest/action/cat/RestSegmentsAction.java index 11fb62dc6f960..f568826fea231 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/cat/RestSegmentsAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/cat/RestSegmentsAction.java @@ -16,6 +16,7 @@ import org.elasticsearch.action.admin.indices.segments.IndicesSegmentResponse; import org.elasticsearch.action.admin.indices.segments.IndicesSegmentsRequest; import org.elasticsearch.action.admin.indices.segments.ShardSegments; +import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.client.internal.node.NodeClient; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.common.Strings; @@ -33,6 +34,7 @@ import java.util.List; import java.util.Map; +import java.util.Set; import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestUtils.getMasterNodeTimeout; @@ -40,6 +42,8 @@ @ServerlessScope(Scope.INTERNAL) public class RestSegmentsAction extends AbstractCatAction { + private static final Set CAPABILITIES = Set.of("allow_closed"); + @Override public List routes() { return List.of(new Route(GET, "/_cat/segments"), new Route(GET, "/_cat/segments/{index}")); @@ -61,16 +65,23 @@ protected RestChannelConsumer doCatRequest(final RestRequest request, final Node final ClusterStateRequest clusterStateRequest = new ClusterStateRequest(getMasterNodeTimeout(request)); RestUtils.consumeDeprecatedLocalParameter(request); - clusterStateRequest.clear().nodes(true).routingTable(true).indices(indices); + + final boolean allowClosed = request.paramAsBoolean("allow_closed", false); + final IndicesOptions defaultOptions = allowClosed + ? IndicesOptions.strictExpandHidden() + : IndicesOptions.strictExpandOpenAndForbidClosed(); + final IndicesOptions indicesOptions = IndicesOptions.fromRequest(request, defaultOptions); + + clusterStateRequest.clear().nodes(true); final RestCancellableNodeClient cancelClient = new RestCancellableNodeClient(client, request.getHttpChannel()); - return channel -> cancelClient.admin().cluster().state(clusterStateRequest, new RestActionListener(channel) { + return channel -> cancelClient.admin().cluster().state(clusterStateRequest, new RestActionListener<>(channel) { @Override public void processResponse(final ClusterStateResponse clusterStateResponse) { final IndicesSegmentsRequest indicesSegmentsRequest = new IndicesSegmentsRequest(); - indicesSegmentsRequest.indices(indices); - cancelClient.admin().indices().segments(indicesSegmentsRequest, new RestResponseListener(channel) { + indicesSegmentsRequest.indices(indices).indicesOptions(indicesOptions); + cancelClient.admin().indices().segments(indicesSegmentsRequest, new RestResponseListener<>(channel) { @Override public RestResponse buildResponse(final IndicesSegmentResponse indicesSegmentResponse) throws Exception { if (request.getHttpChannel().isOpen() == false) { @@ -157,4 +168,9 @@ private Table buildTable(final RestRequest request, ClusterStateResponse state, return table; } + + @Override + public Set supportedCapabilities() { + return CAPABILITIES; + } }