@@ -10,10 +10,12 @@ import (
10
10
configv1 "github.com/openshift/api/config/v1"
11
11
"github.com/stretchr/testify/assert"
12
12
"github.com/stretchr/testify/require"
13
+ apimeta "k8s.io/apimachinery/pkg/api/meta"
13
14
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14
15
"k8s.io/apimachinery/pkg/types"
15
16
"k8s.io/client-go/tools/record"
16
17
"sigs.k8s.io/controller-runtime/pkg/client"
18
+ "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
17
19
"sigs.k8s.io/controller-runtime/pkg/reconcile"
18
20
19
21
managedupgradev1beta1 "github.com/appuio/openshift-upgrade-controller/api/v1beta1"
@@ -409,6 +411,115 @@ func requireEventMatches(t *testing.T, recorder *record.FakeRecorder, substrings
409
411
require .NotEmpty (t , matchingEvent , "no event matches %v, got %v" , substrings , events )
410
412
}
411
413
414
+ func Test_UpgradeConfigReconciler_Reconcile_CleanupSuccessfulJobs (t * testing.T ) {
415
+ ctx := context .Background ()
416
+ clock := mockClock {now : time .Date (2022 , time .April , 4 , 8 , 0 , 0 , 0 , time .UTC )}
417
+ t .Log ("Now: " , clock .Now ())
418
+ require .Equal (t , 14 , func () int { _ , isoweek := clock .Now ().ISOWeek (); return isoweek }())
419
+ require .Equal (t , time .Monday , clock .Now ().Weekday ())
420
+
421
+ ucv := & configv1.ClusterVersion {
422
+ ObjectMeta : metav1.ObjectMeta {
423
+ Name : "version" ,
424
+ },
425
+ }
426
+
427
+ upgradeConfig := & managedupgradev1beta1.UpgradeConfig {
428
+ ObjectMeta : metav1.ObjectMeta {
429
+ Name : "daily-maintenance" ,
430
+ Namespace : "appuio-openshift-upgrade-controller" ,
431
+ CreationTimestamp : metav1.Time {Time : clock .Now ().Add (- time .Hour )},
432
+ },
433
+ Spec : managedupgradev1beta1.UpgradeConfigSpec {
434
+ Schedule : managedupgradev1beta1.UpgradeConfigSchedule {
435
+ Cron : "0 22 * * *" , // At 22:00 every day
436
+ Location : "UTC" ,
437
+ Suspend : true ,
438
+ },
439
+ MaxSchedulingDelay : metav1.Duration {Duration : time .Minute },
440
+ SuccessfulJobsHistoryLimit : 2 ,
441
+ },
442
+ }
443
+
444
+ client := controllerClient (t , ucv , upgradeConfig )
445
+
446
+ jobStartTs := []time.Time {
447
+ clock .Now ().Add (- 24 * time .Hour ),
448
+ clock .Now ().Add (- 24 * time .Hour * 2 ),
449
+ clock .Now ().Add (- 24 * time .Hour * 3 ),
450
+ }
451
+
452
+ for i , ts := range jobStartTs {
453
+ job := & managedupgradev1beta1.UpgradeJob {
454
+ ObjectMeta : metav1.ObjectMeta {
455
+ Name : "job-" + strconv .Itoa (i ),
456
+ Namespace : upgradeConfig .Namespace ,
457
+ },
458
+ Spec : managedupgradev1beta1.UpgradeJobSpec {
459
+ StartAfter : metav1 .NewTime (ts ),
460
+ },
461
+ }
462
+ {
463
+ successfulOwned := job .DeepCopy ()
464
+ successfulOwned .Name = "successful-owned-" + successfulOwned .Name
465
+ require .NoError (t , controllerutil .SetControllerReference (upgradeConfig , successfulOwned , client .Scheme ()))
466
+ require .NoError (t , client .Create (ctx , successfulOwned ))
467
+ apimeta .SetStatusCondition (& successfulOwned .Status .Conditions , metav1.Condition {
468
+ Type : managedupgradev1beta1 .UpgradeJobConditionSucceeded ,
469
+ Status : metav1 .ConditionTrue ,
470
+ })
471
+ client .Status ().Update (ctx , successfulOwned )
472
+ }
473
+ {
474
+ notSuccessfulOwned := job .DeepCopy ()
475
+ notSuccessfulOwned .Name = "not-successful-owned-" + notSuccessfulOwned .Name
476
+ require .NoError (t , controllerutil .SetControllerReference (upgradeConfig , notSuccessfulOwned , client .Scheme ()))
477
+ require .NoError (t , client .Create (ctx , notSuccessfulOwned ))
478
+ }
479
+ {
480
+ successfulNotOwned := job .DeepCopy ()
481
+ successfulNotOwned .Name = "successful-not-owned-" + successfulNotOwned .Name
482
+ require .NoError (t , client .Create (ctx , successfulNotOwned ))
483
+ apimeta .SetStatusCondition (& successfulNotOwned .Status .Conditions , metav1.Condition {
484
+ Type : managedupgradev1beta1 .UpgradeJobConditionSucceeded ,
485
+ Status : metav1 .ConditionTrue ,
486
+ })
487
+ client .Status ().Update (ctx , successfulNotOwned )
488
+ }
489
+ }
490
+
491
+ recorder := record .NewFakeRecorder (5 )
492
+ subject := & UpgradeConfigReconciler {
493
+ Client : client ,
494
+ Scheme : client .Scheme (),
495
+ Recorder : recorder ,
496
+
497
+ Clock : & clock ,
498
+
499
+ ManagedUpstreamClusterVersionName : "version" ,
500
+ }
501
+
502
+ _ , err := subject .Reconcile (ctx , requestForObject (upgradeConfig ))
503
+ require .NoError (t , err )
504
+
505
+ var nj managedupgradev1beta1.UpgradeJobList
506
+ require .NoError (t , client .List (ctx , & nj ))
507
+ names := []string {}
508
+ for _ , j := range nj .Items {
509
+ names = append (names , j .Name )
510
+ }
511
+ require .ElementsMatch (t , names , []string {
512
+ "not-successful-owned-job-0" ,
513
+ "not-successful-owned-job-1" ,
514
+ "not-successful-owned-job-2" ,
515
+ "successful-not-owned-job-0" ,
516
+ "successful-not-owned-job-1" ,
517
+ "successful-not-owned-job-2" ,
518
+ "successful-owned-job-0" ,
519
+ "successful-owned-job-1" ,
520
+ }, "only owned and successful jobs should be cleaned up, higher numbers are older" )
521
+ }
522
+
412
523
// requireTimeEqual asserts that two times are equal, ignoring their timezones.
413
524
func requireTimeEqual (t * testing.T , expected , actual time.Time , msgAndArgs ... any ) {
414
525
t .Helper ()
0 commit comments