mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	VolumeDevices validation and tests
Signed-off-by: Serguei Bezverkhi <sbezverk@cisco.com>
This commit is contained in:
		@@ -264,7 +264,7 @@ func DropDisabledFields(podSpec, oldPodSpec *api.PodSpec) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dropDisabledVolumeDevicesAlphaFields(podSpec, oldPodSpec)
 | 
						dropDisabledVolumeDevicesFields(podSpec, oldPodSpec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dropDisabledRunAsGroupField(podSpec, oldPodSpec)
 | 
						dropDisabledRunAsGroupField(podSpec, oldPodSpec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -330,25 +330,16 @@ func dropDisabledProcMountField(podSpec, oldPodSpec *api.PodSpec) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// dropDisabledVolumeDevicesAlphaFields removes disabled fields from []VolumeDevice.
 | 
					// dropDisabledVolumeDevicesFields removes disabled fields from []VolumeDevice if it has not been already populated.
 | 
				
			||||||
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a VolumeDevice
 | 
					// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a VolumeDevice
 | 
				
			||||||
func dropDisabledVolumeDevicesAlphaFields(podSpec, oldPodSpec *api.PodSpec) {
 | 
					func dropDisabledVolumeDevicesFields(podSpec, oldPodSpec *api.PodSpec) {
 | 
				
			||||||
	if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
 | 
						if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeDevicesInUse(oldPodSpec) {
 | 
				
			||||||
		for i := range podSpec.Containers {
 | 
							for i := range podSpec.Containers {
 | 
				
			||||||
			podSpec.Containers[i].VolumeDevices = nil
 | 
								podSpec.Containers[i].VolumeDevices = nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for i := range podSpec.InitContainers {
 | 
							for i := range podSpec.InitContainers {
 | 
				
			||||||
			podSpec.InitContainers[i].VolumeDevices = nil
 | 
								podSpec.InitContainers[i].VolumeDevices = nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if oldPodSpec != nil {
 | 
					 | 
				
			||||||
			for i := range oldPodSpec.Containers {
 | 
					 | 
				
			||||||
				oldPodSpec.Containers[i].VolumeDevices = nil
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for i := range oldPodSpec.InitContainers {
 | 
					 | 
				
			||||||
				oldPodSpec.InitContainers[i].VolumeDevices = nil
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -436,3 +427,21 @@ func emptyDirSizeLimitInUse(podSpec *api.PodSpec) bool {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// volumeDevicesInUse returns true if the pod spec is non-nil and has VolumeDevices set.
 | 
				
			||||||
 | 
					func volumeDevicesInUse(podSpec *api.PodSpec) bool {
 | 
				
			||||||
 | 
						if podSpec == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := range podSpec.Containers {
 | 
				
			||||||
 | 
							if podSpec.Containers[i].VolumeDevices != nil {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := range podSpec.InitContainers {
 | 
				
			||||||
 | 
							if podSpec.InitContainers[i].VolumeDevices != nil {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -266,7 +266,8 @@ func TestPodConfigmaps(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestDropAlphaVolumeDevices(t *testing.T) {
 | 
					func TestDropAlphaVolumeDevices(t *testing.T) {
 | 
				
			||||||
	testPod := api.Pod{
 | 
						podWithVolumeDevices := func() *api.Pod {
 | 
				
			||||||
 | 
							return &api.Pod{
 | 
				
			||||||
			Spec: api.PodSpec{
 | 
								Spec: api.PodSpec{
 | 
				
			||||||
				RestartPolicy: api.RestartPolicyNever,
 | 
									RestartPolicy: api.RestartPolicyNever,
 | 
				
			||||||
				Containers: []api.Container{
 | 
									Containers: []api.Container{
 | 
				
			||||||
@@ -305,35 +306,106 @@ func TestDropAlphaVolumeDevices(t *testing.T) {
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Enable alpha feature BlockVolume
 | 
					 | 
				
			||||||
	defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// now test dropping the fields - should not be dropped
 | 
					 | 
				
			||||||
	DropDisabledFields(&testPod.Spec, nil)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// check to make sure VolumeDevices is still present
 | 
					 | 
				
			||||||
	// if featureset is set to true
 | 
					 | 
				
			||||||
	if testPod.Spec.Containers[0].VolumeDevices == nil {
 | 
					 | 
				
			||||||
		t.Error("VolumeDevices in Container should not have been dropped based on feature-gate")
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if testPod.Spec.InitContainers[0].VolumeDevices == nil {
 | 
						podWithoutVolumeDevices := func() *api.Pod {
 | 
				
			||||||
		t.Error("VolumeDevices in InitContainers should not have been dropped based on feature-gate")
 | 
							return &api.Pod{
 | 
				
			||||||
 | 
								Spec: api.PodSpec{
 | 
				
			||||||
 | 
									RestartPolicy: api.RestartPolicyNever,
 | 
				
			||||||
 | 
									Containers: []api.Container{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Name:  "container1",
 | 
				
			||||||
 | 
											Image: "testimage",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									InitContainers: []api.Container{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Name:  "container1",
 | 
				
			||||||
 | 
											Image: "testimage",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Volumes: []api.Volume{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Name: "myvolume",
 | 
				
			||||||
 | 
											VolumeSource: api.VolumeSource{
 | 
				
			||||||
 | 
												HostPath: &api.HostPathVolumeSource{
 | 
				
			||||||
 | 
													Path: "/dev/xvdc",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Disable alpha feature BlockVolume
 | 
						podInfo := []struct {
 | 
				
			||||||
	defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
 | 
							description      string
 | 
				
			||||||
 | 
							hasVolumeDevices bool
 | 
				
			||||||
	// now test dropping the fields
 | 
							pod              func() *api.Pod
 | 
				
			||||||
	DropDisabledFields(&testPod.Spec, nil)
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
	// check to make sure VolumeDevices is nil
 | 
								description:      "has VolumeDevices",
 | 
				
			||||||
	// if featureset is set to false
 | 
								hasVolumeDevices: true,
 | 
				
			||||||
	if testPod.Spec.Containers[0].VolumeDevices != nil {
 | 
								pod:              podWithVolumeDevices,
 | 
				
			||||||
		t.Error("DropDisabledFields for Containers failed")
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								description:      "does not have VolumeDevices",
 | 
				
			||||||
 | 
								hasVolumeDevices: false,
 | 
				
			||||||
 | 
								pod:              podWithoutVolumeDevices,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								description:      "is nil",
 | 
				
			||||||
 | 
								hasVolumeDevices: false,
 | 
				
			||||||
 | 
								pod:              func() *api.Pod { return nil },
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, enabled := range []bool{true, false} {
 | 
				
			||||||
 | 
							for _, oldPodInfo := range podInfo {
 | 
				
			||||||
 | 
								for _, newPodInfo := range podInfo {
 | 
				
			||||||
 | 
									oldPodHasVolumeDevices, oldPod := oldPodInfo.hasVolumeDevices, oldPodInfo.pod()
 | 
				
			||||||
 | 
									newPodHasVolumeDevices, newPod := newPodInfo.hasVolumeDevices, newPodInfo.pod()
 | 
				
			||||||
 | 
									if newPod == nil {
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) {
 | 
				
			||||||
 | 
										defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, enabled)()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										var oldPodSpec *api.PodSpec
 | 
				
			||||||
 | 
										if oldPod != nil {
 | 
				
			||||||
 | 
											oldPodSpec = &oldPod.Spec
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										DropDisabledFields(&newPod.Spec, oldPodSpec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// old pod should never be changed
 | 
				
			||||||
 | 
										if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) {
 | 
				
			||||||
 | 
											t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod()))
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										switch {
 | 
				
			||||||
 | 
										case enabled || oldPodHasVolumeDevices:
 | 
				
			||||||
 | 
											// new pod should not be changed if the feature is enabled, or if the old pod had VolumeDevices
 | 
				
			||||||
 | 
											if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
 | 
				
			||||||
 | 
												t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										case newPodHasVolumeDevices:
 | 
				
			||||||
 | 
											// new pod should be changed
 | 
				
			||||||
 | 
											if reflect.DeepEqual(newPod, newPodInfo.pod()) {
 | 
				
			||||||
 | 
												t.Errorf("new pod was not changed")
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											// new pod should not have VolumeDevices
 | 
				
			||||||
 | 
											if !reflect.DeepEqual(newPod, podWithoutVolumeDevices()) {
 | 
				
			||||||
 | 
												t.Errorf("new pod had VolumeDevices: %v", diff.ObjectReflectDiff(newPod, podWithoutVolumeDevices()))
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										default:
 | 
				
			||||||
 | 
											// new pod should not need to be changed
 | 
				
			||||||
 | 
											if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
 | 
				
			||||||
 | 
												t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	if testPod.Spec.InitContainers[0].VolumeDevices != nil {
 | 
					 | 
				
			||||||
		t.Error("DropDisabledFields for InitContainers failed")
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2298,10 +2298,6 @@ func ValidateVolumeDevices(devices []core.VolumeDevice, volmounts map[string]str
 | 
				
			|||||||
	devicepath := sets.NewString()
 | 
						devicepath := sets.NewString()
 | 
				
			||||||
	devicename := sets.NewString()
 | 
						devicename := sets.NewString()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if devices != nil && !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, field.Forbidden(fldPath.Child("volumeDevices"), "Container volumeDevices is disabled by feature-gate"))
 | 
					 | 
				
			||||||
		return allErrs
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if devices != nil {
 | 
						if devices != nil {
 | 
				
			||||||
		for i, dev := range devices {
 | 
							for i, dev := range devices {
 | 
				
			||||||
			idxPath := fldPath.Index(i)
 | 
								idxPath := fldPath.Index(i)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4974,10 +4974,6 @@ func TestAlphaValidateVolumeDevices(t *testing.T) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	disabledAlphaVolDevice := []core.VolumeDevice{
 | 
					 | 
				
			||||||
		{Name: "abc", DevicePath: "/foo"},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	successCase := []core.VolumeDevice{
 | 
						successCase := []core.VolumeDevice{
 | 
				
			||||||
		{Name: "abc", DevicePath: "/foo"},
 | 
							{Name: "abc", DevicePath: "/foo"},
 | 
				
			||||||
		{Name: "abc-123", DevicePath: "/usr/share/test"},
 | 
							{Name: "abc-123", DevicePath: "/usr/share/test"},
 | 
				
			||||||
@@ -5005,8 +5001,6 @@ func TestAlphaValidateVolumeDevices(t *testing.T) {
 | 
				
			|||||||
		{Name: "abc-123", MountPath: "/this/path/exists"},
 | 
							{Name: "abc-123", MountPath: "/this/path/exists"},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// enable BlockVolume
 | 
					 | 
				
			||||||
	defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
 | 
					 | 
				
			||||||
	// Success Cases:
 | 
						// Success Cases:
 | 
				
			||||||
	// Validate normal success cases - only PVC volumeSource
 | 
						// Validate normal success cases - only PVC volumeSource
 | 
				
			||||||
	if errs := ValidateVolumeDevices(successCase, GetVolumeMountMap(goodVolumeMounts), vols, field.NewPath("field")); len(errs) != 0 {
 | 
						if errs := ValidateVolumeDevices(successCase, GetVolumeMountMap(goodVolumeMounts), vols, field.NewPath("field")); len(errs) != 0 {
 | 
				
			||||||
@@ -5020,12 +5014,6 @@ func TestAlphaValidateVolumeDevices(t *testing.T) {
 | 
				
			|||||||
			t.Errorf("expected failure for %s", k)
 | 
								t.Errorf("expected failure for %s", k)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// disable BlockVolume
 | 
					 | 
				
			||||||
	defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
 | 
					 | 
				
			||||||
	if errs := ValidateVolumeDevices(disabledAlphaVolDevice, GetVolumeMountMap(goodVolumeMounts), vols, field.NewPath("field")); len(errs) == 0 {
 | 
					 | 
				
			||||||
		t.Errorf("expected failure: %v", errs)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestValidateProbe(t *testing.T) {
 | 
					func TestValidateProbe(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user