Skip to content

Commit 84d4249

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

File tree

2 files changed

+82
-4
lines changed

2 files changed

+82
-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

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

0 commit comments

Comments
 (0)