diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index d1728e6a7e..ebf4fb559d 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -51,7 +51,6 @@ import ( "k8s.io/apiserver/pkg/server/options/encryptionconfig" serverstorage "k8s.io/apiserver/pkg/server/storage" aggregatorapiserver "k8s.io/kube-aggregator/pkg/apiserver" - //aggregatorinformers "k8s.io/kube-aggregator/pkg/client/informers/internalversion" openapi "k8s.io/kube-openapi/pkg/common" "k8s.io/apiserver/pkg/storage/etcd3/preflight" @@ -548,9 +547,8 @@ func BuildStorageFactory(s *options.ServerRunOptions) (*serverstorage.DefaultSto storageFactory, err := kubeapiserver.NewStorageFactory( s.Etcd.StorageConfig, s.Etcd.DefaultStorageMediaType, api.Codecs, serverstorage.NewDefaultResourceEncodingConfig(api.Registry), storageGroupsToEncodingVersion, - // FIXME: this GroupVersionResource override should be configurable - // TODO we need to update this to batch/v1beta1 when it's enabled by default - []schema.GroupVersionResource{batch.Resource("cronjobs").WithVersion("v2alpha1")}, + // FIXME (soltysh): this GroupVersionResource override should be configurable + []schema.GroupVersionResource{batch.Resource("cronjobs").WithVersion("v1beta1")}, master.DefaultAPIResourceConfigSource(), s.APIEnablement.RuntimeConfig) if err != nil { return nil, fmt.Errorf("error in initializing storage factory: %s", err) diff --git a/cmd/kube-controller-manager/app/BUILD b/cmd/kube-controller-manager/app/BUILD index 92fadcacf5..683c45450c 100644 --- a/cmd/kube-controller-manager/app/BUILD +++ b/cmd/kube-controller-manager/app/BUILD @@ -29,7 +29,6 @@ go_library( "//pkg/apis/authentication/install:go_default_library", "//pkg/apis/authorization/install:go_default_library", "//pkg/apis/autoscaling/install:go_default_library", - "//pkg/apis/batch:go_default_library", "//pkg/apis/batch/install:go_default_library", "//pkg/apis/certificates/install:go_default_library", "//pkg/apis/componentconfig:go_default_library", diff --git a/cmd/kube-controller-manager/app/batch.go b/cmd/kube-controller-manager/app/batch.go index 2fea55c6aa..0333206144 100644 --- a/cmd/kube-controller-manager/app/batch.go +++ b/cmd/kube-controller-manager/app/batch.go @@ -22,8 +22,6 @@ package app import ( "k8s.io/apimachinery/pkg/runtime/schema" - clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/controller/cronjob" "k8s.io/kubernetes/pkg/controller/job" ) @@ -41,14 +39,11 @@ func startJobController(ctx ControllerContext) (bool, error) { } func startCronJobController(ctx ControllerContext) (bool, error) { - if !ctx.AvailableResources[schema.GroupVersionResource{Group: "batch", Version: "v2alpha1", Resource: "cronjobs"}] { + if !ctx.AvailableResources[schema.GroupVersionResource{Group: "batch", Version: "v1beta1", Resource: "cronjobs"}] { return false, nil } - // TODO: this is a temp fix for allowing kubeClient list v2alpha1 sj, should switch to using clientset - cronjobConfig := ctx.ClientBuilder.ConfigOrDie("cronjob-controller") - cronjobConfig.ContentConfig.GroupVersion = &schema.GroupVersion{Group: batch.GroupName, Version: "v2alpha1"} go cronjob.NewCronJobController( - clientset.NewForConfigOrDie(cronjobConfig), + ctx.ClientBuilder.ClientOrDie("cronjob-controller"), ).Run(ctx.Stop) return true, nil } diff --git a/hack/make-rules/test-cmd-util.sh b/hack/make-rules/test-cmd-util.sh index 0c2c61ce05..2d57e5843c 100755 --- a/hack/make-rules/test-cmd-util.sh +++ b/hack/make-rules/test-cmd-util.sh @@ -1224,16 +1224,14 @@ run_kubectl_run_tests() { # Clean up kubectl delete deployment nginx-apps "${kube_flags[@]}" - # TODO: enable batch/v1beta1 by default before 1.8 release, after issues - # with CronJobs existing in multiple versions at once is solved - # # Pre-Condition: no Job exists - # kube::test::get_object_assert cronjobs "{{range.items}}{{$id_field}}:{{end}}" '' - # # Command - # kubectl run pi --schedule="*/5 * * * *" --generator=cronjob/v1beta1 "--image=$IMAGE_PERL" --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(20)' "${kube_flags[@]}" - # # Post-Condition: CronJob "pi" is created - # kube::test::get_object_assert cronjobs "{{range.items}}{{$id_field}}:{{end}}" 'pi:' - # # Clean up - # kubectl delete cronjobs pi "${kube_flags[@]}" + # Pre-Condition: no Job exists + kube::test::get_object_assert cronjob.v1beta1.batch "{{range.items}}{{$id_field}}:{{end}}" '' + # Command + kubectl run pi --schedule="*/5 * * * *" --generator=cronjob/v1beta1 "--image=$IMAGE_PERL" --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(20)' "${kube_flags[@]}" + # Post-Condition: CronJob "pi" is created + kube::test::get_object_assert cronjob.v1beta1.batch "{{range.items}}{{$id_field}}:{{end}}" 'pi:' + # Clean up + kubectl delete cronjob.v1beta1.batch pi "${kube_flags[@]}" set +o nounset set +o errexit diff --git a/pkg/apis/batch/v1beta1/defaults_test.go b/pkg/apis/batch/v1beta1/defaults_test.go index 57f86e1c46..8c23ae1922 100644 --- a/pkg/apis/batch/v1beta1/defaults_test.go +++ b/pkg/apis/batch/v1beta1/defaults_test.go @@ -34,7 +34,7 @@ func TestSetDefaultCronJob(t *testing.T) { original *batchv1beta1.CronJob expected *batchv1beta1.CronJob }{ - "empty batchv2alpha1.CronJob should default batchv2alpha1.ConcurrencyPolicy and Suspend": { + "empty batchv1beta1.CronJob should default batchv1beta1.ConcurrencyPolicy and Suspend": { original: &batchv1beta1.CronJob{}, expected: &batchv1beta1.CronJob{ Spec: batchv1beta1.CronJobSpec{ diff --git a/pkg/controller/cronjob/BUILD b/pkg/controller/cronjob/BUILD index 8a12acd522..3ceb655c3e 100644 --- a/pkg/controller/cronjob/BUILD +++ b/pkg/controller/cronjob/BUILD @@ -20,7 +20,7 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/robfig/cron:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", @@ -50,7 +50,7 @@ go_test( "//pkg/api/install:go_default_library", "//pkg/apis/batch/install:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", diff --git a/pkg/controller/cronjob/cronjob_controller.go b/pkg/controller/cronjob/cronjob_controller.go index ca2b5d2cd3..2ed8ddf6b2 100644 --- a/pkg/controller/cronjob/cronjob_controller.go +++ b/pkg/controller/cronjob/cronjob_controller.go @@ -36,7 +36,7 @@ import ( "github.com/golang/glog" batchv1 "k8s.io/api/batch/v1" - batchv2alpha1 "k8s.io/api/batch/v2alpha1" + batchv1beta1 "k8s.io/api/batch/v1beta1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -56,7 +56,7 @@ import ( // Utilities for dealing with Jobs and CronJobs and time. // controllerKind contains the schema.GroupVersionKind for this controller type. -var controllerKind = batchv2alpha1.SchemeGroupVersion.WithKind("CronJob") +var controllerKind = batchv1beta1.SchemeGroupVersion.WithKind("CronJob") type CronJobController struct { kubeClient clientset.Interface @@ -116,7 +116,7 @@ func (jm *CronJobController) syncAll() { js := jl.Items glog.V(4).Infof("Found %d jobs", len(js)) - sjl, err := jm.kubeClient.BatchV2alpha1().CronJobs(metav1.NamespaceAll).List(metav1.ListOptions{}) + sjl, err := jm.kubeClient.BatchV1beta1().CronJobs(metav1.NamespaceAll).List(metav1.ListOptions{}) if err != nil { utilruntime.HandleError(fmt.Errorf("can't list CronJobs: %v", err)) return @@ -134,7 +134,7 @@ func (jm *CronJobController) syncAll() { } // cleanupFinishedJobs cleanups finished jobs created by a CronJob -func cleanupFinishedJobs(sj *batchv2alpha1.CronJob, js []batchv1.Job, jc jobControlInterface, +func cleanupFinishedJobs(sj *batchv1beta1.CronJob, js []batchv1.Job, jc jobControlInterface, sjc sjControlInterface, pc podControlInterface, recorder record.EventRecorder) { // If neither limits are active, there is no need to do anything. if sj.Spec.FailedJobsHistoryLimit == nil && sj.Spec.SuccessfulJobsHistoryLimit == nil { @@ -179,7 +179,7 @@ func cleanupFinishedJobs(sj *batchv2alpha1.CronJob, js []batchv1.Job, jc jobCont } // removeOldestJobs removes the oldest jobs from a list of jobs -func removeOldestJobs(sj *batchv2alpha1.CronJob, js []batchv1.Job, jc jobControlInterface, +func removeOldestJobs(sj *batchv1beta1.CronJob, js []batchv1.Job, jc jobControlInterface, pc podControlInterface, maxJobs int32, recorder record.EventRecorder) { numToDelete := len(js) - int(maxJobs) if numToDelete <= 0 { @@ -200,7 +200,7 @@ func removeOldestJobs(sj *batchv2alpha1.CronJob, js []batchv1.Job, jc jobControl // All known jobs created by "sj" should be included in "js". // The current time is passed in to facilitate testing. // It has no receiver, to facilitate testing. -func syncOne(sj *batchv2alpha1.CronJob, js []batchv1.Job, now time.Time, jc jobControlInterface, sjc sjControlInterface, pc podControlInterface, recorder record.EventRecorder) { +func syncOne(sj *batchv1beta1.CronJob, js []batchv1.Job, now time.Time, jc jobControlInterface, sjc sjControlInterface, pc podControlInterface, recorder record.EventRecorder) { nameForLog := fmt.Sprintf("%s/%s", sj.Namespace, sj.Name) childrenJobs := make(map[types.UID]bool) @@ -284,7 +284,7 @@ func syncOne(sj *batchv2alpha1.CronJob, js []batchv1.Job, now time.Time, jc jobC // can see easily that there was a missed execution. return } - if sj.Spec.ConcurrencyPolicy == batchv2alpha1.ForbidConcurrent && len(sj.Status.Active) > 0 { + if sj.Spec.ConcurrencyPolicy == batchv1beta1.ForbidConcurrent && len(sj.Status.Active) > 0 { // Regardless which source of information we use for the set of active jobs, // there is some risk that we won't see an active job when there is one. // (because we haven't seen the status update to the SJ or the created pod). @@ -297,7 +297,7 @@ func syncOne(sj *batchv2alpha1.CronJob, js []batchv1.Job, now time.Time, jc jobC glog.V(4).Infof("Not starting job for %s because of prior execution still running and concurrency policy is Forbid", nameForLog) return } - if sj.Spec.ConcurrencyPolicy == batchv2alpha1.ReplaceConcurrent { + if sj.Spec.ConcurrencyPolicy == batchv1beta1.ReplaceConcurrent { for _, j := range sj.Status.Active { // TODO: this should be replaced with server side job deletion // currently this mimics JobReaper from pkg/kubectl/stop.go @@ -353,7 +353,7 @@ func syncOne(sj *batchv2alpha1.CronJob, js []batchv1.Job, now time.Time, jc jobC } // deleteJob reaps a job, deleting the job, the pobs and the reference in the active list -func deleteJob(sj *batchv2alpha1.CronJob, job *batchv1.Job, jc jobControlInterface, +func deleteJob(sj *batchv1beta1.CronJob, job *batchv1.Job, jc jobControlInterface, pc podControlInterface, recorder record.EventRecorder, reason string) bool { // TODO: this should be replaced with server side job deletion // currencontinuetly this mimics JobReaper from pkg/kubectl/stop.go diff --git a/pkg/controller/cronjob/cronjob_controller_test.go b/pkg/controller/cronjob/cronjob_controller_test.go index e5f22cfda0..ec7ead4e78 100644 --- a/pkg/controller/cronjob/cronjob_controller_test.go +++ b/pkg/controller/cronjob/cronjob_controller_test.go @@ -24,7 +24,7 @@ import ( "time" batchv1 "k8s.io/api/batch/v1" - batchv2alpha1 "k8s.io/api/batch/v2alpha1" + batchV1beta1 "k8s.io/api/batch/v1beta1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -96,19 +96,19 @@ func startTimeStringToTime(startTime string) time.Time { } // returns a cronJob with some fields filled in. -func cronJob() batchv2alpha1.CronJob { - return batchv2alpha1.CronJob{ +func cronJob() batchV1beta1.CronJob { + return batchV1beta1.CronJob{ ObjectMeta: metav1.ObjectMeta{ Name: "mycronjob", Namespace: "snazzycats", UID: types.UID("1a2b3c"), - SelfLink: "/apis/batch/v2alpha1/namespaces/snazzycats/cronjobs/mycronjob", + SelfLink: "/apis/batch/v1beta1/namespaces/snazzycats/cronjobs/mycronjob", CreationTimestamp: metav1.Time{Time: justBeforeTheHour()}, }, - Spec: batchv2alpha1.CronJobSpec{ + Spec: batchV1beta1.CronJobSpec{ Schedule: "* * * * ?", - ConcurrencyPolicy: batchv2alpha1.AllowConcurrent, - JobTemplate: batchv2alpha1.JobTemplateSpec{ + ConcurrencyPolicy: batchV1beta1.AllowConcurrent, + JobTemplate: batchV1beta1.JobTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{"a": "b"}, Annotations: map[string]string{"x": "y"}, @@ -152,15 +152,15 @@ func newJob(UID string) batchv1.Job { } var ( - shortDead int64 = 10 - mediumDead int64 = 2 * 60 * 60 - longDead int64 = 1000000 - noDead int64 = -12345 - A batchv2alpha1.ConcurrencyPolicy = batchv2alpha1.AllowConcurrent - f batchv2alpha1.ConcurrencyPolicy = batchv2alpha1.ForbidConcurrent - R batchv2alpha1.ConcurrencyPolicy = batchv2alpha1.ReplaceConcurrent - T bool = true - F bool = false + shortDead int64 = 10 + mediumDead int64 = 2 * 60 * 60 + longDead int64 = 1000000 + noDead int64 = -12345 + A batchV1beta1.ConcurrencyPolicy = batchV1beta1.AllowConcurrent + f batchV1beta1.ConcurrencyPolicy = batchV1beta1.ForbidConcurrent + R batchV1beta1.ConcurrencyPolicy = batchV1beta1.ReplaceConcurrent + T bool = true + F bool = false ) func TestSyncOne_RunOrNot(t *testing.T) { @@ -179,7 +179,7 @@ func TestSyncOne_RunOrNot(t *testing.T) { testCases := map[string]struct { // sj spec - concurrencyPolicy batchv2alpha1.ConcurrencyPolicy + concurrencyPolicy batchV1beta1.ConcurrencyPolicy suspend bool schedule string deadline int64 @@ -298,7 +298,7 @@ func TestSyncOne_RunOrNot(t *testing.T) { if controllerRef == nil { t.Errorf("%s: expected job to have ControllerRef: %#v", name, job) } else { - if got, want := controllerRef.APIVersion, "batch/v2alpha1"; got != want { + if got, want := controllerRef.APIVersion, "batch/v1beta1"; got != want { t.Errorf("%s: controllerRef.APIVersion = %q, want %q", name, got, want) } if got, want := controllerRef.Kind, "CronJob"; got != want { @@ -596,7 +596,7 @@ func TestSyncOne_Status(t *testing.T) { testCases := map[string]struct { // sj spec - concurrencyPolicy batchv2alpha1.ConcurrencyPolicy + concurrencyPolicy batchV1beta1.ConcurrencyPolicy suspend bool schedule string deadline int64 diff --git a/pkg/controller/cronjob/injection.go b/pkg/controller/cronjob/injection.go index 201a2b2554..4756358868 100644 --- a/pkg/controller/cronjob/injection.go +++ b/pkg/controller/cronjob/injection.go @@ -21,7 +21,7 @@ import ( "sync" batchv1 "k8s.io/api/batch/v1" - batchv2alpha1 "k8s.io/api/batch/v2alpha1" + batchv1beta1 "k8s.io/api/batch/v1beta1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -33,7 +33,7 @@ import ( // sjControlInterface is an interface that knows how to update CronJob status // created as an interface to allow testing. type sjControlInterface interface { - UpdateStatus(sj *batchv2alpha1.CronJob) (*batchv2alpha1.CronJob, error) + UpdateStatus(sj *batchv1beta1.CronJob) (*batchv1beta1.CronJob, error) } // realSJControl is the default implementation of sjControlInterface. @@ -43,18 +43,18 @@ type realSJControl struct { var _ sjControlInterface = &realSJControl{} -func (c *realSJControl) UpdateStatus(sj *batchv2alpha1.CronJob) (*batchv2alpha1.CronJob, error) { - return c.KubeClient.BatchV2alpha1().CronJobs(sj.Namespace).UpdateStatus(sj) +func (c *realSJControl) UpdateStatus(sj *batchv1beta1.CronJob) (*batchv1beta1.CronJob, error) { + return c.KubeClient.BatchV1beta1().CronJobs(sj.Namespace).UpdateStatus(sj) } // fakeSJControl is the default implementation of sjControlInterface. type fakeSJControl struct { - Updates []batchv2alpha1.CronJob + Updates []batchv1beta1.CronJob } var _ sjControlInterface = &fakeSJControl{} -func (c *fakeSJControl) UpdateStatus(sj *batchv2alpha1.CronJob) (*batchv2alpha1.CronJob, error) { +func (c *fakeSJControl) UpdateStatus(sj *batchv1beta1.CronJob) (*batchv1beta1.CronJob, error) { c.Updates = append(c.Updates, *sj) return sj, nil } @@ -85,7 +85,7 @@ type realJobControl struct { var _ jobControlInterface = &realJobControl{} -func copyLabels(template *batchv2alpha1.JobTemplateSpec) labels.Set { +func copyLabels(template *batchv1beta1.JobTemplateSpec) labels.Set { l := make(labels.Set) for k, v := range template.Labels { l[k] = v @@ -93,7 +93,7 @@ func copyLabels(template *batchv2alpha1.JobTemplateSpec) labels.Set { return l } -func copyAnnotations(template *batchv2alpha1.JobTemplateSpec) labels.Set { +func copyAnnotations(template *batchv1beta1.JobTemplateSpec) labels.Set { a := make(labels.Set) for k, v := range template.Annotations { a[k] = v diff --git a/pkg/controller/cronjob/utils.go b/pkg/controller/cronjob/utils.go index abee870998..2416dbeb94 100644 --- a/pkg/controller/cronjob/utils.go +++ b/pkg/controller/cronjob/utils.go @@ -24,7 +24,7 @@ import ( "github.com/robfig/cron" batchv1 "k8s.io/api/batch/v1" - batchv2alpha1 "k8s.io/api/batch/v2alpha1" + batchv1beta1 "k8s.io/api/batch/v1beta1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -36,7 +36,7 @@ import ( // Utilities for dealing with Jobs and CronJobs and time. -func inActiveList(sj batchv2alpha1.CronJob, uid types.UID) bool { +func inActiveList(sj batchv1beta1.CronJob, uid types.UID) bool { for _, j := range sj.Status.Active { if j.UID == uid { return true @@ -45,7 +45,7 @@ func inActiveList(sj batchv2alpha1.CronJob, uid types.UID) bool { return false } -func deleteFromActiveList(sj *batchv2alpha1.CronJob, uid types.UID) { +func deleteFromActiveList(sj *batchv1beta1.CronJob, uid types.UID) { if sj == nil { return } @@ -111,7 +111,7 @@ func getNextStartTimeAfter(schedule string, now time.Time) (time.Time, error) { // // If there are too many (>100) unstarted times, just give up and return an empty slice. // If there were missed times prior to the last known start time, then those are not returned. -func getRecentUnmetScheduleTimes(sj batchv2alpha1.CronJob, now time.Time) ([]time.Time, error) { +func getRecentUnmetScheduleTimes(sj batchv1beta1.CronJob, now time.Time) ([]time.Time, error) { starts := []time.Time{} sched, err := cron.ParseStandard(sj.Spec.Schedule) if err != nil { @@ -170,7 +170,7 @@ func getRecentUnmetScheduleTimes(sj batchv2alpha1.CronJob, now time.Time) ([]tim } // getJobFromTemplate makes a Job from a CronJob -func getJobFromTemplate(sj *batchv2alpha1.CronJob, scheduledTime time.Time) (*batchv1.Job, error) { +func getJobFromTemplate(sj *batchv1beta1.CronJob, scheduledTime time.Time) (*batchv1.Job, error) { // TODO: consider adding the following labels: // nominal-start-time=$RFC_3339_DATE_OF_INTENDED_START -- for user convenience // scheduled-job-name=$SJ_NAME -- for user convenience diff --git a/pkg/controller/cronjob/utils_test.go b/pkg/controller/cronjob/utils_test.go index 9bd9f3aa33..dbb1512121 100644 --- a/pkg/controller/cronjob/utils_test.go +++ b/pkg/controller/cronjob/utils_test.go @@ -22,7 +22,7 @@ import ( "time" batchv1 "k8s.io/api/batch/v1" - batchv2alpha1 "k8s.io/api/batch/v2alpha1" + batchv1beta1 "k8s.io/api/batch/v1beta1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -37,17 +37,17 @@ func TestGetJobFromTemplate(t *testing.T) { var one int64 = 1 var no bool = false - sj := batchv2alpha1.CronJob{ + sj := batchv1beta1.CronJob{ ObjectMeta: metav1.ObjectMeta{ Name: "mycronjob", Namespace: "snazzycats", UID: types.UID("1a2b3c"), SelfLink: "/apis/batch/v1/namespaces/snazzycats/jobs/mycronjob", }, - Spec: batchv2alpha1.CronJobSpec{ + Spec: batchv1beta1.CronJobSpec{ Schedule: "* * * * ?", - ConcurrencyPolicy: batchv2alpha1.AllowConcurrent, - JobTemplate: batchv2alpha1.JobTemplateSpec{ + ConcurrencyPolicy: batchv1beta1.AllowConcurrent, + JobTemplate: batchv1beta1.JobTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{"a": "b"}, Annotations: map[string]string{"x": "y"}, @@ -267,16 +267,16 @@ func TestGetRecentUnmetScheduleTimes(t *testing.T) { t.Errorf("test setup error: %v", err) } - sj := batchv2alpha1.CronJob{ + sj := batchv1beta1.CronJob{ ObjectMeta: metav1.ObjectMeta{ Name: "mycronjob", Namespace: metav1.NamespaceDefault, UID: types.UID("1a2b3c"), }, - Spec: batchv2alpha1.CronJobSpec{ + Spec: batchv1beta1.CronJobSpec{ Schedule: schedule, - ConcurrencyPolicy: batchv2alpha1.AllowConcurrent, - JobTemplate: batchv2alpha1.JobTemplateSpec{}, + ConcurrencyPolicy: batchv1beta1.AllowConcurrent, + JobTemplate: batchv1beta1.JobTemplateSpec{}, }, } { diff --git a/pkg/kubectl/BUILD b/pkg/kubectl/BUILD index 48ab26973d..12888490be 100644 --- a/pkg/kubectl/BUILD +++ b/pkg/kubectl/BUILD @@ -51,6 +51,7 @@ go_test( "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", @@ -142,6 +143,7 @@ go_library( "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", diff --git a/pkg/kubectl/cmd/BUILD b/pkg/kubectl/cmd/BUILD index 36b2f64f7e..c9d981029d 100644 --- a/pkg/kubectl/cmd/BUILD +++ b/pkg/kubectl/cmd/BUILD @@ -108,6 +108,7 @@ go_library( "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index d9811bd8a7..ae705796d8 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -24,6 +24,7 @@ import ( "github.com/spf13/cobra" batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" batchv2alpha1 "k8s.io/api/batch/v2alpha1" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/errors" @@ -225,7 +226,11 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c generatorName := cmdutil.GetFlagString(cmd, "generator") schedule := cmdutil.GetFlagString(cmd, "schedule") if len(schedule) != 0 && len(generatorName) == 0 { - generatorName = cmdutil.CronJobV2Alpha1GeneratorName + if contains(resourcesList, batchv1beta1.SchemeGroupVersion.WithResource("cronjobs")) { + generatorName = cmdutil.CronJobV1Beta1GeneratorName + } else { + generatorName = cmdutil.CronJobV2Alpha1GeneratorName + } } if len(generatorName) == 0 { switch restartPolicy { diff --git a/pkg/kubectl/cmd/util/factory_client_access.go b/pkg/kubectl/cmd/util/factory_client_access.go index e71a5a2571..8ac2369737 100644 --- a/pkg/kubectl/cmd/util/factory_client_access.go +++ b/pkg/kubectl/cmd/util/factory_client_access.go @@ -479,6 +479,7 @@ const ( DeploymentBasicAppsV1Beta1GeneratorName = "deployment-basic/apps.v1beta1" JobV1GeneratorName = "job/v1" CronJobV2Alpha1GeneratorName = "cronjob/v2alpha1" + CronJobV1Beta1GeneratorName = "cronjob/v1beta1" NamespaceV1GeneratorName = "namespace/v1" ResourceQuotaV1GeneratorName = "resourcequotas/v1" SecretV1GeneratorName = "secret/v1" @@ -528,6 +529,7 @@ func DefaultGenerators(cmdName string) map[string]kubectl.Generator { DeploymentAppsV1Beta1GeneratorName: kubectl.DeploymentAppsV1Beta1{}, JobV1GeneratorName: kubectl.JobV1{}, CronJobV2Alpha1GeneratorName: kubectl.CronJobV2Alpha1{}, + CronJobV1Beta1GeneratorName: kubectl.CronJobV1Beta1{}, } case "autoscale": generator = map[string]kubectl.Generator{ diff --git a/pkg/kubectl/run.go b/pkg/kubectl/run.go index dbf9ba7d0c..7dd77f1f39 100644 --- a/pkg/kubectl/run.go +++ b/pkg/kubectl/run.go @@ -23,6 +23,7 @@ import ( appsv1beta1 "k8s.io/api/apps/v1beta1" batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" batchv2alpha1 "k8s.io/api/batch/v2alpha1" "k8s.io/api/core/v1" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" @@ -483,6 +484,107 @@ func (CronJobV2Alpha1) Generate(genericParams map[string]interface{}) (runtime.O return &cronJob, nil } +type CronJobV1Beta1 struct{} + +func (CronJobV1Beta1) ParamNames() []GeneratorParam { + return []GeneratorParam{ + {"labels", false}, + {"default-name", false}, + {"name", true}, + {"image", true}, + {"image-pull-policy", false}, + {"port", false}, + {"hostport", false}, + {"stdin", false}, + {"leave-stdin-open", false}, + {"tty", false}, + {"command", false}, + {"args", false}, + {"env", false}, + {"requests", false}, + {"limits", false}, + {"restart", false}, + {"schedule", true}, + {"serviceaccount", false}, + } +} + +func (CronJobV1Beta1) Generate(genericParams map[string]interface{}) (runtime.Object, error) { + args, err := getArgs(genericParams) + if err != nil { + return nil, err + } + + envs, err := getEnvs(genericParams) + if err != nil { + return nil, err + } + + params, err := getParams(genericParams) + if err != nil { + return nil, err + } + + name, err := getName(params) + if err != nil { + return nil, err + } + + labels, err := getLabels(params, name) + if err != nil { + return nil, err + } + + podSpec, err := makePodSpec(params, name) + if err != nil { + return nil, err + } + + imagePullPolicy := v1.PullPolicy(params["image-pull-policy"]) + if err = updatePodContainers(params, args, envs, imagePullPolicy, podSpec); err != nil { + return nil, err + } + + leaveStdinOpen, err := GetBool(params, "leave-stdin-open", false) + if err != nil { + return nil, err + } + podSpec.Containers[0].StdinOnce = !leaveStdinOpen && podSpec.Containers[0].Stdin + + if err := updatePodPorts(params, podSpec); err != nil { + return nil, err + } + + restartPolicy := v1.RestartPolicy(params["restart"]) + if len(restartPolicy) == 0 { + restartPolicy = v1.RestartPolicyNever + } + podSpec.RestartPolicy = restartPolicy + + cronJob := batchv1beta1.CronJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Labels: labels, + }, + Spec: batchv1beta1.CronJobSpec{ + Schedule: params["schedule"], + ConcurrencyPolicy: batchv1beta1.AllowConcurrent, + JobTemplate: batchv1beta1.JobTemplateSpec{ + Spec: batchv1.JobSpec{ + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: labels, + }, + Spec: *podSpec, + }, + }, + }, + }, + } + + return &cronJob, nil +} + type BasicReplicationController struct{} func (BasicReplicationController) ParamNames() []GeneratorParam { diff --git a/pkg/kubectl/run_test.go b/pkg/kubectl/run_test.go index 114550ff3b..f2f217e486 100644 --- a/pkg/kubectl/run_test.go +++ b/pkg/kubectl/run_test.go @@ -22,6 +22,7 @@ import ( appsv1beta1 "k8s.io/api/apps/v1beta1" batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" batchv2alpha1 "k8s.io/api/batch/v2alpha1" "k8s.io/api/core/v1" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" @@ -922,7 +923,7 @@ func TestGenerateJob(t *testing.T) { } } -func TestGenerateCronJob(t *testing.T) { +func TestGenerateCronJobAlpha(t *testing.T) { tests := []struct { params map[string]interface{} expected *batchv2alpha1.CronJob @@ -1020,6 +1021,104 @@ func TestGenerateCronJob(t *testing.T) { } } +func TestGenerateCronJobBeta(t *testing.T) { + tests := []struct { + params map[string]interface{} + expected *batchv1beta1.CronJob + expectErr bool + }{ + { + params: map[string]interface{}{ + "labels": "foo=bar,baz=blah", + "name": "foo", + "image": "someimage", + "port": "80", + "hostport": "80", + "stdin": "true", + "leave-stdin-open": "true", + "command": "true", + "args": []string{"bar", "baz", "blah"}, + "env": []string{"a=b", "c=d"}, + "requests": "cpu=100m,memory=100Mi", + "limits": "cpu=400m,memory=200Mi", + "restart": "OnFailure", + "schedule": "0/5 * * * ?", + }, + expected: &batchv1beta1.CronJob{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Labels: map[string]string{"foo": "bar", "baz": "blah"}, + }, + Spec: batchv1beta1.CronJobSpec{ + Schedule: "0/5 * * * ?", + ConcurrencyPolicy: batchv1beta1.AllowConcurrent, + JobTemplate: batchv1beta1.JobTemplateSpec{ + Spec: batchv1.JobSpec{ + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{"foo": "bar", "baz": "blah"}, + }, + Spec: v1.PodSpec{ + RestartPolicy: v1.RestartPolicyOnFailure, + Containers: []v1.Container{ + { + Name: "foo", + Image: "someimage", + Stdin: true, + StdinOnce: false, + Ports: []v1.ContainerPort{ + { + ContainerPort: 80, + HostPort: 80, + }, + }, + Command: []string{"bar", "baz", "blah"}, + Env: []v1.EnvVar{ + { + Name: "a", + Value: "b", + }, + { + Name: "c", + Value: "d", + }, + }, + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("100m"), + v1.ResourceMemory: resource.MustParse("100Mi"), + }, + Limits: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("400m"), + v1.ResourceMemory: resource.MustParse("200Mi"), + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + generator := CronJobV1Beta1{} + for _, test := range tests { + obj, err := generator.Generate(test.params) + if !test.expectErr && err != nil { + t.Errorf("unexpected error: %v", err) + } + if test.expectErr && err != nil { + continue + } + if !reflect.DeepEqual(obj.(*batchv1beta1.CronJob), test.expected) { + t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*batchv1beta1.CronJob)) + } + } +} + func TestParseEnv(t *testing.T) { tests := []struct { envArray []string diff --git a/pkg/master/BUILD b/pkg/master/BUILD index 77811ad284..4d900c9451 100644 --- a/pkg/master/BUILD +++ b/pkg/master/BUILD @@ -73,6 +73,7 @@ go_library( "//vendor/k8s.io/api/authorization/v1beta1:go_default_library", "//vendor/k8s.io/api/autoscaling/v1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", @@ -134,7 +135,7 @@ go_test( "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/autoscaling/v1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", diff --git a/pkg/master/master.go b/pkg/master/master.go index d6f7130a07..33e99e719b 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -32,6 +32,7 @@ import ( authorizationapiv1beta1 "k8s.io/api/authorization/v1beta1" autoscalingapiv1 "k8s.io/api/autoscaling/v1" batchapiv1 "k8s.io/api/batch/v1" + batchapiv1beta1 "k8s.io/api/batch/v1beta1" certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1" apiv1 "k8s.io/api/core/v1" extensionsapiv1beta1 "k8s.io/api/extensions/v1beta1" @@ -381,9 +382,7 @@ func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig { apiv1.SchemeGroupVersion, extensionsapiv1beta1.SchemeGroupVersion, batchapiv1.SchemeGroupVersion, - // TODO: enable batch/v1beta1 by default before 1.8 release, after issues - // with CronJobs existing in multiple versions at once is solved - // batchapiv1beta1.SchemeGroupVersion, + batchapiv1beta1.SchemeGroupVersion, authenticationv1.SchemeGroupVersion, authenticationv1beta1.SchemeGroupVersion, autoscalingapiv1.SchemeGroupVersion, diff --git a/pkg/master/master_test.go b/pkg/master/master_test.go index 44a0cffe04..8c3bc7ca89 100644 --- a/pkg/master/master_test.go +++ b/pkg/master/master_test.go @@ -29,7 +29,7 @@ import ( appsapiv1beta1 "k8s.io/api/apps/v1beta1" autoscalingapiv1 "k8s.io/api/autoscaling/v1" batchapiv1 "k8s.io/api/batch/v1" - batchapiv2alpha1 "k8s.io/api/batch/v2alpha1" + batchapiv1beta1 "k8s.io/api/batch/v1beta1" certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1" apiv1 "k8s.io/api/core/v1" extensionsapiv1beta1 "k8s.io/api/extensions/v1beta1" @@ -80,6 +80,8 @@ func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, *assert.Assertion resourceEncoding.SetVersionEncoding(api.GroupName, api.Registry.GroupOrDie(api.GroupName).GroupVersion, schema.GroupVersion{Group: api.GroupName, Version: runtime.APIVersionInternal}) resourceEncoding.SetVersionEncoding(autoscaling.GroupName, *testapi.Autoscaling.GroupVersion(), schema.GroupVersion{Group: autoscaling.GroupName, Version: runtime.APIVersionInternal}) resourceEncoding.SetVersionEncoding(batch.GroupName, *testapi.Batch.GroupVersion(), schema.GroupVersion{Group: batch.GroupName, Version: runtime.APIVersionInternal}) + // FIXME (soltysh): this GroupVersionResource override should be configurable + resourceEncoding.SetResourceEncoding(schema.GroupResource{Group: "batch", Resource: "cronjobs"}, schema.GroupVersion{Group: batch.GroupName, Version: "v1beta1"}, schema.GroupVersion{Group: batch.GroupName, Version: runtime.APIVersionInternal}) resourceEncoding.SetVersionEncoding(apps.GroupName, *testapi.Apps.GroupVersion(), schema.GroupVersion{Group: apps.GroupName, Version: runtime.APIVersionInternal}) resourceEncoding.SetVersionEncoding(extensions.GroupName, *testapi.Extensions.GroupVersion(), schema.GroupVersion{Group: extensions.GroupName, Version: runtime.APIVersionInternal}) resourceEncoding.SetVersionEncoding(rbac.GroupName, *testapi.Rbac.GroupVersion(), schema.GroupVersion{Group: rbac.GroupName, Version: runtime.APIVersionInternal}) @@ -193,7 +195,7 @@ func limitedAPIResourceConfigSource() *serverstorage.ResourceConfig { apiv1.SchemeGroupVersion, extensionsapiv1beta1.SchemeGroupVersion, batchapiv1.SchemeGroupVersion, - batchapiv2alpha1.SchemeGroupVersion, + batchapiv1beta1.SchemeGroupVersion, appsapiv1beta1.SchemeGroupVersion, autoscalingapiv1.SchemeGroupVersion, ) diff --git a/pkg/printers/internalversion/BUILD b/pkg/printers/internalversion/BUILD index fa0ad5d66b..874559afa9 100644 --- a/pkg/printers/internalversion/BUILD +++ b/pkg/printers/internalversion/BUILD @@ -88,7 +88,7 @@ go_library( "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/autoscaling/v2alpha1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/certificates/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index 5283c82d80..5a6aa5b10e 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -29,7 +29,7 @@ import ( appsv1beta1 "k8s.io/api/apps/v1beta1" autoscalingv2alpha1 "k8s.io/api/autoscaling/v2alpha1" batchv1 "k8s.io/api/batch/v1" - batchv2alpha1 "k8s.io/api/batch/v2alpha1" + batchv1beta1 "k8s.io/api/batch/v1beta1" certificatesv1beta1 "k8s.io/api/certificates/v1beta1" apiv1 "k8s.io/api/core/v1" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" @@ -160,10 +160,10 @@ func AddHandlers(h printers.PrintHandler) { cronJobColumnDefinitions := []metav1alpha1.TableColumnDefinition{ {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, - {Name: "Schedule", Type: "string", Description: batchv2alpha1.CronJobSpec{}.SwaggerDoc()["schedule"]}, - {Name: "Suspend", Type: "boolean", Description: batchv2alpha1.CronJobSpec{}.SwaggerDoc()["suspend"]}, - {Name: "Active", Type: "integer", Description: batchv2alpha1.CronJobStatus{}.SwaggerDoc()["active"]}, - {Name: "Last Schedule", Type: "string", Description: batchv2alpha1.CronJobStatus{}.SwaggerDoc()["lastScheduleTime"]}, + {Name: "Schedule", Type: "string", Description: batchv1beta1.CronJobSpec{}.SwaggerDoc()["schedule"]}, + {Name: "Suspend", Type: "boolean", Description: batchv1beta1.CronJobSpec{}.SwaggerDoc()["suspend"]}, + {Name: "Active", Type: "integer", Description: batchv1beta1.CronJobStatus{}.SwaggerDoc()["active"]}, + {Name: "Last Schedule", Type: "string", Description: batchv1beta1.CronJobStatus{}.SwaggerDoc()["lastScheduleTime"]}, {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, {Name: "Containers", Type: "string", Priority: 1, Description: "Names of each container in the template."}, {Name: "Images", Type: "string", Priority: 1, Description: "Images referenced by each container in the template."}, diff --git a/test/e2e/apimachinery/BUILD b/test/e2e/apimachinery/BUILD index 96bb4738f9..7846f980ae 100644 --- a/test/e2e/apimachinery/BUILD +++ b/test/e2e/apimachinery/BUILD @@ -32,7 +32,7 @@ go_library( "//vendor/github.com/onsi/gomega:go_default_library", "//vendor/k8s.io/api/admissionregistration/v1alpha1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/api/rbac/v1beta1:go_default_library", diff --git a/test/e2e/apimachinery/garbage_collector.go b/test/e2e/apimachinery/garbage_collector.go index b9dedf9353..05c54eed62 100644 --- a/test/e2e/apimachinery/garbage_collector.go +++ b/test/e2e/apimachinery/garbage_collector.go @@ -21,7 +21,7 @@ import ( "time" batchv1 "k8s.io/api/batch/v1" - batchv2alpha1 "k8s.io/api/batch/v2alpha1" + batchv1beta1 "k8s.io/api/batch/v1beta1" "k8s.io/api/core/v1" "k8s.io/api/extensions/v1beta1" apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" @@ -66,7 +66,7 @@ func getNonOrphanOptions() *metav1.DeleteOptions { var ( zero = int64(0) - CronJobGroupVersionResource = schema.GroupVersionResource{Group: batchv2alpha1.GroupName, Version: "v2alpha1", Resource: "cronjobs"} + CronJobGroupVersionResource = schema.GroupVersionResource{Group: batchv1beta1.GroupName, Version: "v1beta1", Resource: "cronjobs"} ) func getPodTemplateSpec(labels map[string]string) v1.PodTemplateSpec { @@ -264,19 +264,19 @@ func gatherMetrics(f *framework.Framework) { } } -func newCronJob(name, schedule string) *batchv2alpha1.CronJob { +func newCronJob(name, schedule string) *batchv1beta1.CronJob { parallelism := int32(1) completions := int32(1) - return &batchv2alpha1.CronJob{ + return &batchv1beta1.CronJob{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, TypeMeta: metav1.TypeMeta{ Kind: "CronJob", }, - Spec: batchv2alpha1.CronJobSpec{ + Spec: batchv1beta1.CronJobSpec{ Schedule: schedule, - JobTemplate: batchv2alpha1.JobTemplateSpec{ + JobTemplate: batchv1beta1.JobTemplateSpec{ Spec: batchv1.JobSpec{ Parallelism: ¶llelism, Completions: &completions, @@ -940,7 +940,7 @@ var _ = SIGDescribe("Garbage collector", func() { By("Create the cronjob") cronJob := newCronJob("simple", "*/1 * * * ?") - cronJob, err := f.ClientSet.BatchV2alpha1().CronJobs(f.Namespace.Name).Create(cronJob) + cronJob, err := f.ClientSet.BatchV1beta1().CronJobs(f.Namespace.Name).Create(cronJob) Expect(err).NotTo(HaveOccurred()) By("Wait for the CronJob to create new Job") diff --git a/test/e2e/apimachinery/generated_clientset.go b/test/e2e/apimachinery/generated_clientset.go index f5ac6b42db..b3ef079b90 100644 --- a/test/e2e/apimachinery/generated_clientset.go +++ b/test/e2e/apimachinery/generated_clientset.go @@ -21,7 +21,7 @@ import ( "time" batchv1 "k8s.io/api/batch/v1" - batchv2alpha1 "k8s.io/api/batch/v2alpha1" + batchv1beta1 "k8s.io/api/batch/v1beta1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -212,20 +212,20 @@ var _ = SIGDescribe("Generated release_1_5 clientset", func() { }) }) -func newTestingCronJob(name string, value string) *batchv2alpha1.CronJob { +func newTestingCronJob(name string, value string) *batchv1beta1.CronJob { parallelism := int32(1) completions := int32(1) - return &batchv2alpha1.CronJob{ + return &batchv1beta1.CronJob{ ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: map[string]string{ "time": value, }, }, - Spec: batchv2alpha1.CronJobSpec{ + Spec: batchv1beta1.CronJobSpec{ Schedule: "*/1 * * * ?", - ConcurrencyPolicy: batchv2alpha1.AllowConcurrent, - JobTemplate: batchv2alpha1.JobTemplateSpec{ + ConcurrencyPolicy: batchv1beta1.AllowConcurrent, + JobTemplate: batchv1beta1.JobTemplateSpec{ Spec: batchv1.JobSpec{ Parallelism: ¶llelism, Completions: &completions, @@ -262,25 +262,13 @@ func newTestingCronJob(name string, value string) *batchv2alpha1.CronJob { var _ = SIGDescribe("Generated release_1_5 clientset", func() { f := framework.NewDefaultFramework("clientset") - It("should create v2alpha1 cronJobs, delete cronJobs, watch cronJobs", func() { - var enabled bool - groupList, err := f.ClientSet.Discovery().ServerGroups() - framework.ExpectNoError(err) - for _, group := range groupList.Groups { - if group.Name == batchv2alpha1.GroupName { - for _, version := range group.Versions { - if version.Version == batchv2alpha1.SchemeGroupVersion.Version { - enabled = true - break - } - } - } - } - if !enabled { - framework.Logf("%s is not enabled, test skipped", batchv2alpha1.SchemeGroupVersion) - return - } - cronJobClient := f.ClientSet.BatchV2alpha1().CronJobs(f.Namespace.Name) + + BeforeEach(func() { + framework.SkipIfMissingResource(f.ClientPool, CronJobGroupVersionResource, f.Namespace.Name) + }) + + It("should create v1beta1 cronJobs, delete cronJobs, watch cronJobs", func() { + cronJobClient := f.ClientSet.BatchV1beta1().CronJobs(f.Namespace.Name) By("constructing the cronJob") name := "cronjob" + string(uuid.NewUUID()) value := strconv.Itoa(time.Now().Nanosecond()) diff --git a/test/e2e/apps/BUILD b/test/e2e/apps/BUILD index 864e878a98..ac45d47022 100644 --- a/test/e2e/apps/BUILD +++ b/test/e2e/apps/BUILD @@ -24,7 +24,6 @@ go_library( "//pkg/api:go_default_library", "//pkg/api/v1/pod:go_default_library", "//pkg/apis/batch:go_default_library", - "//pkg/apis/batch/v2alpha1:go_default_library", "//pkg/apis/extensions:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/controller:go_default_library", @@ -45,7 +44,7 @@ go_library( "//vendor/k8s.io/api/apps/v1beta1:go_default_library", "//vendor/k8s.io/api/apps/v1beta2:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library", - "//vendor/k8s.io/api/batch/v2alpha1:go_default_library", + "//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/api/policy/v1beta1:go_default_library", diff --git a/test/e2e/apps/cronjob.go b/test/e2e/apps/cronjob.go index 3d8f70e35d..ef9835fba3 100644 --- a/test/e2e/apps/cronjob.go +++ b/test/e2e/apps/cronjob.go @@ -24,7 +24,7 @@ import ( . "github.com/onsi/gomega" batchv1 "k8s.io/api/batch/v1" - batchv2alpha1 "k8s.io/api/batch/v2alpha1" + batchv1beta1 "k8s.io/api/batch/v1beta1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -51,13 +51,13 @@ var _ = SIGDescribe("CronJob", func() { successCommand := []string{"/bin/true"} BeforeEach(func() { - framework.SkipIfMissingResource(f.ClientPool, CronJobGroupVersionResource, f.Namespace.Name) + framework.SkipIfMissingResource(f.ClientPool, CronJobGroupVersionResourceBeta, f.Namespace.Name) }) // multiple jobs running at once It("should schedule multiple jobs concurrently", func() { By("Creating a cronjob") - cronJob := newTestCronJob("concurrent", "*/1 * * * ?", batchv2alpha1.AllowConcurrent, + cronJob := newTestCronJob("concurrent", "*/1 * * * ?", batchv1beta1.AllowConcurrent, sleepCommand, nil) cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob) Expect(err).NotTo(HaveOccurred()) @@ -80,7 +80,7 @@ var _ = SIGDescribe("CronJob", func() { // suspended should not schedule jobs It("should not schedule jobs when suspended [Slow]", func() { By("Creating a suspended cronjob") - cronJob := newTestCronJob("suspended", "*/1 * * * ?", batchv2alpha1.AllowConcurrent, + cronJob := newTestCronJob("suspended", "*/1 * * * ?", batchv1beta1.AllowConcurrent, sleepCommand, nil) t := true cronJob.Spec.Suspend = &t @@ -104,7 +104,7 @@ var _ = SIGDescribe("CronJob", func() { // only single active job is allowed for ForbidConcurrent It("should not schedule new jobs when ForbidConcurrent [Slow]", func() { By("Creating a ForbidConcurrent cronjob") - cronJob := newTestCronJob("forbid", "*/1 * * * ?", batchv2alpha1.ForbidConcurrent, + cronJob := newTestCronJob("forbid", "*/1 * * * ?", batchv1beta1.ForbidConcurrent, sleepCommand, nil) cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob) Expect(err).NotTo(HaveOccurred()) @@ -136,7 +136,7 @@ var _ = SIGDescribe("CronJob", func() { // only single active job is allowed for ReplaceConcurrent It("should replace jobs when ReplaceConcurrent", func() { By("Creating a ReplaceConcurrent cronjob") - cronJob := newTestCronJob("replace", "*/1 * * * ?", batchv2alpha1.ReplaceConcurrent, + cronJob := newTestCronJob("replace", "*/1 * * * ?", batchv1beta1.ReplaceConcurrent, sleepCommand, nil) cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob) Expect(err).NotTo(HaveOccurred()) @@ -168,7 +168,7 @@ var _ = SIGDescribe("CronJob", func() { // shouldn't give us unexpected warnings It("should not emit unexpected warnings", func() { By("Creating a cronjob") - cronJob := newTestCronJob("concurrent", "*/1 * * * ?", batchv2alpha1.AllowConcurrent, + cronJob := newTestCronJob("concurrent", "*/1 * * * ?", batchv1beta1.AllowConcurrent, nil, nil) cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob) Expect(err).NotTo(HaveOccurred()) @@ -191,7 +191,7 @@ var _ = SIGDescribe("CronJob", func() { // deleted jobs should be removed from the active list It("should remove from active list jobs that have been deleted", func() { By("Creating a ForbidConcurrent cronjob") - cronJob := newTestCronJob("forbid", "*/1 * * * ?", batchv2alpha1.ForbidConcurrent, + cronJob := newTestCronJob("forbid", "*/1 * * * ?", batchv1beta1.ForbidConcurrent, sleepCommand, nil) cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob) Expect(err).NotTo(HaveOccurred()) @@ -235,7 +235,7 @@ var _ = SIGDescribe("CronJob", func() { It("should delete successful finished jobs with limit of one successful job", func() { By("Creating a AllowConcurrent cronjob with custom history limits") successLimit := int32(1) - cronJob := newTestCronJob("concurrent-limit", "*/1 * * * ?", batchv2alpha1.AllowConcurrent, + cronJob := newTestCronJob("concurrent-limit", "*/1 * * * ?", batchv1beta1.AllowConcurrent, successCommand, &successLimit) cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob) Expect(err).NotTo(HaveOccurred()) @@ -271,21 +271,21 @@ var _ = SIGDescribe("CronJob", func() { }) // newTestCronJob returns a cronjob which does one of several testing behaviors. -func newTestCronJob(name, schedule string, concurrencyPolicy batchv2alpha1.ConcurrencyPolicy, - command []string, successfulJobsHistoryLimit *int32) *batchv2alpha1.CronJob { +func newTestCronJob(name, schedule string, concurrencyPolicy batchv1beta1.ConcurrencyPolicy, + command []string, successfulJobsHistoryLimit *int32) *batchv1beta1.CronJob { parallelism := int32(1) completions := int32(1) - sj := &batchv2alpha1.CronJob{ + sj := &batchv1beta1.CronJob{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, TypeMeta: metav1.TypeMeta{ Kind: "CronJob", }, - Spec: batchv2alpha1.CronJobSpec{ + Spec: batchv1beta1.CronJobSpec{ Schedule: schedule, ConcurrencyPolicy: concurrencyPolicy, - JobTemplate: batchv2alpha1.JobTemplateSpec{ + JobTemplate: batchv1beta1.JobTemplateSpec{ Spec: batchv1.JobSpec{ Parallelism: ¶llelism, Completions: &completions, @@ -325,22 +325,22 @@ func newTestCronJob(name, schedule string, concurrencyPolicy batchv2alpha1.Concu return sj } -func createCronJob(c clientset.Interface, ns string, cronJob *batchv2alpha1.CronJob) (*batchv2alpha1.CronJob, error) { - return c.BatchV2alpha1().CronJobs(ns).Create(cronJob) +func createCronJob(c clientset.Interface, ns string, cronJob *batchv1beta1.CronJob) (*batchv1beta1.CronJob, error) { + return c.BatchV1beta1().CronJobs(ns).Create(cronJob) } -func getCronJob(c clientset.Interface, ns, name string) (*batchv2alpha1.CronJob, error) { - return c.BatchV2alpha1().CronJobs(ns).Get(name, metav1.GetOptions{}) +func getCronJob(c clientset.Interface, ns, name string) (*batchv1beta1.CronJob, error) { + return c.BatchV1beta1().CronJobs(ns).Get(name, metav1.GetOptions{}) } func deleteCronJob(c clientset.Interface, ns, name string) error { - return c.BatchV2alpha1().CronJobs(ns).Delete(name, nil) + return c.BatchV1beta1().CronJobs(ns).Delete(name, nil) } // Wait for at least given amount of active jobs. func waitForActiveJobs(c clientset.Interface, ns, cronJobName string, active int) error { return wait.Poll(framework.Poll, cronJobTimeout, func() (bool, error) { - curr, err := c.BatchV2alpha1().CronJobs(ns).Get(cronJobName, metav1.GetOptions{}) + curr, err := c.BatchV1beta1().CronJobs(ns).Get(cronJobName, metav1.GetOptions{}) if err != nil { return false, err } @@ -354,7 +354,7 @@ func waitForActiveJobs(c clientset.Interface, ns, cronJobName string, active int // empty after the timeout. func waitForNoJobs(c clientset.Interface, ns, jobName string, failIfNonEmpty bool) error { return wait.Poll(framework.Poll, cronJobTimeout, func() (bool, error) { - curr, err := c.BatchV2alpha1().CronJobs(ns).Get(jobName, metav1.GetOptions{}) + curr, err := c.BatchV1beta1().CronJobs(ns).Get(jobName, metav1.GetOptions{}) if err != nil { return false, err } @@ -432,7 +432,7 @@ func waitForAnyFinishedJob(c clientset.Interface, ns string) error { // checkNoEventWithReason checks no events with a reason within a list has occured func checkNoEventWithReason(c clientset.Interface, ns, cronJobName string, reasons []string) error { - sj, err := c.BatchV2alpha1().CronJobs(ns).Get(cronJobName, metav1.GetOptions{}) + sj, err := c.BatchV1beta1().CronJobs(ns).Get(cronJobName, metav1.GetOptions{}) if err != nil { return fmt.Errorf("Error in getting cronjob %s/%s: %v", ns, cronJobName, err) } diff --git a/test/e2e/apps/types.go b/test/e2e/apps/types.go index 2f875e947a..443f34e1c6 100644 --- a/test/e2e/apps/types.go +++ b/test/e2e/apps/types.go @@ -18,7 +18,6 @@ package apps import ( "k8s.io/apimachinery/pkg/runtime/schema" - batchv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1" ) const ( @@ -32,5 +31,6 @@ const ( ) var ( - CronJobGroupVersionResource = schema.GroupVersionResource{Group: batchv2alpha1.GroupName, Version: "v2alpha1", Resource: "cronjobs"} + CronJobGroupVersionResourceAlpha = schema.GroupVersionResource{Group: "batch", Version: "v2alpha1", Resource: "cronjobs"} + CronJobGroupVersionResourceBeta = schema.GroupVersionResource{Group: "batch", Version: "v1beta1", Resource: "cronjobs"} ) diff --git a/test/e2e/kubectl/BUILD b/test/e2e/kubectl/BUILD index 58c5ef9c92..44a777ef28 100644 --- a/test/e2e/kubectl/BUILD +++ b/test/e2e/kubectl/BUILD @@ -13,7 +13,6 @@ go_library( "portforward.go", ], deps = [ - "//pkg/apis/batch/v2alpha1:go_default_library", "//pkg/controller:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/util/version:go_default_library", diff --git a/test/e2e/kubectl/kubectl.go b/test/e2e/kubectl/kubectl.go index bfd4869868..19ab8c848c 100644 --- a/test/e2e/kubectl/kubectl.go +++ b/test/e2e/kubectl/kubectl.go @@ -56,7 +56,6 @@ import ( "k8s.io/apiserver/pkg/authentication/serviceaccount" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" clientset "k8s.io/client-go/kubernetes" - batchv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/kubectl/cmd/util" utilversion "k8s.io/kubernetes/pkg/util/version" @@ -145,7 +144,8 @@ var ( // so we don't expect tests that verifies return code to work on kubectl clients before that. kubectlContainerExitCodeVersion = utilversion.MustParseSemantic("v1.4.0-alpha.3") - CronJobGroupVersionResource = schema.GroupVersionResource{Group: batchv2alpha1.GroupName, Version: "v2alpha1", Resource: "cronjobs"} + CronJobGroupVersionResourceAlpha = schema.GroupVersionResource{Group: "batch", Version: "v2alpha1", Resource: "cronjobs"} + CronJobGroupVersionResourceBeta = schema.GroupVersionResource{Group: "batch", Version: "v1beta1", Resource: "cronjobs"} ) // Stops everything from filePath from namespace ns and checks if everything matching selectors from the given namespace is correctly stopped. @@ -203,15 +203,15 @@ var _ = SIGDescribe("Kubectl alpha client", func() { BeforeEach(func() { nsFlag = fmt.Sprintf("--namespace=%v", ns) - cjName = "e2e-test-echo-cronjob" + cjName = "e2e-test-echo-cronjob-alpha" }) AfterEach(func() { - framework.RunKubectlOrDie("delete", "cronjobs", cjName, nsFlag) + framework.RunKubectlOrDie("delete", "cronjob.v2alpha1.batch", cjName, nsFlag) }) It("should create a CronJob", func() { - framework.SkipIfMissingResource(f.ClientPool, CronJobGroupVersionResource, f.Namespace.Name) + framework.SkipIfMissingResource(f.ClientPool, CronJobGroupVersionResourceAlpha, f.Namespace.Name) schedule := "*/5 * * * ?" framework.RunKubectlOrDie("run", cjName, "--restart=OnFailure", "--generator=cronjob/v2alpha1", @@ -1349,6 +1349,43 @@ metadata: }) }) + framework.KubeDescribe("Kubectl run CronJob", func() { + var nsFlag string + var cjName string + + BeforeEach(func() { + nsFlag = fmt.Sprintf("--namespace=%v", ns) + cjName = "e2e-test-echo-cronjob-beta" + }) + + AfterEach(func() { + framework.RunKubectlOrDie("delete", "cronjob.v1beta1.batch", cjName, nsFlag) + }) + + It("should create a CronJob", func() { + framework.SkipIfMissingResource(f.ClientPool, CronJobGroupVersionResourceBeta, f.Namespace.Name) + + schedule := "*/5 * * * ?" + framework.RunKubectlOrDie("run", cjName, "--restart=OnFailure", "--generator=cronjob/v1beta1", + "--schedule="+schedule, "--image="+busyboxImage, nsFlag) + By("verifying the CronJob " + cjName + " was created") + cj, err := c.BatchV1beta1().CronJobs(ns).Get(cjName, metav1.GetOptions{}) + if err != nil { + framework.Failf("Failed getting CronJob %s: %v", cjName, err) + } + if cj.Spec.Schedule != schedule { + framework.Failf("Failed creating a CronJob with correct schedule %s", schedule) + } + containers := cj.Spec.JobTemplate.Spec.Template.Spec.Containers + if containers == nil || len(containers) != 1 || containers[0].Image != busyboxImage { + framework.Failf("Failed creating CronJob %s for 1 pod with expected image %s: %#v", cjName, busyboxImage, containers) + } + if cj.Spec.JobTemplate.Spec.Template.Spec.RestartPolicy != v1.RestartPolicyOnFailure { + framework.Failf("Failed creating a CronJob with correct restart policy for --restart=OnFailure") + } + }) + }) + framework.KubeDescribe("Kubectl run pod", func() { var nsFlag string var podName string diff --git a/test/integration/etcd/etcd_storage_path_test.go b/test/integration/etcd/etcd_storage_path_test.go index d94be2fe09..5ef6f89fb3 100644 --- a/test/integration/etcd/etcd_storage_path_test.go +++ b/test/integration/etcd/etcd_storage_path_test.go @@ -201,8 +201,6 @@ var etcdStorageData = map[schema.GroupVersionResource]struct { gvr("batch", "v1beta1", "cronjobs"): { stub: `{"metadata": {"name": "cjv1beta1"}, "spec": {"jobTemplate": {"spec": {"template": {"metadata": {"labels": {"controller-uid": "uid0"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container0"}], "dnsPolicy": "ClusterFirst", "restartPolicy": "Never"}}}}, "schedule": "* * * * *"}}`, expectedEtcdPath: "/registry/cronjobs/etcdstoragepathtestnamespace/cjv1beta1", - // TODO this needs to be updated to batch/v1beta1 when it's enabed by default - expectedGVK: gvkP("batch", "v2alpha1", "CronJob"), }, // -- @@ -210,6 +208,7 @@ var etcdStorageData = map[schema.GroupVersionResource]struct { gvr("batch", "v2alpha1", "cronjobs"): { stub: `{"metadata": {"name": "cjv2alpha1"}, "spec": {"jobTemplate": {"spec": {"template": {"metadata": {"labels": {"controller-uid": "uid0"}}, "spec": {"containers": [{"image": "fedora:latest", "name": "container0"}], "dnsPolicy": "ClusterFirst", "restartPolicy": "Never"}}}}, "schedule": "* * * * *"}}`, expectedEtcdPath: "/registry/cronjobs/etcdstoragepathtestnamespace/cjv2alpha1", + expectedGVK: gvkP("batch", "v1beta1", "CronJob"), }, // -- diff --git a/test/integration/framework/master_utils.go b/test/integration/framework/master_utils.go index a6b9a85665..9577cdce55 100644 --- a/test/integration/framework/master_utils.go +++ b/test/integration/framework/master_utils.go @@ -300,7 +300,13 @@ func NewMasterConfig() *master.Config { info, _ := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON) ns := NewSingleContentTypeSerializer(api.Scheme, info) - storageFactory := serverstorage.NewDefaultStorageFactory(etcdOptions.StorageConfig, runtime.ContentTypeJSON, ns, serverstorage.NewDefaultResourceEncodingConfig(api.Registry), master.DefaultAPIResourceConfigSource()) + resourceEncoding := serverstorage.NewDefaultResourceEncodingConfig(api.Registry) + // FIXME (soltysh): this GroupVersionResource override should be configurable + // we need to set both for the whole group and for cronjobs, separately + resourceEncoding.SetVersionEncoding(batch.GroupName, *testapi.Batch.GroupVersion(), schema.GroupVersion{Group: batch.GroupName, Version: runtime.APIVersionInternal}) + resourceEncoding.SetResourceEncoding(schema.GroupResource{Group: "batch", Resource: "cronjobs"}, schema.GroupVersion{Group: batch.GroupName, Version: "v1beta1"}, schema.GroupVersion{Group: batch.GroupName, Version: runtime.APIVersionInternal}) + + storageFactory := serverstorage.NewDefaultStorageFactory(etcdOptions.StorageConfig, runtime.ContentTypeJSON, ns, resourceEncoding, master.DefaultAPIResourceConfigSource()) storageFactory.SetSerializer( schema.GroupResource{Group: v1.GroupName, Resource: serverstorage.AllResources}, "",