diff --git a/hack/make-rules/test-cmd-util.sh b/hack/make-rules/test-cmd-util.sh index 34fcbfefcc9..2b5df4265b7 100755 --- a/hack/make-rules/test-cmd-util.sh +++ b/hack/make-rules/test-cmd-util.sh @@ -77,6 +77,7 @@ selfsubjectaccessreviews="selfsubjectaccessreviews" customresourcedefinitions="customresourcedefinitions" daemonsets="daemonsets" controllerrevisions="controllerrevisions" +job="jobs" # include shell2junit library @@ -4006,6 +4007,46 @@ run_service_accounts_tests() { set +o errexit } +run_job_tests() { + set -o nounset + set -o errexit + + create_and_use_new_namespace + kube::log::status "Testing job" + + ### Create a new namespace + # Pre-condition: the test-jobs namespace does not exist + kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"test-jobs\" }}found{{end}}{{end}}:' ':' + # Command + kubectl create namespace test-jobs + # Post-condition: namespace 'test-jobs' is created. + kube::test::get_object_assert 'namespaces/test-jobs' "{{$id_field}}" 'test-jobs' + + ### Create a cronjob in a specific namespace + kubectl run pi --schedule="59 23 31 2 *" --namespace=test-jobs --generator=cronjob/v1beta1 "--image=$IMAGE_PERL" --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(20)' "${kube_flags[@]}" + # Post-Condition: assertion object exists + kube::test::get_object_assert 'cronjob/pi --namespace=test-jobs' "{{$id_field}}" 'pi' + + ### Create a job in dry-run mode + output_message=$(kubectl create job test-job --from=cronjob/pi --dry-run=true --namespace=test-jobs -o name) + # Post-condition: The text 'job.batch/test-job' should be part of the output + kube::test::if_has_string "${output_message}" 'job.batch/test-job' + # Post-condition: The test-job wasn't created actually + kube::test::get_object_assert jobs "{{range.items}}{{$id_field}}{{end}}" '' + + ### Create a job in a specific namespace + kubectl create job test-job --from=cronjob/pi --namespace=test-jobs + # Post-Condition: assertion object exists + kube::test::get_object_assert 'job/test-job --namespace=test-jobs' "{{$id_field}}" 'test-job' + #Clean up + kubectl delete job test-job --namespace=test-jobs + kubectl delete cronjob pi --namespace=test-jobs + kubectl delete namespace test-jobs + + set +o nounset + set +o errexit +} + run_pod_templates_tests() { set -o nounset set -o errexit @@ -4980,6 +5021,14 @@ runTests() { record_command run_service_accounts_tests fi + #################### + # Job # + #################### + + if kube::test::if_supports_resource "${job}" ; then + record_command run_job_tests + fi + ################# # Pod templates # ################# diff --git a/pkg/kubectl/cmd/create_job.go b/pkg/kubectl/cmd/create_job.go index 382ca5c346e..adf7b1f03ad 100644 --- a/pkg/kubectl/cmd/create_job.go +++ b/pkg/kubectl/cmd/create_job.go @@ -45,12 +45,13 @@ type CreateJobOptions struct { Name string From string - Namespace string - Client clientbatchv1.BatchV1Interface - Out io.Writer - DryRun bool - Builder *resource.Builder - Cmd *cobra.Command + Namespace string + OutputFormat string + Client clientbatchv1.BatchV1Interface + Out io.Writer + DryRun bool + Builder *resource.Builder + Cmd *cobra.Command } // NewCmdCreateJob is a command to ease creating Jobs from CronJobs. @@ -71,6 +72,7 @@ func NewCmdCreateJob(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddValidateFlags(cmd) cmdutil.AddPrinterFlags(cmd) + cmdutil.AddDryRunFlag(cmd) cmd.Flags().String("from", "", "The name of the resource to create a Job from (only cronjob is supported).") return cmd @@ -94,7 +96,9 @@ func (c *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args } c.Client = clientset.BatchV1() c.Builder = f.NewBuilder() + c.DryRun = cmdutil.GetDryRunFlag(cmd) c.Cmd = cmd + c.OutputFormat = cmdutil.GetFlagString(cmd, "output") return nil } @@ -128,7 +132,7 @@ func (c *CreateJobOptions) createJob(cronJob *batchv1beta1.CronJob) error { for k, v := range cronJob.Spec.JobTemplate.Annotations { annotations[k] = v } - jobToCreate := &batchv1.Job{ + job := &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ Name: c.Name, Namespace: c.Namespace, @@ -138,9 +142,18 @@ func (c *CreateJobOptions) createJob(cronJob *batchv1beta1.CronJob) error { Spec: cronJob.Spec.JobTemplate.Spec, } - job, err := c.Client.Jobs(c.Namespace).Create(jobToCreate) - if err != nil { - return fmt.Errorf("failed to create job: %v", err) + if !c.DryRun { + var err error + job, err = c.Client.Jobs(c.Namespace).Create(job) + if err != nil { + return fmt.Errorf("failed to create job: %v", err) + } } + + if useShortOutput := c.OutputFormat == "name"; useShortOutput || len(c.OutputFormat) == 0 { + cmdutil.PrintSuccess(useShortOutput, c.Out, job, c.DryRun, "created") + return nil + } + return cmdutil.PrintObject(c.Cmd, job, c.Out) }