Browse Source

Get data stream accepts single search parameter (#54530)

Dan Hermann 5 years ago
parent
commit
959f41e3d1

+ 2 - 2
rest-api-spec/src/main/resources/rest-api-spec/api/indices.get_data_streams.json

@@ -20,8 +20,8 @@
           ],
           "parts":{
             "name":{
-              "type":"list",
-              "description":"The comma separated names of data streams"
+              "type":"string",
+              "description":"The name or wildcard expression of the requested data streams"
             }
           }
         }

+ 66 - 1
rest-api-spec/src/main/resources/rest-api-spec/test/indices.data_stream/10_basic.yml

@@ -19,7 +19,8 @@
   - is_true: acknowledged
 
   - do:
-      indices.get_data_streams: {}
+      indices.get_data_streams:
+        name: "*"
   - match: { 0.name: simple-data-stream1 }
   - match: { 0.timestamp_field: '@timestamp' }
   - length: { 0.indices: 1 }
@@ -54,3 +55,67 @@
 
   - match: { status: 400 }
   - match: { error.root_cause.0.type: "illegal_argument_exception" }
+
+---
+"Get data stream":
+  - skip:
+      version: " - 7.99.99"
+      reason: available only in 7.7+
+
+  - do:
+      indices.create_data_stream:
+        name: get-data-stream1
+        body:
+          timestamp_field: "@timestamp"
+  - is_true: acknowledged
+
+  - do:
+      indices.create_data_stream:
+        name: get-data-stream2
+        body:
+          timestamp_field: "@timestamp2"
+  - is_true: acknowledged
+
+  - do:
+      indices.get_data_streams: {}
+  - match: { 0.name: get-data-stream1 }
+  - match: { 0.timestamp_field: '@timestamp' }
+  - match: { 1.name: get-data-stream2 }
+  - match: { 1.timestamp_field: '@timestamp2' }
+
+  - do:
+      indices.get_data_streams:
+        name: get-data-stream1
+  - match: { 0.name: get-data-stream1 }
+  - match: { 0.timestamp_field: '@timestamp' }
+
+  - do:
+      indices.get_data_streams:
+        name: get-data-*
+  - match: { 0.name: get-data-stream1 }
+  - match: { 0.timestamp_field: '@timestamp' }
+  - match: { 1.name: get-data-stream2 }
+  - match: { 1.timestamp_field: '@timestamp2' }
+
+  - do:
+      indices.get_data_streams:
+        name: nonexistent-data-stream
+      catch: missing
+
+  - match: { status: 404 }
+  - match: { error.root_cause.0.type: "resource_not_found_exception" }
+
+  - do:
+      indices.get_data_streams:
+        name: nonexistent*
+  - match: { $body: [] }
+
+  - do:
+      indices.delete_data_stream:
+        name: get-data-stream1
+  - is_true: acknowledged
+
+  - do:
+      indices.delete_data_stream:
+        name: get-data-stream2
+  - is_true: acknowledged

+ 17 - 17
server/src/main/java/org/elasticsearch/action/admin/indices/datastream/GetDataStreamsAction.java

@@ -18,6 +18,7 @@
  */
 package org.elasticsearch.action.admin.indices.datastream;
 
+import org.elasticsearch.ResourceNotFoundException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.ActionRequestValidationException;
 import org.elasticsearch.action.ActionResponse;
@@ -43,7 +44,7 @@ import org.elasticsearch.transport.TransportService;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -59,10 +60,10 @@ public class GetDataStreamsAction extends ActionType<GetDataStreamsAction.Respon
 
     public static class Request extends MasterNodeReadRequest<Request> {
 
-        private final String[] names;
+        private final String name;
 
-        public Request(String[] names) {
-            this.names = Objects.requireNonNull(names);
+        public Request(String name) {
+            this.name = name;
         }
 
         @Override
@@ -72,13 +73,13 @@ public class GetDataStreamsAction extends ActionType<GetDataStreamsAction.Respon
 
         public Request(StreamInput in) throws IOException {
             super(in);
-            this.names = in.readStringArray();
+            this.name = in.readOptionalString();
         }
 
         @Override
         public void writeTo(StreamOutput out) throws IOException {
             super.writeTo(out);
-            out.writeStringArray(names);
+            out.writeOptionalString(name);
         }
 
         @Override
@@ -86,12 +87,12 @@ public class GetDataStreamsAction extends ActionType<GetDataStreamsAction.Respon
             if (this == o) return true;
             if (o == null || getClass() != o.getClass()) return false;
             Request request = (Request) o;
-            return Arrays.equals(names, request.names);
+            return Objects.equals(name, request.name);
         }
 
         @Override
         public int hashCode() {
-            return Arrays.hashCode(names);
+            return Objects.hash(name);
         }
     }
 
