Skip to content

Commit cc1c2cd

Browse files
committedMar 5, 2018
Merge pull request kubernetes#18792 from sjenning/pick-54530-3.9
Automatic merge from submit-queue. [3.9] UPSTREAM: 54530: api: validate container phase transitions master PR openshift/origin#18791 kubernetes#54530 fixes kubernetes#17595 xref https://bugzilla.redhat.com/show_bug.cgi?id=1534492 @tnozicka @smarterclayton @derekwaynecarr Origin-commit: 30679c747f8b96fabaeccd07b1e8742547bf896c
2 parents f8e64c0 + 5321f80 commit cc1c2cd

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed
 

‎pkg/apis/core/validation/validation.go

+32-1
Original file line numberDiff line numberDiff line change
@@ -3319,17 +3319,48 @@ func ValidatePodUpdate(newPod, oldPod *core.Pod) field.ErrorList {
33193319
return allErrs
33203320
}
33213321

3322+
// ValidateContainerStateTransition test to if any illegal container state transitions are being attempted
3323+
func ValidateContainerStateTransition(newStatuses, oldStatuses []core.ContainerStatus, fldpath *field.Path, restartPolicy core.RestartPolicy) field.ErrorList {
3324+
allErrs := field.ErrorList{}
3325+
// If we should always restart, containers are allowed to leave the terminated state
3326+
if restartPolicy == core.RestartPolicyAlways {
3327+
return allErrs
3328+
}
3329+
for i, oldStatus := range oldStatuses {
3330+
// Skip any container that is not terminated
3331+
if oldStatus.State.Terminated == nil {
3332+
continue
3333+
}
3334+
// Skip any container that failed but is allowed to restart
3335+
if oldStatus.State.Terminated.ExitCode != 0 && restartPolicy == core.RestartPolicyOnFailure {
3336+
continue
3337+
}
3338+
for _, newStatus := range newStatuses {
3339+
if oldStatus.Name == newStatus.Name && newStatus.State.Terminated == nil {
3340+
allErrs = append(allErrs, field.Forbidden(fldpath.Index(i).Child("state"), "may not be transitioned to non-terminated state"))
3341+
}
3342+
}
3343+
}
3344+
return allErrs
3345+
}
3346+
33223347
// ValidatePodStatusUpdate tests to see if the update is legal for an end user to make. newPod is updated with fields
33233348
// that cannot be changed.
33243349
func ValidatePodStatusUpdate(newPod, oldPod *core.Pod) field.ErrorList {
33253350
fldPath := field.NewPath("metadata")
33263351
allErrs := ValidateObjectMetaUpdate(&newPod.ObjectMeta, &oldPod.ObjectMeta, fldPath)
33273352
allErrs = append(allErrs, ValidatePodSpecificAnnotationUpdates(newPod, oldPod, fldPath.Child("annotations"))...)
33283353

3354+
fldPath = field.NewPath("status")
33293355
if newPod.Spec.NodeName != oldPod.Spec.NodeName {
3330-
allErrs = append(allErrs, field.Forbidden(field.NewPath("status", "nodeName"), "may not be changed directly"))
3356+
allErrs = append(allErrs, field.Forbidden(fldPath.Child("nodeName"), "may not be changed directly"))
33313357
}
33323358

3359+
// If pod should not restart, make sure the status update does not transition
3360+
// any terminated containers to a non-terminated state.
3361+
allErrs = append(allErrs, ValidateContainerStateTransition(newPod.Status.ContainerStatuses, oldPod.Status.ContainerStatuses, fldPath.Child("containerStatuses"), oldPod.Spec.RestartPolicy)...)
3362+
allErrs = append(allErrs, ValidateContainerStateTransition(newPod.Status.InitContainerStatuses, oldPod.Status.InitContainerStatuses, fldPath.Child("initContainerStatuses"), oldPod.Spec.RestartPolicy)...)
3363+
33333364
// For status update we ignore changes to pod spec.
33343365
newPod.Spec = oldPod.Spec
33353366

0 commit comments

Comments
 (0)
Please sign in to comment.