diff --git a/controllers/promise_controller_test.go b/controllers/promise_controller_test.go index 7ad9ada5..f0271047 100644 --- a/controllers/promise_controller_test.go +++ b/controllers/promise_controller_test.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "regexp" + "sort" "strings" "time" @@ -806,8 +807,8 @@ var _ = Describe("PromiseController", func() { }) When("the promise is updated repeatedly", func() { - It("ensures only the last 5 jobs are kept", func() { - var timestamp time.Time + var timestamp time.Time + BeforeEach(func() { for i := 0; i < 10; i++ { if i == 6 { timestamp = time.Now() @@ -825,6 +826,9 @@ var _ = Describe("PromiseController", func() { Expect(result).To(Equal(ctrl.Result{})) } + }) + + It("ensures only the last 5 jobs are kept", func() { jobs := &batchv1.JobList{} Expect(fakeK8sClient.List(ctx, jobs)).To(Succeed()) Expect(jobs.Items).To(HaveLen(5)) @@ -832,6 +836,37 @@ var _ = Describe("PromiseController", func() { Expect(job.CreationTimestamp.Time).To(BeTemporally(">", timestamp)) } }) + + When("a pipeline is in progress", func() { + BeforeEach(func() { + //Mark the latest job as still running + jobs := &batchv1.JobList{} + Expect(fakeK8sClient.List(ctx, jobs)).To(Succeed()) + latestJob := jobs.Items[len(jobs.Items)-1] + latestJob.Status.Conditions = nil + latestJob.Status.Succeeded = 0 + Expect(fakeK8sClient.Status().Update(ctx, &latestJob)).To(Succeed()) + + _, err := t.reconcileUntilCompletion(reconciler, promise, &opts{ + funcs: []func(client.Object) error{autoMarkCRDAsEstablished}, + }) + t.reconcileCount = 0 + Expect(err).To(MatchError("reconcile loop detected")) + }) + + It("suspends all existing jobs apart from the latest", func() { + jobs := &batchv1.JobList{} + Expect(fakeK8sClient.List(ctx, jobs)).To(Succeed()) + Expect(jobs.Items).To(HaveLen(5)) + sortedJobs := sortJobsByCreationDateTime(jobs.Items) + for x := 0; x < len(jobs.Items)-1; x++ { + job := sortedJobs[x] + Expect(job.Spec.Suspend).NotTo(BeNil()) + Expect(*job.Spec.Suspend).To(BeTrue()) + } + Expect(jobs.Items[len(jobs.Items)-1].Spec.Suspend).To(BeNil()) + }) + }) }) }) @@ -913,3 +948,12 @@ func autoMarkCRDAsEstablished(obj client.Object) error { } return nil } + +func sortJobsByCreationDateTime(jobs []batchv1.Job) []batchv1.Job { + sort.Slice(jobs, func(i, j int) bool { + t1 := jobs[i].GetCreationTimestamp().Time + t2 := jobs[j].GetCreationTimestamp().Time + return t1.Before(t2) + }) + return jobs +} diff --git a/controllers/shared_test.go b/controllers/shared_test.go index 346ee340..cc27baac 100644 --- a/controllers/shared_test.go +++ b/controllers/shared_test.go @@ -213,7 +213,7 @@ func autoCompleteJobAndCreateWork(labels map[string]string, workName string) fun //Fake library doesn't set timestamp, and we need it set for comparing age //of jobs. This ensures its set once, and only when its first created, and //that they differ by a large enough amont (time.Now() alone was not enough) - job.CreationTimestamp = metav1.NewTime(time.Now().Add(time.Duration(callCount) * time.Hour)) + job.CreationTimestamp = metav1.NewTime(time.Now().Add(time.Duration(callCount) * time.Minute)) err := fakeK8sClient.Update(ctx, job) if err != nil { return err