diff --git a/pkg/api/pod/util.go b/pkg/api/pod/util.go index 1d8dbf4846..8f9a50cc8a 100644 --- a/pkg/api/pod/util.go +++ b/pkg/api/pod/util.go @@ -234,10 +234,14 @@ func UpdatePodCondition(status *api.PodStatus, condition *api.PodCondition) bool // DropDisabledFields removes disabled fields from the pod spec. // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pod spec. -func DropDisabledFields(podSpec *api.PodSpec) { +func DropDisabledFields(podSpec, oldPodSpec *api.PodSpec) { if !utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) { podSpec.Priority = nil podSpec.PriorityClassName = "" + if oldPodSpec != nil { + oldPodSpec.Priority = nil + oldPodSpec.PriorityClassName = "" + } } if !utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { @@ -246,22 +250,32 @@ func DropDisabledFields(podSpec *api.PodSpec) { podSpec.Volumes[i].EmptyDir.SizeLimit = nil } } + if oldPodSpec != nil { + for i := range oldPodSpec.Volumes { + if oldPodSpec.Volumes[i].EmptyDir != nil { + oldPodSpec.Volumes[i].EmptyDir.SizeLimit = nil + } + } + } } - DropDisabledVolumeDevicesAlphaFields(podSpec) + dropDisabledVolumeDevicesAlphaFields(podSpec, oldPodSpec) - DropDisabledRunAsGroupField(podSpec) + dropDisabledRunAsGroupField(podSpec, oldPodSpec) - if !utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) && podSpec.RuntimeClassName != nil { + if !utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) { podSpec.RuntimeClassName = nil + if oldPodSpec != nil { + oldPodSpec.RuntimeClassName = nil + } } - DropDisabledProcMountField(podSpec) + dropDisabledProcMountField(podSpec, oldPodSpec) } -// DropDisabledRunAsGroupField removes disabled fields from PodSpec related +// dropDisabledRunAsGroupField removes disabled fields from PodSpec related // to RunAsGroup -func DropDisabledRunAsGroupField(podSpec *api.PodSpec) { +func dropDisabledRunAsGroupField(podSpec, oldPodSpec *api.PodSpec) { if !utilfeature.DefaultFeatureGate.Enabled(features.RunAsGroup) { if podSpec.SecurityContext != nil { podSpec.SecurityContext.RunAsGroup = nil @@ -276,12 +290,28 @@ func DropDisabledRunAsGroupField(podSpec *api.PodSpec) { podSpec.InitContainers[i].SecurityContext.RunAsGroup = nil } } + + if oldPodSpec != nil { + if oldPodSpec.SecurityContext != nil { + oldPodSpec.SecurityContext.RunAsGroup = nil + } + for i := range oldPodSpec.Containers { + if oldPodSpec.Containers[i].SecurityContext != nil { + oldPodSpec.Containers[i].SecurityContext.RunAsGroup = nil + } + } + for i := range oldPodSpec.InitContainers { + if oldPodSpec.InitContainers[i].SecurityContext != nil { + oldPodSpec.InitContainers[i].SecurityContext.RunAsGroup = nil + } + } + } } } -// DropDisabledProcMountField removes disabled fields from PodSpec related +// dropDisabledProcMountField removes disabled fields from PodSpec related // to ProcMount -func DropDisabledProcMountField(podSpec *api.PodSpec) { +func dropDisabledProcMountField(podSpec, oldPodSpec *api.PodSpec) { if !utilfeature.DefaultFeatureGate.Enabled(features.ProcMountType) { defProcMount := api.DefaultProcMount for i := range podSpec.Containers { @@ -294,12 +324,25 @@ func DropDisabledProcMountField(podSpec *api.PodSpec) { podSpec.InitContainers[i].SecurityContext.ProcMount = &defProcMount } } + + if oldPodSpec != nil { + for i := range oldPodSpec.Containers { + if oldPodSpec.Containers[i].SecurityContext != nil { + oldPodSpec.Containers[i].SecurityContext.ProcMount = &defProcMount + } + } + for i := range oldPodSpec.InitContainers { + if oldPodSpec.InitContainers[i].SecurityContext != nil { + oldPodSpec.InitContainers[i].SecurityContext.ProcMount = &defProcMount + } + } + } } } -// DropDisabledVolumeDevicesAlphaFields removes disabled fields from []VolumeDevice. +// dropDisabledVolumeDevicesAlphaFields removes disabled fields from []VolumeDevice. // This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a VolumeDevice -func DropDisabledVolumeDevicesAlphaFields(podSpec *api.PodSpec) { +func dropDisabledVolumeDevicesAlphaFields(podSpec, oldPodSpec *api.PodSpec) { if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { for i := range podSpec.Containers { podSpec.Containers[i].VolumeDevices = nil @@ -307,5 +350,14 @@ func DropDisabledVolumeDevicesAlphaFields(podSpec *api.PodSpec) { for i := range podSpec.InitContainers { 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 + } + } } } diff --git a/pkg/api/pod/util_test.go b/pkg/api/pod/util_test.go index f5bf91e945..264e8451cf 100644 --- a/pkg/api/pod/util_test.go +++ b/pkg/api/pod/util_test.go @@ -307,7 +307,7 @@ func TestDropAlphaVolumeDevices(t *testing.T) { defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)() // now test dropping the fields - should not be dropped - DropDisabledFields(&testPod.Spec) + DropDisabledFields(&testPod.Spec, nil) // check to make sure VolumeDevices is still present // if featureset is set to true @@ -322,7 +322,7 @@ func TestDropAlphaVolumeDevices(t *testing.T) { defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)() // now test dropping the fields - DropDisabledFields(&testPod.Spec) + DropDisabledFields(&testPod.Spec, nil) // check to make sure VolumeDevices is nil // if featureset is set to false diff --git a/pkg/registry/apps/daemonset/strategy.go b/pkg/registry/apps/daemonset/strategy.go index e635bfda63..08ffd63f73 100644 --- a/pkg/registry/apps/daemonset/strategy.go +++ b/pkg/registry/apps/daemonset/strategy.go @@ -75,7 +75,7 @@ func (daemonSetStrategy) PrepareForCreate(ctx context.Context, obj runtime.Objec daemonSet.Spec.TemplateGeneration = 1 } - pod.DropDisabledFields(&daemonSet.Spec.Template.Spec) + pod.DropDisabledFields(&daemonSet.Spec.Template.Spec, nil) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -83,8 +83,7 @@ func (daemonSetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime. newDaemonSet := obj.(*apps.DaemonSet) oldDaemonSet := old.(*apps.DaemonSet) - pod.DropDisabledFields(&newDaemonSet.Spec.Template.Spec) - pod.DropDisabledFields(&oldDaemonSet.Spec.Template.Spec) + pod.DropDisabledFields(&newDaemonSet.Spec.Template.Spec, &oldDaemonSet.Spec.Template.Spec) // update is not allowed to set status newDaemonSet.Status = oldDaemonSet.Status diff --git a/pkg/registry/apps/deployment/strategy.go b/pkg/registry/apps/deployment/strategy.go index e3d70031a3..cccd62116f 100644 --- a/pkg/registry/apps/deployment/strategy.go +++ b/pkg/registry/apps/deployment/strategy.go @@ -73,7 +73,7 @@ func (deploymentStrategy) PrepareForCreate(ctx context.Context, obj runtime.Obje deployment.Status = apps.DeploymentStatus{} deployment.Generation = 1 - pod.DropDisabledFields(&deployment.Spec.Template.Spec) + pod.DropDisabledFields(&deployment.Spec.Template.Spec, nil) } // Validate validates a new deployment. @@ -97,8 +97,7 @@ func (deploymentStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime oldDeployment := old.(*apps.Deployment) newDeployment.Status = oldDeployment.Status - pod.DropDisabledFields(&newDeployment.Spec.Template.Spec) - pod.DropDisabledFields(&oldDeployment.Spec.Template.Spec) + pod.DropDisabledFields(&newDeployment.Spec.Template.Spec, &oldDeployment.Spec.Template.Spec) // Spec updates bump the generation so that we can distinguish between // scaling events and template changes, annotation updates bump the generation diff --git a/pkg/registry/apps/replicaset/strategy.go b/pkg/registry/apps/replicaset/strategy.go index 18d09d7f58..37bf07eaa3 100644 --- a/pkg/registry/apps/replicaset/strategy.go +++ b/pkg/registry/apps/replicaset/strategy.go @@ -80,7 +80,7 @@ func (rsStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { rs.Generation = 1 - pod.DropDisabledFields(&rs.Spec.Template.Spec) + pod.DropDisabledFields(&rs.Spec.Template.Spec, nil) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -90,8 +90,7 @@ func (rsStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) // update is not allowed to set status newRS.Status = oldRS.Status - pod.DropDisabledFields(&newRS.Spec.Template.Spec) - pod.DropDisabledFields(&oldRS.Spec.Template.Spec) + pod.DropDisabledFields(&newRS.Spec.Template.Spec, &oldRS.Spec.Template.Spec) // Any changes to the spec increment the generation number, any changes to the // status should reflect the generation number of the corresponding object. We push diff --git a/pkg/registry/apps/statefulset/strategy.go b/pkg/registry/apps/statefulset/strategy.go index 0094429201..1a8608900b 100644 --- a/pkg/registry/apps/statefulset/strategy.go +++ b/pkg/registry/apps/statefulset/strategy.go @@ -72,7 +72,7 @@ func (statefulSetStrategy) PrepareForCreate(ctx context.Context, obj runtime.Obj statefulSet.Generation = 1 - pod.DropDisabledFields(&statefulSet.Spec.Template.Spec) + pod.DropDisabledFields(&statefulSet.Spec.Template.Spec, nil) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -82,8 +82,7 @@ func (statefulSetStrategy) PrepareForUpdate(ctx context.Context, obj, old runtim // Update is not allowed to set status newStatefulSet.Status = oldStatefulSet.Status - pod.DropDisabledFields(&newStatefulSet.Spec.Template.Spec) - pod.DropDisabledFields(&oldStatefulSet.Spec.Template.Spec) + pod.DropDisabledFields(&newStatefulSet.Spec.Template.Spec, &oldStatefulSet.Spec.Template.Spec) // Any changes to the spec increment the generation number, any changes to the // status should reflect the generation number of the corresponding object. diff --git a/pkg/registry/batch/cronjob/strategy.go b/pkg/registry/batch/cronjob/strategy.go index 82bd78496a..3ccbee4eb4 100644 --- a/pkg/registry/batch/cronjob/strategy.go +++ b/pkg/registry/batch/cronjob/strategy.go @@ -68,7 +68,7 @@ func (cronJobStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) cronJob := obj.(*batch.CronJob) cronJob.Status = batch.CronJobStatus{} - pod.DropDisabledFields(&cronJob.Spec.JobTemplate.Spec.Template.Spec) + pod.DropDisabledFields(&cronJob.Spec.JobTemplate.Spec.Template.Spec, nil) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -77,8 +77,7 @@ func (cronJobStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Ob oldCronJob := old.(*batch.CronJob) newCronJob.Status = oldCronJob.Status - pod.DropDisabledFields(&newCronJob.Spec.JobTemplate.Spec.Template.Spec) - pod.DropDisabledFields(&oldCronJob.Spec.JobTemplate.Spec.Template.Spec) + pod.DropDisabledFields(&newCronJob.Spec.JobTemplate.Spec.Template.Spec, &oldCronJob.Spec.JobTemplate.Spec.Template.Spec) } // Validate validates a new scheduled job. diff --git a/pkg/registry/batch/job/strategy.go b/pkg/registry/batch/job/strategy.go index 8fc8881132..4f5845d62d 100644 --- a/pkg/registry/batch/job/strategy.go +++ b/pkg/registry/batch/job/strategy.go @@ -80,7 +80,7 @@ func (jobStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { job.Spec.TTLSecondsAfterFinished = nil } - pod.DropDisabledFields(&job.Spec.Template.Spec) + pod.DropDisabledFields(&job.Spec.Template.Spec, nil) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -94,8 +94,7 @@ func (jobStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object oldJob.Spec.TTLSecondsAfterFinished = nil } - pod.DropDisabledFields(&newJob.Spec.Template.Spec) - pod.DropDisabledFields(&oldJob.Spec.Template.Spec) + pod.DropDisabledFields(&newJob.Spec.Template.Spec, &oldJob.Spec.Template.Spec) } // Validate validates a new job. diff --git a/pkg/registry/core/pod/strategy.go b/pkg/registry/core/pod/strategy.go index 5282882476..52fb9ec45a 100644 --- a/pkg/registry/core/pod/strategy.go +++ b/pkg/registry/core/pod/strategy.go @@ -73,7 +73,7 @@ func (podStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { QOSClass: qos.GetPodQOS(pod), } - podutil.DropDisabledFields(&pod.Spec) + podutil.DropDisabledFields(&pod.Spec, nil) } // PrepareForUpdate clears fields that are not allowed to be set by end users on update. @@ -82,8 +82,7 @@ func (podStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object oldPod := old.(*api.Pod) newPod.Status = oldPod.Status - podutil.DropDisabledFields(&newPod.Spec) - podutil.DropDisabledFields(&oldPod.Spec) + podutil.DropDisabledFields(&newPod.Spec, &oldPod.Spec) } // Validate validates a new pod. diff --git a/pkg/registry/core/podtemplate/strategy.go b/pkg/registry/core/podtemplate/strategy.go index bddc4752c2..13d841f782 100644 --- a/pkg/registry/core/podtemplate/strategy.go +++ b/pkg/registry/core/podtemplate/strategy.go @@ -47,7 +47,7 @@ func (podTemplateStrategy) NamespaceScoped() bool { func (podTemplateStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { template := obj.(*api.PodTemplate) - pod.DropDisabledFields(&template.Template.Spec) + pod.DropDisabledFields(&template.Template.Spec, nil) } // Validate validates a new pod template. @@ -70,8 +70,7 @@ func (podTemplateStrategy) PrepareForUpdate(ctx context.Context, obj, old runtim newTemplate := obj.(*api.PodTemplate) oldTemplate := old.(*api.PodTemplate) - pod.DropDisabledFields(&newTemplate.Template.Spec) - pod.DropDisabledFields(&oldTemplate.Template.Spec) + pod.DropDisabledFields(&newTemplate.Template.Spec, &oldTemplate.Template.Spec) } // ValidateUpdate is the default update validation for an end user. diff --git a/pkg/registry/core/replicationcontroller/strategy.go b/pkg/registry/core/replicationcontroller/strategy.go index ed39903124..2c0cc34a40 100644 --- a/pkg/registry/core/replicationcontroller/strategy.go +++ b/pkg/registry/core/replicationcontroller/strategy.go @@ -81,7 +81,7 @@ func (rcStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) { controller.Generation = 1 if controller.Spec.Template != nil { - pod.DropDisabledFields(&controller.Spec.Template.Spec) + pod.DropDisabledFields(&controller.Spec.Template.Spec, nil) } } @@ -92,12 +92,16 @@ func (rcStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) // update is not allowed to set status newController.Status = oldController.Status + var newSpec, oldSpec *api.PodSpec if oldController.Spec.Template != nil { - pod.DropDisabledFields(&oldController.Spec.Template.Spec) + oldSpec = &oldController.Spec.Template.Spec } if newController.Spec.Template != nil { - pod.DropDisabledFields(&newController.Spec.Template.Spec) + newSpec = &newController.Spec.Template.Spec + } else { + newSpec = &api.PodSpec{} } + pod.DropDisabledFields(newSpec, oldSpec) // Any changes to the spec increment the generation number, any changes to the // status should reflect the generation number of the corresponding object. We push