Skip to content

Commit ae5e196

Browse files
committed
Support all Kubernetes access modes
Signed-off-by: Luis Pabón <[email protected]>
1 parent 7257060 commit ae5e196

File tree

2 files changed

+144
-12
lines changed

2 files changed

+144
-12
lines changed

pkg/controller/controller.go

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,6 @@ type csiProvisioner struct {
9393
var _ controller.Provisioner = &csiProvisioner{}
9494

9595
var (
96-
accessMode = &csi.VolumeCapability_AccessMode{
97-
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
98-
}
9996
accessType = &csi.VolumeCapability_Mount{
10097
Mount: &csi.VolumeCapability_MountVolume{},
10198
}
@@ -370,17 +367,40 @@ func (p *csiProvisioner) Provision(options controller.VolumeOptions) (*v1.Persis
370367
capacity := options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
371368
volSizeBytes := capacity.Value()
372369

370+
// Get access mode
371+
volumeCaps := make([]*csi.VolumeCapability, 0)
372+
for _, cap := range options.PVC.Spec.AccessModes {
373+
switch cap {
374+
case v1.ReadWriteOnce:
375+
volumeCaps = append(volumeCaps, &csi.VolumeCapability{
376+
AccessMode: &csi.VolumeCapability_AccessMode{
377+
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
378+
},
379+
AccessType: accessType,
380+
})
381+
case v1.ReadWriteMany:
382+
volumeCaps = append(volumeCaps, &csi.VolumeCapability{
383+
AccessMode: &csi.VolumeCapability_AccessMode{
384+
Mode: csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER,
385+
},
386+
AccessType: accessType,
387+
})
388+
case v1.ReadOnlyMany:
389+
volumeCaps = append(volumeCaps, &csi.VolumeCapability{
390+
AccessMode: &csi.VolumeCapability_AccessMode{
391+
Mode: csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY,
392+
},
393+
AccessType: accessType,
394+
})
395+
}
396+
}
397+
373398
// Create a CSI CreateVolumeRequest and Response
374399
req := csi.CreateVolumeRequest{
375400

376-
Name: pvName,
377-
Parameters: options.Parameters,
378-
VolumeCapabilities: []*csi.VolumeCapability{
379-
{
380-
AccessType: accessType,
381-
AccessMode: accessMode,
382-
},
383-
},
401+
Name: pvName,
402+
Parameters: options.Parameters,
403+
VolumeCapabilities: volumeCaps,
384404
CapacityRange: &csi.CapacityRange{
385405
RequiredBytes: int64(volSizeBytes),
386406
},

pkg/controller/controller_test.go

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package controller
1818

1919
import (
20+
"context"
2021
"errors"
2122
"fmt"
2223
"reflect"
@@ -820,6 +821,7 @@ func TestProvision(t *testing.T) {
820821
expectedPVSpec *pvSpec
821822
withSecretRefs bool
822823
expectErr bool
824+
expectCreateVolDo interface{}
823825
}{
824826
"normal provision": {
825827
volOpts: controller.VolumeOptions{
@@ -846,7 +848,103 @@ func TestProvision(t *testing.T) {
846848
},
847849
},
848850
},
849-
"provision with access modes": {
851+
"provision with access mode multi node multi writer": {
852+
volOpts: controller.VolumeOptions{
853+
PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete,
854+
PVName: "test-name",
855+
PVC: &v1.PersistentVolumeClaim{
856+
ObjectMeta: metav1.ObjectMeta{
857+
UID: "testid",
858+
},
859+
Spec: v1.PersistentVolumeClaimSpec{
860+
Selector: nil,
861+
Resources: v1.ResourceRequirements{
862+
Requests: v1.ResourceList{
863+
v1.ResourceName(v1.ResourceStorage): resource.MustParse(strconv.FormatInt(requestedBytes, 10)),
864+
},
865+
},
866+
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteMany},
867+
},
868+
},
869+
Parameters: map[string]string{},
870+
},
871+
expectedPVSpec: &pvSpec{
872+
Name: "test-testi",
873+
ReclaimPolicy: v1.PersistentVolumeReclaimDelete,
874+
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteMany},
875+
Capacity: v1.ResourceList{
876+
v1.ResourceName(v1.ResourceStorage): bytesToGiQuantity(requestedBytes),
877+
},
878+
CSIPVS: &v1.CSIPersistentVolumeSource{
879+
Driver: "test-driver",
880+
VolumeHandle: "test-volume-id",
881+
FSType: "ext4",
882+
VolumeAttributes: map[string]string{
883+
"storage.kubernetes.io/csiProvisionerIdentity": "test-provisioner",
884+
},
885+
},
886+
},
887+
expectCreateVolDo: func(ctx context.Context, req *csi.CreateVolumeRequest) {
888+
if len(req.GetVolumeCapabilities()) != 1 {
889+
t.Errorf("Incorrect length in volume capabilities")
890+
}
891+
if req.GetVolumeCapabilities()[0].GetAccessMode() == nil {
892+
t.Errorf("Expected access mode to be set")
893+
}
894+
if req.GetVolumeCapabilities()[0].GetAccessMode().GetMode() != csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER {
895+
t.Errorf("Expected multi_node_multi_writer")
896+
}
897+
},
898+
},
899+
"provision with access mode multi node multi readonly": {
900+
volOpts: controller.VolumeOptions{
901+
PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete,
902+
PVName: "test-name",
903+
PVC: &v1.PersistentVolumeClaim{
904+
ObjectMeta: metav1.ObjectMeta{
905+
UID: "testid",
906+
},
907+
Spec: v1.PersistentVolumeClaimSpec{
908+
Selector: nil,
909+
Resources: v1.ResourceRequirements{
910+
Requests: v1.ResourceList{
911+
v1.ResourceName(v1.ResourceStorage): resource.MustParse(strconv.FormatInt(requestedBytes, 10)),
912+
},
913+
},
914+
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadOnlyMany},
915+
},
916+
},
917+
Parameters: map[string]string{},
918+
},
919+
expectedPVSpec: &pvSpec{
920+
Name: "test-testi",
921+
ReclaimPolicy: v1.PersistentVolumeReclaimDelete,
922+
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadOnlyMany},
923+
Capacity: v1.ResourceList{
924+
v1.ResourceName(v1.ResourceStorage): bytesToGiQuantity(requestedBytes),
925+
},
926+
CSIPVS: &v1.CSIPersistentVolumeSource{
927+
Driver: "test-driver",
928+
VolumeHandle: "test-volume-id",
929+
FSType: "ext4",
930+
VolumeAttributes: map[string]string{
931+
"storage.kubernetes.io/csiProvisionerIdentity": "test-provisioner",
932+
},
933+
},
934+
},
935+
expectCreateVolDo: func(ctx context.Context, req *csi.CreateVolumeRequest) {
936+
if len(req.GetVolumeCapabilities()) != 1 {
937+
t.Errorf("Incorrect length in volume capabilities")
938+
}
939+
if req.GetVolumeCapabilities()[0].GetAccessMode() == nil {
940+
t.Errorf("Expected access mode to be set")
941+
}
942+
if req.GetVolumeCapabilities()[0].GetAccessMode().GetMode() != csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY {
943+
t.Errorf("Expected multi_node_reader_only")
944+
}
945+
},
946+
},
947+
"provision with access mode single writer": {
850948
volOpts: controller.VolumeOptions{
851949
PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete,
852950
PVName: "test-name",
@@ -882,6 +980,17 @@ func TestProvision(t *testing.T) {
882980
},
883981
},
884982
},
983+
expectCreateVolDo: func(ctx context.Context, req *csi.CreateVolumeRequest) {
984+
if len(req.GetVolumeCapabilities()) != 1 {
985+
t.Errorf("Incorrect length in volume capabilities")
986+
}
987+
if req.GetVolumeCapabilities()[0].GetAccessMode() == nil {
988+
t.Errorf("Expected access mode to be set")
989+
}
990+
if req.GetVolumeCapabilities()[0].GetAccessMode().GetMode() != csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER {
991+
t.Errorf("Expected single_node_writer")
992+
}
993+
},
885994
},
886995
"provision with secrets": {
887996
volOpts: controller.VolumeOptions{
@@ -1038,6 +1147,9 @@ func TestProvision(t *testing.T) {
10381147
provisionMockServerSetupExpectations(identityServer, controllerServer)
10391148
controllerServer.EXPECT().CreateVolume(gomock.Any(), gomock.Any()).Return(out, nil).Times(1)
10401149
controllerServer.EXPECT().DeleteVolume(gomock.Any(), gomock.Any()).Return(&csi.DeleteVolumeResponse{}, nil).Times(1)
1150+
} else if tc.expectCreateVolDo != nil {
1151+
provisionMockServerSetupExpectations(identityServer, controllerServer)
1152+
controllerServer.EXPECT().CreateVolume(gomock.Any(), gomock.Any()).Do(tc.expectCreateVolDo).Return(out, nil).Times(1)
10411153
} else {
10421154
// Setup regular mock call expectations.
10431155
provisionMockServerSetupExpectations(identityServer, controllerServer)

0 commit comments

Comments
 (0)