Skip to content

Commit afb2992

Browse files
Merge pull request #628 from darkdoc/improve_acm_check
feat: haveACMHub and usage refactor
2 parents a3a23cb + 1089063 commit afb2992

3 files changed

Lines changed: 44 additions & 31 deletions

File tree

internal/controller/acm.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"context"
2222
"fmt"
2323
"log"
24+
"strings"
2425

2526
kerrors "k8s.io/apimachinery/pkg/api/errors"
2627
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -30,12 +31,16 @@ import (
3031
func haveACMHub(r *PatternReconciler) bool {
3132
gvrMCH := schema.GroupVersionResource{Group: "operator.open-cluster-management.io", Version: "v1", Resource: "multiclusterhubs"}
3233

33-
_, err := r.dynamicClient.Resource(gvrMCH).Namespace("open-cluster-management").Get(context.Background(), "multiclusterhub", metav1.GetOptions{})
34+
mch, err := r.dynamicClient.Resource(gvrMCH).Namespace("open-cluster-management").Get(context.Background(), "multiclusterhub", metav1.GetOptions{})
3435
if err != nil {
3536
log.Printf("Error obtaining hub: %s\n", err)
3637
return false
3738
}
38-
return true
39+
40+
return strings.EqualFold(
41+
mch.GetAnnotations()["patterns.gitops.validatedpatterns.io/managed"],
42+
"true",
43+
)
3944
}
4045

4146
// listManagedClusters lists all ManagedCluster resources (excluding local-cluster)

internal/controller/acm_test.go

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ var _ = Describe("HaveACMHub", func() {
4141

4242
})
4343

44-
Context("when the ACM Hub exists", func() {
44+
Context("when the ACM Hub exists, and owned by the pattern operator", func() {
4545
BeforeEach(func() {
4646
hub := &unstructured.Unstructured{
4747
Object: map[string]any{
@@ -50,6 +50,9 @@ var _ = Describe("HaveACMHub", func() {
5050
"metadata": map[string]any{
5151
"name": "multiclusterhub",
5252
"namespace": "open-cluster-management",
53+
"annotations": map[string]any{
54+
"patterns.gitops.validatedpatterns.io/managed": "true",
55+
},
5356
},
5457
},
5558
}
@@ -63,21 +66,30 @@ var _ = Describe("HaveACMHub", func() {
6366
})
6467
})
6568

66-
Context("when the ACM Hub does not exist", func() {
69+
Context("when the ACM Hub exists, and NOT owned by the pattern operator", func() {
70+
BeforeEach(func() {
71+
hub := &unstructured.Unstructured{
72+
Object: map[string]any{
73+
"apiVersion": "operator.open-cluster-management.io/v1",
74+
"kind": "MultiClusterHub",
75+
"metadata": map[string]any{
76+
"name": "multiclusterhub",
77+
"namespace": "open-cluster-management",
78+
},
79+
},
80+
}
81+
_, err := dynamicClient.Resource(gvrMCH).Namespace("open-cluster-management").Create(context.Background(), hub, metav1.CreateOptions{})
82+
Expect(err).ToNot(HaveOccurred())
83+
})
84+
6785
It("should return false", func() {
6886
result := haveACMHub(patternReconciler)
6987
Expect(result).To(BeFalse())
7088
})
7189
})
7290

73-
Context("when there is an error listing ConfigMaps", func() {
74-
BeforeEach(func() {
75-
kubeClient.PrependReactor("list", "configmaps", func(testing.Action) (handled bool, ret runtime.Object, err error) {
76-
return true, nil, fmt.Errorf("config map error")
77-
})
78-
})
79-
80-
It("should return false and log the error", func() {
91+
Context("when the ACM Hub does not exist", func() {
92+
It("should return false", func() {
8193
result := haveACMHub(patternReconciler)
8294
Expect(result).To(BeFalse())
8395
})

internal/controller/pattern_controller.go

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -721,17 +721,21 @@ func (r *PatternReconciler) deleteHubApps(targetApp, app *argoapi.Application, n
721721
// Delete managed clusters (excluding local-cluster)
722722
// These must be removed before hub deletion can proceed because ACM won't delete properly if they exist
723723
// we do not care about the error, since we might be on a standalone cluster
724-
managedClusters, _ := r.listManagedClusters(context.Background())
724+
// Only do this if the pattern is in charge of the acm hub
725725

726-
if len(managedClusters) > 0 {
727-
deletedCount, err := r.deleteManagedClusters(context.TODO())
728-
if err != nil {
729-
return fmt.Errorf("failed to delete managed clusters: %w", err)
730-
}
726+
if haveACMHub(r) {
727+
managedClusters, _ := r.listManagedClusters(context.Background())
728+
729+
if len(managedClusters) > 0 {
730+
deletedCount, err := r.deleteManagedClusters(context.TODO())
731+
if err != nil {
732+
return fmt.Errorf("failed to delete managed clusters: %w", err)
733+
}
731734

732-
if deletedCount > 0 {
733-
log.Printf("Deleted %d managed cluster(s), waiting for them to be fully removed", deletedCount)
734-
return fmt.Errorf("deleted %d managed cluster(s), waiting for removal to complete before proceeding with hub deletion", deletedCount)
735+
if deletedCount > 0 {
736+
log.Printf("Deleted %d managed cluster(s), waiting for them to be fully removed", deletedCount)
737+
return fmt.Errorf("deleted %d managed cluster(s), waiting for removal to complete before proceeding with hub deletion", deletedCount)
738+
}
735739
}
736740
}
737741

@@ -784,17 +788,9 @@ func (r *PatternReconciler) finalizeObject(instance *api.Pattern) error {
784788
// Initialize deletion phase if not set
785789
if qualifiedInstance.Status.DeletionPhase == api.InitializeDeletion {
786790
log.Printf("Initializing deletion phase")
787-
if haveACMHub(r) {
788-
if err := r.updateDeletionPhase(qualifiedInstance, api.DeleteSpokeChildApps); err != nil {
789-
return err
790-
}
791-
} else {
792-
// There is no acm/spoke, we can directly start cleaning up child apps (from hub)
793-
if err := r.updateDeletionPhase(qualifiedInstance, api.DeleteHubChildApps); err != nil {
794-
return err
795-
}
791+
if err := r.updateDeletionPhase(qualifiedInstance, api.DeleteSpokeChildApps); err != nil {
792+
return err
796793
}
797-
798794
return fmt.Errorf("initialized deletion phase, requeueing now")
799795
}
800796

0 commit comments

Comments
 (0)