Change:
Is this a BUG REPORT or FEATURE REQUEST? BUG Kubernetes version (use ): kubernetes 1.5+ Environment: n/a What happened: examining events that happened in my cluster, i see an event like the following: this surprised me, as it implies a container had an imageName=" " What you expected to happen: i expected a validation failure error if a [i].imageName had leading or trailing whitespace. How to reproduce it (as minimally and precisely as possible): kubectl create -f my-pod kubectl edit pod/my-pod -o json change image to " " save Anything else we need to know: nope
There are no sig labels on this issue. Please by:<br(1) mentioning a sig: <br(2) specifying the label manually: <br<brNote: method (1) will trigger a notification to the team. You can find the team list and label list
discovered when looking at odd event messages in production cluster.

Discussion:
} else { allNames.Insert(ctr.Name) } <ins> // TODO: do not validate leading and trailing whitespace to preserve backward compatibility. // for example: https://github.com/openshift/origin/issues/14659 image = " " is special token in pod template // others may have done similar </ins> if len(ctr.Image) == 0 { allErrs = append(allErrs, field.Required(idxPath.Child("image"), "")) }

return allErrors } <ins> // validateContainersOnlyForPod does additional validation for containers on a pod versus a pod template // it only does additive validation of fields not covered in validateContainers func validateContainersOnlyForPod(containers []api.Container, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for i, ctr := range containers { idxPath := fldPath.Index(i) if len(ctr.Image) != len(strings.TrimSpace(ctr.Image)) { allErrs = append(allErrs, field.Invalid(idxPath.Child("image"), ctr.Image, "must not have leading or trailing whitespace")) } } return allErrs } </ins> // ValidatePod tests if required fields in the pod are set. func ValidatePod(pod *api.Pod) field.ErrorList { fldPath := field.NewPath("metadata") allErrs := ValidateObjectMeta(&pod.ObjectMeta, true, ValidatePodName, fldPath) allErrs = append(allErrs, ValidatePodSpecificAnnotations(pod.ObjectMeta.Annotations, &pod.Spec, fldPath.Child("annotations"))...) allErrs = append(allErrs, ValidatePodSpec(&pod.Spec, field.NewPath("spec"))...) <ins> // we do additional validation only pertinent for pods and not pod templates // this was done to preserve backwards compatibility specPath := field.NewPath("spec") allErrs = append(allErrs, validateContainersOnlyForPod(pod.Spec.Containers, specPath.Child("containers"))...) allErrs = append(allErrs, validateContainersOnlyForPod(pod.Spec.InitContainers, specPath.Child("initContainers"))...) </ins> return allErrs }

if len(ctr.Image) == 0 { allErrs = append(allErrs, field.Required(fldPath.Index(i).Child("image"), "")) } <ins> // this is only called from ValidatePodUpdate so its safe to check leading/trailing whitespace. if len(strings.TrimSpace(ctr.Image)) != len(ctr.Image) { allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("image"), ctr.Image, "must not have leading or trailing whitespace")) } </ins> } return allErrs, false }

successCase := []api.Container{ {Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}, <ins> // backwards compatibility to ensure containers in pod template spec do not check for this {Name: "def", Image: " ", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}, {Name: "ghi", Image: " some  ", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}, </ins> {Name: "123", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}, {Name: "abc-123", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}, {

}) errorCases := map[string][]api.Container{ "zero-length name":     {{Name: "", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, <ins> "zero-length-image":    {{Name: "abc", Image: "", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, </ins> "name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, "name not a DNS label": {{Name: "a.b.c", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, "name not unique": {

}, }, }, <ins> "image whitespace": { expectedError: "spec.containers[0].image", spec: api.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: "ns"}, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicyAlways, DNSPolicy:     api.DNSClusterFirst, Containers:    []api.Container{{Name: "ctr", Image: " ", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, }, }, }, "image leading and trailing whitespace": { expectedError: "spec.containers[0].image", spec: api.Pod{ ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: "ns"}, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicyAlways, DNSPolicy:     api.DNSClusterFirst, Containers:    []api.Container{{Name: "ctr", Image: " something ", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, }, }, }, </ins> "bad namespace": { expectedError: "metadata.namespace", spec: api.Pod{