Skip to content

Commit a80ed6b

Browse files
committed
Add implicit ListVolumesResponse#Entry pagination limit
1 parent 23a3d0a commit a80ed6b

File tree

2 files changed

+81
-4
lines changed

2 files changed

+81
-4
lines changed

pkg/gce-pd-csi-driver/controller.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ const (
8181

8282
replicationTypeNone = "none"
8383
replicationTypeRegionalPD = "regional-pd"
84+
85+
// The maximum number of entries that we can include in the
86+
// ListVolumesResposne
87+
// In reality, the limit here is 4MB (based on gRPC client response limits),
88+
// but 500 is a good proxy (gives ~8KB of data per ListVolumesResponse#Entry)
89+
// See https://github.com/grpc/grpc/blob/master/include/grpc/impl/codegen/grpc_types.h#L503)
90+
maxListVolumesResponseEntries = 500
8491
)
8592

8693
func isDiskReady(disk *gce.CloudDisk) (bool, error) {
@@ -708,7 +715,7 @@ func (gceCS *GCEControllerServer) ListVolumes(ctx context.Context, req *csi.List
708715

709716
var maxEntries int = int(req.MaxEntries)
710717
if maxEntries == 0 {
711-
maxEntries = len(gceCS.disks)
718+
maxEntries = maxListVolumesResponseEntries
712719
}
713720

714721
entries := []*csi.ListVolumesResponse_Entry{}

pkg/gce-pd-csi-driver/controller_test.go

+73-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ limitations under the License.
1515
package gceGCEDriver
1616

1717
import (
18+
"context"
1819
"fmt"
1920
"math/rand"
2021
"reflect"
@@ -25,8 +26,6 @@ import (
2526
"github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/meta"
2627
"github.com/golang/protobuf/ptypes"
2728

28-
"context"
29-
3029
compute "google.golang.org/api/compute/v1"
3130
"google.golang.org/grpc/codes"
3231
"google.golang.org/grpc/status"
@@ -840,8 +839,79 @@ func TestCreateVolumeArguments(t *testing.T) {
840839
}
841840
}
842841

842+
func TestListVolumePagination(t *testing.T) {
843+
testCases := []struct {
844+
name string
845+
diskCount int
846+
maxEntries int32
847+
expectedEntries []int
848+
}{
849+
{
850+
name: "no pagination (implicit)",
851+
diskCount: 325,
852+
expectedEntries: []int{325},
853+
},
854+
{
855+
name: "no pagination (explicit)",
856+
diskCount: 2500,
857+
maxEntries: 2500,
858+
expectedEntries: []int{2500},
859+
},
860+
{
861+
name: "pagination (implicit)",
862+
diskCount: 1327,
863+
expectedEntries: []int{500, 500, 327},
864+
},
865+
{
866+
name: "pagination (explicit)",
867+
diskCount: 723,
868+
maxEntries: 200,
869+
expectedEntries: []int{200, 200, 200, 123},
870+
},
871+
{
872+
name: "pagination (explicit)",
873+
diskCount: 3253,
874+
maxEntries: 1000,
875+
expectedEntries: []int{1000, 1000, 1000, 253},
876+
},
877+
}
878+
879+
for _, tc := range testCases {
880+
t.Run(tc.name, func(t *testing.T) {
881+
// Setup new driver each time so no interference
882+
var d []*gce.CloudDisk
883+
for i := 0; i < tc.diskCount; i++ {
884+
// Create diskCount dummy disks
885+
d = append(d, gce.CloudDiskFromV1(&compute.Disk{Name: fmt.Sprintf("%v", i)}))
886+
}
887+
gceDriver := initGCEDriver(t, d)
888+
tok := ""
889+
for i, expectedEntry := range tc.expectedEntries {
890+
lvr := &csi.ListVolumesRequest{
891+
MaxEntries: tc.maxEntries,
892+
StartingToken: tok,
893+
}
894+
resp, err := gceDriver.cs.ListVolumes(context.TODO(), lvr)
895+
if err != nil {
896+
t.Fatalf("Got error %v", err)
897+
return
898+
}
899+
900+
if len(resp.Entries) != expectedEntry {
901+
t.Fatalf("Got %v entries, expected %v on call # %d", len(resp.Entries), expectedEntry, i+1)
902+
}
903+
904+
tok = resp.NextToken
905+
}
906+
if len(tok) != 0 {
907+
t.Fatalf("Expected no more entries, but got NextToken in response: %s", tok)
908+
}
909+
})
910+
}
911+
}
912+
843913
func TestListVolumeArgs(t *testing.T) {
844-
diskCount := 600
914+
diskCount := 500
845915
testCases := []struct {
846916
name string
847917
maxEntries int32

0 commit comments

Comments
 (0)