Change:
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks! If the matter is security related, please disclose it privately via --What happened: Deployed an cronJob with an empty and it defaulted to which is an invalid option: Leaving the key out completely has the same result What you expected to happen: The empty key to default to something valid like or . Also document what this default is, my proposal would be to have as default since some tasks can't be reran easily. But it might be nice to force as default to enforce the stateless mindset even for crons :) How to reproduce it (as minimally and precisely as possible): Anything else we need to know?: I guess not but I am open for questions :) Environment: Kubernetes version (use ): 1.19.2
My guess would be /sig api-machinery If it is better practice to wait for the triage instead of guessing the sig, let me know :+1:
/sig api-machinery
/assign
/remove-sig api-machinery /sig apps
/assign
/triage accepted

Discussion:
package validation import ( <ins> "fmt" </ins> "github.com/robfig/cron" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

} allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template, fldPath.Child("template"), opts)...) <del> if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure && spec.Template.Spec.RestartPolicy != api.RestartPolicyNever { </del> <ins> // spec.Template.Spec.RestartPolicy can be defaulted as RestartPolicyAlways // by SetDefaults_PodSpec function when the user does not explicitly specify a value for it, // so we check both empty and RestartPolicyAlways cases here if spec.Template.Spec.RestartPolicy == api.RestartPolicyAlways || spec.Template.Spec.RestartPolicy == "" { allErrs = append(allErrs, field.Required(fldPath.Child("template", "spec", "restartPolicy"), fmt.Sprintf("valid values: %q, %q", api.RestartPolicyOnFailure, api.RestartPolicyNever))) } else if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure && spec.Template.Spec.RestartPolicy != api.RestartPolicyNever { </ins> allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"), spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyOnFailure), string(api.RestartPolicyNever)})) }

}, }, }, <del> "spec.template.spec.restartPolicy: Unsupported value": { </del> <ins> "spec.template.spec.restartPolicy: Required value": { </ins> ObjectMeta: metav1.ObjectMeta{ Name:      "myjob", Namespace: metav1.NamespaceDefault,

}, }, }, <ins> "spec.template.spec.restartPolicy: Unsupported value": { ObjectMeta: metav1.ObjectMeta{ Name:      "myjob", Namespace: metav1.NamespaceDefault, UID:       types.UID("1a2b3c"), }, Spec: batch.JobSpec{ Selector:       validManualSelector, ManualSelector: newBool(true), Template: api.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: validManualSelector.MatchLabels, }, Spec: api.PodSpec{ RestartPolicy: "Invalid", DNSPolicy:     api.DNSClusterFirst, Containers:    []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: api.TerminationMessageReadFile}}, }, }, }, }, </ins> } for _, setFeature := range []bool{true, false} {

}, }, }, <del> "spec.jobTemplate.spec.template.spec.restartPolicy: Unsupported value": { </del> <ins> "spec.jobTemplate.spec.template.spec.restartPolicy: Required value": { </ins> ObjectMeta: metav1.ObjectMeta{ Name:      "mycronjob", Namespace: metav1.NamespaceDefault,

}, }, }, <ins> "spec.jobTemplate.spec.template.spec.restartPolicy: Unsupported value": { ObjectMeta: metav1.ObjectMeta{ Name:      "mycronjob", Namespace: metav1.NamespaceDefault, UID:       types.UID("1a2b3c"), }, Spec: batch.CronJobSpec{ Schedule:          "* * * * ?", ConcurrencyPolicy: batch.AllowConcurrent, JobTemplate: batch.JobTemplateSpec{ Spec: batch.JobSpec{ Template: api.PodTemplateSpec{ Spec: api.PodSpec{ RestartPolicy: "Invalid", DNSPolicy:     api.DNSClusterFirst, Containers:    []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: api.TerminationMessageReadFile}}, }, }, }, }, }, }, </ins> } if utilfeature.DefaultFeatureGate.Enabled(features.TTLAfterFinished) { errorCases["spec.jobTemplate.spec.ttlSecondsAfterFinished:must be greater than or equal to 0"] = batch.CronJob{