diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index 4f916bba76d..1e68c927bbc 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -352,6 +352,22 @@ func validateVolumeMounts(mounts []api.VolumeMount, volumes util.StringSet) errs return allErrs } +func validateProbe(probe *api.Probe) errs.ValidationErrorList { + allErrs := errs.ValidationErrorList{} + + if probe == nil { + return allErrs + } + allErrs = append(allErrs, validateHandler(&probe.Handler)...) + if probe.InitialDelaySeconds < 0 { + allErrs = append(allErrs, errs.NewFieldInvalid("initialDelay", probe.InitialDelaySeconds, "may not be less than zero")) + } + if probe.TimeoutSeconds < 0 { + allErrs = append(allErrs, errs.NewFieldInvalid("timeout", probe.TimeoutSeconds, "may not be less than zero")) + } + return allErrs +} + // AccumulateUniquePorts runs an extraction function on each Port of each Container, // accumulating the results and returning an error if any ports conflict. func AccumulateUniquePorts(containers []api.Container, accumulator map[int]bool, extract func(*api.Port) int) errs.ValidationErrorList { @@ -465,6 +481,8 @@ func validateContainers(containers []api.Container, volumes util.StringSet) errs if ctr.Lifecycle != nil { cErrs = append(cErrs, validateLifecycle(ctr.Lifecycle).Prefix("lifecycle")...) } + cErrs = append(cErrs, validateProbe(ctr.LivenessProbe).Prefix("livenessProbe")...) + cErrs = append(cErrs, validateProbe(ctr.ReadinessProbe).Prefix("readinessProbe")...) cErrs = append(cErrs, validatePorts(ctr.Ports).Prefix("ports")...) cErrs = append(cErrs, validateEnv(ctr.Env).Prefix("env")...) cErrs = append(cErrs, validateVolumeMounts(ctr.VolumeMounts, volumes).Prefix("volumeMounts")...) diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index e19e90c568d..ac3bd0b5801 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -304,6 +304,32 @@ func TestValidateVolumeMounts(t *testing.T) { } } +func TestValidateProbe(t *testing.T) { + handler := api.Handler{Exec: &api.ExecAction{Command: []string{"echo"}}} + successCases := []*api.Probe{ + nil, + {TimeoutSeconds: 10, InitialDelaySeconds: 0, Handler: handler}, + {TimeoutSeconds: 0, InitialDelaySeconds: 10, Handler: handler}, + } + for _, p := range successCases { + if errs := validateProbe(p); len(errs) != 0 { + t.Errorf("expected success: %v", errs) + } + } + + errorCases := []*api.Probe{ + {TimeoutSeconds: 10, InitialDelaySeconds: 10}, + {TimeoutSeconds: 10, InitialDelaySeconds: -10, Handler: handler}, + {TimeoutSeconds: -10, InitialDelaySeconds: 10, Handler: handler}, + {TimeoutSeconds: -10, InitialDelaySeconds: -10, Handler: handler}, + } + for _, p := range errorCases { + if errs := validateProbe(p); len(errs) == 0 { + t.Errorf("expected failure for %v", p) + } + } +} + func TestValidatePullPolicy(t *testing.T) { type T struct { Container api.Container