mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 05:27:21 +00:00
Merge pull request #47491 from derekwaynecarr/fix-image-name-validation
Automatic merge from submit-queue image name must not have leading or trailing whitespace **What this PR does / why we need it**: verifies that an image name can not have leading or trailing whitespace **Which issue this PR fixes** fixes https://github.com/kubernetes/kubernetes/issues/47490 **Special notes for your reviewer**: i was surprised we had not caught this, so if there is an image spec that says leading and trailing whitespace is a good thing, i am open to correction. i was made aware of downstream users of validate pod template spec that used " " as a special token. as a result, i only do the validation of image name " " in the `Pod` only. **Release note**: ```release-note NONE ```
This commit is contained in:
commit
23aafdabba
@ -1972,6 +1972,9 @@ func validateContainers(containers []api.Container, volumes sets.String, fldPath
|
|||||||
} else {
|
} else {
|
||||||
allNames.Insert(ctr.Name)
|
allNames.Insert(ctr.Name)
|
||||||
}
|
}
|
||||||
|
// 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
|
||||||
if len(ctr.Image) == 0 {
|
if len(ctr.Image) == 0 {
|
||||||
allErrs = append(allErrs, field.Required(idxPath.Child("image"), ""))
|
allErrs = append(allErrs, field.Required(idxPath.Child("image"), ""))
|
||||||
}
|
}
|
||||||
@ -2211,12 +2214,33 @@ func ValidateTolerations(tolerations []api.Toleration, fldPath *field.Path) fiel
|
|||||||
return allErrors
|
return allErrors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
// ValidatePod tests if required fields in the pod are set.
|
// ValidatePod tests if required fields in the pod are set.
|
||||||
func ValidatePod(pod *api.Pod) field.ErrorList {
|
func ValidatePod(pod *api.Pod) field.ErrorList {
|
||||||
fldPath := field.NewPath("metadata")
|
fldPath := field.NewPath("metadata")
|
||||||
allErrs := ValidateObjectMeta(&pod.ObjectMeta, true, ValidatePodName, fldPath)
|
allErrs := ValidateObjectMeta(&pod.ObjectMeta, true, ValidatePodName, fldPath)
|
||||||
allErrs = append(allErrs, ValidatePodSpecificAnnotations(pod.ObjectMeta.Annotations, &pod.Spec, fldPath.Child("annotations"))...)
|
allErrs = append(allErrs, ValidatePodSpecificAnnotations(pod.ObjectMeta.Annotations, &pod.Spec, fldPath.Child("annotations"))...)
|
||||||
allErrs = append(allErrs, ValidatePodSpec(&pod.Spec, field.NewPath("spec"))...)
|
allErrs = append(allErrs, ValidatePodSpec(&pod.Spec, field.NewPath("spec"))...)
|
||||||
|
|
||||||
|
// 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"))...)
|
||||||
|
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2605,6 +2629,10 @@ func ValidateContainerUpdates(newContainers, oldContainers []api.Container, fldP
|
|||||||
if len(ctr.Image) == 0 {
|
if len(ctr.Image) == 0 {
|
||||||
allErrs = append(allErrs, field.Required(fldPath.Index(i).Child("image"), ""))
|
allErrs = append(allErrs, field.Required(fldPath.Index(i).Child("image"), ""))
|
||||||
}
|
}
|
||||||
|
// 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"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return allErrs, false
|
return allErrs, false
|
||||||
}
|
}
|
||||||
|
@ -3080,6 +3080,9 @@ func TestValidateContainers(t *testing.T) {
|
|||||||
|
|
||||||
successCase := []api.Container{
|
successCase := []api.Container{
|
||||||
{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
|
{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
|
||||||
|
// 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"},
|
||||||
{Name: "123", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
|
{Name: "123", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
|
||||||
{Name: "abc-123", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
|
{Name: "abc-123", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
|
||||||
{
|
{
|
||||||
@ -3234,6 +3237,7 @@ func TestValidateContainers(t *testing.T) {
|
|||||||
})
|
})
|
||||||
errorCases := map[string][]api.Container{
|
errorCases := map[string][]api.Container{
|
||||||
"zero-length name": {{Name: "", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
|
"zero-length name": {{Name: "", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
|
||||||
|
"zero-length-image": {{Name: "abc", Image: "", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
|
||||||
"name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
|
"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 a DNS label": {{Name: "a.b.c", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
|
||||||
"name not unique": {
|
"name not unique": {
|
||||||
@ -4214,6 +4218,28 @@ func TestValidatePod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"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"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
"bad namespace": {
|
"bad namespace": {
|
||||||
expectedError: "metadata.namespace",
|
expectedError: "metadata.namespace",
|
||||||
spec: api.Pod{
|
spec: api.Pod{
|
||||||
|
Loading…
Reference in New Issue
Block a user