storage validation: accept generic ephemeral volumes as volume device

Raw block devices are possible with generic ephemeral volumes, so rejecting a
pod with that combination is wrong.
This commit is contained in:
Patrick Ohly 2021-10-14 18:01:09 +02:00
parent dea052ceba
commit a40d2eb18c
2 changed files with 34 additions and 5 deletions

View File

@ -416,9 +416,12 @@ func IsMatchedVolume(name string, volumes map[string]core.VolumeSource) bool {
return false
}
func isMatchedDevice(name string, volumes map[string]core.VolumeSource) (bool, bool) {
// isMatched checks whether the volume with the given name is used by a
// container and if so, if it involves a PVC.
func isMatchedDevice(name string, volumes map[string]core.VolumeSource) (isMatched bool, isPVC bool) {
if source, ok := volumes[name]; ok {
if source.PersistentVolumeClaim != nil {
if source.PersistentVolumeClaim != nil ||
source.Ephemeral != nil {
return true, true
}
return true, false
@ -2609,9 +2612,9 @@ func ValidateVolumeDevices(devices []core.VolumeDevice, volmounts map[string]str
if devicename.Has(devName) {
allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), devName, "must be unique"))
}
// Must be PersistentVolumeClaim volume source
// Must be based on PersistentVolumeClaim (PVC reference or generic ephemeral inline volume)
if didMatch && !isPVC {
allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), devName, "can only use volume source type of PersistentVolumeClaim for block mode"))
allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), devName, "can only use volume source type of PersistentVolumeClaim or Ephemeral for block mode"))
}
if !didMatch {
allErrs = append(allErrs, field.NotFound(idxPath.Child("name"), devName))

View File

@ -5532,6 +5532,18 @@ func TestValidateVolumeMounts(t *testing.T) {
{Name: "abc", VolumeSource: core.VolumeSource{PersistentVolumeClaim: &core.PersistentVolumeClaimVolumeSource{ClaimName: "testclaim1"}}},
{Name: "abc-123", VolumeSource: core.VolumeSource{PersistentVolumeClaim: &core.PersistentVolumeClaimVolumeSource{ClaimName: "testclaim2"}}},
{Name: "123", VolumeSource: core.VolumeSource{HostPath: &core.HostPathVolumeSource{Path: "/foo/baz", Type: newHostPathType(string(core.HostPathUnset))}}},
{Name: "ephemeral", VolumeSource: core.VolumeSource{Ephemeral: &core.EphemeralVolumeSource{VolumeClaimTemplate: &core.PersistentVolumeClaimTemplate{
Spec: core.PersistentVolumeClaimSpec{
AccessModes: []core.PersistentVolumeAccessMode{
core.ReadWriteOnce,
},
Resources: core.ResourceRequirements{
Requests: core.ResourceList{
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
},
},
},
}}}},
}
vols, v1err := ValidateVolumes(volumes, nil, field.NewPath("field"), PodValidationOptions{})
if len(v1err) > 0 {
@ -5554,6 +5566,7 @@ func TestValidateVolumeMounts(t *testing.T) {
{Name: "abc-123", MountPath: "G:\\mount", SubPath: ""},
{Name: "abc-123", MountPath: "/bac", SubPath: ".baz"},
{Name: "abc-123", MountPath: "/bad", SubPath: "..baz"},
{Name: "ephemeral", MountPath: "/foobar"},
}
goodVolumeDevices := []core.VolumeDevice{
{Name: "xyz", DevicePath: "/foofoo"},
@ -5851,6 +5864,18 @@ func TestAlphaValidateVolumeDevices(t *testing.T) {
{Name: "abc", VolumeSource: core.VolumeSource{PersistentVolumeClaim: &core.PersistentVolumeClaimVolumeSource{ClaimName: "testclaim1"}}},
{Name: "abc-123", VolumeSource: core.VolumeSource{PersistentVolumeClaim: &core.PersistentVolumeClaimVolumeSource{ClaimName: "testclaim2"}}},
{Name: "def", VolumeSource: core.VolumeSource{HostPath: &core.HostPathVolumeSource{Path: "/foo/baz", Type: newHostPathType(string(core.HostPathUnset))}}},
{Name: "ephemeral", VolumeSource: core.VolumeSource{Ephemeral: &core.EphemeralVolumeSource{VolumeClaimTemplate: &core.PersistentVolumeClaimTemplate{
Spec: core.PersistentVolumeClaimSpec{
AccessModes: []core.PersistentVolumeAccessMode{
core.ReadWriteOnce,
},
Resources: core.ResourceRequirements{
Requests: core.ResourceList{
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
},
},
},
}}}},
}
vols, v1err := ValidateVolumes(volumes, nil, field.NewPath("field"), PodValidationOptions{})
@ -5862,6 +5887,7 @@ func TestAlphaValidateVolumeDevices(t *testing.T) {
successCase := []core.VolumeDevice{
{Name: "abc", DevicePath: "/foo"},
{Name: "abc-123", DevicePath: "/usr/share/test"},
{Name: "ephemeral", DevicePath: "/disk"},
}
goodVolumeMounts := []core.VolumeMount{
{Name: "xyz", MountPath: "/foofoo"},
@ -5887,7 +5913,7 @@ func TestAlphaValidateVolumeDevices(t *testing.T) {
}
// Success Cases:
// Validate normal success cases - only PVC volumeSource
// Validate normal success cases - only PVC volumeSource or generic ephemeral volume
if errs := ValidateVolumeDevices(successCase, GetVolumeMountMap(goodVolumeMounts), vols, field.NewPath("field")); len(errs) != 0 {
t.Errorf("expected success: %v", errs)
}