mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 17:30:00 +00:00
Merge pull request #111435 from soltysh/cronjob_timezone_beta
Promote CronJobTimeZone to beta
This commit is contained in:
commit
6fbeacdf73
2
api/openapi-spec/swagger.json
generated
2
api/openapi-spec/swagger.json
generated
@ -3542,7 +3542,7 @@
|
|||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"timeZone": {
|
"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.",
|
"description": "The time zone name for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will default to the time zone of the kube-controller-manager process. The set of valid time zone names and the time zone offset is loaded from the system-wide time zone database by the API server during CronJob validation and the controller manager during execution. If no system-wide time zone database can be found a bundled version of the database is used instead. If the time zone name becomes invalid during the lifetime of a CronJob or due to a change in host configuration, the controller will stop creating new new Jobs and will create a system event with the reason UnknownTimeZone. More information can be found in https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#time-zones This is beta field and must be enabled via the `CronJobTimeZone` feature gate.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -135,7 +135,7 @@
|
|||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"timeZone": {
|
"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.",
|
"description": "The time zone name for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will default to the time zone of the kube-controller-manager process. The set of valid time zone names and the time zone offset is loaded from the system-wide time zone database by the API server during CronJob validation and the controller manager during execution. If no system-wide time zone database can be found a bundled version of the database is used instead. If the time zone name becomes invalid during the lifetime of a CronJob or due to a change in host configuration, the controller will stop creating new new Jobs and will create a system event with the reason UnknownTimeZone. More information can be found in https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#time-zones This is beta field and must be enabled via the `CronJobTimeZone` feature gate.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -376,9 +376,16 @@ type CronJobSpec struct {
|
|||||||
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
||||||
Schedule string
|
Schedule string
|
||||||
|
|
||||||
// The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
|
// The time zone name 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.
|
// If not specified, this will default to the time zone of the kube-controller-manager process.
|
||||||
// ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.
|
// The set of valid time zone names and the time zone offset is loaded from the system-wide time zone
|
||||||
|
// database by the API server during CronJob validation and the controller manager during execution.
|
||||||
|
// If no system-wide time zone database can be found a bundled version of the database is used instead.
|
||||||
|
// If the time zone name becomes invalid during the lifetime of a CronJob or due to a change in host
|
||||||
|
// configuration, the controller will stop creating new new Jobs and will create a system event with the
|
||||||
|
// reason UnknownTimeZone.
|
||||||
|
// More information can be found in https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#time-zones
|
||||||
|
// This is beta field and must be enabled via the `CronJobTimeZone` feature gate.
|
||||||
// +optional
|
// +optional
|
||||||
TimeZone *string
|
TimeZone *string
|
||||||
|
|
||||||
|
@ -17,6 +17,10 @@ limitations under the License.
|
|||||||
package validation
|
package validation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -33,15 +37,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
timeZoneEmpty = ""
|
timeZoneEmpty = ""
|
||||||
timeZoneLocal = "LOCAL"
|
timeZoneLocal = "LOCAL"
|
||||||
timeZoneUTC = "UTC"
|
timeZoneUTC = "UTC"
|
||||||
timeZoneCorrectCasing = "America/New_York"
|
timeZoneCorrect = "Continent/Zone"
|
||||||
timeZoneBadCasing = "AMERICA/new_york"
|
timeZoneBadPrefix = " Continent/Zone"
|
||||||
timeZoneBadPrefix = " America/New_York"
|
timeZoneBadSuffix = "Continent/Zone "
|
||||||
timeZoneBadSuffix = "America/New_York "
|
timeZoneBadName = "Continent/InvalidZone"
|
||||||
timeZoneBadName = "America/New York"
|
timeZoneEmptySpace = " "
|
||||||
timeZoneEmptySpace = " "
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ignoreErrValueDetail = cmpopts.IgnoreFields(field.Error{}, "BadValue", "Detail")
|
var ignoreErrValueDetail = cmpopts.IgnoreFields(field.Error{}, "BadValue", "Detail")
|
||||||
@ -882,6 +885,12 @@ func TestValidateCronJob(t *testing.T) {
|
|||||||
validPodTemplateSpec := getValidPodTemplateSpecForGenerated(getValidGeneratedSelector())
|
validPodTemplateSpec := getValidPodTemplateSpecForGenerated(getValidGeneratedSelector())
|
||||||
validPodTemplateSpec.Labels = map[string]string{}
|
validPodTemplateSpec.Labels = map[string]string{}
|
||||||
|
|
||||||
|
zoneDir := t.TempDir()
|
||||||
|
if err := setupFakeTimeZoneDatabase(zoneDir); err != nil {
|
||||||
|
t.Fatalf("Unexpected error setting up fake timezone database: %v", err)
|
||||||
|
}
|
||||||
|
t.Setenv("ZONEINFO", zoneDir)
|
||||||
|
|
||||||
successCases := map[string]batch.CronJob{
|
successCases := map[string]batch.CronJob{
|
||||||
"basic scheduled job": {
|
"basic scheduled job": {
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -915,7 +924,7 @@ func TestValidateCronJob(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"correct timeZone value casing": {
|
"correct timeZone value": {
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "mycronjob",
|
Name: "mycronjob",
|
||||||
Namespace: metav1.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
@ -923,7 +932,7 @@ func TestValidateCronJob(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Spec: batch.CronJobSpec{
|
Spec: batch.CronJobSpec{
|
||||||
Schedule: "0 * * * *",
|
Schedule: "0 * * * *",
|
||||||
TimeZone: &timeZoneCorrectCasing,
|
TimeZone: &timeZoneCorrect,
|
||||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||||
JobTemplate: batch.JobTemplateSpec{
|
JobTemplate: batch.JobTemplateSpec{
|
||||||
Spec: batch.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
@ -934,17 +943,19 @@ func TestValidateCronJob(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for k, v := range successCases {
|
for k, v := range successCases {
|
||||||
if errs := ValidateCronJobCreate(&v, corevalidation.PodValidationOptions{}); len(errs) != 0 {
|
t.Run(k, func(t *testing.T) {
|
||||||
t.Errorf("expected success for %s: %v", k, errs)
|
if errs := ValidateCronJobCreate(&v, corevalidation.PodValidationOptions{}); len(errs) != 0 {
|
||||||
}
|
t.Errorf("expected success for %s: %v", k, errs)
|
||||||
|
}
|
||||||
|
|
||||||
// Update validation should pass same success cases
|
// Update validation should pass same success cases
|
||||||
// copy to avoid polluting the testcase object, set a resourceVersion to allow validating update, and test a no-op update
|
// copy to avoid polluting the testcase object, set a resourceVersion to allow validating update, and test a no-op update
|
||||||
v = *v.DeepCopy()
|
v = *v.DeepCopy()
|
||||||
v.ResourceVersion = "1"
|
v.ResourceVersion = "1"
|
||||||
if errs := ValidateCronJobUpdate(&v, &v, corevalidation.PodValidationOptions{}); len(errs) != 0 {
|
if errs := ValidateCronJobUpdate(&v, &v, corevalidation.PodValidationOptions{}); len(errs) != 0 {
|
||||||
t.Errorf("expected success for %s: %v", k, errs)
|
t.Errorf("expected success for %s: %v", k, errs)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
negative := int32(-1)
|
negative := int32(-1)
|
||||||
@ -1034,7 +1045,7 @@ func TestValidateCronJob(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"spec.timeZone: Invalid value: \" America/New_York\": unknown time zone America/New_York": {
|
"spec.timeZone: Invalid value: \" Continent/Zone\": unknown time zone Continent/Zone": {
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "mycronjob",
|
Name: "mycronjob",
|
||||||
Namespace: metav1.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
@ -1051,7 +1062,7 @@ func TestValidateCronJob(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"spec.timeZone: Invalid value: \"America/New_York \": unknown time zone America/New_York ": {
|
"spec.timeZone: Invalid value: \"Continent/Zone \": unknown time zone Continent/Zone ": {
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "mycronjob",
|
Name: "mycronjob",
|
||||||
Namespace: metav1.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
@ -1068,7 +1079,7 @@ func TestValidateCronJob(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"spec.timeZone: Invalid value: \"America/New York\": unknown time zone America/New York": {
|
"spec.timeZone: Invalid value: \"Continent/InvalidZone\": unknown time zone Continent/InvalidZone": {
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "mycronjob",
|
Name: "mycronjob",
|
||||||
Namespace: metav1.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
@ -1314,82 +1325,100 @@ func TestValidateCronJob(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
"spec.jobTemplate.spec.ttlSecondsAfterFinished:must be greater than or equal to 0": {
|
||||||
errorCases["spec.jobTemplate.spec.ttlSecondsAfterFinished:must be greater than or equal to 0"] = batch.CronJob{
|
|
||||||
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{
|
|
||||||
TTLSecondsAfterFinished: &negative,
|
|
||||||
Template: validPodTemplateSpec,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if runtime.GOOS != "darwin" {
|
|
||||||
// Skip this error case on darwin, see https://github.com/golang/go/issues/21512
|
|
||||||
errorCases["spec.timeZone: Invalid value: \"AMERICA/new_york\": unknown time zone AMERICA/new_york"] = batch.CronJob{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "mycronjob",
|
Name: "mycronjob",
|
||||||
Namespace: metav1.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
UID: types.UID("1a2b3c"),
|
UID: types.UID("1a2b3c"),
|
||||||
},
|
},
|
||||||
Spec: batch.CronJobSpec{
|
Spec: batch.CronJobSpec{
|
||||||
Schedule: "0 * * * *",
|
Schedule: "* * * * ?",
|
||||||
TimeZone: &timeZoneBadCasing,
|
|
||||||
ConcurrencyPolicy: batch.AllowConcurrent,
|
ConcurrencyPolicy: batch.AllowConcurrent,
|
||||||
JobTemplate: batch.JobTemplateSpec{
|
JobTemplate: batch.JobTemplateSpec{
|
||||||
Spec: batch.JobSpec{
|
Spec: batch.JobSpec{
|
||||||
Template: validPodTemplateSpec,
|
TTLSecondsAfterFinished: &negative,
|
||||||
|
Template: validPodTemplateSpec,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range errorCases {
|
for k, v := range errorCases {
|
||||||
errs := ValidateCronJobCreate(&v, corevalidation.PodValidationOptions{})
|
t.Run(k, func(t *testing.T) {
|
||||||
if len(errs) == 0 {
|
errs := ValidateCronJobCreate(&v, corevalidation.PodValidationOptions{})
|
||||||
t.Errorf("expected failure for %s", k)
|
if len(errs) == 0 {
|
||||||
} else {
|
t.Errorf("expected failure for %s", k)
|
||||||
s := strings.Split(k, ":")
|
} else {
|
||||||
err := errs[0]
|
s := strings.Split(k, ":")
|
||||||
if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) {
|
err := errs[0]
|
||||||
t.Errorf("unexpected error: %v, expected: %s", err, k)
|
if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) {
|
||||||
|
t.Errorf("unexpected error: %v, expected: %s", err, k)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Update validation should fail all failure cases other than the 52 character name limit
|
// 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
|
// copy to avoid polluting the testcase object, set a resourceVersion to allow validating update, and test a no-op update
|
||||||
oldSpec := *v.DeepCopy()
|
oldSpec := *v.DeepCopy()
|
||||||
oldSpec.ResourceVersion = "1"
|
oldSpec.ResourceVersion = "1"
|
||||||
oldSpec.Spec.TimeZone = nil
|
oldSpec.Spec.TimeZone = nil
|
||||||
|
|
||||||
newSpec := *v.DeepCopy()
|
newSpec := *v.DeepCopy()
|
||||||
newSpec.ResourceVersion = "2"
|
newSpec.ResourceVersion = "2"
|
||||||
|
|
||||||
errs = ValidateCronJobUpdate(&newSpec, &oldSpec, corevalidation.PodValidationOptions{})
|
errs = ValidateCronJobUpdate(&newSpec, &oldSpec, corevalidation.PodValidationOptions{})
|
||||||
if len(errs) == 0 {
|
if len(errs) == 0 {
|
||||||
if k == "metadata.name: must be no more than 52 characters" {
|
if k == "metadata.name: must be no more than 52 characters" {
|
||||||
continue
|
return
|
||||||
|
}
|
||||||
|
t.Errorf("expected failure for %s", k)
|
||||||
|
} else {
|
||||||
|
s := strings.Split(k, ":")
|
||||||
|
err := errs[0]
|
||||||
|
if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) {
|
||||||
|
t.Errorf("unexpected error: %v, expected: %s", err, k)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
t.Errorf("expected failure for %s", k)
|
})
|
||||||
} else {
|
|
||||||
s := strings.Split(k, ":")
|
|
||||||
err := errs[0]
|
|
||||||
if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) {
|
|
||||||
t.Errorf("unexpected error: %v, expected: %s", err, k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets up fake timezone database in a zoneDir directory with a single valid
|
||||||
|
// time zone called "Continent/Zone" by copying UTC metadata from golang's
|
||||||
|
// built-in databse. Returns an error in case of problems.
|
||||||
|
func setupFakeTimeZoneDatabase(zoneDir string) error {
|
||||||
|
reader, err := zip.OpenReader(runtime.GOROOT() + "/lib/time/zoneinfo.zip")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
|
if err := os.Mkdir(filepath.Join(zoneDir, "Continent"), os.ModePerm); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
zoneFile, err := os.OpenFile(filepath.Join(zoneDir, "Continent", "Zone"), os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer zoneFile.Close()
|
||||||
|
|
||||||
|
for _, file := range reader.File {
|
||||||
|
if file.Name != "UTC" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rc, err := file.Open()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.Copy(zoneFile, rc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rc.Close()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestValidateCronJobSpec(t *testing.T) {
|
func TestValidateCronJobSpec(t *testing.T) {
|
||||||
validPodTemplateSpec := getValidPodTemplateSpecForGenerated(getValidGeneratedSelector())
|
validPodTemplateSpec := getValidPodTemplateSpecForGenerated(getValidGeneratedSelector())
|
||||||
validPodTemplateSpec.Labels = map[string]string{}
|
validPodTemplateSpec.Labels = map[string]string{}
|
||||||
|
@ -207,9 +207,10 @@ const (
|
|||||||
// Enables Leader Migration for kube-controller-manager and cloud-controller-manager
|
// Enables Leader Migration for kube-controller-manager and cloud-controller-manager
|
||||||
ControllerManagerLeaderMigration featuregate.Feature = "ControllerManagerLeaderMigration"
|
ControllerManagerLeaderMigration featuregate.Feature = "ControllerManagerLeaderMigration"
|
||||||
|
|
||||||
// owner: @deejross
|
// owner: @deejross, @soltysh
|
||||||
// kep: http://kep.k8s.io/3140
|
// kep: http://kep.k8s.io/3140
|
||||||
// alpha: v1.24
|
// alpha: v1.24
|
||||||
|
// beta: v1.25
|
||||||
//
|
//
|
||||||
// Enables support for time zones in CronJobs.
|
// Enables support for time zones in CronJobs.
|
||||||
CronJobTimeZone featuregate.Feature = "CronJobTimeZone"
|
CronJobTimeZone featuregate.Feature = "CronJobTimeZone"
|
||||||
@ -910,7 +911,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
|||||||
|
|
||||||
ControllerManagerLeaderMigration: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26
|
ControllerManagerLeaderMigration: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26
|
||||||
|
|
||||||
CronJobTimeZone: {Default: false, PreRelease: featuregate.Alpha},
|
CronJobTimeZone: {Default: true, PreRelease: featuregate.Beta},
|
||||||
|
|
||||||
DaemonSetUpdateSurge: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27
|
DaemonSetUpdateSurge: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27
|
||||||
|
|
||||||
|
4
pkg/generated/openapi/zz_generated.openapi.go
generated
4
pkg/generated/openapi/zz_generated.openapi.go
generated
@ -12703,7 +12703,7 @@ func schema_k8sio_api_batch_v1_CronJobSpec(ref common.ReferenceCallback) common.
|
|||||||
},
|
},
|
||||||
"timeZone": {
|
"timeZone": {
|
||||||
SchemaProps: spec.SchemaProps{
|
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.",
|
Description: "The time zone name for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will default to the time zone of the kube-controller-manager process. The set of valid time zone names and the time zone offset is loaded from the system-wide time zone database by the API server during CronJob validation and the controller manager during execution. If no system-wide time zone database can be found a bundled version of the database is used instead. If the time zone name becomes invalid during the lifetime of a CronJob or due to a change in host configuration, the controller will stop creating new new Jobs and will create a system event with the reason UnknownTimeZone. More information can be found in https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#time-zones This is beta field and must be enabled via the `CronJobTimeZone` feature gate.",
|
||||||
Type: []string{"string"},
|
Type: []string{"string"},
|
||||||
Format: "",
|
Format: "",
|
||||||
},
|
},
|
||||||
@ -13340,7 +13340,7 @@ func schema_k8sio_api_batch_v1beta1_CronJobSpec(ref common.ReferenceCallback) co
|
|||||||
},
|
},
|
||||||
"timeZone": {
|
"timeZone": {
|
||||||
SchemaProps: spec.SchemaProps{
|
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.",
|
Description: "The time zone name for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will default to the time zone of the kube-controller-manager process. The set of valid time zone names and the time zone offset is loaded from the system-wide time zone database by the API server during CronJob validation and the controller manager during execution. If no system-wide time zone database can be found a bundled version of the database is used instead. If the time zone name becomes invalid during the lifetime of a CronJob or due to a change in host configuration, the controller will stop creating new new Jobs and will create a system event with the reason UnknownTimeZone. More information can be found in https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#time-zones This is beta field and must be enabled via the `CronJobTimeZone` feature gate.",
|
||||||
Type: []string{"string"},
|
Type: []string{"string"},
|
||||||
Format: "",
|
Format: "",
|
||||||
},
|
},
|
||||||
|
@ -63,9 +63,16 @@ message CronJobSpec {
|
|||||||
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
||||||
optional string schedule = 1;
|
optional string schedule = 1;
|
||||||
|
|
||||||
// The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
|
// The time zone name 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.
|
// If not specified, this will default to the time zone of the kube-controller-manager process.
|
||||||
// ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.
|
// The set of valid time zone names and the time zone offset is loaded from the system-wide time zone
|
||||||
|
// database by the API server during CronJob validation and the controller manager during execution.
|
||||||
|
// If no system-wide time zone database can be found a bundled version of the database is used instead.
|
||||||
|
// If the time zone name becomes invalid during the lifetime of a CronJob or due to a change in host
|
||||||
|
// configuration, the controller will stop creating new new Jobs and will create a system event with the
|
||||||
|
// reason UnknownTimeZone.
|
||||||
|
// More information can be found in https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#time-zones
|
||||||
|
// This is beta field and must be enabled via the `CronJobTimeZone` feature gate.
|
||||||
// +optional
|
// +optional
|
||||||
optional string timeZone = 8;
|
optional string timeZone = 8;
|
||||||
|
|
||||||
|
@ -375,9 +375,16 @@ type CronJobSpec struct {
|
|||||||
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
||||||
Schedule string `json:"schedule" protobuf:"bytes,1,opt,name=schedule"`
|
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.
|
// The time zone name 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.
|
// If not specified, this will default to the time zone of the kube-controller-manager process.
|
||||||
// ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.
|
// The set of valid time zone names and the time zone offset is loaded from the system-wide time zone
|
||||||
|
// database by the API server during CronJob validation and the controller manager during execution.
|
||||||
|
// If no system-wide time zone database can be found a bundled version of the database is used instead.
|
||||||
|
// If the time zone name becomes invalid during the lifetime of a CronJob or due to a change in host
|
||||||
|
// configuration, the controller will stop creating new new Jobs and will create a system event with the
|
||||||
|
// reason UnknownTimeZone.
|
||||||
|
// More information can be found in https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#time-zones
|
||||||
|
// This is beta field and must be enabled via the `CronJobTimeZone` feature gate.
|
||||||
// +optional
|
// +optional
|
||||||
TimeZone *string `json:"timeZone,omitempty" protobuf:"bytes,8,opt,name=timeZone"`
|
TimeZone *string `json:"timeZone,omitempty" protobuf:"bytes,8,opt,name=timeZone"`
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ func (CronJobList) SwaggerDoc() map[string]string {
|
|||||||
var map_CronJobSpec = map[string]string{
|
var map_CronJobSpec = map[string]string{
|
||||||
"": "CronJobSpec describes how the job execution will look like and when it will actually run.",
|
"": "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.",
|
"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.",
|
"timeZone": "The time zone name for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will default to the time zone of the kube-controller-manager process. The set of valid time zone names and the time zone offset is loaded from the system-wide time zone database by the API server during CronJob validation and the controller manager during execution. If no system-wide time zone database can be found a bundled version of the database is used instead. If the time zone name becomes invalid during the lifetime of a CronJob or due to a change in host configuration, the controller will stop creating new new Jobs and will create a system event with the reason UnknownTimeZone. More information can be found in https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#time-zones This is beta field 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.",
|
"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",
|
"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.",
|
"suspend": "This flag tells the controller to suspend subsequent executions, it does not apply to already started executions. Defaults to false.",
|
||||||
|
@ -64,9 +64,16 @@ message CronJobSpec {
|
|||||||
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
||||||
optional string schedule = 1;
|
optional string schedule = 1;
|
||||||
|
|
||||||
// The time zone for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
|
// The time zone name 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.
|
// If not specified, this will default to the time zone of the kube-controller-manager process.
|
||||||
// ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.
|
// The set of valid time zone names and the time zone offset is loaded from the system-wide time zone
|
||||||
|
// database by the API server during CronJob validation and the controller manager during execution.
|
||||||
|
// If no system-wide time zone database can be found a bundled version of the database is used instead.
|
||||||
|
// If the time zone name becomes invalid during the lifetime of a CronJob or due to a change in host
|
||||||
|
// configuration, the controller will stop creating new new Jobs and will create a system event with the
|
||||||
|
// reason UnknownTimeZone.
|
||||||
|
// More information can be found in https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#time-zones
|
||||||
|
// This is beta field and must be enabled via the `CronJobTimeZone` feature gate.
|
||||||
// +optional
|
// +optional
|
||||||
optional string timeZone = 8;
|
optional string timeZone = 8;
|
||||||
|
|
||||||
|
@ -104,9 +104,16 @@ type CronJobSpec struct {
|
|||||||
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
|
||||||
Schedule string `json:"schedule" protobuf:"bytes,1,opt,name=schedule"`
|
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.
|
// The time zone name 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.
|
// If not specified, this will default to the time zone of the kube-controller-manager process.
|
||||||
// ALPHA: This field is in alpha and must be enabled via the `CronJobTimeZone` feature gate.
|
// The set of valid time zone names and the time zone offset is loaded from the system-wide time zone
|
||||||
|
// database by the API server during CronJob validation and the controller manager during execution.
|
||||||
|
// If no system-wide time zone database can be found a bundled version of the database is used instead.
|
||||||
|
// If the time zone name becomes invalid during the lifetime of a CronJob or due to a change in host
|
||||||
|
// configuration, the controller will stop creating new new Jobs and will create a system event with the
|
||||||
|
// reason UnknownTimeZone.
|
||||||
|
// More information can be found in https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#time-zones
|
||||||
|
// This is beta field and must be enabled via the `CronJobTimeZone` feature gate.
|
||||||
// +optional
|
// +optional
|
||||||
TimeZone *string `json:"timeZone,omitempty" protobuf:"bytes,8,opt,name=timeZone"`
|
TimeZone *string `json:"timeZone,omitempty" protobuf:"bytes,8,opt,name=timeZone"`
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ func (CronJobList) SwaggerDoc() map[string]string {
|
|||||||
var map_CronJobSpec = map[string]string{
|
var map_CronJobSpec = map[string]string{
|
||||||
"": "CronJobSpec describes how the job execution will look like and when it will actually run.",
|
"": "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.",
|
"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.",
|
"timeZone": "The time zone name for the given schedule, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. If not specified, this will default to the time zone of the kube-controller-manager process. The set of valid time zone names and the time zone offset is loaded from the system-wide time zone database by the API server during CronJob validation and the controller manager during execution. If no system-wide time zone database can be found a bundled version of the database is used instead. If the time zone name becomes invalid during the lifetime of a CronJob or due to a change in host configuration, the controller will stop creating new new Jobs and will create a system event with the reason UnknownTimeZone. More information can be found in https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#time-zones This is beta field 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.",
|
"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",
|
"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.",
|
"suspend": "This flag tells the controller to suspend subsequent executions, it does not apply to already started executions. Defaults to false.",
|
||||||
|
@ -298,6 +298,17 @@ var _ = SIGDescribe("CronJob", func() {
|
|||||||
ensureHistoryLimits(f.ClientSet, f.Namespace.Name, cronJob)
|
ensureHistoryLimits(f.ClientSet, f.Namespace.Name, cronJob)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should support timezone", func() {
|
||||||
|
ginkgo.By("Creating a cronjob with TimeZone")
|
||||||
|
cronJob := newTestCronJob("cronjob-with-timezone", "*/1 * * * ?", batchv1.AllowConcurrent,
|
||||||
|
failureCommand, nil, nil)
|
||||||
|
badTimeZone := "bad-time-zone"
|
||||||
|
cronJob.Spec.TimeZone = &badTimeZone
|
||||||
|
_, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob)
|
||||||
|
framework.ExpectError(err, "CronJob creation should fail with invalid time zone error")
|
||||||
|
framework.ExpectEqual(apierrors.IsInvalid(err), true, "CronJob creation should fail with invalid time zone error")
|
||||||
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Release: v1.21
|
Release: v1.21
|
||||||
Testname: CronJob API Operations
|
Testname: CronJob API Operations
|
||||||
|
Loading…
Reference in New Issue
Block a user