Merge pull request #108032 from deejross/kep3140-cronjob-timezone
KEP 3140: TimeZone support for CronJob
This commit is contained in:
commit
0f2300575c
8
api/openapi-spec/swagger.json
generated
8
api/openapi-spec/swagger.json
generated
@ -4079,6 +4079,10 @@
|
||||
"suspend": {
|
||||
"description": "This flag tells the controller to suspend subsequent executions, it does not apply to already started executions. Defaults to false.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"timeZone": {
|
||||
"description": "The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will rely on the time zone of the kube-controller-manager process. ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@ -4454,6 +4458,10 @@
|
||||
"suspend": {
|
||||
"description": "This flag tells the controller to suspend subsequent executions, it does not apply to already started executions. Defaults to false.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"timeZone": {
|
||||
"description": "The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will rely on the time zone of the kube-controller-manager process. ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -114,6 +114,10 @@
|
||||
"suspend": {
|
||||
"description": "This flag tells the controller to suspend subsequent executions, it does not apply to already started executions. Defaults to false.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"timeZone": {
|
||||
"description": "The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will rely on the time zone of the kube-controller-manager process. ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -164,6 +164,10 @@
|
||||
"suspend": {
|
||||
"description": "This flag tells the controller to suspend subsequent executions, it does not apply to already started executions. Defaults to false.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"timeZone": {
|
||||
"description": "The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will rely on the time zone of the kube-controller-manager process. ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -20,6 +20,7 @@ package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
_ "time/tzdata" // for timeZone support in CronJob
|
||||
|
||||
"k8s.io/component-base/cli"
|
||||
_ "k8s.io/component-base/logs/json/register" // for JSON log format registration
|
||||
|
@ -22,6 +22,7 @@ package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
_ "time/tzdata" // for CronJob Time Zone support
|
||||
|
||||
"k8s.io/component-base/cli"
|
||||
_ "k8s.io/component-base/logs/json/register" // for JSON log format registration
|
||||
|
@ -376,6 +376,12 @@ type CronJobSpec struct {
|
||||
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
||||
Schedule string
|
||||
|
||||
// The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
|
||||
// If not specified, this will rely on the time zone of the kube-controller-manager process.
|
||||
// ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.
|
||||
// +optional
|
||||
TimeZone *string
|
||||
|
||||
// Optional deadline in seconds for starting the job if it misses scheduled
|
||||
// time for any reason. Missed jobs executions will be counted as failed ones.
|
||||
// +optional
|
||||
|
2
pkg/apis/batch/v1/zz_generated.conversion.go
generated
2
pkg/apis/batch/v1/zz_generated.conversion.go
generated
@ -231,6 +231,7 @@ func Convert_batch_CronJobList_To_v1_CronJobList(in *batch.CronJobList, out *v1.
|
||||
|
||||
func autoConvert_v1_CronJobSpec_To_batch_CronJobSpec(in *v1.CronJobSpec, out *batch.CronJobSpec, s conversion.Scope) error {
|
||||
out.Schedule = in.Schedule
|
||||
out.TimeZone = (*string)(unsafe.Pointer(in.TimeZone))
|
||||
out.StartingDeadlineSeconds = (*int64)(unsafe.Pointer(in.StartingDeadlineSeconds))
|
||||
out.ConcurrencyPolicy = batch.ConcurrencyPolicy(in.ConcurrencyPolicy)
|
||||
out.Suspend = (*bool)(unsafe.Pointer(in.Suspend))
|
||||
@ -249,6 +250,7 @@ func Convert_v1_CronJobSpec_To_batch_CronJobSpec(in *v1.CronJobSpec, out *batch.
|
||||
|
||||
func autoConvert_batch_CronJobSpec_To_v1_CronJobSpec(in *batch.CronJobSpec, out *v1.CronJobSpec, s conversion.Scope) error {
|
||||
out.Schedule = in.Schedule
|
||||
out.TimeZone = (*string)(unsafe.Pointer(in.TimeZone))
|
||||
out.StartingDeadlineSeconds = (*int64)(unsafe.Pointer(in.StartingDeadlineSeconds))
|
||||
out.ConcurrencyPolicy = v1.ConcurrencyPolicy(in.ConcurrencyPolicy)
|
||||
out.Suspend = (*bool)(unsafe.Pointer(in.Suspend))
|
||||
|
@ -180,6 +180,7 @@ func Convert_batch_CronJobList_To_v1beta1_CronJobList(in *batch.CronJobList, out
|
||||
|
||||
func autoConvert_v1beta1_CronJobSpec_To_batch_CronJobSpec(in *v1beta1.CronJobSpec, out *batch.CronJobSpec, s conversion.Scope) error {
|
||||
out.Schedule = in.Schedule
|
||||
out.TimeZone = (*string)(unsafe.Pointer(in.TimeZone))
|
||||
out.StartingDeadlineSeconds = (*int64)(unsafe.Pointer(in.StartingDeadlineSeconds))
|
||||
out.ConcurrencyPolicy = batch.ConcurrencyPolicy(in.ConcurrencyPolicy)
|
||||
out.Suspend = (*bool)(unsafe.Pointer(in.Suspend))
|
||||
@ -198,6 +199,7 @@ func Convert_v1beta1_CronJobSpec_To_batch_CronJobSpec(in *v1beta1.CronJobSpec, o
|
||||
|
||||
func autoConvert_batch_CronJobSpec_To_v1beta1_CronJobSpec(in *batch.CronJobSpec, out *v1beta1.CronJobSpec, s conversion.Scope) error {
|
||||
out.Schedule = in.Schedule
|
||||
out.TimeZone = (*string)(unsafe.Pointer(in.TimeZone))
|
||||
out.StartingDeadlineSeconds = (*int64)(unsafe.Pointer(in.StartingDeadlineSeconds))
|
||||
out.ConcurrencyPolicy = v1beta1.ConcurrencyPolicy(in.ConcurrencyPolicy)
|
||||
out.Suspend = (*bool)(unsafe.Pointer(in.Suspend))
|
||||
|
@ -18,6 +18,8 @@ package validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@ -29,6 +31,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
|
||||
"k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
// maxParallelismForIndexJob is the maximum parallelism that an Indexed Job
|
||||
@ -277,11 +280,11 @@ func ValidateJobStatusUpdate(status, oldStatus batch.JobStatus) field.ErrorList
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCronJob validates a CronJob and returns an ErrorList with any errors.
|
||||
func ValidateCronJob(cronJob *batch.CronJob, opts apivalidation.PodValidationOptions) field.ErrorList {
|
||||
// ValidateCronJobCreate validates a CronJob on creation and returns an ErrorList with any errors.
|
||||
func ValidateCronJobCreate(cronJob *batch.CronJob, opts apivalidation.PodValidationOptions) field.ErrorList {
|
||||
// CronJobs and rcs have the same name validation
|
||||
allErrs := apivalidation.ValidateObjectMeta(&cronJob.ObjectMeta, true, apivalidation.ValidateReplicationControllerName, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidateCronJobSpec(&cronJob.Spec, field.NewPath("spec"), opts)...)
|
||||
allErrs = append(allErrs, validateCronJobSpec(&cronJob.Spec, nil, field.NewPath("spec"), opts)...)
|
||||
if len(cronJob.ObjectMeta.Name) > apimachineryvalidation.DNS1035LabelMaxLength-11 {
|
||||
// The cronjob controller appends a 11-character suffix to the cronjob (`-$TIMESTAMP`) when
|
||||
// creating a job. The job name length limit is 63 characters.
|
||||
@ -295,24 +298,31 @@ func ValidateCronJob(cronJob *batch.CronJob, opts apivalidation.PodValidationOpt
|
||||
// ValidateCronJobUpdate validates an update to a CronJob and returns an ErrorList with any errors.
|
||||
func ValidateCronJobUpdate(job, oldJob *batch.CronJob, opts apivalidation.PodValidationOptions) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&job.ObjectMeta, &oldJob.ObjectMeta, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidateCronJobSpec(&job.Spec, field.NewPath("spec"), opts)...)
|
||||
allErrs = append(allErrs, validateCronJobSpec(&job.Spec, &oldJob.Spec, field.NewPath("spec"), opts)...)
|
||||
|
||||
// skip the 52-character name validation limit on update validation
|
||||
// to allow old cronjobs with names > 52 chars to be updated/deleted
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCronJobSpec validates a CronJobSpec and returns an ErrorList with any errors.
|
||||
func ValidateCronJobSpec(spec *batch.CronJobSpec, fldPath *field.Path, opts apivalidation.PodValidationOptions) field.ErrorList {
|
||||
// validateCronJobSpec validates a CronJobSpec and returns an ErrorList with any errors.
|
||||
func validateCronJobSpec(spec, oldSpec *batch.CronJobSpec, fldPath *field.Path, opts apivalidation.PodValidationOptions) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if len(spec.Schedule) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("schedule"), ""))
|
||||
} else {
|
||||
allErrs = append(allErrs, validateScheduleFormat(spec.Schedule, fldPath.Child("schedule"))...)
|
||||
allErrs = append(allErrs, validateScheduleFormat(spec.Schedule, spec.TimeZone, fldPath.Child("schedule"))...)
|
||||
}
|
||||
|
||||
if spec.StartingDeadlineSeconds != nil {
|
||||
allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.StartingDeadlineSeconds), fldPath.Child("startingDeadlineSeconds"))...)
|
||||
}
|
||||
|
||||
if oldSpec == nil || !pointer.StringEqual(oldSpec.TimeZone, spec.TimeZone) {
|
||||
allErrs = append(allErrs, validateTimeZone(spec.TimeZone, fldPath.Child("timeZone"))...)
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, validateConcurrencyPolicy(&spec.ConcurrencyPolicy, fldPath.Child("concurrencyPolicy"))...)
|
||||
allErrs = append(allErrs, ValidateJobTemplateSpec(&spec.JobTemplate, fldPath.Child("jobTemplate"), opts)...)
|
||||
|
||||
@ -343,11 +353,36 @@ func validateConcurrencyPolicy(concurrencyPolicy *batch.ConcurrencyPolicy, fldPa
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateScheduleFormat(schedule string, fldPath *field.Path) field.ErrorList {
|
||||
func validateScheduleFormat(schedule string, timeZone *string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if _, err := cron.ParseStandard(schedule); err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, schedule, err.Error()))
|
||||
}
|
||||
if strings.Contains(schedule, "TZ") && timeZone != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, schedule, "cannot use both timeZone field and TZ or CRON_TZ in schedule"))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateTimeZone(timeZone *string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if timeZone == nil {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if len(*timeZone) == 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, timeZone, "timeZone must be nil or non-empty string"))
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if strings.EqualFold(*timeZone, "Local") {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, timeZone, "timeZone must be an explicit time zone as defined in https://www.iana.org/time-zones"))
|
||||
}
|
||||
|
||||
if _, err := time.LoadLocation(*timeZone); err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, timeZone, err.Error()))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
@ -31,6 +31,18 @@ import (
|
||||
"k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
var (
|
||||
timeZoneEmpty = ""
|
||||
timeZoneLocal = "LOCAL"
|
||||
timeZoneUTC = "UTC"
|
||||
timeZoneCorrectCasing = "America/New_York"
|
||||
timeZoneBadCasing = "AMERICA/new_york"
|
||||
timeZoneBadPrefix = " America/New_York"
|
||||
timeZoneBadSuffix = "America/New_York "
|
||||
timeZoneBadName = "America/New York"
|
||||
timeZoneEmptySpace = " "
|
||||
)
|
||||
|
||||
var ignoreErrValueDetail = cmpopts.IgnoreFields(field.Error{}, "BadValue", "Detail")
|
||||
|
||||
func getValidManualSelector() *metav1.LabelSelector {
|
||||
@ -902,9 +914,26 @@ func TestValidateCronJob(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"correct timeZone value casing": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mycronjob",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
UID: types.UID("1a2b3c"),
|
||||
},
|
||||
Spec: batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: &timeZoneCorrectCasing,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for k, v := range successCases {
|
||||
if errs := ValidateCronJob(&v, corevalidation.PodValidationOptions{}); len(errs) != 0 {
|
||||
if errs := ValidateCronJobCreate(&v, corevalidation.PodValidationOptions{}); len(errs) != 0 {
|
||||
t.Errorf("expected success for %s: %v", k, errs)
|
||||
}
|
||||
|
||||
@ -953,6 +982,142 @@ func TestValidateCronJob(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"spec.schedule: cannot use both timeZone field and TZ or CRON_TZ in schedule": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mycronjob",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
UID: types.UID("1a2b3c"),
|
||||
},
|
||||
Spec: batch.CronJobSpec{
|
||||
Schedule: "TZ=UTC 0 * * * *",
|
||||
TimeZone: &timeZoneUTC,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"spec.timeZone: timeZone must be nil or non-empty string": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mycronjob",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
UID: types.UID("1a2b3c"),
|
||||
},
|
||||
Spec: batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: &timeZoneEmpty,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"spec.timeZone: timeZone must be an explicit time zone as defined in https://www.iana.org/time-zones": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mycronjob",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
UID: types.UID("1a2b3c"),
|
||||
},
|
||||
Spec: batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: &timeZoneLocal,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"spec.timeZone: Invalid value: \"AMERICA/new_york\": unknown time zone AMERICA/new_york": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mycronjob",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
UID: types.UID("1a2b3c"),
|
||||
},
|
||||
Spec: batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: &timeZoneBadCasing,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"spec.timeZone: Invalid value: \" America/New_York\": unknown time zone America/New_York": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mycronjob",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
UID: types.UID("1a2b3c"),
|
||||
},
|
||||
Spec: batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: &timeZoneBadPrefix,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"spec.timeZone: Invalid value: \"America/New_York \": unknown time zone America/New_York ": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mycronjob",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
UID: types.UID("1a2b3c"),
|
||||
},
|
||||
Spec: batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: &timeZoneBadSuffix,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"spec.timeZone: Invalid value: \"America/New York\": unknown time zone America/New York": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mycronjob",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
UID: types.UID("1a2b3c"),
|
||||
},
|
||||
Spec: batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: &timeZoneBadName,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"spec.timeZone: Invalid value: \" \": unknown time zone ": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mycronjob",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
UID: types.UID("1a2b3c"),
|
||||
},
|
||||
Spec: batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: &timeZoneEmptySpace,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"spec.startingDeadlineSeconds:must be greater than or equal to 0": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mycronjob",
|
||||
@ -1185,7 +1350,7 @@ func TestValidateCronJob(t *testing.T) {
|
||||
}
|
||||
|
||||
for k, v := range errorCases {
|
||||
errs := ValidateCronJob(&v, corevalidation.PodValidationOptions{})
|
||||
errs := ValidateCronJobCreate(&v, corevalidation.PodValidationOptions{})
|
||||
if len(errs) == 0 {
|
||||
t.Errorf("expected failure for %s", k)
|
||||
} else {
|
||||
@ -1198,9 +1363,14 @@ func TestValidateCronJob(t *testing.T) {
|
||||
|
||||
// Update validation should fail all failure cases other than the 52 character name limit
|
||||
// copy to avoid polluting the testcase object, set a resourceVersion to allow validating update, and test a no-op update
|
||||
v = *v.DeepCopy()
|
||||
v.ResourceVersion = "1"
|
||||
errs = ValidateCronJobUpdate(&v, &v, corevalidation.PodValidationOptions{})
|
||||
oldSpec := *v.DeepCopy()
|
||||
oldSpec.ResourceVersion = "1"
|
||||
oldSpec.Spec.TimeZone = nil
|
||||
|
||||
newSpec := *v.DeepCopy()
|
||||
newSpec.ResourceVersion = "2"
|
||||
|
||||
errs = ValidateCronJobUpdate(&newSpec, &oldSpec, corevalidation.PodValidationOptions{})
|
||||
if len(errs) == 0 {
|
||||
if k == "metadata.name: must be no more than 52 characters" {
|
||||
continue
|
||||
@ -1216,6 +1386,208 @@ func TestValidateCronJob(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCronJobSpec(t *testing.T) {
|
||||
validPodTemplateSpec := getValidPodTemplateSpecForGenerated(getValidGeneratedSelector())
|
||||
validPodTemplateSpec.Labels = map[string]string{}
|
||||
|
||||
type testCase struct {
|
||||
old *batch.CronJobSpec
|
||||
new *batch.CronJobSpec
|
||||
expectErr bool
|
||||
}
|
||||
|
||||
cases := map[string]testCase{
|
||||
"no validation because timeZone is nil for old and new": {
|
||||
old: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: nil,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
new: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: nil,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"check validation because timeZone is different for new": {
|
||||
old: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: nil,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
new: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: pointer.String("America/New_York"),
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"check validation because timeZone is different for new and invalid": {
|
||||
old: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: nil,
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
new: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: pointer.String("broken"),
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
"old timeZone and new timeZone are valid": {
|
||||
old: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: pointer.String("America/New_York"),
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
new: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: pointer.String("America/Chicago"),
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"old timeZone is valid, but new timeZone is invalid": {
|
||||
old: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: pointer.String("America/New_York"),
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
new: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: pointer.String("broken"),
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
"old timeZone and new timeZone are invalid, but unchanged": {
|
||||
old: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: pointer.String("broken"),
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
new: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: pointer.String("broken"),
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"old timeZone and new timeZone are invalid, but different": {
|
||||
old: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: pointer.String("broken"),
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
new: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: pointer.String("still broken"),
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
"old timeZone is invalid, but new timeZone is valid": {
|
||||
old: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: pointer.String("broken"),
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
new: &batch.CronJobSpec{
|
||||
Schedule: "0 * * * *",
|
||||
TimeZone: pointer.String("America/New_York"),
|
||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||
JobTemplate: batch.JobTemplateSpec{
|
||||
Spec: batch.JobSpec{
|
||||
Template: validPodTemplateSpec,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range cases {
|
||||
errs := validateCronJobSpec(v.new, v.old, field.NewPath("spec"), corevalidation.PodValidationOptions{})
|
||||
if len(errs) > 0 && !v.expectErr {
|
||||
t.Errorf("unexpected error for %s: %v", k, errs)
|
||||
} else if len(errs) == 0 && v.expectErr {
|
||||
t.Errorf("expected error for %s but got nil", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func completionModePtr(m batch.CompletionMode) *batch.CompletionMode {
|
||||
return &m
|
||||
}
|
||||
|
5
pkg/apis/batch/zz_generated.deepcopy.go
generated
5
pkg/apis/batch/zz_generated.deepcopy.go
generated
@ -92,6 +92,11 @@ func (in *CronJobList) DeepCopyObject() runtime.Object {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CronJobSpec) DeepCopyInto(out *CronJobSpec) {
|
||||
*out = *in
|
||||
if in.TimeZone != nil {
|
||||
in, out := &in.TimeZone, &out.TimeZone
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.StartingDeadlineSeconds != nil {
|
||||
in, out := &in.StartingDeadlineSeconds, &out.StartingDeadlineSeconds
|
||||
*out = new(int64)
|
||||
|
@ -35,6 +35,8 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
batchv1informers "k8s.io/client-go/informers/batch/v1"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
@ -48,6 +50,7 @@ import (
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/controller/cronjob/metrics"
|
||||
"k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -371,6 +374,7 @@ func (jm *ControllerV2) enqueueControllerAfter(obj interface{}, t time.Duration)
|
||||
// updateCronJob re-queues the CronJob for next scheduled time if there is a
|
||||
// change in spec.schedule otherwise it re-queues it now
|
||||
func (jm *ControllerV2) updateCronJob(old interface{}, curr interface{}) {
|
||||
timeZoneEnabled := utilfeature.DefaultFeatureGate.Enabled(features.CronJobTimeZone)
|
||||
oldCJ, okOld := old.(*batchv1.CronJob)
|
||||
newCJ, okNew := curr.(*batchv1.CronJob)
|
||||
|
||||
@ -381,9 +385,9 @@ func (jm *ControllerV2) updateCronJob(old interface{}, curr interface{}) {
|
||||
// if the change in schedule results in next requeue having to be sooner than it already was,
|
||||
// it will be handled here by the queue. If the next requeue is further than previous schedule,
|
||||
// the sync loop will essentially be a no-op for the already queued key with old schedule.
|
||||
if oldCJ.Spec.Schedule != newCJ.Spec.Schedule {
|
||||
// schedule changed, change the requeue time
|
||||
sched, err := cron.ParseStandard(newCJ.Spec.Schedule)
|
||||
if oldCJ.Spec.Schedule != newCJ.Spec.Schedule || (timeZoneEnabled && !pointer.StringEqual(oldCJ.Spec.TimeZone, newCJ.Spec.TimeZone)) {
|
||||
// schedule changed, change the requeue time, pass nil recorder so that syncCronJob will output any warnings
|
||||
sched, err := cron.ParseStandard(formatSchedule(timeZoneEnabled, newCJ, nil))
|
||||
if err != nil {
|
||||
// this is likely a user error in defining the spec value
|
||||
// we should log the error and not reconcile this cronjob until an update to spec
|
||||
@ -420,6 +424,7 @@ func (jm *ControllerV2) syncCronJob(
|
||||
cronJob = cronJob.DeepCopy()
|
||||
now := jm.now()
|
||||
updateStatus := false
|
||||
timeZoneEnabled := utilfeature.DefaultFeatureGate.Enabled(features.CronJobTimeZone)
|
||||
|
||||
childrenJobs := make(map[types.UID]bool)
|
||||
for _, j := range jobs {
|
||||
@ -487,12 +492,21 @@ func (jm *ControllerV2) syncCronJob(
|
||||
return cronJob, nil, updateStatus, nil
|
||||
}
|
||||
|
||||
if timeZoneEnabled && cronJob.Spec.TimeZone != nil {
|
||||
if _, err := time.LoadLocation(*cronJob.Spec.TimeZone); err != nil {
|
||||
timeZone := pointer.StringDeref(cronJob.Spec.TimeZone, "")
|
||||
klog.V(4).InfoS("Not starting job because timeZone is invalid", "cronjob", klog.KRef(cronJob.GetNamespace(), cronJob.GetName()), "timeZone", timeZone, "err", err)
|
||||
jm.recorder.Eventf(cronJob, corev1.EventTypeWarning, "UnknownTimeZone", "invalid timeZone: %q: %s", timeZone, err)
|
||||
return cronJob, nil, updateStatus, nil
|
||||
}
|
||||
}
|
||||
|
||||
if cronJob.Spec.Suspend != nil && *cronJob.Spec.Suspend {
|
||||
klog.V(4).InfoS("Not starting job because the cron is suspended", "cronjob", klog.KRef(cronJob.GetNamespace(), cronJob.GetName()))
|
||||
return cronJob, nil, updateStatus, nil
|
||||
}
|
||||
|
||||
sched, err := cron.ParseStandard(cronJob.Spec.Schedule)
|
||||
sched, err := cron.ParseStandard(formatSchedule(timeZoneEnabled, cronJob, jm.recorder))
|
||||
if err != nil {
|
||||
// this is likely a user error in defining the spec value
|
||||
// we should log the error and not reconcile this cronjob until an update to spec
|
||||
@ -501,10 +515,6 @@ func (jm *ControllerV2) syncCronJob(
|
||||
return cronJob, nil, updateStatus, nil
|
||||
}
|
||||
|
||||
if strings.Contains(cronJob.Spec.Schedule, "TZ") {
|
||||
jm.recorder.Eventf(cronJob, corev1.EventTypeWarning, "UnsupportedSchedule", "CRON_TZ or TZ used in schedule %q is not officially supported, see https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/ for more details", cronJob.Spec.Schedule)
|
||||
}
|
||||
|
||||
scheduledTime, err := getNextScheduleTime(*cronJob, now, sched, jm.recorder)
|
||||
if err != nil {
|
||||
// this is likely a user error in defining the spec value
|
||||
@ -739,3 +749,23 @@ func deleteJob(cj *batchv1.CronJob, job *batchv1.Job, jc jobControlInterface, re
|
||||
func getRef(object runtime.Object) (*corev1.ObjectReference, error) {
|
||||
return ref.GetReference(scheme.Scheme, object)
|
||||
}
|
||||
|
||||
func formatSchedule(timeZoneEnabled bool, cj *batchv1.CronJob, recorder record.EventRecorder) string {
|
||||
if strings.Contains(cj.Spec.Schedule, "TZ") {
|
||||
if recorder != nil {
|
||||
recorder.Eventf(cj, corev1.EventTypeWarning, "UnsupportedSchedule", "CRON_TZ or TZ used in schedule %q is not officially supported, see https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/ for more details", cj.Spec.Schedule)
|
||||
}
|
||||
|
||||
return cj.Spec.Schedule
|
||||
}
|
||||
|
||||
if timeZoneEnabled && cj.Spec.TimeZone != nil {
|
||||
if _, err := time.LoadLocation(*cj.Spec.TimeZone); err != nil {
|
||||
return cj.Spec.Schedule
|
||||
}
|
||||
|
||||
return fmt.Sprintf("TZ=%s %s", *cj.Spec.TimeZone, cj.Spec.Schedule)
|
||||
}
|
||||
|
||||
return cj.Spec.Schedule
|
||||
}
|
||||
|
@ -32,10 +32,13 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
_ "k8s.io/kubernetes/pkg/apis/batch/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
@ -50,6 +53,9 @@ var (
|
||||
errorSchedule = "obvious error schedule"
|
||||
// schedule is hourly on the hour
|
||||
onTheHour = "0 * * * ?"
|
||||
|
||||
errorTimeZone = "bad timezone"
|
||||
newYork = "America/New_York"
|
||||
)
|
||||
|
||||
// returns a cronJob with some fields filled in.
|
||||
@ -127,6 +133,19 @@ func justAfterTheHour() *time.Time {
|
||||
return &T1
|
||||
}
|
||||
|
||||
func justAfterTheHourInZone(tz string) time.Time {
|
||||
location, err := time.LoadLocation(tz)
|
||||
if err != nil {
|
||||
panic("tz error: " + err.Error())
|
||||
}
|
||||
|
||||
T1, err := time.ParseInLocation(time.RFC3339, "2016-05-19T10:01:00Z", location)
|
||||
if err != nil {
|
||||
panic("test setup error: " + err.Error())
|
||||
}
|
||||
return T1
|
||||
}
|
||||
|
||||
func justBeforeTheHour() time.Time {
|
||||
T1, err := time.Parse(time.RFC3339, "2016-05-19T09:59:00Z")
|
||||
if err != nil {
|
||||
@ -162,6 +181,7 @@ func TestControllerV2SyncCronJob(t *testing.T) {
|
||||
concurrencyPolicy batchv1.ConcurrencyPolicy
|
||||
suspend bool
|
||||
schedule string
|
||||
timeZone *string
|
||||
deadline int64
|
||||
|
||||
// cj status
|
||||
@ -173,6 +193,7 @@ func TestControllerV2SyncCronJob(t *testing.T) {
|
||||
now time.Time
|
||||
jobCreateError error
|
||||
jobGetErr error
|
||||
enableTimeZone bool
|
||||
|
||||
// expectations
|
||||
expectCreate bool
|
||||
@ -212,6 +233,17 @@ func TestControllerV2SyncCronJob(t *testing.T) {
|
||||
expectedWarnings: 1,
|
||||
jobPresentInCJActiveStatus: true,
|
||||
},
|
||||
"never ran, not valid time zone": {
|
||||
concurrencyPolicy: "Allow",
|
||||
schedule: onTheHour,
|
||||
timeZone: &errorTimeZone,
|
||||
deadline: noDead,
|
||||
jobCreationTime: justAfterThePriorHour(),
|
||||
now: justBeforeTheHour(),
|
||||
enableTimeZone: true,
|
||||
expectedWarnings: 1,
|
||||
jobPresentInCJActiveStatus: true,
|
||||
},
|
||||
"never ran, not time, A": {
|
||||
concurrencyPolicy: "Allow",
|
||||
schedule: onTheHour,
|
||||
@ -238,6 +270,17 @@ func TestControllerV2SyncCronJob(t *testing.T) {
|
||||
expectRequeueAfter: true,
|
||||
jobPresentInCJActiveStatus: true,
|
||||
},
|
||||
"never ran, not time in zone": {
|
||||
concurrencyPolicy: "Allow",
|
||||
schedule: onTheHour,
|
||||
timeZone: &newYork,
|
||||
deadline: noDead,
|
||||
jobCreationTime: justAfterThePriorHour(),
|
||||
now: justBeforeTheHour(),
|
||||
enableTimeZone: true,
|
||||
expectRequeueAfter: true,
|
||||
jobPresentInCJActiveStatus: true,
|
||||
},
|
||||
"never ran, is time, A": {
|
||||
concurrencyPolicy: "Allow",
|
||||
schedule: onTheHour,
|
||||
@ -274,6 +317,48 @@ func TestControllerV2SyncCronJob(t *testing.T) {
|
||||
expectUpdateStatus: true,
|
||||
jobPresentInCJActiveStatus: true,
|
||||
},
|
||||
"never ran, is time in zone, but time zone disabled": {
|
||||
concurrencyPolicy: "Allow",
|
||||
schedule: onTheHour,
|
||||
timeZone: &newYork,
|
||||
deadline: noDead,
|
||||
jobCreationTime: justAfterThePriorHour(),
|
||||
now: justAfterTheHourInZone(newYork),
|
||||
enableTimeZone: false,
|
||||
expectCreate: true,
|
||||
expectActive: 1,
|
||||
expectRequeueAfter: true,
|
||||
expectUpdateStatus: true,
|
||||
jobPresentInCJActiveStatus: true,
|
||||
},
|
||||
"never ran, is time in zone": {
|
||||
concurrencyPolicy: "Allow",
|
||||
schedule: onTheHour,
|
||||
timeZone: &newYork,
|
||||
deadline: noDead,
|
||||
jobCreationTime: justAfterThePriorHour(),
|
||||
now: justAfterTheHourInZone(newYork),
|
||||
enableTimeZone: true,
|
||||
expectCreate: true,
|
||||
expectActive: 1,
|
||||
expectRequeueAfter: true,
|
||||
expectUpdateStatus: true,
|
||||
jobPresentInCJActiveStatus: true,
|
||||
},
|
||||
"never ran, is time in zone, but TZ is also set in schedule": {
|
||||
concurrencyPolicy: "Allow",
|
||||
schedule: "TZ=UTC " + onTheHour,
|
||||
timeZone: &newYork,
|
||||
deadline: noDead,
|
||||
jobCreationTime: justAfterThePriorHour(),
|
||||
now: justAfterTheHourInZone(newYork),
|
||||
enableTimeZone: true,
|
||||
expectCreate: true,
|
||||
expectedWarnings: 1,
|
||||
expectRequeueAfter: true,
|
||||
expectUpdateStatus: true,
|
||||
jobPresentInCJActiveStatus: true,
|
||||
},
|
||||
"never ran, is time, suspended": {
|
||||
concurrencyPolicy: "Allow",
|
||||
suspend: true,
|
||||
@ -815,11 +900,15 @@ func TestControllerV2SyncCronJob(t *testing.T) {
|
||||
for name, tc := range testCases {
|
||||
name := name
|
||||
tc := tc
|
||||
|
||||
t.Run(name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.CronJobTimeZone, tc.enableTimeZone)()
|
||||
|
||||
cj := cronJob()
|
||||
cj.Spec.ConcurrencyPolicy = tc.concurrencyPolicy
|
||||
cj.Spec.Suspend = &tc.suspend
|
||||
cj.Spec.Schedule = tc.schedule
|
||||
cj.Spec.TimeZone = tc.timeZone
|
||||
if tc.deadline != noDead {
|
||||
cj.Spec.StartingDeadlineSeconds = &tc.deadline
|
||||
}
|
||||
@ -1058,6 +1147,63 @@ func TestControllerV2UpdateCronJob(t *testing.T) {
|
||||
},
|
||||
expectedDelay: 1*time.Second + nextScheduleDelta,
|
||||
},
|
||||
{
|
||||
name: "spec.timeZone not changed",
|
||||
oldCronJob: &batchv1.CronJob{
|
||||
Spec: batchv1.CronJobSpec{
|
||||
TimeZone: &newYork,
|
||||
JobTemplate: batchv1.JobTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{"a": "b"},
|
||||
Annotations: map[string]string{"x": "y"},
|
||||
},
|
||||
Spec: jobSpec(),
|
||||
},
|
||||
},
|
||||
},
|
||||
newCronJob: &batchv1.CronJob{
|
||||
Spec: batchv1.CronJobSpec{
|
||||
TimeZone: &newYork,
|
||||
JobTemplate: batchv1.JobTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{"a": "foo"},
|
||||
Annotations: map[string]string{"x": "y"},
|
||||
},
|
||||
Spec: jobSpec(),
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedDelay: 0 * time.Second,
|
||||
},
|
||||
{
|
||||
name: "spec.timeZone changed",
|
||||
oldCronJob: &batchv1.CronJob{
|
||||
Spec: batchv1.CronJobSpec{
|
||||
TimeZone: &newYork,
|
||||
JobTemplate: batchv1.JobTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{"a": "b"},
|
||||
Annotations: map[string]string{"x": "y"},
|
||||
},
|
||||
Spec: jobSpec(),
|
||||
},
|
||||
},
|
||||
},
|
||||
newCronJob: &batchv1.CronJob{
|
||||
Spec: batchv1.CronJobSpec{
|
||||
TimeZone: nil,
|
||||
JobTemplate: batchv1.JobTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{"a": "foo"},
|
||||
Annotations: map[string]string{"x": "y"},
|
||||
},
|
||||
Spec: jobSpec(),
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedDelay: 0 * time.Second,
|
||||
},
|
||||
|
||||
// TODO: Add more test cases for updating scheduling.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
14
pkg/generated/openapi/zz_generated.openapi.go
generated
14
pkg/generated/openapi/zz_generated.openapi.go
generated
@ -12682,6 +12682,13 @@ func schema_k8sio_api_batch_v1_CronJobSpec(ref common.ReferenceCallback) common.
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"timeZone": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will rely on the time zone of the kube-controller-manager process. ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"startingDeadlineSeconds": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Optional deadline in seconds for starting the job if it misses scheduled time for any reason. Missed jobs executions will be counted as failed ones.",
|
||||
@ -13312,6 +13319,13 @@ func schema_k8sio_api_batch_v1beta1_CronJobSpec(ref common.ReferenceCallback) co
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"timeZone": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will rely on the time zone of the kube-controller-manager process. ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"startingDeadlineSeconds": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Optional deadline in seconds for starting the job if it misses scheduled time for any reason. Missed jobs executions will be counted as failed ones.",
|
||||
|
@ -27,8 +27,10 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/api/pod"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
@ -88,6 +90,10 @@ func (cronJobStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object)
|
||||
|
||||
cronJob.Generation = 1
|
||||
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CronJobTimeZone) {
|
||||
cronJob.Spec.TimeZone = nil
|
||||
}
|
||||
|
||||
pod.DropDisabledTemplateFields(&cronJob.Spec.JobTemplate.Spec.Template, nil)
|
||||
}
|
||||
|
||||
@ -97,6 +103,10 @@ func (cronJobStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Ob
|
||||
oldCronJob := old.(*batch.CronJob)
|
||||
newCronJob.Status = oldCronJob.Status
|
||||
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CronJobTimeZone) && oldCronJob.Spec.TimeZone == nil {
|
||||
newCronJob.Spec.TimeZone = nil
|
||||
}
|
||||
|
||||
pod.DropDisabledTemplateFields(&newCronJob.Spec.JobTemplate.Spec.Template, &oldCronJob.Spec.JobTemplate.Spec.Template)
|
||||
|
||||
// Any changes to the spec increment the generation number.
|
||||
@ -110,7 +120,7 @@ func (cronJobStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Ob
|
||||
func (cronJobStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
|
||||
cronJob := obj.(*batch.CronJob)
|
||||
opts := pod.GetValidationOptionsFromPodTemplate(&cronJob.Spec.JobTemplate.Spec.Template, nil)
|
||||
return validation.ValidateCronJob(cronJob, opts)
|
||||
return validation.ValidateCronJobCreate(cronJob, opts)
|
||||
}
|
||||
|
||||
// WarningsOnCreate returns warnings for the creation of the given object.
|
||||
|
226
staging/src/k8s.io/api/batch/v1/generated.pb.go
generated
226
staging/src/k8s.io/api/batch/v1/generated.pb.go
generated
@ -375,96 +375,97 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_3b52da57c93de713 = []byte{
|
||||
// 1416 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0xc1, 0x6f, 0x1b, 0x45,
|
||||
0x17, 0xcf, 0x26, 0x71, 0x6c, 0x8f, 0x93, 0xd4, 0x9d, 0x7e, 0x6d, 0xfd, 0xf9, 0xab, 0xbc, 0xa9,
|
||||
0xbf, 0x82, 0x02, 0x2a, 0x6b, 0x12, 0x22, 0x04, 0x08, 0x90, 0xb2, 0xa9, 0x0a, 0x0d, 0x8e, 0x1a,
|
||||
0xc6, 0x8e, 0x90, 0xa0, 0x20, 0xd6, 0xbb, 0x63, 0x67, 0x9b, 0xdd, 0x1d, 0x6b, 0x67, 0x1c, 0xe1,
|
||||
0x1b, 0x12, 0xff, 0x00, 0xfc, 0x13, 0x88, 0x13, 0x42, 0x82, 0x33, 0x47, 0xd4, 0x63, 0x8f, 0x3d,
|
||||
0xad, 0xe8, 0xf2, 0x07, 0x70, 0x0f, 0x17, 0x34, 0xb3, 0xe3, 0xdd, 0xb5, 0xbd, 0x1b, 0xd2, 0x1e,
|
||||
0x2a, 0x6e, 0xdd, 0x37, 0xbf, 0xf7, 0x9b, 0xe7, 0xf7, 0x7e, 0xf3, 0xde, 0x4b, 0xc1, 0xbb, 0x27,
|
||||
0x6f, 0x51, 0xcd, 0x26, 0xad, 0x93, 0x51, 0x0f, 0xfb, 0x1e, 0x66, 0x98, 0xb6, 0x4e, 0xb1, 0x67,
|
||||
0x11, 0xbf, 0x25, 0x0f, 0x8c, 0xa1, 0xdd, 0xea, 0x19, 0xcc, 0x3c, 0x6e, 0x9d, 0x6e, 0xb5, 0x06,
|
||||
0xd8, 0xc3, 0xbe, 0xc1, 0xb0, 0xa5, 0x0d, 0x7d, 0xc2, 0x08, 0xbc, 0x12, 0x81, 0x34, 0x63, 0x68,
|
||||
0x6b, 0x02, 0xa4, 0x9d, 0x6e, 0xd5, 0x5f, 0x1b, 0xd8, 0xec, 0x78, 0xd4, 0xd3, 0x4c, 0xe2, 0xb6,
|
||||
0x06, 0x64, 0x40, 0x5a, 0x02, 0xdb, 0x1b, 0xf5, 0xc5, 0x97, 0xf8, 0x10, 0xff, 0x8a, 0x38, 0xea,
|
||||
0xcd, 0xd4, 0x45, 0x26, 0xf1, 0x71, 0xc6, 0x3d, 0xf5, 0x9d, 0x04, 0xe3, 0x1a, 0xe6, 0xb1, 0xed,
|
||||
0x61, 0x7f, 0xdc, 0x1a, 0x9e, 0x0c, 0xb8, 0x81, 0xb6, 0x5c, 0xcc, 0x8c, 0x2c, 0xaf, 0x56, 0x9e,
|
||||
0x97, 0x3f, 0xf2, 0x98, 0xed, 0xe2, 0x39, 0x87, 0x37, 0xff, 0xc9, 0x81, 0x9a, 0xc7, 0xd8, 0x35,
|
||||
0x66, 0xfd, 0x9a, 0x7f, 0x29, 0xa0, 0xb8, 0xe7, 0x13, 0x6f, 0x9f, 0xf4, 0xe0, 0x97, 0xa0, 0xc4,
|
||||
0xe3, 0xb1, 0x0c, 0x66, 0xd4, 0x94, 0x0d, 0x65, 0xb3, 0xb2, 0xfd, 0xba, 0x96, 0x64, 0x29, 0xa6,
|
||||
0xd5, 0x86, 0x27, 0x03, 0x6e, 0xa0, 0x1a, 0x47, 0x6b, 0xa7, 0x5b, 0xda, 0xfd, 0xde, 0x43, 0x6c,
|
||||
0xb2, 0x03, 0xcc, 0x0c, 0x1d, 0x3e, 0x0a, 0xd4, 0x85, 0x30, 0x50, 0x41, 0x62, 0x43, 0x31, 0x2b,
|
||||
0xd4, 0xc1, 0x32, 0x1d, 0x62, 0xb3, 0xb6, 0x28, 0xd8, 0x37, 0xb4, 0x8c, 0x1a, 0x68, 0x32, 0x9a,
|
||||
0xce, 0x10, 0x9b, 0xfa, 0xaa, 0x64, 0x5b, 0xe6, 0x5f, 0x48, 0xf8, 0xc2, 0x7d, 0xb0, 0x42, 0x99,
|
||||
0xc1, 0x46, 0xb4, 0xb6, 0x24, 0x58, 0x9a, 0xe7, 0xb2, 0x08, 0xa4, 0xbe, 0x2e, 0x79, 0x56, 0xa2,
|
||||
0x6f, 0x24, 0x19, 0x9a, 0x3f, 0x2a, 0xa0, 0x22, 0x91, 0x6d, 0x9b, 0x32, 0xf8, 0x60, 0x2e, 0x03,
|
||||
0xda, 0xc5, 0x32, 0xc0, 0xbd, 0xc5, 0xef, 0xaf, 0xca, 0x9b, 0x4a, 0x13, 0x4b, 0xea, 0xd7, 0xef,
|
||||
0x82, 0x82, 0xcd, 0xb0, 0x4b, 0x6b, 0x8b, 0x1b, 0x4b, 0x9b, 0x95, 0xed, 0x1b, 0xe7, 0x05, 0xae,
|
||||
0xaf, 0x49, 0xa2, 0xc2, 0x3d, 0xee, 0x82, 0x22, 0xcf, 0xe6, 0x0f, 0xcb, 0x71, 0xc0, 0x3c, 0x25,
|
||||
0xf0, 0x36, 0x28, 0xf1, 0xc2, 0x5a, 0x23, 0x07, 0x8b, 0x80, 0xcb, 0x49, 0x00, 0x1d, 0x69, 0x47,
|
||||
0x31, 0x02, 0x1e, 0x81, 0xeb, 0x94, 0x19, 0x3e, 0xb3, 0xbd, 0xc1, 0x1d, 0x6c, 0x58, 0x8e, 0xed,
|
||||
0xe1, 0x0e, 0x36, 0x89, 0x67, 0x51, 0x51, 0x91, 0x25, 0xfd, 0x7f, 0x61, 0xa0, 0x5e, 0xef, 0x64,
|
||||
0x43, 0x50, 0x9e, 0x2f, 0x7c, 0x00, 0x2e, 0x9b, 0xc4, 0x33, 0x47, 0xbe, 0x8f, 0x3d, 0x73, 0x7c,
|
||||
0x48, 0x1c, 0xdb, 0x1c, 0x8b, 0xe2, 0x94, 0x75, 0x4d, 0x46, 0x73, 0x79, 0x6f, 0x16, 0x70, 0x96,
|
||||
0x65, 0x44, 0xf3, 0x44, 0xf0, 0x25, 0x50, 0xa4, 0x23, 0x3a, 0xc4, 0x9e, 0x55, 0x5b, 0xde, 0x50,
|
||||
0x36, 0x4b, 0x7a, 0x25, 0x0c, 0xd4, 0x62, 0x27, 0x32, 0xa1, 0xc9, 0x19, 0xfc, 0x0c, 0x54, 0x1e,
|
||||
0x92, 0x5e, 0x17, 0xbb, 0x43, 0xc7, 0x60, 0xb8, 0x56, 0x10, 0xd5, 0xbb, 0x95, 0x99, 0xe2, 0xfd,
|
||||
0x04, 0x27, 0x54, 0x76, 0x45, 0x06, 0x59, 0x49, 0x1d, 0xa0, 0x34, 0x1b, 0xfc, 0x02, 0xd4, 0xe9,
|
||||
0xc8, 0x34, 0x31, 0xa5, 0xfd, 0x91, 0xb3, 0x4f, 0x7a, 0xf4, 0x43, 0x9b, 0x32, 0xe2, 0x8f, 0xdb,
|
||||
0xb6, 0x6b, 0xb3, 0xda, 0xca, 0x86, 0xb2, 0x59, 0xd0, 0x1b, 0x61, 0xa0, 0xd6, 0x3b, 0xb9, 0x28,
|
||||
0x74, 0x0e, 0x03, 0x44, 0xe0, 0x5a, 0xdf, 0xb0, 0x1d, 0x6c, 0xcd, 0x71, 0x17, 0x05, 0x77, 0x3d,
|
||||
0x0c, 0xd4, 0x6b, 0x77, 0x33, 0x11, 0x28, 0xc7, 0xb3, 0xf9, 0xeb, 0x22, 0x58, 0x9b, 0x7a, 0x05,
|
||||
0xf0, 0x23, 0xb0, 0x62, 0x98, 0xcc, 0x3e, 0xe5, 0x52, 0xe1, 0x02, 0xfc, 0x7f, 0x3a, 0x3b, 0xbc,
|
||||
0x7f, 0x25, 0x6f, 0x19, 0xe1, 0x3e, 0xe6, 0x45, 0xc0, 0xc9, 0xd3, 0xd9, 0x15, 0xae, 0x48, 0x52,
|
||||
0x40, 0x07, 0x54, 0x1d, 0x83, 0xb2, 0x89, 0xca, 0xba, 0xb6, 0x8b, 0x45, 0x7d, 0x2a, 0xdb, 0xaf,
|
||||
0x5e, 0xec, 0xc9, 0x70, 0x0f, 0xfd, 0x3f, 0x61, 0xa0, 0x56, 0xdb, 0x33, 0x3c, 0x68, 0x8e, 0x19,
|
||||
0xfa, 0x00, 0x0a, 0x5b, 0x9c, 0x42, 0x71, 0x5f, 0xe1, 0x99, 0xef, 0xbb, 0x16, 0x06, 0x2a, 0x6c,
|
||||
0xcf, 0x31, 0xa1, 0x0c, 0xf6, 0xe6, 0x9f, 0x0a, 0x58, 0x7a, 0x31, 0x6d, 0xf1, 0xfd, 0xa9, 0xb6,
|
||||
0x78, 0x23, 0x4f, 0xb4, 0xb9, 0x2d, 0xf1, 0xee, 0x4c, 0x4b, 0x6c, 0xe4, 0x32, 0x9c, 0xdf, 0x0e,
|
||||
0x7f, 0x5b, 0x02, 0xab, 0xfb, 0xa4, 0xb7, 0x47, 0x3c, 0xcb, 0x66, 0x36, 0xf1, 0xe0, 0x0e, 0x58,
|
||||
0x66, 0xe3, 0xe1, 0xa4, 0xb5, 0x6c, 0x4c, 0xae, 0xee, 0x8e, 0x87, 0xf8, 0x2c, 0x50, 0xab, 0x69,
|
||||
0x2c, 0xb7, 0x21, 0x81, 0x86, 0xed, 0x38, 0x9c, 0x45, 0xe1, 0xb7, 0x33, 0x7d, 0xdd, 0x59, 0xa0,
|
||||
0x66, 0x0c, 0x4e, 0x2d, 0x66, 0x9a, 0x0e, 0x0a, 0x0e, 0xc0, 0x1a, 0x2f, 0xce, 0xa1, 0x4f, 0x7a,
|
||||
0x91, 0xca, 0x96, 0x9e, 0xb9, 0xea, 0x57, 0x65, 0x00, 0x6b, 0xed, 0x34, 0x11, 0x9a, 0xe6, 0x85,
|
||||
0xa7, 0x91, 0xc6, 0xba, 0xbe, 0xe1, 0xd1, 0xe8, 0x27, 0x3d, 0x9f, 0xa6, 0xeb, 0xf2, 0x36, 0xa1,
|
||||
0xb3, 0x69, 0x36, 0x94, 0x71, 0x03, 0x7c, 0x19, 0xac, 0xf8, 0xd8, 0xa0, 0xc4, 0x13, 0x7a, 0x2e,
|
||||
0x27, 0xd5, 0x41, 0xc2, 0x8a, 0xe4, 0x29, 0x7c, 0x05, 0x14, 0x5d, 0x4c, 0xa9, 0x31, 0xc0, 0xa2,
|
||||
0xe3, 0x94, 0xf5, 0x4b, 0x12, 0x58, 0x3c, 0x88, 0xcc, 0x68, 0x72, 0xde, 0xfc, 0x5e, 0x01, 0xc5,
|
||||
0x17, 0x33, 0xd3, 0xde, 0x9b, 0x9e, 0x69, 0xb5, 0x3c, 0xe5, 0xe5, 0xcc, 0xb3, 0x9f, 0x0a, 0x22,
|
||||
0x50, 0x31, 0xcb, 0xb6, 0x40, 0x65, 0x68, 0xf8, 0x86, 0xe3, 0x60, 0xc7, 0xa6, 0xae, 0x88, 0xb5,
|
||||
0xa0, 0x5f, 0xe2, 0x7d, 0xf9, 0x30, 0x31, 0xa3, 0x34, 0x86, 0xbb, 0x98, 0xc4, 0x1d, 0x3a, 0x98,
|
||||
0x27, 0x33, 0x92, 0x9b, 0x74, 0xd9, 0x4b, 0xcc, 0x28, 0x8d, 0x81, 0xf7, 0xc1, 0xd5, 0xa8, 0x83,
|
||||
0xcd, 0x4e, 0xc0, 0x25, 0x31, 0x01, 0xff, 0x1b, 0x06, 0xea, 0xd5, 0xdd, 0x2c, 0x00, 0xca, 0xf6,
|
||||
0x83, 0x3b, 0x60, 0xb5, 0x67, 0x98, 0x27, 0xa4, 0xdf, 0x4f, 0x77, 0xec, 0x6a, 0x18, 0xa8, 0xab,
|
||||
0x7a, 0xca, 0x8e, 0xa6, 0x50, 0xf0, 0x73, 0x50, 0xa2, 0xd8, 0xc1, 0x26, 0x23, 0xbe, 0x94, 0xd8,
|
||||
0x1b, 0x17, 0xac, 0x8a, 0xd1, 0xc3, 0x4e, 0x47, 0xba, 0xea, 0xab, 0x62, 0xd2, 0xcb, 0x2f, 0x14,
|
||||
0x53, 0xc2, 0x77, 0xc0, 0xba, 0x6b, 0x78, 0x23, 0x23, 0x46, 0x0a, 0x6d, 0x95, 0x74, 0x18, 0x06,
|
||||
0xea, 0xfa, 0xc1, 0xd4, 0x09, 0x9a, 0x41, 0xc2, 0x8f, 0x41, 0x89, 0x4d, 0xc6, 0xe8, 0x8a, 0x08,
|
||||
0x2d, 0x73, 0x50, 0x1c, 0x12, 0x6b, 0x6a, 0x8a, 0xc6, 0x2a, 0x89, 0x47, 0x68, 0x4c, 0xc3, 0x17,
|
||||
0x0f, 0xc6, 0x1c, 0x99, 0xb1, 0xdd, 0x3e, 0xc3, 0xfe, 0x5d, 0xdb, 0xb3, 0xe9, 0x31, 0xb6, 0x6a,
|
||||
0x25, 0x91, 0x2e, 0xb1, 0x78, 0x74, 0xbb, 0xed, 0x2c, 0x08, 0xca, 0xf3, 0x85, 0x6d, 0xb0, 0x9e,
|
||||
0x94, 0xf6, 0x80, 0x58, 0xb8, 0x56, 0x16, 0x0f, 0xe3, 0x16, 0xff, 0x95, 0x7b, 0x53, 0x27, 0x67,
|
||||
0x73, 0x16, 0x34, 0xe3, 0x9b, 0x5e, 0x34, 0x40, 0xfe, 0xa2, 0xd1, 0xfc, 0xae, 0x00, 0xca, 0xc9,
|
||||
0x4c, 0x3d, 0x02, 0xc0, 0x9c, 0x34, 0x2e, 0x2a, 0xe7, 0xea, 0xcd, 0xbc, 0x47, 0x10, 0xb7, 0xb8,
|
||||
0x64, 0x1e, 0xc4, 0x26, 0x8a, 0x52, 0x44, 0xf0, 0x13, 0x50, 0x16, 0xdb, 0x96, 0x68, 0x41, 0x8b,
|
||||
0xcf, 0xdc, 0x82, 0xd6, 0xc2, 0x40, 0x2d, 0x77, 0x26, 0x04, 0x28, 0xe1, 0x82, 0xfd, 0x74, 0xca,
|
||||
0x9e, 0xb3, 0x9d, 0xc2, 0xe9, 0xf4, 0x8a, 0x2b, 0x66, 0x58, 0x79, 0x53, 0x93, 0xbb, 0xc6, 0xb2,
|
||||
0x28, 0x70, 0xde, 0x1a, 0xd1, 0x02, 0x65, 0xb1, 0x17, 0x61, 0x0b, 0x5b, 0x42, 0xa3, 0x05, 0xfd,
|
||||
0xb2, 0x84, 0x96, 0x3b, 0x93, 0x03, 0x94, 0x60, 0x38, 0x71, 0xb4, 0xf0, 0xc8, 0xb5, 0x2b, 0x26,
|
||||
0x8e, 0xd6, 0x23, 0x24, 0x4f, 0xe1, 0x1d, 0x50, 0x95, 0x21, 0x61, 0xeb, 0x9e, 0x67, 0xe1, 0xaf,
|
||||
0x30, 0x15, 0x4f, 0xb3, 0xac, 0xd7, 0xa4, 0x47, 0x75, 0x6f, 0xe6, 0x1c, 0xcd, 0x79, 0xc0, 0x6f,
|
||||
0x14, 0x70, 0x7d, 0xe4, 0x99, 0x64, 0xe4, 0x31, 0x6c, 0x75, 0xb1, 0xef, 0xda, 0x1e, 0xff, 0xe3,
|
||||
0xe9, 0x90, 0x58, 0x54, 0x28, 0xb7, 0xb2, 0x7d, 0x3b, 0xb3, 0xd8, 0x47, 0xd9, 0x3e, 0x91, 0xce,
|
||||
0x73, 0x0e, 0x51, 0xde, 0x4d, 0x50, 0x05, 0x05, 0x1f, 0x1b, 0xd6, 0x58, 0xc8, 0xbb, 0xa0, 0x97,
|
||||
0x79, 0x1b, 0x45, 0xdc, 0x80, 0x22, 0x7b, 0xf3, 0x67, 0x05, 0x5c, 0x9a, 0xd9, 0x6a, 0xff, 0xfd,
|
||||
0x6b, 0x4b, 0xf3, 0x17, 0x05, 0xe4, 0xe5, 0x02, 0x1e, 0xa6, 0x75, 0xc1, 0x9f, 0x55, 0x59, 0xdf,
|
||||
0x9e, 0xd2, 0xc4, 0x59, 0xa0, 0xde, 0xcc, 0xfb, 0x9b, 0x97, 0x6f, 0x21, 0x54, 0x3b, 0xba, 0x77,
|
||||
0x27, 0x2d, 0x9c, 0x0f, 0x62, 0xe1, 0x2c, 0x0a, 0xba, 0x56, 0x22, 0x9a, 0x8b, 0x71, 0x49, 0x77,
|
||||
0xfd, 0xed, 0x47, 0x4f, 0x1b, 0x0b, 0x8f, 0x9f, 0x36, 0x16, 0x9e, 0x3c, 0x6d, 0x2c, 0x7c, 0x1d,
|
||||
0x36, 0x94, 0x47, 0x61, 0x43, 0x79, 0x1c, 0x36, 0x94, 0x27, 0x61, 0x43, 0xf9, 0x3d, 0x6c, 0x28,
|
||||
0xdf, 0xfe, 0xd1, 0x58, 0xf8, 0xf4, 0x4a, 0xc6, 0x7f, 0x42, 0xfc, 0x1d, 0x00, 0x00, 0xff, 0xff,
|
||||
0x07, 0x84, 0xfd, 0x6a, 0xb3, 0x10, 0x00, 0x00,
|
||||
// 1431 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0x41, 0x6f, 0x1b, 0xc5,
|
||||
0x17, 0xcf, 0xc6, 0x71, 0x6c, 0x8f, 0x93, 0xd4, 0x9d, 0xfe, 0xdb, 0xfa, 0x6f, 0x2a, 0x6f, 0x6a,
|
||||
0x0a, 0x0a, 0xa8, 0xac, 0x49, 0x88, 0x10, 0x20, 0x40, 0xca, 0xa6, 0x2a, 0x34, 0x38, 0x6a, 0x18,
|
||||
0x3b, 0x42, 0x2a, 0x05, 0xb1, 0xde, 0x1d, 0x3b, 0xdb, 0xac, 0x77, 0xac, 0x9d, 0x71, 0x84, 0x6f,
|
||||
0x48, 0x7c, 0x01, 0xf8, 0x12, 0x1c, 0x11, 0x12, 0x9c, 0x39, 0xa2, 0x1e, 0x2b, 0x4e, 0x3d, 0xad,
|
||||
0xe8, 0xf2, 0x01, 0xb8, 0x87, 0x0b, 0x9a, 0xd9, 0xf1, 0xee, 0xda, 0xde, 0x0d, 0x49, 0x0f, 0x15,
|
||||
0xb7, 0xcc, 0x9b, 0xdf, 0xfb, 0xcd, 0xdb, 0x79, 0xbf, 0x79, 0xef, 0x39, 0xe0, 0xfd, 0xe3, 0x77,
|
||||
0xa8, 0x66, 0x93, 0xe6, 0xf1, 0xa8, 0x8b, 0x3d, 0x17, 0x33, 0x4c, 0x9b, 0x27, 0xd8, 0xb5, 0x88,
|
||||
0xd7, 0x94, 0x1b, 0xc6, 0xd0, 0x6e, 0x76, 0x0d, 0x66, 0x1e, 0x35, 0x4f, 0x36, 0x9b, 0x7d, 0xec,
|
||||
0x62, 0xcf, 0x60, 0xd8, 0xd2, 0x86, 0x1e, 0x61, 0x04, 0x5e, 0x09, 0x41, 0x9a, 0x31, 0xb4, 0x35,
|
||||
0x01, 0xd2, 0x4e, 0x36, 0x6b, 0x6f, 0xf4, 0x6d, 0x76, 0x34, 0xea, 0x6a, 0x26, 0x19, 0x34, 0xfb,
|
||||
0xa4, 0x4f, 0x9a, 0x02, 0xdb, 0x1d, 0xf5, 0xc4, 0x4a, 0x2c, 0xc4, 0x5f, 0x21, 0x47, 0xad, 0x91,
|
||||
0x38, 0xc8, 0x24, 0x1e, 0x4e, 0x39, 0xa7, 0xb6, 0x1d, 0x63, 0x06, 0x86, 0x79, 0x64, 0xbb, 0xd8,
|
||||
0x1b, 0x37, 0x87, 0xc7, 0x7d, 0x6e, 0xa0, 0xcd, 0x01, 0x66, 0x46, 0x9a, 0x57, 0x33, 0xcb, 0xcb,
|
||||
0x1b, 0xb9, 0xcc, 0x1e, 0xe0, 0x39, 0x87, 0xb7, 0xff, 0xcd, 0x81, 0x9a, 0x47, 0x78, 0x60, 0xcc,
|
||||
0xfa, 0x35, 0xfe, 0x56, 0x40, 0x61, 0xd7, 0x23, 0xee, 0x1e, 0xe9, 0xc2, 0xaf, 0x40, 0x91, 0xc7,
|
||||
0x63, 0x19, 0xcc, 0xa8, 0x2a, 0xeb, 0xca, 0x46, 0x79, 0xeb, 0x4d, 0x2d, 0xbe, 0xa5, 0x88, 0x56,
|
||||
0x1b, 0x1e, 0xf7, 0xb9, 0x81, 0x6a, 0x1c, 0xad, 0x9d, 0x6c, 0x6a, 0xf7, 0xbb, 0x8f, 0xb0, 0xc9,
|
||||
0xf6, 0x31, 0x33, 0x74, 0xf8, 0xd8, 0x57, 0x17, 0x02, 0x5f, 0x05, 0xb1, 0x0d, 0x45, 0xac, 0x50,
|
||||
0x07, 0x4b, 0x74, 0x88, 0xcd, 0xea, 0xa2, 0x60, 0x5f, 0xd7, 0x52, 0x72, 0xa0, 0xc9, 0x68, 0xda,
|
||||
0x43, 0x6c, 0xea, 0x2b, 0x92, 0x6d, 0x89, 0xaf, 0x90, 0xf0, 0x85, 0x7b, 0x60, 0x99, 0x32, 0x83,
|
||||
0x8d, 0x68, 0x35, 0x27, 0x58, 0x1a, 0x67, 0xb2, 0x08, 0xa4, 0xbe, 0x26, 0x79, 0x96, 0xc3, 0x35,
|
||||
0x92, 0x0c, 0x8d, 0x1f, 0x15, 0x50, 0x96, 0xc8, 0x96, 0x4d, 0x19, 0x7c, 0x38, 0x77, 0x03, 0xda,
|
||||
0xf9, 0x6e, 0x80, 0x7b, 0x8b, 0xef, 0xaf, 0xc8, 0x93, 0x8a, 0x13, 0x4b, 0xe2, 0xeb, 0x77, 0x40,
|
||||
0xde, 0x66, 0x78, 0x40, 0xab, 0x8b, 0xeb, 0xb9, 0x8d, 0xf2, 0xd6, 0x8d, 0xb3, 0x02, 0xd7, 0x57,
|
||||
0x25, 0x51, 0xfe, 0x1e, 0x77, 0x41, 0xa1, 0x67, 0xe3, 0xf7, 0xa5, 0x28, 0x60, 0x7e, 0x25, 0xf0,
|
||||
0x36, 0x28, 0xf2, 0xc4, 0x5a, 0x23, 0x07, 0x8b, 0x80, 0x4b, 0x71, 0x00, 0x6d, 0x69, 0x47, 0x11,
|
||||
0x02, 0x6e, 0x80, 0x22, 0xd7, 0xc2, 0x03, 0xe2, 0xe2, 0x6a, 0x51, 0xa0, 0x57, 0x38, 0xb2, 0x23,
|
||||
0x6d, 0x28, 0xda, 0x85, 0x87, 0xe0, 0x3a, 0x65, 0x86, 0xc7, 0x6c, 0xb7, 0x7f, 0x07, 0x1b, 0x96,
|
||||
0x63, 0xbb, 0xb8, 0x8d, 0x4d, 0xe2, 0x5a, 0x54, 0xe4, 0x2e, 0xa7, 0xbf, 0x14, 0xf8, 0xea, 0xf5,
|
||||
0x76, 0x3a, 0x04, 0x65, 0xf9, 0xc2, 0x87, 0xe0, 0xb2, 0x49, 0x5c, 0x73, 0xe4, 0x79, 0xd8, 0x35,
|
||||
0xc7, 0x07, 0xc4, 0xb1, 0xcd, 0xb1, 0x48, 0x63, 0x49, 0xd7, 0x64, 0xdc, 0x97, 0x77, 0x67, 0x01,
|
||||
0xa7, 0x69, 0x46, 0x34, 0x4f, 0x04, 0x5f, 0x01, 0x05, 0x3a, 0xa2, 0x43, 0xec, 0x5a, 0xd5, 0xa5,
|
||||
0x75, 0x65, 0xa3, 0xa8, 0x97, 0x03, 0x5f, 0x2d, 0xb4, 0x43, 0x13, 0x9a, 0xec, 0xc1, 0xcf, 0x41,
|
||||
0xf9, 0x11, 0xe9, 0x76, 0xf0, 0x60, 0xe8, 0x18, 0x0c, 0x57, 0xf3, 0x22, 0xcf, 0xb7, 0x52, 0x93,
|
||||
0xb1, 0x17, 0xe3, 0x84, 0x1e, 0xaf, 0xc8, 0x20, 0xcb, 0x89, 0x0d, 0x94, 0x64, 0x83, 0x5f, 0x82,
|
||||
0x1a, 0x1d, 0x99, 0x26, 0xa6, 0xb4, 0x37, 0x72, 0xf6, 0x48, 0x97, 0x7e, 0x6c, 0x53, 0x46, 0xbc,
|
||||
0x71, 0xcb, 0x1e, 0xd8, 0xac, 0xba, 0xbc, 0xae, 0x6c, 0xe4, 0xf5, 0x7a, 0xe0, 0xab, 0xb5, 0x76,
|
||||
0x26, 0x0a, 0x9d, 0xc1, 0x00, 0x11, 0xb8, 0xd6, 0x33, 0x6c, 0x07, 0x5b, 0x73, 0xdc, 0x05, 0xc1,
|
||||
0x5d, 0x0b, 0x7c, 0xf5, 0xda, 0xdd, 0x54, 0x04, 0xca, 0xf0, 0x6c, 0xfc, 0xba, 0x08, 0x56, 0xa7,
|
||||
0xde, 0x0b, 0xfc, 0x04, 0x2c, 0x1b, 0x26, 0xb3, 0x4f, 0xb8, 0xa8, 0xb8, 0x54, 0x5f, 0x4e, 0xde,
|
||||
0x0e, 0xaf, 0x74, 0xf1, 0xab, 0x47, 0xb8, 0x87, 0x79, 0x12, 0x70, 0xfc, 0xc8, 0x76, 0x84, 0x2b,
|
||||
0x92, 0x14, 0xd0, 0x01, 0x15, 0xc7, 0xa0, 0x6c, 0xa2, 0x47, 0xae, 0x36, 0x91, 0x9f, 0xf2, 0xd6,
|
||||
0xeb, 0xe7, 0x7b, 0x5c, 0xdc, 0x43, 0xff, 0x5f, 0xe0, 0xab, 0x95, 0xd6, 0x0c, 0x0f, 0x9a, 0x63,
|
||||
0x86, 0x1e, 0x80, 0xc2, 0x16, 0x5d, 0xa1, 0x38, 0x2f, 0x7f, 0xe1, 0xf3, 0xae, 0x05, 0xbe, 0x0a,
|
||||
0x5b, 0x73, 0x4c, 0x28, 0x85, 0xbd, 0xf1, 0x97, 0x02, 0x72, 0x2f, 0xa6, 0x80, 0x7e, 0x38, 0x55,
|
||||
0x40, 0x6f, 0x64, 0x89, 0x36, 0xb3, 0x78, 0xde, 0x9d, 0x29, 0x9e, 0xf5, 0x4c, 0x86, 0xb3, 0x0b,
|
||||
0xe7, 0x6f, 0x39, 0xb0, 0xb2, 0x47, 0xba, 0xbb, 0xc4, 0xb5, 0x6c, 0x66, 0x13, 0x17, 0x6e, 0x83,
|
||||
0x25, 0x36, 0x1e, 0x4e, 0x8a, 0xd0, 0xfa, 0xe4, 0xe8, 0xce, 0x78, 0x88, 0x4f, 0x7d, 0xb5, 0x92,
|
||||
0xc4, 0x72, 0x1b, 0x12, 0x68, 0xd8, 0x8a, 0xc2, 0x59, 0x14, 0x7e, 0xdb, 0xd3, 0xc7, 0x9d, 0xfa,
|
||||
0x6a, 0x4a, 0x8b, 0xd5, 0x22, 0xa6, 0xe9, 0xa0, 0x60, 0x1f, 0xac, 0xf2, 0xe4, 0x1c, 0x78, 0xa4,
|
||||
0x1b, 0xaa, 0x2c, 0x77, 0xe1, 0xac, 0x5f, 0x95, 0x01, 0xac, 0xb6, 0x92, 0x44, 0x68, 0x9a, 0x17,
|
||||
0x9e, 0x84, 0x1a, 0xeb, 0x78, 0x86, 0x4b, 0xc3, 0x4f, 0x7a, 0x3e, 0x4d, 0xd7, 0xe4, 0x69, 0x42,
|
||||
0x67, 0xd3, 0x6c, 0x28, 0xe5, 0x04, 0xf8, 0x2a, 0x58, 0xf6, 0xb0, 0x41, 0x89, 0x2b, 0xf4, 0x5c,
|
||||
0x8a, 0xb3, 0x83, 0x84, 0x15, 0xc9, 0x5d, 0xf8, 0x1a, 0x28, 0x0c, 0x30, 0xa5, 0x46, 0x1f, 0x8b,
|
||||
0x8a, 0x53, 0xd2, 0x2f, 0x49, 0x60, 0x61, 0x3f, 0x34, 0xa3, 0xc9, 0x7e, 0xe3, 0x07, 0x05, 0x14,
|
||||
0x5e, 0x4c, 0xf7, 0xfb, 0x60, 0xba, 0xfb, 0x55, 0xb3, 0x94, 0x97, 0xd1, 0xf9, 0x7e, 0xca, 0x8b,
|
||||
0x40, 0x45, 0xd7, 0xdb, 0x04, 0xe5, 0xa1, 0xe1, 0x19, 0x8e, 0x83, 0x1d, 0x9b, 0x0e, 0x44, 0xac,
|
||||
0x79, 0xfd, 0x12, 0xaf, 0xcb, 0x07, 0xb1, 0x19, 0x25, 0x31, 0xdc, 0xc5, 0x24, 0x83, 0xa1, 0x83,
|
||||
0xf9, 0x65, 0x86, 0x72, 0x93, 0x2e, 0xbb, 0xb1, 0x19, 0x25, 0x31, 0xf0, 0x3e, 0xb8, 0x1a, 0x56,
|
||||
0xb0, 0xd9, 0x0e, 0x98, 0x13, 0x1d, 0xf0, 0xff, 0x81, 0xaf, 0x5e, 0xdd, 0x49, 0x03, 0xa0, 0x74,
|
||||
0x3f, 0xb8, 0x0d, 0x56, 0xba, 0x86, 0x79, 0x4c, 0x7a, 0xbd, 0x64, 0xc5, 0xae, 0x04, 0xbe, 0xba,
|
||||
0xa2, 0x27, 0xec, 0x68, 0x0a, 0x05, 0xbf, 0x00, 0x45, 0x8a, 0x1d, 0x6c, 0x32, 0xe2, 0x49, 0x89,
|
||||
0xbd, 0x75, 0xce, 0xac, 0x18, 0x5d, 0xec, 0xb4, 0xa5, 0x6b, 0xd8, 0xe9, 0x27, 0x2b, 0x14, 0x51,
|
||||
0xc2, 0xf7, 0xc0, 0xda, 0xc0, 0x70, 0x47, 0x46, 0x84, 0x14, 0xda, 0x2a, 0xea, 0x30, 0xf0, 0xd5,
|
||||
0xb5, 0xfd, 0xa9, 0x1d, 0x34, 0x83, 0x84, 0x9f, 0x82, 0x22, 0x9b, 0xb4, 0xd1, 0x65, 0x11, 0x5a,
|
||||
0x6a, 0xa3, 0x38, 0x20, 0xd6, 0x54, 0x17, 0x8d, 0x54, 0x12, 0xb5, 0xd0, 0x88, 0x86, 0x0f, 0x1e,
|
||||
0x8c, 0x39, 0xf2, 0xc6, 0x76, 0x7a, 0x0c, 0x7b, 0x77, 0x6d, 0xd7, 0xa6, 0x47, 0xd8, 0x12, 0x13,
|
||||
0x4b, 0x3e, 0x1c, 0x3c, 0x3a, 0x9d, 0x56, 0x1a, 0x04, 0x65, 0xf9, 0xc2, 0x16, 0x58, 0x8b, 0x53,
|
||||
0xbb, 0x4f, 0x2c, 0x5c, 0x2d, 0x89, 0x87, 0x71, 0x8b, 0x7f, 0xe5, 0xee, 0xd4, 0xce, 0xe9, 0x9c,
|
||||
0x05, 0xcd, 0xf8, 0x26, 0x07, 0x0d, 0x90, 0x3d, 0x68, 0x34, 0xbe, 0xcf, 0x83, 0x52, 0xdc, 0x53,
|
||||
0x0f, 0x01, 0x30, 0x27, 0x85, 0x8b, 0xca, 0xbe, 0x7a, 0x33, 0xeb, 0x11, 0x44, 0x25, 0x2e, 0xee,
|
||||
0x07, 0x91, 0x89, 0xa2, 0x04, 0x11, 0xfc, 0x0c, 0x94, 0xc4, 0xb4, 0x25, 0x4a, 0xd0, 0xe2, 0x85,
|
||||
0x4b, 0xd0, 0x6a, 0xe0, 0xab, 0xa5, 0xf6, 0x84, 0x00, 0xc5, 0x5c, 0xb0, 0x97, 0xbc, 0xb2, 0xe7,
|
||||
0x2c, 0xa7, 0x70, 0xfa, 0x7a, 0xc5, 0x11, 0x33, 0xac, 0xbc, 0xa8, 0xc9, 0x59, 0x63, 0x49, 0x24,
|
||||
0x38, 0x6b, 0x8c, 0x68, 0x82, 0x92, 0x98, 0x8b, 0xb0, 0x85, 0x2d, 0xa1, 0xd1, 0xbc, 0x7e, 0x59,
|
||||
0x42, 0x4b, 0xed, 0xc9, 0x06, 0x8a, 0x31, 0x9c, 0x38, 0x1c, 0x78, 0xe4, 0xd8, 0x15, 0x11, 0x87,
|
||||
0xe3, 0x11, 0x92, 0xbb, 0xf0, 0x0e, 0xa8, 0xc8, 0x90, 0xb0, 0x75, 0xcf, 0xb5, 0xf0, 0xd7, 0x98,
|
||||
0x8a, 0xa7, 0x59, 0xd2, 0xab, 0xd2, 0xa3, 0xb2, 0x3b, 0xb3, 0x8f, 0xe6, 0x3c, 0xe0, 0xb7, 0x0a,
|
||||
0xb8, 0x3e, 0x72, 0x4d, 0x32, 0x72, 0x19, 0xb6, 0x3a, 0xd8, 0x1b, 0xd8, 0x2e, 0xff, 0x99, 0x75,
|
||||
0x40, 0x2c, 0x2a, 0x94, 0x5b, 0xde, 0xba, 0x9d, 0x9a, 0xec, 0xc3, 0x74, 0x9f, 0x50, 0xe7, 0x19,
|
||||
0x9b, 0x28, 0xeb, 0x24, 0xa8, 0x82, 0xbc, 0x87, 0x0d, 0x6b, 0x2c, 0xe4, 0x9d, 0xd7, 0x4b, 0xbc,
|
||||
0x8c, 0x22, 0x6e, 0x40, 0xa1, 0xbd, 0xf1, 0xb3, 0x02, 0x2e, 0xcd, 0x4c, 0xb5, 0xff, 0xfd, 0xb1,
|
||||
0xa5, 0xf1, 0x8b, 0x02, 0xb2, 0xee, 0x02, 0x1e, 0x24, 0x75, 0xc1, 0x9f, 0x55, 0x49, 0xdf, 0x9a,
|
||||
0xd2, 0xc4, 0xa9, 0xaf, 0xde, 0xcc, 0xfa, 0x75, 0xcc, 0xa7, 0x10, 0xaa, 0x1d, 0xde, 0xbb, 0x93,
|
||||
0x14, 0xce, 0x47, 0x91, 0x70, 0x16, 0x05, 0x5d, 0x33, 0x16, 0xcd, 0xf9, 0xb8, 0xa4, 0xbb, 0xfe,
|
||||
0xee, 0xe3, 0x67, 0xf5, 0x85, 0x27, 0xcf, 0xea, 0x0b, 0x4f, 0x9f, 0xd5, 0x17, 0xbe, 0x09, 0xea,
|
||||
0xca, 0xe3, 0xa0, 0xae, 0x3c, 0x09, 0xea, 0xca, 0xd3, 0xa0, 0xae, 0xfc, 0x11, 0xd4, 0x95, 0xef,
|
||||
0xfe, 0xac, 0x2f, 0x3c, 0xb8, 0x92, 0xf2, 0xef, 0x8a, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0xae,
|
||||
0xfd, 0x54, 0xb2, 0xdd, 0x10, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *CronJob) Marshal() (dAtA []byte, err error) {
|
||||
@ -587,6 +588,13 @@ func (m *CronJobSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.TimeZone != nil {
|
||||
i -= len(*m.TimeZone)
|
||||
copy(dAtA[i:], *m.TimeZone)
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.TimeZone)))
|
||||
i--
|
||||
dAtA[i] = 0x42
|
||||
}
|
||||
if m.FailedJobsHistoryLimit != nil {
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(*m.FailedJobsHistoryLimit))
|
||||
i--
|
||||
@ -1199,6 +1207,10 @@ func (m *CronJobSpec) Size() (n int) {
|
||||
if m.FailedJobsHistoryLimit != nil {
|
||||
n += 1 + sovGenerated(uint64(*m.FailedJobsHistoryLimit))
|
||||
}
|
||||
if m.TimeZone != nil {
|
||||
l = len(*m.TimeZone)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@ -1433,6 +1445,7 @@ func (this *CronJobSpec) String() string {
|
||||
`JobTemplate:` + strings.Replace(strings.Replace(this.JobTemplate.String(), "JobTemplateSpec", "JobTemplateSpec", 1), `&`, ``, 1) + `,`,
|
||||
`SuccessfulJobsHistoryLimit:` + valueToStringGenerated(this.SuccessfulJobsHistoryLimit) + `,`,
|
||||
`FailedJobsHistoryLimit:` + valueToStringGenerated(this.FailedJobsHistoryLimit) + `,`,
|
||||
`TimeZone:` + valueToStringGenerated(this.TimeZone) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
@ -2042,6 +2055,39 @@ func (m *CronJobSpec) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
}
|
||||
m.FailedJobsHistoryLimit = &v
|
||||
case 8:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field TimeZone", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.TimeZone = &s
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
|
@ -63,6 +63,12 @@ message CronJobSpec {
|
||||
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
||||
optional string schedule = 1;
|
||||
|
||||
// The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
|
||||
// If not specified, this will rely on the time zone of the kube-controller-manager process.
|
||||
// ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.
|
||||
// +optional
|
||||
optional string timeZone = 8;
|
||||
|
||||
// Optional deadline in seconds for starting the job if it misses scheduled
|
||||
// time for any reason. Missed jobs executions will be counted as failed ones.
|
||||
// +optional
|
||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||
package v1
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
@ -146,7 +146,7 @@ type JobSpec struct {
|
||||
|
||||
// Describes the pod that will be created when executing a job.
|
||||
// More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/
|
||||
Template v1.PodTemplateSpec `json:"template" protobuf:"bytes,6,opt,name=template"`
|
||||
Template corev1.PodTemplateSpec `json:"template" protobuf:"bytes,6,opt,name=template"`
|
||||
|
||||
// ttlSecondsAfterFinished limits the lifetime of a Job that has finished
|
||||
// execution (either Complete or Failed). If this field is set,
|
||||
@ -304,7 +304,7 @@ type JobCondition struct {
|
||||
// Type of job condition, Complete or Failed.
|
||||
Type JobConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=JobConditionType"`
|
||||
// Status of the condition, one of True, False, Unknown.
|
||||
Status v1.ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=k8s.io/api/core/v1.ConditionStatus"`
|
||||
Status corev1.ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=k8s.io/api/core/v1.ConditionStatus"`
|
||||
// Last time the condition was checked.
|
||||
// +optional
|
||||
LastProbeTime metav1.Time `json:"lastProbeTime,omitempty" protobuf:"bytes,3,opt,name=lastProbeTime"`
|
||||
@ -375,6 +375,12 @@ type CronJobSpec struct {
|
||||
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
||||
Schedule string `json:"schedule" protobuf:"bytes,1,opt,name=schedule"`
|
||||
|
||||
// The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
|
||||
// If not specified, this will rely on the time zone of the kube-controller-manager process.
|
||||
// ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.
|
||||
// +optional
|
||||
TimeZone *string `json:"timeZone,omitempty" protobuf:"bytes,8,opt,name=timeZone"`
|
||||
|
||||
// Optional deadline in seconds for starting the job if it misses scheduled
|
||||
// time for any reason. Missed jobs executions will be counted as failed ones.
|
||||
// +optional
|
||||
@ -431,7 +437,7 @@ type CronJobStatus struct {
|
||||
// A list of pointers to currently running jobs.
|
||||
// +optional
|
||||
// +listType=atomic
|
||||
Active []v1.ObjectReference `json:"active,omitempty" protobuf:"bytes,1,rep,name=active"`
|
||||
Active []corev1.ObjectReference `json:"active,omitempty" protobuf:"bytes,1,rep,name=active"`
|
||||
|
||||
// Information when was the last time the job was successfully scheduled.
|
||||
// +optional
|
||||
|
@ -51,6 +51,7 @@ func (CronJobList) SwaggerDoc() map[string]string {
|
||||
var map_CronJobSpec = map[string]string{
|
||||
"": "CronJobSpec describes how the job execution will look like and when it will actually run.",
|
||||
"schedule": "The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.",
|
||||
"timeZone": "The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will rely on the time zone of the kube-controller-manager process. ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.",
|
||||
"startingDeadlineSeconds": "Optional deadline in seconds for starting the job if it misses scheduled time for any reason. Missed jobs executions will be counted as failed ones.",
|
||||
"concurrencyPolicy": "Specifies how to treat concurrent executions of a Job. Valid values are: - \"Allow\" (default): allows CronJobs to run concurrently; - \"Forbid\": forbids concurrent runs, skipping next run if previous run hasn't finished yet; - \"Replace\": cancels currently running job and replaces it with a new one",
|
||||
"suspend": "This flag tells the controller to suspend subsequent executions, it does not apply to already started executions. Defaults to false.",
|
||||
|
@ -92,6 +92,11 @@ func (in *CronJobList) DeepCopyObject() runtime.Object {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CronJobSpec) DeepCopyInto(out *CronJobSpec) {
|
||||
*out = *in
|
||||
if in.TimeZone != nil {
|
||||
in, out := &in.TimeZone, &out.TimeZone
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.StartingDeadlineSeconds != nil {
|
||||
in, out := &in.StartingDeadlineSeconds, &out.StartingDeadlineSeconds
|
||||
*out = new(int64)
|
||||
|
148
staging/src/k8s.io/api/batch/v1beta1/generated.pb.go
generated
148
staging/src/k8s.io/api/batch/v1beta1/generated.pb.go
generated
@ -227,57 +227,58 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_e57b277b05179ae7 = []byte{
|
||||
// 796 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x96, 0x41, 0x6f, 0xdc, 0x44,
|
||||
0x14, 0xc7, 0xd7, 0x9b, 0x6c, 0xb2, 0x9d, 0xa5, 0x90, 0x0e, 0x28, 0xb5, 0x16, 0x64, 0x87, 0xad,
|
||||
0x2a, 0x02, 0x82, 0x31, 0x89, 0x10, 0xe2, 0x54, 0xa9, 0x2e, 0x2a, 0x10, 0x82, 0x8a, 0x66, 0x8b,
|
||||
0x90, 0x50, 0x85, 0x3a, 0x1e, 0xbf, 0x6c, 0xa6, 0xb1, 0x3d, 0x96, 0x67, 0x1c, 0x29, 0x37, 0x2e,
|
||||
0xdc, 0xf9, 0x22, 0x9c, 0xb8, 0x73, 0xce, 0xb1, 0xc7, 0x9e, 0x2c, 0x62, 0xbe, 0x05, 0x27, 0xe4,
|
||||
0x59, 0xc7, 0xbb, 0xdd, 0xf5, 0x36, 0xed, 0x25, 0xb7, 0xcc, 0x9b, 0xff, 0xff, 0x37, 0xcf, 0xef,
|
||||
0xbd, 0x99, 0x2c, 0xba, 0x7f, 0xf2, 0x95, 0x22, 0x42, 0x7a, 0x27, 0x79, 0x00, 0x59, 0x02, 0x1a,
|
||||
0x94, 0x77, 0x0a, 0x49, 0x28, 0x33, 0xaf, 0xde, 0x60, 0xa9, 0xf0, 0x02, 0xa6, 0xf9, 0xb1, 0x77,
|
||||
0xba, 0x17, 0x80, 0x66, 0x7b, 0xde, 0x04, 0x12, 0xc8, 0x98, 0x86, 0x90, 0xa4, 0x99, 0xd4, 0x12,
|
||||
0xdb, 0x53, 0x25, 0x61, 0xa9, 0x20, 0x46, 0x49, 0x6a, 0xe5, 0xf0, 0xb3, 0x89, 0xd0, 0xc7, 0x79,
|
||||
0x40, 0xb8, 0x8c, 0xbd, 0x89, 0x9c, 0x48, 0xcf, 0x18, 0x82, 0xfc, 0xc8, 0xac, 0xcc, 0xc2, 0xfc,
|
||||
0x35, 0x05, 0x0d, 0xef, 0xb4, 0x1c, 0xb9, 0x78, 0xda, 0x70, 0x34, 0x27, 0xe2, 0x32, 0x83, 0x36,
|
||||
0xcd, 0x17, 0x33, 0x4d, 0xcc, 0xf8, 0xb1, 0x48, 0x20, 0x3b, 0xf3, 0xd2, 0x93, 0x49, 0x15, 0x50,
|
||||
0x5e, 0x0c, 0x9a, 0xb5, 0xb9, 0xbc, 0x55, 0xae, 0x2c, 0x4f, 0xb4, 0x88, 0x61, 0xc9, 0xf0, 0xe5,
|
||||
0x55, 0x06, 0xc5, 0x8f, 0x21, 0x66, 0x8b, 0xbe, 0xd1, 0xef, 0x5d, 0xb4, 0xf9, 0x20, 0x93, 0xc9,
|
||||
0x81, 0x0c, 0xf0, 0x53, 0xd4, 0xaf, 0xf2, 0x09, 0x99, 0x66, 0xb6, 0xb5, 0x63, 0xed, 0x0e, 0xf6,
|
||||
0x3f, 0x27, 0xb3, 0x7a, 0x36, 0x58, 0x92, 0x9e, 0x4c, 0xaa, 0x80, 0x22, 0x95, 0x9a, 0x9c, 0xee,
|
||||
0x91, 0x47, 0xc1, 0x33, 0xe0, 0xfa, 0x07, 0xd0, 0xcc, 0xc7, 0xe7, 0x85, 0xdb, 0x29, 0x0b, 0x17,
|
||||
0xcd, 0x62, 0xb4, 0xa1, 0xe2, 0x6f, 0xd0, 0xba, 0x4a, 0x81, 0xdb, 0x5d, 0x43, 0xbf, 0x4b, 0x56,
|
||||
0x75, 0x8b, 0xd4, 0x29, 0x8d, 0x53, 0xe0, 0xfe, 0x5b, 0x35, 0x72, 0xbd, 0x5a, 0x51, 0x03, 0xc0,
|
||||
0x8f, 0xd0, 0x86, 0xd2, 0x4c, 0xe7, 0xca, 0x5e, 0x33, 0xa8, 0x8f, 0xae, 0x46, 0x19, 0xb9, 0xff,
|
||||
0x76, 0x0d, 0xdb, 0x98, 0xae, 0x69, 0x8d, 0x19, 0xfd, 0x65, 0xa1, 0x41, 0xad, 0x3c, 0x14, 0x4a,
|
||||
0xe3, 0x27, 0x4b, 0xb5, 0x20, 0xaf, 0x57, 0x8b, 0xca, 0x6d, 0x2a, 0xb1, 0x55, 0x9f, 0xd4, 0xbf,
|
||||
0x8c, 0xcc, 0xd5, 0xe1, 0x21, 0xea, 0x09, 0x0d, 0xb1, 0xb2, 0xbb, 0x3b, 0x6b, 0xbb, 0x83, 0xfd,
|
||||
0x0f, 0xaf, 0xcc, 0xde, 0xbf, 0x59, 0xd3, 0x7a, 0xdf, 0x55, 0x3e, 0x3a, 0xb5, 0x8f, 0xfe, 0x5c,
|
||||
0x6f, 0xb2, 0xae, 0x8a, 0x83, 0x3f, 0x45, 0xfd, 0xaa, 0xcf, 0x61, 0x1e, 0x81, 0xc9, 0xfa, 0xc6,
|
||||
0x2c, 0x8b, 0x71, 0x1d, 0xa7, 0x8d, 0x02, 0xff, 0x84, 0x6e, 0x2b, 0xcd, 0x32, 0x2d, 0x92, 0xc9,
|
||||
0xd7, 0xc0, 0xc2, 0x48, 0x24, 0x30, 0x06, 0x2e, 0x93, 0x50, 0x99, 0x06, 0xad, 0xf9, 0xef, 0x97,
|
||||
0x85, 0x7b, 0x7b, 0xdc, 0x2e, 0xa1, 0xab, 0xbc, 0xf8, 0x09, 0xba, 0xc5, 0x65, 0xc2, 0xf3, 0x2c,
|
||||
0x83, 0x84, 0x9f, 0xfd, 0x28, 0x23, 0xc1, 0xcf, 0x4c, 0x9b, 0x6e, 0xf8, 0xa4, 0xce, 0xe6, 0xd6,
|
||||
0x83, 0x45, 0xc1, 0x7f, 0x6d, 0x41, 0xba, 0x0c, 0xc2, 0x77, 0xd1, 0xa6, 0xca, 0x55, 0x0a, 0x49,
|
||||
0x68, 0xaf, 0xef, 0x58, 0xbb, 0x7d, 0x7f, 0x50, 0x16, 0xee, 0xe6, 0x78, 0x1a, 0xa2, 0x97, 0x7b,
|
||||
0xf8, 0x29, 0x1a, 0x3c, 0x93, 0xc1, 0x63, 0x88, 0xd3, 0x88, 0x69, 0xb0, 0x7b, 0xa6, 0x85, 0x1f,
|
||||
0xaf, 0xae, 0xf3, 0xc1, 0x4c, 0x6c, 0x86, 0xee, 0xdd, 0x3a, 0xd3, 0xc1, 0xdc, 0x06, 0x9d, 0x47,
|
||||
0xe2, 0x5f, 0xd1, 0x50, 0xe5, 0x9c, 0x83, 0x52, 0x47, 0x79, 0x74, 0x20, 0x03, 0xf5, 0xad, 0x50,
|
||||
0x5a, 0x66, 0x67, 0x87, 0x22, 0x16, 0xda, 0xde, 0xd8, 0xb1, 0x76, 0x7b, 0xbe, 0x53, 0x16, 0xee,
|
||||
0x70, 0xbc, 0x52, 0x45, 0x5f, 0x41, 0xc0, 0x14, 0x6d, 0x1f, 0x31, 0x11, 0x41, 0xb8, 0xc4, 0xde,
|
||||
0x34, 0xec, 0x61, 0x59, 0xb8, 0xdb, 0x0f, 0x5b, 0x15, 0x74, 0x85, 0x73, 0xf4, 0x77, 0x17, 0xdd,
|
||||
0x7c, 0xe9, 0x3e, 0xe0, 0xef, 0xd1, 0x06, 0xe3, 0x5a, 0x9c, 0x56, 0xf3, 0x52, 0x8d, 0xe2, 0x9d,
|
||||
0xf9, 0x12, 0x55, 0x6f, 0xda, 0xec, 0x7e, 0x53, 0x38, 0x82, 0xaa, 0x13, 0x30, 0xbb, 0x44, 0xf7,
|
||||
0x8d, 0x95, 0xd6, 0x08, 0x1c, 0xa1, 0xad, 0x88, 0x29, 0x7d, 0x39, 0x6a, 0x8f, 0x45, 0x0c, 0xa6,
|
||||
0x49, 0x83, 0xfd, 0x4f, 0x5e, 0xef, 0xf2, 0x54, 0x0e, 0xff, 0xbd, 0xb2, 0x70, 0xb7, 0x0e, 0x17,
|
||||
0x38, 0x74, 0x89, 0x8c, 0x33, 0x84, 0x4d, 0xac, 0x29, 0xa1, 0x39, 0xaf, 0xf7, 0xc6, 0xe7, 0x6d,
|
||||
0x97, 0x85, 0x8b, 0x0f, 0x97, 0x48, 0xb4, 0x85, 0x3e, 0x3a, 0xb7, 0xd0, 0xfc, 0x44, 0x5c, 0xc3,
|
||||
0x93, 0xf9, 0x33, 0xea, 0xeb, 0xcb, 0x29, 0xee, 0xbe, 0xe9, 0x14, 0x37, 0xb7, 0xbf, 0x19, 0xe1,
|
||||
0x06, 0x56, 0xbd, 0x78, 0xef, 0x2c, 0xe8, 0xaf, 0xe1, 0x73, 0xee, 0xbd, 0xf4, 0x1f, 0xe0, 0x83,
|
||||
0xb6, 0x4f, 0x21, 0xaf, 0x78, 0xf8, 0xfd, 0x7b, 0xe7, 0x17, 0x4e, 0xe7, 0xf9, 0x85, 0xd3, 0x79,
|
||||
0x71, 0xe1, 0x74, 0x7e, 0x2b, 0x1d, 0xeb, 0xbc, 0x74, 0xac, 0xe7, 0xa5, 0x63, 0xbd, 0x28, 0x1d,
|
||||
0xeb, 0x9f, 0xd2, 0xb1, 0xfe, 0xf8, 0xd7, 0xe9, 0xfc, 0x62, 0xaf, 0xfa, 0xc1, 0xf0, 0x7f, 0x00,
|
||||
0x00, 0x00, 0xff, 0xff, 0x4f, 0x1b, 0x4a, 0x8e, 0x64, 0x08, 0x00, 0x00,
|
||||
// 814 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x96, 0x41, 0x6f, 0x1b, 0x45,
|
||||
0x14, 0xc7, 0xbd, 0x4e, 0x9c, 0xb8, 0xe3, 0x16, 0xd2, 0x01, 0xa5, 0x2b, 0x83, 0xd6, 0xc1, 0x55,
|
||||
0x85, 0x41, 0x30, 0x4b, 0x22, 0x84, 0x38, 0x55, 0xea, 0x16, 0x15, 0x08, 0x41, 0x45, 0xe3, 0x22,
|
||||
0xa4, 0xaa, 0x42, 0x9d, 0x1d, 0xbf, 0x38, 0xd3, 0x78, 0x77, 0x56, 0x3b, 0xb3, 0x91, 0x72, 0xe3,
|
||||
0xc2, 0x9d, 0xef, 0xc2, 0x9d, 0x73, 0x8e, 0xbd, 0xd1, 0xd3, 0x8a, 0x2c, 0xdf, 0x82, 0x13, 0x9a,
|
||||
0xf1, 0x7a, 0xed, 0xda, 0xeb, 0xa6, 0xbd, 0xf4, 0xe6, 0x79, 0xf3, 0xff, 0xff, 0xe6, 0xed, 0x7b,
|
||||
0x6f, 0x67, 0x8d, 0xee, 0x9d, 0x7e, 0xad, 0x88, 0x90, 0xfe, 0x69, 0x16, 0x42, 0x1a, 0x83, 0x06,
|
||||
0xe5, 0x9f, 0x41, 0x3c, 0x92, 0xa9, 0x5f, 0x6e, 0xb0, 0x44, 0xf8, 0x21, 0xd3, 0xfc, 0xc4, 0x3f,
|
||||
0xdb, 0x0f, 0x41, 0xb3, 0x7d, 0x7f, 0x0c, 0x31, 0xa4, 0x4c, 0xc3, 0x88, 0x24, 0xa9, 0xd4, 0x12,
|
||||
0xbb, 0x53, 0x25, 0x61, 0x89, 0x20, 0x56, 0x49, 0x4a, 0x65, 0xf7, 0xf3, 0xb1, 0xd0, 0x27, 0x59,
|
||||
0x48, 0xb8, 0x8c, 0xfc, 0xb1, 0x1c, 0x4b, 0xdf, 0x1a, 0xc2, 0xec, 0xd8, 0xae, 0xec, 0xc2, 0xfe,
|
||||
0x9a, 0x82, 0xba, 0xb7, 0x6b, 0x8e, 0x5c, 0x3e, 0xad, 0xdb, 0x5f, 0x10, 0x71, 0x99, 0x42, 0x9d,
|
||||
0xe6, 0xcb, 0xb9, 0x26, 0x62, 0xfc, 0x44, 0xc4, 0x90, 0x9e, 0xfb, 0xc9, 0xe9, 0xd8, 0x04, 0x94,
|
||||
0x1f, 0x81, 0x66, 0x75, 0x2e, 0x7f, 0x9d, 0x2b, 0xcd, 0x62, 0x2d, 0x22, 0x58, 0x31, 0x7c, 0x75,
|
||||
0x95, 0x41, 0xf1, 0x13, 0x88, 0xd8, 0xb2, 0xaf, 0xff, 0x7b, 0x13, 0x6d, 0xdf, 0x4f, 0x65, 0x7c,
|
||||
0x28, 0x43, 0xfc, 0x14, 0xb5, 0x4d, 0x3e, 0x23, 0xa6, 0x99, 0xeb, 0xec, 0x39, 0x83, 0xce, 0xc1,
|
||||
0x17, 0x64, 0x5e, 0xcf, 0x0a, 0x4b, 0x92, 0xd3, 0xb1, 0x09, 0x28, 0x62, 0xd4, 0xe4, 0x6c, 0x9f,
|
||||
0x3c, 0x0c, 0x9f, 0x01, 0xd7, 0x3f, 0x82, 0x66, 0x01, 0xbe, 0xc8, 0x7b, 0x8d, 0x22, 0xef, 0xa1,
|
||||
0x79, 0x8c, 0x56, 0x54, 0xfc, 0x2d, 0xda, 0x54, 0x09, 0x70, 0xb7, 0x69, 0xe9, 0x77, 0xc8, 0xba,
|
||||
0x6e, 0x91, 0x32, 0xa5, 0x61, 0x02, 0x3c, 0xb8, 0x5e, 0x22, 0x37, 0xcd, 0x8a, 0x5a, 0x00, 0x7e,
|
||||
0x88, 0xb6, 0x94, 0x66, 0x3a, 0x53, 0xee, 0x86, 0x45, 0x7d, 0x7c, 0x35, 0xca, 0xca, 0x83, 0x77,
|
||||
0x4a, 0xd8, 0xd6, 0x74, 0x4d, 0x4b, 0x4c, 0xff, 0x4f, 0x07, 0x75, 0x4a, 0xe5, 0x91, 0x50, 0x1a,
|
||||
0x3f, 0x59, 0xa9, 0x05, 0x79, 0xbd, 0x5a, 0x18, 0xb7, 0xad, 0xc4, 0x4e, 0x79, 0x52, 0x7b, 0x16,
|
||||
0x59, 0xa8, 0xc3, 0x03, 0xd4, 0x12, 0x1a, 0x22, 0xe5, 0x36, 0xf7, 0x36, 0x06, 0x9d, 0x83, 0x8f,
|
||||
0xae, 0xcc, 0x3e, 0xb8, 0x51, 0xd2, 0x5a, 0xdf, 0x1b, 0x1f, 0x9d, 0xda, 0xfb, 0x7f, 0x6f, 0x56,
|
||||
0x59, 0x9b, 0xe2, 0xe0, 0xcf, 0x50, 0xdb, 0xf4, 0x79, 0x94, 0x4d, 0xc0, 0x66, 0x7d, 0x6d, 0x9e,
|
||||
0xc5, 0xb0, 0x8c, 0xd3, 0x4a, 0x81, 0x07, 0xa8, 0x6d, 0x46, 0xe3, 0xb1, 0x8c, 0xc1, 0x6d, 0x5b,
|
||||
0xf5, 0x75, 0xa3, 0x7c, 0x54, 0xc6, 0x68, 0xb5, 0x8b, 0x7f, 0x46, 0xb7, 0x94, 0x66, 0xa9, 0x16,
|
||||
0xf1, 0xf8, 0x1b, 0x60, 0xa3, 0x89, 0x88, 0x61, 0x08, 0x5c, 0xc6, 0x23, 0x65, 0x5b, 0xb9, 0x11,
|
||||
0x7c, 0x50, 0xe4, 0xbd, 0x5b, 0xc3, 0x7a, 0x09, 0x5d, 0xe7, 0xc5, 0x4f, 0xd0, 0x4d, 0x2e, 0x63,
|
||||
0x9e, 0xa5, 0x29, 0xc4, 0xfc, 0xfc, 0x27, 0x39, 0x11, 0xfc, 0xdc, 0x36, 0xf4, 0x5a, 0x40, 0xca,
|
||||
0xbc, 0x6f, 0xde, 0x5f, 0x16, 0xfc, 0x57, 0x17, 0xa4, 0xab, 0x20, 0x7c, 0x07, 0x6d, 0xab, 0x4c,
|
||||
0x25, 0x10, 0x8f, 0xdc, 0xcd, 0x3d, 0x67, 0xd0, 0x0e, 0x3a, 0x45, 0xde, 0xdb, 0x1e, 0x4e, 0x43,
|
||||
0x74, 0xb6, 0x87, 0x9f, 0xa2, 0xce, 0x33, 0x19, 0x3e, 0x82, 0x28, 0x99, 0x30, 0x0d, 0x6e, 0xcb,
|
||||
0x36, 0xfb, 0x93, 0xf5, 0x1d, 0x39, 0x9c, 0x8b, 0xed, 0x78, 0xbe, 0x57, 0x66, 0xda, 0x59, 0xd8,
|
||||
0xa0, 0x8b, 0x48, 0xfc, 0x2b, 0xea, 0xaa, 0x8c, 0x73, 0x50, 0xea, 0x38, 0x9b, 0x1c, 0xca, 0x50,
|
||||
0x7d, 0x27, 0x94, 0x96, 0xe9, 0xf9, 0x91, 0x88, 0x84, 0x76, 0xb7, 0xf6, 0x9c, 0x41, 0x2b, 0xf0,
|
||||
0x8a, 0xbc, 0xd7, 0x1d, 0xae, 0x55, 0xd1, 0x57, 0x10, 0x30, 0x45, 0xbb, 0xc7, 0x4c, 0x4c, 0x60,
|
||||
0xb4, 0xc2, 0xde, 0xb6, 0xec, 0x6e, 0x91, 0xf7, 0x76, 0x1f, 0xd4, 0x2a, 0xe8, 0x1a, 0x67, 0xff,
|
||||
0xaf, 0x26, 0xba, 0xf1, 0xd2, 0x9b, 0x83, 0x7f, 0x40, 0x5b, 0x8c, 0x6b, 0x71, 0x66, 0x26, 0xcb,
|
||||
0x0c, 0xed, 0xed, 0xc5, 0x12, 0x99, 0xdb, 0x6f, 0x7e, 0x13, 0x50, 0x38, 0x06, 0xd3, 0x09, 0x98,
|
||||
0xbf, 0x6e, 0xf7, 0xac, 0x95, 0x96, 0x08, 0x3c, 0x41, 0x3b, 0x13, 0xa6, 0xf4, 0x6c, 0x28, 0xcd,
|
||||
0xc8, 0xd9, 0x26, 0x75, 0x0e, 0x3e, 0x7d, 0xbd, 0xd7, 0xcc, 0x38, 0x82, 0xf7, 0x8b, 0xbc, 0xb7,
|
||||
0x73, 0xb4, 0xc4, 0xa1, 0x2b, 0x64, 0x9c, 0x22, 0x6c, 0x63, 0x55, 0x09, 0xed, 0x79, 0xad, 0x37,
|
||||
0x3e, 0x6f, 0xb7, 0xc8, 0x7b, 0xf8, 0x68, 0x85, 0x44, 0x6b, 0xe8, 0xfd, 0x0b, 0x07, 0x2d, 0x4e,
|
||||
0xc4, 0x5b, 0xb8, 0x5c, 0x7f, 0x41, 0x6d, 0x3d, 0x9b, 0xe2, 0xe6, 0x9b, 0x4e, 0x71, 0x75, 0x4f,
|
||||
0x54, 0x23, 0x5c, 0xc1, 0xcc, 0xdd, 0xf8, 0xee, 0x92, 0xfe, 0x2d, 0x3c, 0xce, 0xdd, 0x97, 0xbe,
|
||||
0x15, 0x1f, 0xd6, 0x3d, 0x0a, 0x79, 0xc5, 0x27, 0x22, 0xb8, 0x7b, 0x71, 0xe9, 0x35, 0x9e, 0x5f,
|
||||
0x7a, 0x8d, 0x17, 0x97, 0x5e, 0xe3, 0xb7, 0xc2, 0x73, 0x2e, 0x0a, 0xcf, 0x79, 0x5e, 0x78, 0xce,
|
||||
0x8b, 0xc2, 0x73, 0xfe, 0x29, 0x3c, 0xe7, 0x8f, 0x7f, 0xbd, 0xc6, 0x63, 0x77, 0xdd, 0x5f, 0x8b,
|
||||
0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xd7, 0xf2, 0x8b, 0xe9, 0x8e, 0x08, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *CronJob) Marshal() (dAtA []byte, err error) {
|
||||
@ -400,6 +401,13 @@ func (m *CronJobSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.TimeZone != nil {
|
||||
i -= len(*m.TimeZone)
|
||||
copy(dAtA[i:], *m.TimeZone)
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(*m.TimeZone)))
|
||||
i--
|
||||
dAtA[i] = 0x42
|
||||
}
|
||||
if m.FailedJobsHistoryLimit != nil {
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(*m.FailedJobsHistoryLimit))
|
||||
i--
|
||||
@ -662,6 +670,10 @@ func (m *CronJobSpec) Size() (n int) {
|
||||
if m.FailedJobsHistoryLimit != nil {
|
||||
n += 1 + sovGenerated(uint64(*m.FailedJobsHistoryLimit))
|
||||
}
|
||||
if m.TimeZone != nil {
|
||||
l = len(*m.TimeZone)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@ -760,6 +772,7 @@ func (this *CronJobSpec) String() string {
|
||||
`JobTemplate:` + strings.Replace(strings.Replace(this.JobTemplate.String(), "JobTemplateSpec", "JobTemplateSpec", 1), `&`, ``, 1) + `,`,
|
||||
`SuccessfulJobsHistoryLimit:` + valueToStringGenerated(this.SuccessfulJobsHistoryLimit) + `,`,
|
||||
`FailedJobsHistoryLimit:` + valueToStringGenerated(this.FailedJobsHistoryLimit) + `,`,
|
||||
`TimeZone:` + valueToStringGenerated(this.TimeZone) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
@ -1284,6 +1297,39 @@ func (m *CronJobSpec) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
}
|
||||
m.FailedJobsHistoryLimit = &v
|
||||
case 8:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field TimeZone", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
s := string(dAtA[iNdEx:postIndex])
|
||||
m.TimeZone = &s
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
|
@ -64,6 +64,12 @@ message CronJobSpec {
|
||||
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
||||
optional string schedule = 1;
|
||||
|
||||
// The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
|
||||
// If not specified, this will rely on the time zone of the kube-controller-manager process.
|
||||
// ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.
|
||||
// +optional
|
||||
optional string timeZone = 8;
|
||||
|
||||
// Optional deadline in seconds for starting the job if it misses scheduled
|
||||
// time for any reason. Missed jobs executions will be counted as failed ones.
|
||||
// +optional
|
||||
|
@ -104,6 +104,12 @@ type CronJobSpec struct {
|
||||
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
||||
Schedule string `json:"schedule" protobuf:"bytes,1,opt,name=schedule"`
|
||||
|
||||
// The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
|
||||
// If not specified, this will rely on the time zone of the kube-controller-manager process.
|
||||
// ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.
|
||||
// +optional
|
||||
TimeZone *string `json:"timeZone,omitempty" protobuf:"bytes,8,opt,name=timeZone"`
|
||||
|
||||
// Optional deadline in seconds for starting the job if it misses scheduled
|
||||
// time for any reason. Missed jobs executions will be counted as failed ones.
|
||||
// +optional
|
||||
|
@ -51,6 +51,7 @@ func (CronJobList) SwaggerDoc() map[string]string {
|
||||
var map_CronJobSpec = map[string]string{
|
||||
"": "CronJobSpec describes how the job execution will look like and when it will actually run.",
|
||||
"schedule": "The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.",
|
||||
"timeZone": "The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will rely on the time zone of the kube-controller-manager process. ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.",
|
||||
"startingDeadlineSeconds": "Optional deadline in seconds for starting the job if it misses scheduled time for any reason. Missed jobs executions will be counted as failed ones.",
|
||||
"concurrencyPolicy": "Specifies how to treat concurrent executions of a Job. Valid values are: - \"Allow\" (default): allows CronJobs to run concurrently; - \"Forbid\": forbids concurrent runs, skipping next run if previous run hasn't finished yet; - \"Replace\": cancels currently running job and replaces it with a new one",
|
||||
"suspend": "This flag tells the controller to suspend subsequent executions, it does not apply to already started executions. Defaults to false.",
|
||||
|
@ -90,6 +90,11 @@ func (in *CronJobList) DeepCopyObject() runtime.Object {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CronJobSpec) DeepCopyInto(out *CronJobSpec) {
|
||||
*out = *in
|
||||
if in.TimeZone != nil {
|
||||
in, out := &in.TimeZone, &out.TimeZone
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.StartingDeadlineSeconds != nil {
|
||||
in, out := &in.StartingDeadlineSeconds, &out.StartingDeadlineSeconds
|
||||
*out = new(int64)
|
||||
|
@ -46,6 +46,7 @@
|
||||
},
|
||||
"spec": {
|
||||
"schedule": "scheduleValue",
|
||||
"timeZone": "timeZoneValue",
|
||||
"startingDeadlineSeconds": 2,
|
||||
"concurrencyPolicy": "concurrencyPolicyValue",
|
||||
"suspend": true,
|
||||
|
Binary file not shown.
@ -1170,6 +1170,7 @@ spec:
|
||||
startingDeadlineSeconds: 2
|
||||
successfulJobsHistoryLimit: 6
|
||||
suspend: true
|
||||
timeZone: timeZoneValue
|
||||
status:
|
||||
active:
|
||||
- apiVersion: apiVersionValue
|
||||
|
@ -46,6 +46,7 @@
|
||||
},
|
||||
"spec": {
|
||||
"schedule": "scheduleValue",
|
||||
"timeZone": "timeZoneValue",
|
||||
"startingDeadlineSeconds": 2,
|
||||
"concurrencyPolicy": "concurrencyPolicyValue",
|
||||
"suspend": true,
|
||||
|
Binary file not shown.
@ -1170,6 +1170,7 @@ spec:
|
||||
startingDeadlineSeconds: 2
|
||||
successfulJobsHistoryLimit: 6
|
||||
suspend: true
|
||||
timeZone: timeZoneValue
|
||||
status:
|
||||
active:
|
||||
- apiVersion: apiVersionValue
|
||||
|
@ -178,6 +178,13 @@ const (
|
||||
//
|
||||
// Enables server-side field validation.
|
||||
ServerSideFieldValidation featuregate.Feature = "ServerSideFieldValidation"
|
||||
|
||||
// owner: @deejross
|
||||
// kep: http://kep.k8s.io/3140
|
||||
// alpha: v1.24
|
||||
//
|
||||
// Enables support for time zones in CronJobs.
|
||||
CronJobTimeZone featuregate.Feature = "CronJobTimeZone"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -207,4 +214,5 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
CustomResourceValidationExpressions: {Default: false, PreRelease: featuregate.Alpha},
|
||||
OpenAPIV3: {Default: false, PreRelease: featuregate.Alpha},
|
||||
ServerSideFieldValidation: {Default: true, PreRelease: featuregate.Beta},
|
||||
CronJobTimeZone: {Default: false, PreRelease: featuregate.Alpha},
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
// with apply.
|
||||
type CronJobSpecApplyConfiguration struct {
|
||||
Schedule *string `json:"schedule,omitempty"`
|
||||
TimeZone *string `json:"timeZone,omitempty"`
|
||||
StartingDeadlineSeconds *int64 `json:"startingDeadlineSeconds,omitempty"`
|
||||
ConcurrencyPolicy *v1.ConcurrencyPolicy `json:"concurrencyPolicy,omitempty"`
|
||||
Suspend *bool `json:"suspend,omitempty"`
|
||||
@ -48,6 +49,14 @@ func (b *CronJobSpecApplyConfiguration) WithSchedule(value string) *CronJobSpecA
|
||||
return b
|
||||
}
|
||||
|
||||
// WithTimeZone sets the TimeZone field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the TimeZone field is set to the value of the last call.
|
||||
func (b *CronJobSpecApplyConfiguration) WithTimeZone(value string) *CronJobSpecApplyConfiguration {
|
||||
b.TimeZone = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithStartingDeadlineSeconds sets the StartingDeadlineSeconds field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the StartingDeadlineSeconds field is set to the value of the last call.
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
// with apply.
|
||||
type CronJobSpecApplyConfiguration struct {
|
||||
Schedule *string `json:"schedule,omitempty"`
|
||||
TimeZone *string `json:"timeZone,omitempty"`
|
||||
StartingDeadlineSeconds *int64 `json:"startingDeadlineSeconds,omitempty"`
|
||||
ConcurrencyPolicy *v1beta1.ConcurrencyPolicy `json:"concurrencyPolicy,omitempty"`
|
||||
Suspend *bool `json:"suspend,omitempty"`
|
||||
@ -48,6 +49,14 @@ func (b *CronJobSpecApplyConfiguration) WithSchedule(value string) *CronJobSpecA
|
||||
return b
|
||||
}
|
||||
|
||||
// WithTimeZone sets the TimeZone field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the TimeZone field is set to the value of the last call.
|
||||
func (b *CronJobSpecApplyConfiguration) WithTimeZone(value string) *CronJobSpecApplyConfiguration {
|
||||
b.TimeZone = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithStartingDeadlineSeconds sets the StartingDeadlineSeconds field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the StartingDeadlineSeconds field is set to the value of the last call.
|
||||
|
@ -2956,6 +2956,9 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: suspend
|
||||
type:
|
||||
scalar: boolean
|
||||
- name: timeZone
|
||||
type:
|
||||
scalar: string
|
||||
- name: io.k8s.api.batch.v1.CronJobStatus
|
||||
map:
|
||||
fields:
|
||||
@ -3157,6 +3160,9 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: suspend
|
||||
type:
|
||||
scalar: boolean
|
||||
- name: timeZone
|
||||
type:
|
||||
scalar: string
|
||||
- name: io.k8s.api.batch.v1beta1.CronJobStatus
|
||||
map:
|
||||
fields:
|
||||
|
Loading…
Reference in New Issue
Block a user