diff --git a/pkg/controller/bundle/bundle_unpacker.go b/pkg/controller/bundle/bundle_unpacker.go index 7d2614bb01..1c5a69f82e 100644 --- a/pkg/controller/bundle/bundle_unpacker.go +++ b/pkg/controller/bundle/bundle_unpacker.go @@ -926,6 +926,11 @@ func sortUnpackJobs(jobs []*batchv1.Job, maxRetainedJobs int) (latest *batchv1.J if failedI != failedJ { return !failedI // non-failed job goes first } + // If both jobs have no failed condition, condI and condJ will be nil + // fallback to sorting by CreationTimestamp + if condI == nil || condJ == nil { + return jobs[i].CreationTimestamp.After(jobs[j].CreationTimestamp.Time) + } return condI.LastTransitionTime.After(condJ.LastTransitionTime.Time) }) if jobs[0] == nil { diff --git a/pkg/controller/bundle/bundle_unpacker_test.go b/pkg/controller/bundle/bundle_unpacker_test.go index 566f52edf4..dba45cebcb 100644 --- a/pkg/controller/bundle/bundle_unpacker_test.go +++ b/pkg/controller/bundle/bundle_unpacker_test.go @@ -1951,8 +1951,9 @@ func TestSortUnpackJobs(t *testing.T) { } return &batchv1.Job{ ObjectMeta: metav1.ObjectMeta{ - Name: name, - Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, BundleUnpackRefLabel: "test"}, + Name: name, + Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, BundleUnpackRefLabel: "test"}, + CreationTimestamp: metav1.Time{Time: time.Unix(ts, 0)}, }, Status: batchv1.JobStatus{ Conditions: conditions, @@ -1976,6 +1977,11 @@ func TestSortUnpackJobs(t *testing.T) { testJob("f-5", true, 5), } nonFailedJob := testJob("s-1", false, 1) + nonFailedJobs := []*batchv1.Job{ + testJob("nf-1", false, 1), + testJob("nf-2", false, 2), + testJob("nf-3", false, 3), + } for _, tc := range []struct { name string jobs []*batchv1.Job @@ -2053,6 +2059,15 @@ func TestSortUnpackJobs(t *testing.T) { nonFailedJob, }, expectedLatest: nonFailedJob, + }, { + name: "multiple non-failed jobs sorted by creation time", + maxRetained: 3, + jobs: []*batchv1.Job{ + nonFailedJobs[0], + nonFailedJobs[2], + nonFailedJobs[1], + }, + expectedLatest: nonFailedJobs[2], // latest creation time should be first }, } { latest, toDelete := sortUnpackJobs(tc.jobs, tc.maxRetained)