@@ -164,22 +165,21 @@ public class GetDataStreamsAction extends ActionType<GetDataStreamsAction.Respon
             Map<String, DataStream> dataStreams = clusterState.metadata().dataStreams();
 
             // return all data streams if no name was specified
-            if (request.names.length == 0) {
-                return new ArrayList<>(dataStreams.values());
-            }
+            final String requestedName = request.name == null ? "*" : request.name;
 
             final List<DataStream> results = new ArrayList<>();
-            for (String name : request.names) {
-                if (Regex.isSimpleMatchPattern(name)) {
+                if (Regex.isSimpleMatchPattern(requestedName)) {
                     for (Map.Entry<String, DataStream> entry : dataStreams.entrySet()) {
-                        if (Regex.simpleMatch(name, entry.getKey())) {
+                        if (Regex.simpleMatch(requestedName, entry.getKey())) {
                             results.add(entry.getValue());
                         }
                     }
-                } else if (dataStreams.containsKey(name)) {
-                    results.add(dataStreams.get(name));
+                } else if (dataStreams.containsKey(request.name)) {
+                    results.add(dataStreams.get(request.name));
+                } else {
+                    throw new ResourceNotFoundException("data_stream matching [" + request.name + "] not found");
                 }
-            }
+            results.sort(Comparator.comparing(DataStream::getName));
             return results;
         }
 

+ 1 - 3
server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetDataStreamsAction.java

@@ -20,7 +20,6 @@ package org.elasticsearch.rest.action.admin.indices;
 
 import org.elasticsearch.action.admin.indices.datastream.GetDataStreamsAction;
 import org.elasticsearch.client.node.NodeClient;
-import org.elasticsearch.common.Strings;
 import org.elasticsearch.rest.BaseRestHandler;
 import org.elasticsearch.rest.RestRequest;
 import org.elasticsearch.rest.action.RestToXContentListener;
@@ -45,8 +44,7 @@ public class RestGetDataStreamsAction extends BaseRestHandler {
 
     @Override
     protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {
-        String[] names = Strings.splitStringByCommaToArray(request.param("name"));
-        GetDataStreamsAction.Request getDataStreamsRequest = new GetDataStreamsAction.Request(names);
+        GetDataStreamsAction.Request getDataStreamsRequest = new GetDataStreamsAction.Request(request.param("name"));
         return channel -> client.admin().indices().getDataStreams(getDataStreamsRequest, new RestToXContentListener<>(channel));
     }
 }

+ 55 - 13
server/src/test/java/org/elasticsearch/action/admin/indices/datastream/GetDataStreamsRequestTests.java

@@ -18,7 +18,7 @@
  */
 package org.elasticsearch.action.admin.indices.datastream;
 
-import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.ResourceNotFoundException;
 import org.elasticsearch.action.admin.indices.datastream.GetDataStreamsAction.Request;
 import org.elasticsearch.cluster.ClusterName;
 import org.elasticsearch.cluster.ClusterState;
@@ -31,6 +31,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
+import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
 
 public class GetDataStreamsRequestTests extends AbstractWireSerializingTestCase<Request> {
@@ -42,31 +43,72 @@ public class GetDataStreamsRequestTests extends AbstractWireSerializingTestCase<
 
     @Override
     protected Request createTestInstance() {
-        return new Request(generateRandomStringArray(8, 8, false));
+        final String searchParameter;
+        switch (randomIntBetween(1, 4)) {
+            case 1:
+                searchParameter = randomAlphaOfLength(8);
+                break;
+            case 2:
+                searchParameter = randomAlphaOfLength(8) + "*";
+                break;
+            case 3:
+                searchParameter = "*";
+                break;
+            default:
+                searchParameter = null;
+                break;
+        }
+        return new Request(searchParameter);
     }
 
-    public void testValidateRequest() {
-        GetDataStreamsAction.Request req = new GetDataStreamsAction.Request(new String[]{});
-        ActionRequestValidationException e = req.validate();
-        assertNull(e);
-    }
-
-    public void testGetDataStreams() {
+    public void testGetDataStream() {
         final String dataStreamName = "my-data-stream";
         DataStream existingDataStream = new DataStream(dataStreamName, "timestamp", Collections.emptyList());
         ClusterState cs = ClusterState.builder(new ClusterName("_name"))
             .metadata(Metadata.builder().dataStreams(Map.of(dataStreamName, existingDataStream)).build()).build();
-        GetDataStreamsAction.Request req = new GetDataStreamsAction.Request(new String[]{dataStreamName});
+        GetDataStreamsAction.Request req = new GetDataStreamsAction.Request(dataStreamName);
         List<DataStream> dataStreams = GetDataStreamsAction.TransportAction.getDataStreams(cs, req);
         assertThat(dataStreams.size(), equalTo(1));
         assertThat(dataStreams.get(0).getName(), equalTo(dataStreamName));
     }
 
+    public void testGetDataStreamsWithWildcards() {
+        final String[] dataStreamNames = {"my-data-stream", "another-data-stream"};
+        DataStream ds1 = new DataStream(dataStreamNames[0], "timestamp", Collections.emptyList());
+        DataStream ds2 = new DataStream(dataStreamNames[1], "timestamp", Collections.emptyList());
+        ClusterState cs = ClusterState.builder(new ClusterName("_name"))
+            .metadata(Metadata.builder().dataStreams(
+                Map.of(dataStreamNames[0], ds1, dataStreamNames[1], ds2)).build())
+            .build();
+
+        GetDataStreamsAction.Request req = new GetDataStreamsAction.Request(dataStreamNames[1].substring(0, 5) + "*");
+        List<DataStream> dataStreams = GetDataStreamsAction.TransportAction.getDataStreams(cs, req);
+        assertThat(dataStreams.size(), equalTo(1));
+        assertThat(dataStreams.get(0).getName(), equalTo(dataStreamNames[1]));
+
+        req = new GetDataStreamsAction.Request("*");
+        dataStreams = GetDataStreamsAction.TransportAction.getDataStreams(cs, req);
+        assertThat(dataStreams.size(), equalTo(2));
+        assertThat(dataStreams.get(0).getName(), equalTo(dataStreamNames[1]));
+        assertThat(dataStreams.get(1).getName(), equalTo(dataStreamNames[0]));
+
+        req = new GetDataStreamsAction.Request((String) null);
+        dataStreams = GetDataStreamsAction.TransportAction.getDataStreams(cs, req);
+        assertThat(dataStreams.size(), equalTo(2));
+        assertThat(dataStreams.get(0).getName(), equalTo(dataStreamNames[1]));
+        assertThat(dataStreams.get(1).getName(), equalTo(dataStreamNames[0]));
+
+        req = new GetDataStreamsAction.Request("matches-none*");
+        dataStreams = GetDataStreamsAction.TransportAction.getDataStreams(cs, req);
+        assertThat(dataStreams.size(), equalTo(0));
+    }
+
     public void testGetNonexistentDataStream() {
         final String dataStreamName = "my-data-stream";
         ClusterState cs = ClusterState.builder(new ClusterName("_name")).build();
-        GetDataStreamsAction.Request req = new GetDataStreamsAction.Request(new String[]{dataStreamName});
-        List<DataStream> dataStreams = GetDataStreamsAction.TransportAction.getDataStreams(cs, req);
-        assertThat(dataStreams.size(), equalTo(0));
+        GetDataStreamsAction.Request req = new GetDataStreamsAction.Request(dataStreamName);
+        ResourceNotFoundException e = expectThrows(ResourceNotFoundException.class,
+            () -> GetDataStreamsAction.TransportAction.getDataStreams(cs, req));
+        assertThat(e.getMessage(), containsString("data_stream matching [" + dataStreamName + "] not found"));
     }
 }