diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index bfe898b4615..0ed59df24ef 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -3044,7 +3044,7 @@ func validatePullPolicy(policy core.PullPolicy, fldPath *field.Path) field.Error var supportedResizeResources = sets.NewString(string(core.ResourceCPU), string(core.ResourceMemory)) var supportedResizePolicies = sets.NewString(string(core.NotRequired), string(core.RestartContainer)) -func validateResizePolicy(policyList []core.ContainerResizePolicy, fldPath *field.Path, restartPolicy *core.RestartPolicy) field.ErrorList { +func validateResizePolicy(policyList []core.ContainerResizePolicy, fldPath *field.Path, podRestartPolicy *core.RestartPolicy) field.ErrorList { allErrors := field.ErrorList{} // validate that resource name is not repeated, supported resource names and policy values are specified @@ -3069,8 +3069,8 @@ func validateResizePolicy(policyList []core.ContainerResizePolicy, fldPath *fiel allErrors = append(allErrors, field.NotSupported(fldPath, p.RestartPolicy, supportedResizePolicies.List())) } - if *restartPolicy == core.RestartPolicyNever && p.RestartPolicy != core.NotRequired { - allErrors = append(allErrors, field.NotSupported(fldPath, p.RestartPolicy, []string{string(core.NotRequired)})) + if *podRestartPolicy == core.RestartPolicyNever && p.RestartPolicy != core.NotRequired { + allErrors = append(allErrors, field.Invalid(fldPath, p.RestartPolicy, "Only NotRequired is allowed, if pod restartPolicy is Never")) } } return allErrors @@ -3078,7 +3078,7 @@ func validateResizePolicy(policyList []core.ContainerResizePolicy, fldPath *fiel // validateEphemeralContainers is called by pod spec and template validation to validate the list of ephemeral containers. // Note that this is called for pod template even though ephemeral containers aren't allowed in pod templates. -func validateEphemeralContainers(ephemeralContainers []core.EphemeralContainer, containers, initContainers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, fldPath *field.Path, opts PodValidationOptions, restartPolicy *core.RestartPolicy) field.ErrorList { +func validateEphemeralContainers(ephemeralContainers []core.EphemeralContainer, containers, initContainers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy) field.ErrorList { var allErrs field.ErrorList if len(ephemeralContainers) == 0 { @@ -3099,7 +3099,7 @@ func validateEphemeralContainers(ephemeralContainers []core.EphemeralContainer, idxPath := fldPath.Index(i) c := (*core.Container)(&ec.EphemeralContainerCommon) - allErrs = append(allErrs, validateContainerCommon(c, volumes, podClaimNames, idxPath, opts, restartPolicy)...) + allErrs = append(allErrs, validateContainerCommon(c, volumes, podClaimNames, idxPath, opts, podRestartPolicy)...) // Ephemeral containers don't need looser constraints for pod templates, so it's convenient to apply both validations // here where we've already converted EphemeralContainerCommon to Container. allErrs = append(allErrs, validateContainerOnlyForPod(c, idxPath)...) @@ -3161,7 +3161,7 @@ func validateFieldAllowList(value interface{}, allowedFields map[string]bool, er } // validateInitContainers is called by pod spec and template validation to validate the list of init containers -func validateInitContainers(containers []core.Container, regularContainers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, fldPath *field.Path, opts PodValidationOptions, restartPolicy *core.RestartPolicy) field.ErrorList { +func validateInitContainers(containers []core.Container, regularContainers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy) field.ErrorList { var allErrs field.ErrorList allNames := sets.String{} @@ -3172,7 +3172,7 @@ func validateInitContainers(containers []core.Container, regularContainers []cor idxPath := fldPath.Index(i) // Apply the validation common to all container types - allErrs = append(allErrs, validateContainerCommon(&ctr, volumes, podClaimNames, idxPath, opts, restartPolicy)...) + allErrs = append(allErrs, validateContainerCommon(&ctr, volumes, podClaimNames, idxPath, opts, podRestartPolicy)...) // Names must be unique within regular and init containers. Collisions with ephemeral containers // will be detected by validateEphemeralContainers(). @@ -3208,7 +3208,7 @@ func validateInitContainers(containers []core.Container, regularContainers []cor // validateContainerCommon applies validation common to all container types. It's called by regular, init, and ephemeral // container list validation to require a properly formatted name, image, etc. -func validateContainerCommon(ctr *core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, path *field.Path, opts PodValidationOptions, restartPolicy *core.RestartPolicy) field.ErrorList { +func validateContainerCommon(ctr *core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, path *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy) field.ErrorList { var allErrs field.ErrorList namePath := path.Child("name") @@ -3246,7 +3246,7 @@ func validateContainerCommon(ctr *core.Container, volumes map[string]core.Volume allErrs = append(allErrs, ValidateVolumeDevices(ctr.VolumeDevices, volMounts, volumes, path.Child("volumeDevices"))...) allErrs = append(allErrs, validatePullPolicy(ctr.ImagePullPolicy, path.Child("imagePullPolicy"))...) allErrs = append(allErrs, ValidateResourceRequirements(&ctr.Resources, podClaimNames, path.Child("resources"), opts)...) - allErrs = append(allErrs, validateResizePolicy(ctr.ResizePolicy, path.Child("resizePolicy"), restartPolicy)...) + allErrs = append(allErrs, validateResizePolicy(ctr.ResizePolicy, path.Child("resizePolicy"), podRestartPolicy)...) allErrs = append(allErrs, ValidateSecurityContext(ctr.SecurityContext, path.Child("securityContext"))...) return allErrs } @@ -3299,7 +3299,7 @@ func validateHostUsers(spec *core.PodSpec, fldPath *field.Path) field.ErrorList } // validateContainers is called by pod spec and template validation to validate the list of regular containers. -func validateContainers(containers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, fldPath *field.Path, opts PodValidationOptions, restartPolicy *core.RestartPolicy) field.ErrorList { +func validateContainers(containers []core.Container, volumes map[string]core.VolumeSource, podClaimNames sets.String, fldPath *field.Path, opts PodValidationOptions, podRestartPolicy *core.RestartPolicy) field.ErrorList { allErrs := field.ErrorList{} if len(containers) == 0 { @@ -3311,7 +3311,7 @@ func validateContainers(containers []core.Container, volumes map[string]core.Vol path := fldPath.Index(i) // Apply validation common to all containers - allErrs = append(allErrs, validateContainerCommon(&ctr, volumes, podClaimNames, path, opts, restartPolicy)...) + allErrs = append(allErrs, validateContainerCommon(&ctr, volumes, podClaimNames, path, opts, podRestartPolicy)...) // Container names must be unique within the list of regular containers. // Collisions with init or ephemeral container names will be detected by the init or ephemeral diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index 9a0892112e3..55749d594b5 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -6832,13 +6832,40 @@ func TestValidateResizePolicy(t *testing.T) { field.ErrorList{field.Duplicate(field.NewPath("field").Index(2), core.ResourceCPU)}, "Always", }, - "InvalidPolicyWithPodRestartPolicy": { + "InvalidCPUPolicyWithPodRestartPolicy": { []core.ContainerResizePolicy{ {ResourceName: "cpu", RestartPolicy: "NotRequired"}, {ResourceName: "memory", RestartPolicy: "RestartContainer"}, }, true, - field.ErrorList{field.NotSupported(field.NewPath("field"), core.ResourceResizeRestartPolicy("RestartContainer"), []string{string(core.NotRequired)})}, + field.ErrorList{field.Invalid(field.NewPath("field"), core.ResourceResizeRestartPolicy("RestartContainer"), "Only NotRequired is allowed, if pod restartPolicy is Never")}, + "Never", + }, + "InvalidMemoryPolicyWithPodRestartPolicy": { + []core.ContainerResizePolicy{ + {ResourceName: "cpu", RestartPolicy: "RestartContainer"}, + {ResourceName: "memory", RestartPolicy: "NotRequired"}, + }, + true, + field.ErrorList{field.Invalid(field.NewPath("field"), core.ResourceResizeRestartPolicy("RestartContainer"), "Only NotRequired is allowed, if pod restartPolicy is Never")}, + "Never", + }, + "InvalidMemoryCPUPolicyWithPodRestartPolicy": { + []core.ContainerResizePolicy{ + {ResourceName: "cpu", RestartPolicy: "RestartContainer"}, + {ResourceName: "memory", RestartPolicy: "RestartContainer"}, + }, + true, + field.ErrorList{field.Invalid(field.NewPath("field"), core.ResourceResizeRestartPolicy("RestartContainer"), "Only NotRequired is allowed, if pod restartPolicy is Never"), field.Invalid(field.NewPath("field"), core.ResourceResizeRestartPolicy("RestartContainer"), "Only NotRequired is allowed, if pod restartPolicy is Never")}, + "Never", + }, + "ValidMemoryCPUPolicyWithPodRestartPolicy": { + []core.ContainerResizePolicy{ + {ResourceName: "cpu", RestartPolicy: "NotRequired"}, + {ResourceName: "memory", RestartPolicy: "NotRequired"}, + }, + false, + nil, "Never", }, }