Skip to content

Commit b60f08e

Browse files
committed
storage: validate CSIDriver.Spec.VolumeLifecycleModes
This ensures that users get a good error message early on when trying to do something that isn't okay: $ kubectl create -f csi-hostpath-driverinfo.yaml The CSIDriver "hostpath.csi.k8s.io" is invalid: spec.volumeLifecycleModes: Unsupported value: "foobar": supported values: "persistent", "ephemeral"
1 parent f7742fd commit b60f08e

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed

pkg/apis/storage/validation/validation.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ func validateCSIDriverSpec(
419419
allErrs := field.ErrorList{}
420420
allErrs = append(allErrs, validateAttachRequired(spec.AttachRequired, fldPath.Child("attachedRequired"))...)
421421
allErrs = append(allErrs, validatePodInfoOnMount(spec.PodInfoOnMount, fldPath.Child("podInfoOnMount"))...)
422+
allErrs = append(allErrs, validateVolumeLifecycleModes(spec.VolumeLifecycleModes, fldPath.Child("volumeLifecycleModes"))...)
422423
return allErrs
423424
}
424425

@@ -441,3 +442,21 @@ func validatePodInfoOnMount(podInfoOnMount *bool, fldPath *field.Path) field.Err
441442

442443
return allErrs
443444
}
445+
446+
// validateVolumeLifecycleModes tests if mode has one of the allowed values.
447+
func validateVolumeLifecycleModes(modes []storage.VolumeLifecycleMode, fldPath *field.Path) field.ErrorList {
448+
allErrs := field.ErrorList{}
449+
for _, mode := range modes {
450+
switch mode {
451+
case storage.VolumeLifecyclePersistent, storage.VolumeLifecycleEphemeral:
452+
default:
453+
allErrs = append(allErrs, field.NotSupported(fldPath, mode,
454+
[]string{
455+
string(storage.VolumeLifecyclePersistent),
456+
string(storage.VolumeLifecycleEphemeral),
457+
}))
458+
}
459+
}
460+
461+
return allErrs
462+
}

pkg/apis/storage/validation/validation_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1726,6 +1726,49 @@ func TestCSIDriverValidation(t *testing.T) {
17261726
PodInfoOnMount: &notPodInfoOnMount,
17271727
},
17281728
},
1729+
{
1730+
ObjectMeta: metav1.ObjectMeta{Name: driverName},
1731+
Spec: storage.CSIDriverSpec{
1732+
AttachRequired: &attachNotRequired,
1733+
PodInfoOnMount: &notPodInfoOnMount,
1734+
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
1735+
storage.VolumeLifecyclePersistent,
1736+
},
1737+
},
1738+
},
1739+
{
1740+
ObjectMeta: metav1.ObjectMeta{Name: driverName},
1741+
Spec: storage.CSIDriverSpec{
1742+
AttachRequired: &attachNotRequired,
1743+
PodInfoOnMount: &notPodInfoOnMount,
1744+
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
1745+
storage.VolumeLifecycleEphemeral,
1746+
},
1747+
},
1748+
},
1749+
{
1750+
ObjectMeta: metav1.ObjectMeta{Name: driverName},
1751+
Spec: storage.CSIDriverSpec{
1752+
AttachRequired: &attachNotRequired,
1753+
PodInfoOnMount: &notPodInfoOnMount,
1754+
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
1755+
storage.VolumeLifecycleEphemeral,
1756+
storage.VolumeLifecyclePersistent,
1757+
},
1758+
},
1759+
},
1760+
{
1761+
ObjectMeta: metav1.ObjectMeta{Name: driverName},
1762+
Spec: storage.CSIDriverSpec{
1763+
AttachRequired: &attachNotRequired,
1764+
PodInfoOnMount: &notPodInfoOnMount,
1765+
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
1766+
storage.VolumeLifecycleEphemeral,
1767+
storage.VolumeLifecyclePersistent,
1768+
storage.VolumeLifecycleEphemeral,
1769+
},
1770+
},
1771+
},
17291772
}
17301773

17311774
for _, csiDriver := range successCases {
@@ -1764,6 +1807,17 @@ func TestCSIDriverValidation(t *testing.T) {
17641807
PodInfoOnMount: nil,
17651808
},
17661809
},
1810+
{
1811+
// invalid mode
1812+
ObjectMeta: metav1.ObjectMeta{Name: driverName},
1813+
Spec: storage.CSIDriverSpec{
1814+
AttachRequired: &attachNotRequired,
1815+
PodInfoOnMount: &notPodInfoOnMount,
1816+
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
1817+
"no-such-mode",
1818+
},
1819+
},
1820+
},
17671821
}
17681822

17691823
for _, csiDriver := range errorCases {

pkg/registry/storage/csidriver/strategy_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,71 @@ func TestCSIDriverValidation(t *testing.T) {
296296
},
297297
true,
298298
},
299+
{
300+
"invalid volume mode",
301+
&storage.CSIDriver{
302+
ObjectMeta: metav1.ObjectMeta{
303+
Name: "foo",
304+
},
305+
Spec: storage.CSIDriverSpec{
306+
AttachRequired: &attachRequired,
307+
PodInfoOnMount: &podInfoOnMount,
308+
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
309+
storage.VolumeLifecycleMode("no-such-mode"),
310+
},
311+
},
312+
},
313+
true,
314+
},
315+
{
316+
"persistent volume mode",
317+
&storage.CSIDriver{
318+
ObjectMeta: metav1.ObjectMeta{
319+
Name: "foo",
320+
},
321+
Spec: storage.CSIDriverSpec{
322+
AttachRequired: &attachRequired,
323+
PodInfoOnMount: &podInfoOnMount,
324+
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
325+
storage.VolumeLifecyclePersistent,
326+
},
327+
},
328+
},
329+
false,
330+
},
331+
{
332+
"ephemeral volume mode",
333+
&storage.CSIDriver{
334+
ObjectMeta: metav1.ObjectMeta{
335+
Name: "foo",
336+
},
337+
Spec: storage.CSIDriverSpec{
338+
AttachRequired: &attachRequired,
339+
PodInfoOnMount: &podInfoOnMount,
340+
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
341+
storage.VolumeLifecycleEphemeral,
342+
},
343+
},
344+
},
345+
false,
346+
},
347+
{
348+
"both volume modes",
349+
&storage.CSIDriver{
350+
ObjectMeta: metav1.ObjectMeta{
351+
Name: "foo",
352+
},
353+
Spec: storage.CSIDriverSpec{
354+
AttachRequired: &attachRequired,
355+
PodInfoOnMount: &podInfoOnMount,
356+
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
357+
storage.VolumeLifecyclePersistent,
358+
storage.VolumeLifecycleEphemeral,
359+
},
360+
},
361+
},
362+
false,
363+
},
299364
}
300365

301366
for _, test := range tests {

0 commit comments

Comments
 (0)