CronJob: Add e2e test for adoption.

Currently, an e2e test is the only way to ensure we have the proper RBAC
permissions to adopt Jobs.
This commit is contained in:
Anthony Yeh 2017-04-12 17:26:35 -07:00
parent 1e14323ac2
commit 33d7788793
2 changed files with 76 additions and 0 deletions

View File

@ -33,6 +33,7 @@ import (
batchv1 "k8s.io/kubernetes/pkg/apis/batch/v1"
batchv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1"
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/job"
"k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/test/e2e/framework"
@ -274,6 +275,53 @@ var _ = framework.KubeDescribe("CronJob", func() {
err = deleteCronJob(f.ClientSet, f.Namespace.Name, cronJob.Name)
Expect(err).NotTo(HaveOccurred())
})
// Adopt Jobs it owns that don't have ControllerRef yet.
// That is, the Jobs were created by a pre-v1.6.0 master.
It("should adopt Jobs it owns that don't have ControllerRef yet", func() {
By("Creating a cronjob")
cronJob := newTestCronJob("adopt", "*/1 * * * ?", batchv2alpha1.ForbidConcurrent,
sleepCommand, nil)
// Replace cronJob with the one returned from Create() so it has the UID.
// Save Kind since it won't be populated in the returned cronJob.
kind := cronJob.Kind
cronJob, err := createCronJob(f.ClientSet, f.Namespace.Name, cronJob)
Expect(err).NotTo(HaveOccurred())
cronJob.Kind = kind
By("Ensuring a Job is running")
err = waitForActiveJobs(f.ClientSet, f.Namespace.Name, cronJob.Name, 1)
Expect(err).NotTo(HaveOccurred())
By("Orphaning a Job")
jobs, err := f.ClientSet.BatchV1().Jobs(f.Namespace.Name).List(metav1.ListOptions{})
Expect(err).NotTo(HaveOccurred())
Expect(jobs.Items).To(HaveLen(1))
job := jobs.Items[0]
framework.UpdateJobFunc(f.ClientSet, f.Namespace.Name, job.Name, func(job *batchv1.Job) {
job.OwnerReferences = nil
})
By("Checking that the CronJob readopts the Job")
Expect(wait.Poll(framework.Poll, cronJobTimeout, func() (bool, error) {
job, err := framework.GetJob(f.ClientSet, f.Namespace.Name, job.Name)
if err != nil {
return false, err
}
controllerRef := controller.GetControllerOf(job)
if controllerRef == nil {
return false, nil
}
if controllerRef.Kind != cronJob.Kind || controllerRef.Name != cronJob.Name || controllerRef.UID != cronJob.UID {
return false, fmt.Errorf("Job has wrong controllerRef: got %v, want %v", controllerRef, cronJob)
}
return true, nil
})).To(Succeed(), "wait for Job %q to be readopted", job.Name)
By("Removing CronJob")
err = deleteCronJob(f.ClientSet, f.Namespace.Name, cronJob.Name)
Expect(err).NotTo(HaveOccurred())
})
})
// newTestCronJob returns a cronjob which does one of several testing behaviors.
@ -285,6 +333,9 @@ func newTestCronJob(name, schedule string, concurrencyPolicy batchv2alpha1.Concu
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
TypeMeta: metav1.TypeMeta{
Kind: "CronJob",
},
Spec: batchv2alpha1.CronJobSpec{
Schedule: schedule,
ConcurrencyPolicy: concurrencyPolicy,

View File

@ -17,8 +17,10 @@ limitations under the License.
package framework
import (
"fmt"
"time"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/wait"
@ -120,6 +122,29 @@ func UpdateJob(c clientset.Interface, ns string, job *batch.Job) (*batch.Job, er
return c.Batch().Jobs(ns).Update(job)
}
// UpdateJobFunc updates the job object. It retries if there is a conflict, throw out error if
// there is any other errors. name is the job name, updateFn is the function updating the
// job object.
func UpdateJobFunc(c clientset.Interface, ns, name string, updateFn func(job *batch.Job)) {
ExpectNoError(wait.Poll(time.Millisecond*500, time.Second*30, func() (bool, error) {
job, err := GetJob(c, ns, name)
if err != nil {
return false, fmt.Errorf("failed to get pod %q: %v", name, err)
}
updateFn(job)
_, err = UpdateJob(c, ns, job)
if err == nil {
Logf("Successfully updated job %q", name)
return true, nil
}
if errors.IsConflict(err) {
Logf("Conflicting update to job %q, re-get and re-update: %v", name, err)
return false, nil
}
return false, fmt.Errorf("failed to update job %q: %v", name, err)
}))
}
// DeleteJob uses c to delete the Job named name in namespace ns. If the returned error is nil, the Job has been
// deleted.
func DeleteJob(c clientset.Interface, ns, name string) error {