17587: Don't reject federated query with large limit param.
authorTom Clegg <tom@curii.com>
Tue, 4 May 2021 18:20:27 +0000 (14:20 -0400)
committerTom Clegg <tom@curii.com>
Tue, 4 May 2021 20:00:48 +0000 (16:00 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

lib/controller/federation/list.go
lib/controller/federation/list_test.go

index bc6d3e00a493361b4d9897aeab77e3abf5cced27..183557eb15a4780bbe3388e3185ae9064dc609e3 100644 (file)
@@ -205,8 +205,8 @@ func (conn *Conn) splitListRequest(ctx context.Context, opts arvados.ListOptions
        if opts.Count != "none" {
                return httpErrorf(http.StatusBadRequest, "cannot execute federated list query unless count==\"none\"")
        }
-       if opts.Limit >= 0 || opts.Offset != 0 || len(opts.Order) > 0 {
-               return httpErrorf(http.StatusBadRequest, "cannot execute federated list query with limit, offset, or order parameter")
+       if (opts.Limit >= 0 && opts.Limit < int64(nUUIDs)) || opts.Offset != 0 || len(opts.Order) > 0 {
+               return httpErrorf(http.StatusBadRequest, "cannot execute federated list query with limit (%d) < nUUIDs (%d), offset (%d) > 0, or order (%v) parameter", opts.Limit, nUUIDs, opts.Offset, opts.Order)
        }
        if max := conn.cluster.API.MaxItemsPerResponse; nUUIDs > max {
                return httpErrorf(http.StatusBadRequest, "cannot execute federated list query because number of UUIDs (%d) exceeds page size limit %d", nUUIDs, max)
index e6d2816f610417e9c980ba539930532da768fc7c..2a4e230c96c700a0037ed9da589c7e0d8acab152 100644 (file)
@@ -300,6 +300,7 @@ func (s *CollectionListSuite) TestCollectionListMultiSiteExtraFilters(c *check.C
 
 func (s *CollectionListSuite) TestCollectionListMultiSiteWithCount(c *check.C) {
        for _, count := range []string{"", "exact"} {
+               s.SetUpTest(c)
                s.test(c, listTrial{
                        count: count,
                        limit: -1,
@@ -315,11 +316,12 @@ func (s *CollectionListSuite) TestCollectionListMultiSiteWithCount(c *check.C) {
 
 func (s *CollectionListSuite) TestCollectionListMultiSiteWithLimit(c *check.C) {
        for _, limit := range []int64{0, 1, 2} {
+               s.SetUpTest(c)
                s.test(c, listTrial{
                        count: "none",
                        limit: limit,
                        filters: []arvados.Filter{
-                               {"uuid", "in", []string{s.uuids[0][0], s.uuids[1][0]}},
+                               {"uuid", "in", []string{s.uuids[0][0], s.uuids[1][0], s.uuids[2][0]}},
                                {"uuid", "is_a", "teapot"},
                        },
                        expectCalls:  []int{0, 0, 0},
@@ -328,6 +330,22 @@ func (s *CollectionListSuite) TestCollectionListMultiSiteWithLimit(c *check.C) {
        }
 }
 
+func (s *CollectionListSuite) TestCollectionListMultiSiteWithHighLimit(c *check.C) {
+       uuids := []string{s.uuids[0][0], s.uuids[1][0], s.uuids[2][0]}
+       for _, limit := range []int64{3, 4, 1234567890} {
+               s.SetUpTest(c)
+               s.test(c, listTrial{
+                       count: "none",
+                       limit: limit,
+                       filters: []arvados.Filter{
+                               {"uuid", "in", uuids},
+                       },
+                       expectUUIDs: uuids,
+                       expectCalls: []int{1, 1, 1},
+               })
+       }
+}
+
 func (s *CollectionListSuite) TestCollectionListMultiSiteWithOffset(c *check.C) {
        s.test(c, listTrial{
                count:  "none",