@@ -1512,83 +1512,96 @@ var _ = Describe("Reconciler", func() {
15121512 var (
15131513 ctx context.Context
15141514 cancel context.CancelFunc
1515- mgr manager.Manager
1516- reconciledCRs []string
1517- anotherReconciledCRs []string
15181515 matchingLabels map [string ]string
15191516 anotherMatchingLabels map [string ]string
1520- labeledObj * unstructured.Unstructured
1521- anotherObj * unstructured.Unstructured
1522- labeledObjKey types.NamespacedName
1523- anotherObjKey types.NamespacedName
15241517 mu sync.Mutex
1518+ doneChans []chan struct {}
15251519 )
15261520
15271521 BeforeEach (func () {
1528- ctx , cancel = context .WithCancel (context .Background ())
1529-
1530- mu .Lock ()
1531- reconciledCRs = nil
1532- anotherReconciledCRs = nil
1533- mu .Unlock ()
1534-
15351522 matchingLabels = map [string ]string {"app" : "foo" }
15361523 anotherMatchingLabels = map [string ]string {"app" : "bar" }
1524+ doneChans = nil
1525+ ctx , cancel = context .WithCancel (context .Background ())
15371526
1538- trackingHook := hook .PostHookFunc (func (obj * unstructured.Unstructured , _ release.Release , _ logr.Logger ) error {
1539- mu .Lock ()
1540- defer mu .Unlock ()
1541- if ! slices .Contains (reconciledCRs , obj .GetName ()) {
1542- reconciledCRs = append (reconciledCRs , obj .GetName ())
1543- }
1544- return nil
1545- })
1546- mgr = setupManagerWithSelectorAndPostHook (ctx , trackingHook , matchingLabels )
1547-
1548- labeledObj = testutil .BuildTestCR (gvk )
1549- labeledObj .SetName ("labeled-cr" )
1550- labeledObj .SetLabels (matchingLabels )
1551- labeledObjKey = types.NamespacedName {Namespace : labeledObj .GetNamespace (), Name : labeledObj .GetName ()}
1527+ cleanupMgr := getManagerOrFail ()
1528+ cleanupClient := cleanupMgr .GetClient ()
1529+ crList := & unstructured.UnstructuredList {}
1530+ crList .SetGroupVersionKind (gvk )
1531+ Expect (cleanupClient .List (ctx , crList )).To (Succeed ())
1532+
1533+ for i := range crList .Items {
1534+ cr := & crList .Items [i ]
1535+ // Remove all finalizers to allow CR deletion
1536+ cr .SetFinalizers ([]string {})
1537+ Expect (cleanupClient .Update (ctx , cr )).To (Succeed ())
1538+ Expect (cleanupClient .Delete (ctx , cr )).To (Succeed ())
1539+ }
15521540
1553- anotherObj = testutil .BuildTestCR (gvk )
1554- anotherObj .SetName ("another-cr" )
1555- anotherObjKey = types.NamespacedName {Namespace : anotherObj .GetNamespace (), Name : anotherObj .GetName ()}
1541+ // Wait for all CRs to be deleted
1542+ Eventually (func () bool {
1543+ crList := & unstructured.UnstructuredList {}
1544+ crList .SetGroupVersionKind (gvk )
1545+ if err := cleanupClient .List (ctx , crList ); err != nil {
1546+ return false
1547+ }
1548+ return len (crList .Items ) == 0
1549+ }, "10s" , "100ms" ).Should (BeTrue ())
15561550 })
15571551
15581552 AfterEach (func () {
1559- By ("ensuring the labeled CR is deleted" , func () {
1560- ensureDeleteCR (ctx , mgr , labeledObjKey , labeledObj )
1561- })
1562-
1563- By ("ensuring the unlabeled CR is deleted" , func () {
1564- ensureDeleteCR (ctx , mgr , anotherObjKey , anotherObj )
1565- })
1566- cancel ()
1553+ // Cancel the context to stop all managers
1554+ if cancel != nil {
1555+ cancel ()
1556+ }
1557+ // Wait for all managers to shut down completely
1558+ for _ , done := range doneChans {
1559+ select {
1560+ case <- done :
1561+ // Manager has shut down
1562+ case <- time .After (5 * time .Second ):
1563+ // Timeout waiting for manager shutdown
1564+ }
1565+ }
15671566 })
15681567
15691568 It ("should only reconcile CRs matching the label selector" , func () {
1569+ labeledObj := testutil .BuildTestCR (gvk )
1570+ labeledObj .SetName ("labeled-cr-test1" )
1571+ labeledObj .SetLabels (matchingLabels )
1572+ labeledObjKey := types.NamespacedName {Namespace : labeledObj .GetNamespace (), Name : labeledObj .GetName ()}
1573+
1574+ anotherObj := testutil .BuildTestCR (gvk )
1575+ anotherObj .SetName ("another-cr-test1" )
1576+ anotherObjKey := types.NamespacedName {Namespace : anotherObj .GetNamespace (), Name : anotherObj .GetName ()}
1577+
1578+ var reconciledCRs []string
1579+ postHook := makePostHook (& mu , & reconciledCRs )
1580+ mgr , done := setupManagerWithSelectorAndPostHook (ctx , postHook , matchingLabels )
1581+ doneChans = append (doneChans , done )
1582+
15701583 By ("creating a CR without matching labels" , func () {
15711584 Expect (mgr .GetClient ().Create (ctx , anotherObj )).To (Succeed ())
15721585 })
15731586
15741587 By ("verifying that the labeled reconciler does not reconcile CR without labels" , func () {
1575- Consistently (func () [] string {
1588+ Consistently (func () bool {
15761589 mu .Lock ()
15771590 defer mu .Unlock ()
1578- return reconciledCRs
1579- }, "2s" , "100ms" ).Should (BeEmpty ())
1591+ return len ( reconciledCRs ) == 0
1592+ }, "2s" , "100ms" ).Should (BeTrue ())
15801593 })
15811594
15821595 By ("creating a CR with matching labels" , func () {
15831596 Expect (mgr .GetClient ().Create (ctx , labeledObj )).To (Succeed ())
15841597 })
15851598
15861599 By ("verifying only the labeled CR was reconciled" , func () {
1587- Eventually (func () [] string {
1600+ Eventually (func () bool {
15881601 mu .Lock ()
15891602 defer mu .Unlock ()
1590- return reconciledCRs
1591- }).Should (HaveExactElements ( labeledObjKey . Name ))
1603+ return len ( reconciledCRs ) == 1 && reconciledCRs [ 0 ] == labeledObjKey . Name
1604+ }).Should (BeTrue ( ))
15921605 })
15931606
15941607 By ("updating the unlabeled CR to have matching labels" , func () {
@@ -1598,43 +1611,53 @@ var _ = Describe("Reconciler", func() {
15981611 })
15991612
16001613 By ("verifying that both CRs were reconciled after setting label to the unlabeled CR" , func () {
1601- Eventually (func () [] string {
1614+ Eventually (func () bool {
16021615 mu .Lock ()
16031616 defer mu .Unlock ()
1604- return reconciledCRs
1605- }, "10s" , "100ms" ).Should (ContainElements (labeledObjKey .Name , anotherObjKey .Name ))
1617+ return len (reconciledCRs ) == 2 &&
1618+ slices .Contains (reconciledCRs , labeledObjKey .Name ) &&
1619+ slices .Contains (reconciledCRs , anotherObjKey .Name )
1620+ }, "10s" , "100ms" ).Should (BeTrue ())
16061621 })
16071622 })
16081623
16091624 It ("should reconcile CRs independently when using two managers with different label selectors" , func () {
1610- By ("creating another manager with a different label selector" , func () {
1611- postHook := hook .PostHookFunc (func (obj * unstructured.Unstructured , _ release.Release , _ logr.Logger ) error {
1612- mu .Lock ()
1613- defer mu .Unlock ()
1614- if ! slices .Contains (anotherReconciledCRs , obj .GetName ()) {
1615- anotherReconciledCRs = append (anotherReconciledCRs , obj .GetName ())
1616- }
1617- return nil
1618- })
1619- _ = setupManagerWithSelectorAndPostHook (ctx , postHook , anotherMatchingLabels )
1620- })
1625+ labeledObj := testutil .BuildTestCR (gvk )
1626+ labeledObj .SetName ("labeled-cr-test2" )
1627+ labeledObj .SetLabels (matchingLabels )
1628+ labeledObjKey := types.NamespacedName {Namespace : labeledObj .GetNamespace (), Name : labeledObj .GetName ()}
1629+
1630+ anotherObj := testutil .BuildTestCR (gvk )
1631+ anotherObj .SetName ("another-cr-test2" )
1632+ anotherObjKey := types.NamespacedName {Namespace : anotherObj .GetNamespace (), Name : anotherObj .GetName ()}
1633+
1634+ var reconciledCRs []string
1635+ var anotherReconciledCRs []string
1636+
1637+ postHook := makePostHook (& mu , & reconciledCRs )
1638+ mgr , done := setupManagerWithSelectorAndPostHook (ctx , postHook , matchingLabels )
1639+ doneChans = append (doneChans , done )
1640+
1641+ postHook2 := makePostHook (& mu , & anotherReconciledCRs )
1642+ _ , done2 := setupManagerWithSelectorAndPostHook (ctx , postHook2 , anotherMatchingLabels )
1643+ doneChans = append (doneChans , done2 )
16211644
16221645 By ("creating a CR with matching labels for the first manager" , func () {
16231646 Expect (mgr .GetClient ().Create (ctx , labeledObj )).To (Succeed ())
16241647 })
16251648
16261649 By ("verifying that only the first manager reconciled the CR" , func () {
1627- Eventually (func () [] string {
1650+ Eventually (func () bool {
16281651 mu .Lock ()
16291652 defer mu .Unlock ()
1630- return reconciledCRs
1631- }, "10s" , "100ms" ).Should (HaveExactElements ( labeledObjKey . Name ))
1653+ return len ( reconciledCRs ) == 1 && reconciledCRs [ 0 ] == labeledObjKey . Name
1654+ }, "10s" , "100ms" ).Should (BeTrue ( ))
16321655
1633- Consistently (func () [] string {
1656+ Consistently (func () bool {
16341657 mu .Lock ()
16351658 defer mu .Unlock ()
1636- return anotherReconciledCRs
1637- }, "2s" , "100ms" ).Should (BeEmpty ())
1659+ return len ( anotherReconciledCRs ) == 0
1660+ }, "2s" , "100ms" ).Should (BeTrue ())
16381661 })
16391662
16401663 By ("creating a CR with matching labels for the second manager" , func () {
@@ -1645,17 +1668,17 @@ var _ = Describe("Reconciler", func() {
16451668 })
16461669
16471670 By ("verifying that both managers reconcile only matching labels CRs" , func () {
1648- Eventually (func () [] string {
1671+ Eventually (func () bool {
16491672 mu .Lock ()
16501673 defer mu .Unlock ()
1651- return reconciledCRs
1652- }, "10s" , "100ms" ).Should (HaveExactElements ( labeledObjKey . Name ))
1674+ return len ( reconciledCRs ) == 1 && reconciledCRs [ 0 ] == labeledObjKey . Name
1675+ }, "10s" , "100ms" ).Should (BeTrue ( ))
16531676
1654- Eventually (func () [] string {
1677+ Eventually (func () bool {
16551678 mu .Lock ()
16561679 defer mu .Unlock ()
1657- return anotherReconciledCRs
1658- }, "10s" , "100ms" ).Should (HaveExactElements ( anotherObjKey . Name ))
1680+ return len ( anotherReconciledCRs ) == 1 && anotherReconciledCRs [ 0 ] == anotherObjKey . Name
1681+ }, "10s" , "100ms" ).Should (BeTrue ( ))
16591682 })
16601683 })
16611684 })
@@ -1859,18 +1882,18 @@ func verifyEvent(ctx context.Context, cl client.Reader, obj metav1.Object, event
18591882 Message: %q` , eventType , reason , message ))
18601883}
18611884
1862- func ensureDeleteCR ( ctx context. Context , mgr manager. Manager , crKey types. NamespacedName , cr * unstructured. Unstructured ) {
1863- err := mgr . GetAPIReader (). Get ( ctx , crKey , cr )
1864- if apierrors . IsNotFound ( err ) {
1865- return
1866- }
1867- Expect ( err ). ToNot ( HaveOccurred ())
1868- cr . SetFinalizers ([] string {})
1869- Expect ( mgr . GetClient (). Update ( ctx , cr )). To ( Succeed ())
1870- Expect ( mgr . GetClient (). Delete ( ctx , cr )). To ( Succeed () )
1885+ func makePostHook ( mu * sync. Mutex , reconciledCRs * [] string ) hook. PostHook {
1886+ return hook . PostHookFunc ( func ( obj * unstructured. Unstructured , _ release. Release , _ logr. Logger ) error {
1887+ mu . Lock ()
1888+ defer mu . Unlock ()
1889+ if ! slices . Contains ( * reconciledCRs , obj . GetName ()) {
1890+ * reconciledCRs = append ( * reconciledCRs , obj . GetName ())
1891+ }
1892+ return nil
1893+ } )
18711894}
18721895
1873- func setupManagerWithSelectorAndPostHook (ctx context.Context , postHook hook.PostHook , matchingLabels map [string ]string ) manager.Manager {
1896+ func setupManagerWithSelectorAndPostHook (ctx context.Context , postHook hook.PostHook , matchingLabels map [string ]string ) ( manager.Manager , chan struct {}) {
18741897 mgr := getManagerOrFail ()
18751898 r , err := New (
18761899 WithGroupVersionKind (gvk ),
@@ -1880,9 +1903,12 @@ func setupManagerWithSelectorAndPostHook(ctx context.Context, postHook hook.Post
18801903 )
18811904 Expect (err ).ToNot (HaveOccurred ())
18821905 Expect (r .SetupWithManager (mgr )).To (Succeed ())
1906+
1907+ done := make (chan struct {})
18831908 go func () {
1909+ defer close (done )
18841910 Expect (mgr .Start (ctx )).To (Succeed ())
18851911 }()
18861912 Expect (mgr .GetCache ().WaitForCacheSync (ctx )).To (BeTrue ())
1887- return mgr
1913+ return mgr , done
18881914}
0 commit comments