Skip to content

Commit

Permalink
Merge pull request kubernetes#18792 from sjenning/pick-54530-3.9
Browse files Browse the repository at this point in the history
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
  • Loading branch information
k8s-publishing-bot committed Mar 5, 2018
2 parents f8e64c0 + 5321f80 commit cc1c2cd
Showing 1 changed file with 32 additions and 1 deletion.
33 changes: 32 additions & 1 deletion pkg/apis/core/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -3319,17 +3319,48 @@ func ValidatePodUpdate(newPod, oldPod *core.Pod) field.ErrorList {
return allErrs
}

// ValidateContainerStateTransition test to if any illegal container state transitions are being attempted
func ValidateContainerStateTransition(newStatuses, oldStatuses []core.ContainerStatus, fldpath *field.Path, restartPolicy core.RestartPolicy) field.ErrorList {
allErrs := field.ErrorList{}
// If we should always restart, containers are allowed to leave the terminated state
if restartPolicy == core.RestartPolicyAlways {
return allErrs
}
for i, oldStatus := range oldStatuses {
// Skip any container that is not terminated
if oldStatus.State.Terminated == nil {
continue
}
// Skip any container that failed but is allowed to restart
if oldStatus.State.Terminated.ExitCode != 0 && restartPolicy == core.RestartPolicyOnFailure {
continue
}
for _, newStatus := range newStatuses {
if oldStatus.Name == newStatus.Name && newStatus.State.Terminated == nil {
allErrs = append(allErrs, field.Forbidden(fldpath.Index(i).Child("state"), "may not be transitioned to non-terminated state"))
}
}
}
return allErrs
}

// ValidatePodStatusUpdate tests to see if the update is legal for an end user to make. newPod is updated with fields
// that cannot be changed.
func ValidatePodStatusUpdate(newPod, oldPod *core.Pod) field.ErrorList {
fldPath := field.NewPath("metadata")
allErrs := ValidateObjectMetaUpdate(&newPod.ObjectMeta, &oldPod.ObjectMeta, fldPath)
allErrs = append(allErrs, ValidatePodSpecificAnnotationUpdates(newPod, oldPod, fldPath.Child("annotations"))...)

fldPath = field.NewPath("status")
if newPod.Spec.NodeName != oldPod.Spec.NodeName {
allErrs = append(allErrs, field.Forbidden(field.NewPath("status", "nodeName"), "may not be changed directly"))
allErrs = append(allErrs, field.Forbidden(fldPath.Child("nodeName"), "may not be changed directly"))
}

// If pod should not restart, make sure the status update does not transition
// any terminated containers to a non-terminated state.
allErrs = append(allErrs, ValidateContainerStateTransition(newPod.Status.ContainerStatuses, oldPod.Status.ContainerStatuses, fldPath.Child("containerStatuses"), oldPod.Spec.RestartPolicy)...)
allErrs = append(allErrs, ValidateContainerStateTransition(newPod.Status.InitContainerStatuses, oldPod.Status.InitContainerStatuses, fldPath.Child("initContainerStatuses"), oldPod.Spec.RestartPolicy)...)

// For status update we ignore changes to pod spec.
newPod.Spec = oldPod.Spec

Expand Down

0 comments on commit cc1c2cd

Please sign in to comment.