Skip to content

Commit 19d3c9b

Browse files
committed
turn on controller-publish-readonly flag and add validation in pd-csi driver for when readonly is on
1 parent bc88549 commit 19d3c9b

File tree

6 files changed

+90
-8
lines changed

6 files changed

+90
-8
lines changed

deploy/kubernetes/base/controller/controller.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ spec:
3636
# - "--run-node-service=false" # disable the node service of the CSI driver
3737
- "--leader-election"
3838
- "--default-fstype=ext4"
39+
- "--controller-publish-readonly=true"
3940
env:
4041
- name: PDCSI_NAMESPACE
4142
valueFrom:

deploy/kubernetes/images/stable-master/image.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ metadata:
44
name: imagetag-csi-provisioner
55
imageTag:
66
name: k8s.gcr.io/sig-storage/csi-provisioner
7-
newTag: "v2.2.1"
7+
newTag: "v3.0.0"
88

99
---
1010
apiVersion: builtin

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

+4
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ func (gceCS *GCEControllerServer) CreateVolume(ctx context.Context, req *csi.Cre
204204
return nil, status.Errorf(codes.NotFound, "CreateVolume source snapshot %s does not exist", snapshotID)
205205
}
206206
}
207+
} else { // if VolumeContentSource is nil, validate access mode is not read only
208+
if readonly, _ := getReadOnlyFromCapabilities(volumeCapabilities); readonly {
209+
return nil, status.Error(codes.InvalidArgument, "VolumeContentSource must be provided when AccessMode is set to read only")
210+
}
207211
}
208212

209213
// Create the disk

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

+2-7
Original file line numberDiff line numberDiff line change
@@ -356,19 +356,14 @@ func TestCreateVolumeArguments(t *testing.T) {
356356
},
357357
},
358358
{
359-
name: "success with MULTI_NODE_READER_ONLY",
359+
name: "fail with MULTI_NODE_READER_ONLY",
360360
req: &csi.CreateVolumeRequest{
361361
Name: "test-name",
362362
CapacityRange: stdCapRange,
363363
VolumeCapabilities: createVolumeCapabilities(csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY),
364364
Parameters: stdParams,
365365
},
366-
expVol: &csi.Volume{
367-
CapacityBytes: common.GbToBytes(20),
368-
VolumeId: testVolumeID,
369-
VolumeContext: nil,
370-
AccessibleTopology: stdTopology,
371-
},
366+
expErrCode: codes.InvalidArgument,
372367
},
373368
{
374369
name: "fail with mount/MULTI_NODE_MULTI_WRITER capabilities",

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

+25
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,31 @@ func getMultiWriterFromCapabilities(vcs []*csi.VolumeCapability) (bool, error) {
160160
return false, nil
161161
}
162162

163+
func getReadOnlyFromCapability(vc *csi.VolumeCapability) (bool, error) {
164+
if vc.GetAccessMode() == nil {
165+
return false, errors.New("access mode is nil")
166+
}
167+
mode := vc.GetAccessMode().GetMode()
168+
return (mode == csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY ||
169+
mode == csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY), nil
170+
}
171+
172+
func getReadOnlyFromCapabilities(vcs []*csi.VolumeCapability) (bool, error) {
173+
if vcs == nil {
174+
return false, errors.New("volume capabilities is nil")
175+
}
176+
for _, vc := range vcs {
177+
readOnly, err := getReadOnlyFromCapability(vc)
178+
if err != nil {
179+
return false, err
180+
}
181+
if readOnly {
182+
return true, nil
183+
}
184+
}
185+
return false, nil
186+
}
187+
163188
func collectMountOptions(fsType string, mntFlags []string) []string {
164189
var options []string
165190

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

+57
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,60 @@ func TestGetMultiWriterFromCapabilities(t *testing.T) {
234234
}
235235
}
236236
}
237+
238+
func TestGetReadOnlyFromCapabilities(t *testing.T) {
239+
testCases := []struct {
240+
name string
241+
vc []*csi.VolumeCapability
242+
expVal bool
243+
expErr bool
244+
}{
245+
{
246+
name: "false with empty capabilities",
247+
vc: []*csi.VolumeCapability{},
248+
expVal: false,
249+
},
250+
{
251+
name: "fail with capabilities no access mode",
252+
vc: []*csi.VolumeCapability{
253+
{
254+
AccessType: &csi.VolumeCapability_Mount{
255+
Mount: &csi.VolumeCapability_MountVolume{},
256+
},
257+
},
258+
},
259+
expErr: true,
260+
},
261+
{
262+
name: "false with SINGLE_NODE_WRITER capabilities",
263+
vc: createVolumeCapabilities(csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER),
264+
expVal: false,
265+
},
266+
{
267+
name: "true with MULTI_NODE_READER_ONLY capabilities",
268+
vc: createBlockVolumeCapabilities(csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY),
269+
expVal: true,
270+
},
271+
{
272+
name: "true with SINGLE_NODE_READER_ONLY capabilities",
273+
vc: createVolumeCapabilities(csi.VolumeCapability_AccessMode_SINGLE_NODE_READER_ONLY),
274+
expVal: true,
275+
},
276+
}
277+
278+
for _, tc := range testCases {
279+
t.Logf("Running test: %v", tc.name)
280+
val, err := getReadOnlyFromCapabilities(tc.vc)
281+
if tc.expErr && err == nil {
282+
t.Fatalf("Expected error but didn't get any")
283+
}
284+
if !tc.expErr && err != nil {
285+
t.Fatalf("Did not expect error but got: %v", err)
286+
}
287+
if err != nil {
288+
if tc.expVal != val {
289+
t.Fatalf("Expected '%t' but got '%t'", tc.expVal, val)
290+
}
291+
}
292+
}
293+
}

0 commit comments

Comments
 (0)