@@ -545,6 +545,152 @@ func Test_ProcessIncomingAppProjectWithUIDMismatch(t *testing.T) {
545
545
require .Equal (t , expectedCalls , gotCalls )
546
546
require .False (t , a .appManager .IsManaged (incomingAppProject .Name ))
547
547
})
548
+
549
+ // Missing Source UID Annotation scenarios - when existing AppProject lacks the source UID annotation
550
+ t .Run ("Create: Existing AppProject without source UID annotation should be deleted and recreated" , func (t * testing.T ) {
551
+ // Setup separate backend for this test to avoid mock conflicts
552
+ beMissing := backend_mocks .NewAppProject (t )
553
+ var err error
554
+ a .projectManager , err = appproject .NewAppProjectManager (beMissing , "argocd" , appproject .WithAllowUpsert (true ))
555
+ require .NoError (t , err )
556
+
557
+ // Setup for missing source UID scenario
558
+ existingAppProject := & v1alpha1.AppProject {
559
+ ObjectMeta : v1.ObjectMeta {
560
+ Name : "test" ,
561
+ Namespace : "argocd" ,
562
+ UID : ktypes .UID ("existing_uid" ),
563
+ },
564
+ }
565
+
566
+ // Configure separate backend
567
+ getMockMissing := beMissing .On ("Get" , mock .Anything , mock .Anything , mock .Anything ).Return (existingAppProject , nil )
568
+ createMockMissing := beMissing .On ("Create" , mock .Anything , mock .Anything ).Return (createdAppProject , nil )
569
+ deleteMockMissing := beMissing .On ("Delete" , mock .Anything , mock .Anything , mock .Anything , mock .Anything ).Return (nil )
570
+
571
+ defer func () {
572
+ getMockMissing .Unset ()
573
+ createMockMissing .Unset ()
574
+ deleteMockMissing .Unset ()
575
+ }()
576
+
577
+ a .projectManager .Manage (existingAppProject .Name )
578
+ defer a .projectManager .ClearManaged ()
579
+
580
+ ev := event .New (evs .AppProjectEvent (event .Create , incomingAppProject ), event .TargetAppProject )
581
+ err = a .processIncomingAppProject (ev )
582
+
583
+ // The process should succeed after deleting the existing AppProject and creating the new one
584
+ require .NoError (t , err )
585
+
586
+ // Verify the sequence: Get (to compare UID), Delete (existing), Create (new)
587
+ expectedCalls := []string {"Get" , "Delete" , "Create" }
588
+ gotCalls := []string {}
589
+ for _ , call := range beMissing .Calls {
590
+ gotCalls = append (gotCalls , call .Method )
591
+ }
592
+ require .Equal (t , expectedCalls , gotCalls )
593
+
594
+ // Verify the created AppProject has the correct source UID annotation
595
+ appInterface := beMissing .Calls [2 ].ReturnArguments [0 ]
596
+ latestAppProject , ok := appInterface .(* v1alpha1.AppProject )
597
+ require .True (t , ok )
598
+ require .Equal (t , string (incomingAppProject .UID ), latestAppProject .Annotations [manager .SourceUIDAnnotation ])
599
+ })
600
+
601
+ t .Run ("Update: Existing AppProject without source UID annotation should be deleted and recreated" , func (t * testing.T ) {
602
+ // Setup separate backend for this test to avoid mock conflicts
603
+ beMissing := backend_mocks .NewAppProject (t )
604
+ var err error
605
+ a .projectManager , err = appproject .NewAppProjectManager (beMissing , "argocd" , appproject .WithAllowUpsert (true ))
606
+ require .NoError (t , err )
607
+
608
+ // Setup for missing source UID scenario
609
+ existingAppProject := & v1alpha1.AppProject {
610
+ ObjectMeta : v1.ObjectMeta {
611
+ Name : "test" ,
612
+ Namespace : "argocd" ,
613
+ UID : ktypes .UID ("existing_uid" ),
614
+ },
615
+ }
616
+
617
+ // Configure separate backend
618
+ getMockMissing := beMissing .On ("Get" , mock .Anything , mock .Anything , mock .Anything ).Return (existingAppProject , nil )
619
+ createMockMissing := beMissing .On ("Create" , mock .Anything , mock .Anything ).Return (createdAppProject , nil )
620
+ deleteMockMissing := beMissing .On ("Delete" , mock .Anything , mock .Anything , mock .Anything , mock .Anything ).Return (nil )
621
+
622
+ defer func () {
623
+ getMockMissing .Unset ()
624
+ createMockMissing .Unset ()
625
+ deleteMockMissing .Unset ()
626
+ }()
627
+
628
+ a .projectManager .Manage (existingAppProject .Name )
629
+ defer a .projectManager .ClearManaged ()
630
+
631
+ ev := event .New (evs .AppProjectEvent (event .SpecUpdate , incomingAppProject ), event .TargetAppProject )
632
+ err = a .processIncomingAppProject (ev )
633
+
634
+ // The process should succeed after deleting the existing AppProject and creating the new one
635
+ require .NoError (t , err )
636
+
637
+ // Verify the sequence: Get (to compare UID), Delete (existing), Create (new)
638
+ expectedCalls := []string {"Get" , "Delete" , "Create" }
639
+ gotCalls := []string {}
640
+ for _ , call := range beMissing .Calls {
641
+ gotCalls = append (gotCalls , call .Method )
642
+ }
643
+ require .Equal (t , expectedCalls , gotCalls )
644
+
645
+ // Verify the created AppProject has the correct source UID annotation
646
+ appInterface := beMissing .Calls [2 ].ReturnArguments [0 ]
647
+ latestAppProject , ok := appInterface .(* v1alpha1.AppProject )
648
+ require .True (t , ok )
649
+ require .Equal (t , string (incomingAppProject .UID ), latestAppProject .Annotations [manager .SourceUIDAnnotation ])
650
+ })
651
+
652
+ t .Run ("Delete: Existing AppProject without source UID annotation should be deleted" , func (t * testing.T ) {
653
+ // Setup separate backend for this test to avoid mock conflicts
654
+ beMissing := backend_mocks .NewAppProject (t )
655
+ var err error
656
+ a .projectManager , err = appproject .NewAppProjectManager (beMissing , "argocd" , appproject .WithAllowUpsert (true ))
657
+ require .NoError (t , err )
658
+
659
+ // Setup for missing source UID scenario
660
+ existingAppProject := & v1alpha1.AppProject {
661
+ ObjectMeta : v1.ObjectMeta {
662
+ Name : "test" ,
663
+ Namespace : "argocd" ,
664
+ UID : ktypes .UID ("existing_uid" ),
665
+ },
666
+ }
667
+
668
+ // Configure separate backend
669
+ getMockMissing := beMissing .On ("Get" , mock .Anything , mock .Anything , mock .Anything ).Return (existingAppProject , nil )
670
+ deleteMockMissing := beMissing .On ("Delete" , mock .Anything , mock .Anything , mock .Anything , mock .Anything ).Return (nil )
671
+
672
+ defer func () {
673
+ getMockMissing .Unset ()
674
+ deleteMockMissing .Unset ()
675
+ }()
676
+
677
+ a .projectManager .Manage (existingAppProject .Name )
678
+ defer a .projectManager .ClearManaged ()
679
+
680
+ ev := event .New (evs .AppProjectEvent (event .Delete , incomingAppProject ), event .TargetAppProject )
681
+ err = a .processIncomingAppProject (ev )
682
+
683
+ // Delete events should succeed after deleting the existing AppProject
684
+ require .NoError (t , err )
685
+
686
+ // Verify the sequence: Get (to compare UID), Delete (existing)
687
+ expectedCalls := []string {"Get" , "Delete" }
688
+ gotCalls := []string {}
689
+ for _ , call := range beMissing .Calls {
690
+ gotCalls = append (gotCalls , call .Method )
691
+ }
692
+ require .Equal (t , expectedCalls , gotCalls )
693
+ })
548
694
}
549
695
550
696
func Test_UpdateApplication (t * testing.T ) {
0 commit comments