Skip to content

Commit 23aafda

Browse files
author
Kubernetes Submit Queue
authored
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 #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 ```
2 parents 289de0e + 59b1bac commit 23aafda

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

pkg/api/validation/validation.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,6 +1972,9 @@ func validateContainers(containers []api.Container, volumes sets.String, fldPath
19721972
} else {
19731973
allNames.Insert(ctr.Name)
19741974
}
1975+
// TODO: do not validate leading and trailing whitespace to preserve backward compatibility.
1976+
// for example: https://github.com/openshift/origin/issues/14659 image = " " is special token in pod template
1977+
// others may have done similar
19751978
if len(ctr.Image) == 0 {
19761979
allErrs = append(allErrs, field.Required(idxPath.Child("image"), ""))
19771980
}
@@ -2211,12 +2214,33 @@ func ValidateTolerations(tolerations []api.Toleration, fldPath *field.Path) fiel
22112214
return allErrors
22122215
}
22132216

2217+
// validateContainersOnlyForPod does additional validation for containers on a pod versus a pod template
2218+
// it only does additive validation of fields not covered in validateContainers
2219+
func validateContainersOnlyForPod(containers []api.Container, fldPath *field.Path) field.ErrorList {
2220+
allErrs := field.ErrorList{}
2221+
for i, ctr := range containers {
2222+
idxPath := fldPath.Index(i)
2223+
if len(ctr.Image) != len(strings.TrimSpace(ctr.Image)) {
2224+
allErrs = append(allErrs, field.Invalid(idxPath.Child("image"), ctr.Image, "must not have leading or trailing whitespace"))
2225+
}
2226+
}
2227+
return allErrs
2228+
}
2229+
22142230
// ValidatePod tests if required fields in the pod are set.
22152231
func ValidatePod(pod *api.Pod) field.ErrorList {
22162232
fldPath := field.NewPath("metadata")
22172233
allErrs := ValidateObjectMeta(&pod.ObjectMeta, true, ValidatePodName, fldPath)
22182234
allErrs = append(allErrs, ValidatePodSpecificAnnotations(pod.ObjectMeta.Annotations, &pod.Spec, fldPath.Child("annotations"))...)
22192235
allErrs = append(allErrs, ValidatePodSpec(&pod.Spec, field.NewPath("spec"))...)
2236+
2237+
// we do additional validation only pertinent for pods and not pod templates
2238+
// this was done to preserve backwards compatibility
2239+
specPath := field.NewPath("spec")
2240+
2241+
allErrs = append(allErrs, validateContainersOnlyForPod(pod.Spec.Containers, specPath.Child("containers"))...)
2242+
allErrs = append(allErrs, validateContainersOnlyForPod(pod.Spec.InitContainers, specPath.Child("initContainers"))...)
2243+
22202244
return allErrs
22212245
}
22222246

@@ -2605,6 +2629,10 @@ func ValidateContainerUpdates(newContainers, oldContainers []api.Container, fldP
26052629
if len(ctr.Image) == 0 {
26062630
allErrs = append(allErrs, field.Required(fldPath.Index(i).Child("image"), ""))
26072631
}
2632+
// this is only called from ValidatePodUpdate so its safe to check leading/trailing whitespace.
2633+
if len(strings.TrimSpace(ctr.Image)) != len(ctr.Image) {
2634+
allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("image"), ctr.Image, "must not have leading or trailing whitespace"))
2635+
}
26082636
}
26092637
return allErrs, false
26102638
}

pkg/api/validation/validation_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3080,6 +3080,9 @@ func TestValidateContainers(t *testing.T) {
30803080

30813081
successCase := []api.Container{
30823082
{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
3083+
// backwards compatibility to ensure containers in pod template spec do not check for this
3084+
{Name: "def", Image: " ", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
3085+
{Name: "ghi", Image: " some ", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
30833086
{Name: "123", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
30843087
{Name: "abc-123", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
30853088
{
@@ -3234,6 +3237,7 @@ func TestValidateContainers(t *testing.T) {
32343237
})
32353238
errorCases := map[string][]api.Container{
32363239
"zero-length name": {{Name: "", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
3240+
"zero-length-image": {{Name: "abc", Image: "", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
32373241
"name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
32383242
"name not a DNS label": {{Name: "a.b.c", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
32393243
"name not unique": {
@@ -4214,6 +4218,28 @@ func TestValidatePod(t *testing.T) {
42144218
},
42154219
},
42164220
},
4221+
"image whitespace": {
4222+
expectedError: "spec.containers[0].image",
4223+
spec: api.Pod{
4224+
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: "ns"},
4225+
Spec: api.PodSpec{
4226+
RestartPolicy: api.RestartPolicyAlways,
4227+
DNSPolicy: api.DNSClusterFirst,
4228+
Containers: []api.Container{{Name: "ctr", Image: " ", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
4229+
},
4230+
},
4231+
},
4232+
"image leading and trailing whitespace": {
4233+
expectedError: "spec.containers[0].image",
4234+
spec: api.Pod{
4235+
ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: "ns"},
4236+
Spec: api.PodSpec{
4237+
RestartPolicy: api.RestartPolicyAlways,
4238+
DNSPolicy: api.DNSClusterFirst,
4239+
Containers: []api.Container{{Name: "ctr", Image: " something ", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
4240+
},
4241+
},
4242+
},
42174243
"bad namespace": {
42184244
expectedError: "metadata.namespace",
42194245
spec: api.Pod{

0 commit comments

Comments
 (0)