kubectl create job support both v1beta1 and v1 cronjob

This commit is contained in:
Maciej Szulik 2021-02-12 17:04:50 +01:00
parent 2c17621b29
commit 470e23e770
No known key found for this signature in database
GPG Key ID: F15E55D276FA84C4
2 changed files with 110 additions and 14 deletions

View File

@ -177,7 +177,7 @@ func (o *CreateJobOptions) Run() error {
job = o.createJob() job = o.createJob()
} else { } else {
infos, err := o.Builder. infos, err := o.Builder.
Unstructured(). WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
NamespaceParam(o.Namespace).DefaultNamespace(). NamespaceParam(o.Namespace).DefaultNamespace().
ResourceTypeOrNameArgs(false, o.From). ResourceTypeOrNameArgs(false, o.From).
Flatten(). Flatten().
@ -191,16 +191,14 @@ func (o *CreateJobOptions) Run() error {
return fmt.Errorf("from must be an existing cronjob") return fmt.Errorf("from must be an existing cronjob")
} }
uncastVersionedObj, err := scheme.Scheme.ConvertToVersion(infos[0].Object, batchv1beta1.SchemeGroupVersion) switch obj := infos[0].Object.(type) {
if err != nil { case *batchv1.CronJob:
return fmt.Errorf("from must be an existing cronjob: %v", err) job = o.createJobFromCronJob(obj)
case *batchv1beta1.CronJob:
job = o.createJobFromCronJobV1Beta1(obj)
default:
return fmt.Errorf("unknown object type %T", obj)
} }
cronJob, ok := uncastVersionedObj.(*batchv1beta1.CronJob)
if !ok {
return fmt.Errorf("from must be an existing cronjob")
}
job = o.createJobFromCronJob(cronJob)
} }
if err := util.CreateOrUpdateAnnotation(o.CreateAnnotation, job, scheme.DefaultJSONEncoder()); err != nil { if err := util.CreateOrUpdateAnnotation(o.CreateAnnotation, job, scheme.DefaultJSONEncoder()); err != nil {
@ -256,7 +254,39 @@ func (o *CreateJobOptions) createJob() *batchv1.Job {
return job return job
} }
func (o *CreateJobOptions) createJobFromCronJob(cronJob *batchv1beta1.CronJob) *batchv1.Job { func (o *CreateJobOptions) createJobFromCronJobV1Beta1(cronJob *batchv1beta1.CronJob) *batchv1.Job {
annotations := make(map[string]string)
annotations["cronjob.kubernetes.io/instantiate"] = "manual"
for k, v := range cronJob.Spec.JobTemplate.Annotations {
annotations[k] = v
}
job := &batchv1.Job{
// this is ok because we know exactly how we want to be serialized
TypeMeta: metav1.TypeMeta{APIVersion: batchv1.SchemeGroupVersion.String(), Kind: "Job"},
ObjectMeta: metav1.ObjectMeta{
Name: o.Name,
Annotations: annotations,
Labels: cronJob.Spec.JobTemplate.Labels,
OwnerReferences: []metav1.OwnerReference{
{
// TODO (soltysh): switch this to v1 in v1.22, when n-1 skew will be fulfilled
APIVersion: batchv1beta1.SchemeGroupVersion.String(),
Kind: "CronJob",
Name: cronJob.GetName(),
UID: cronJob.GetUID(),
},
},
},
Spec: cronJob.Spec.JobTemplate.Spec,
}
if o.EnforceNamespace {
job.Namespace = o.Namespace
}
return job
}
func (o *CreateJobOptions) createJobFromCronJob(cronJob *batchv1.CronJob) *batchv1.Job {
annotations := make(map[string]string) annotations := make(map[string]string)
annotations["cronjob.kubernetes.io/instantiate"] = "manual" annotations["cronjob.kubernetes.io/instantiate"] = "manual"
for k, v := range cronJob.Spec.JobTemplate.Annotations { for k, v := range cronJob.Spec.JobTemplate.Annotations {
@ -273,7 +303,7 @@ func (o *CreateJobOptions) createJobFromCronJob(cronJob *batchv1beta1.CronJob) *
OwnerReferences: []metav1.OwnerReference{ OwnerReferences: []metav1.OwnerReference{
{ {
APIVersion: batchv1beta1.SchemeGroupVersion.String(), APIVersion: batchv1beta1.SchemeGroupVersion.String(),
Kind: cronJob.Kind, Kind: "CronJob",
Name: cronJob.GetName(), Name: cronJob.GetName(),
UID: cronJob.GetUID(), UID: cronJob.GetUID(),
}, },

View File

@ -135,7 +135,7 @@ func TestCreateJob(t *testing.T) {
} }
} }
func TestCreateJobFromCronJob(t *testing.T) { func TestCreateJobFromCronJobV1Beta1(t *testing.T) {
jobName := "test-job" jobName := "test-job"
cronJob := &batchv1beta1.CronJob{ cronJob := &batchv1beta1.CronJob{
Spec: batchv1beta1.CronJobSpec{ Spec: batchv1beta1.CronJobSpec{
@ -167,7 +167,73 @@ func TestCreateJobFromCronJob(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{ OwnerReferences: []metav1.OwnerReference{
{ {
APIVersion: batchv1beta1.SchemeGroupVersion.String(), APIVersion: batchv1beta1.SchemeGroupVersion.String(),
Kind: cronJob.Kind, Kind: "CronJob",
Name: cronJob.GetName(),
UID: cronJob.GetUID(),
},
},
},
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{Image: "test-image"},
},
RestartPolicy: corev1.RestartPolicyNever,
},
},
},
},
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
o := &CreateJobOptions{
Name: jobName,
}
job := o.createJobFromCronJobV1Beta1(tc.from)
if !apiequality.Semantic.DeepEqual(job, tc.expected) {
t.Errorf("expected:\n%#v\ngot:\n%#v", tc.expected, job)
}
})
}
}
func TestCreateJobFromCronJob(t *testing.T) {
jobName := "test-job"
cronJob := &batchv1.CronJob{
Spec: batchv1.CronJobSpec{
JobTemplate: batchv1.JobTemplateSpec{
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{Image: "test-image"},
},
RestartPolicy: corev1.RestartPolicyNever,
},
},
},
},
},
}
tests := map[string]struct {
from *batchv1.CronJob
expected *batchv1.Job
}{
"from CronJob": {
from: cronJob,
expected: &batchv1.Job{
TypeMeta: metav1.TypeMeta{APIVersion: batchv1.SchemeGroupVersion.String(), Kind: "Job"},
ObjectMeta: metav1.ObjectMeta{
Name: jobName,
Annotations: map[string]string{"cronjob.kubernetes.io/instantiate": "manual"},
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: batchv1beta1.SchemeGroupVersion.String(),
Kind: "CronJob",
Name: cronJob.GetName(), Name: cronJob.GetName(),
UID: cronJob.GetUID(), UID: cronJob.GetUID(),
}, },