Skip to content

Commit bd631b6

Browse files
committed
Add managers cleanup and change Eventually asserting for mutex objects
1 parent ae66a85 commit bd631b6

File tree

1 file changed

+108
-82
lines changed

1 file changed

+108
-82
lines changed

pkg/reconciler/reconciler_test.go

Lines changed: 108 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)