Skip to content

Commit 150ef70

Browse files
committed
WIP: initial try to handle spoke and hub deletions from operator
1 parent 8ff052c commit 150ef70

56 files changed

Lines changed: 27032 additions & 19 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/v1alpha1/pattern_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ type PatternStatus struct {
206206
AnalyticsUUID string `json:"analyticsUUID,omitempty"`
207207
// +operator-sdk:csv:customresourcedefinitions:type=status
208208
LocalCheckoutPath string `json:"path,omitempty"`
209+
// +operator-sdk:csv:customresourcedefinitions:type=status
210+
// DeletionPhase tracks the current phase of pattern deletion
211+
// Values: "" (not deleting), "deletingSpokeApps" (phase 1: delete apps from spoke), "deletingHubApps" (phase 2: delete apps from hub)
212+
DeletionPhase string `json:"deletionPhase,omitempty"`
209213
}
210214

211215
// See: https://book.kubebuilder.io/reference/markers/crd.html

config/crd/bases/gitops.hybrid-cloud-patterns.io_patterns.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ spec:
224224
- type
225225
type: object
226226
type: array
227+
deletionPhase:
228+
description: |-
229+
DeletionPhase tracks the current phase of pattern deletion
230+
Values: "" (not deleting), "deletingSpokeApps" (phase 1: delete apps from spoke), "deletingHubApps" (phase 2: delete apps from hub)
231+
type: string
227232
lastError:
228233
description: Last error encountered by the pattern
229234
type: string

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ require (
2727
sigs.k8s.io/controller-runtime v0.21.0
2828
)
2929

30-
require github.com/argoproj/argo-cd/v3 v3.0.19
30+
require (
31+
github.com/argoproj/argo-cd/v3 v3.0.19
32+
github.com/samber/lo v1.52.0
33+
)
3134

3235
require (
3336
cloud.google.com/go/compute/metadata v0.9.0 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,8 @@ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0t
410410
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
411411
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
412412
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
413+
github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
414+
github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
413415
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
414416
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
415417
github.com/segmentio/analytics-go/v3 v3.3.0 h1:8VOMaVGBW03pdBrj1CMFfY9o/rnjJC+1wyQHlVxjw5o=

internal/controller/acm.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"log"
2424

25+
kerrors "k8s.io/apimachinery/pkg/api/errors"
2526
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2627
"k8s.io/apimachinery/pkg/runtime/schema"
2728
)
@@ -64,3 +65,69 @@ func haveACMHub(r *PatternReconciler) bool {
6465
}
6566
return true
6667
}
68+
69+
// listManagedClusters lists all ManagedCluster resources (excluding local-cluster)
70+
// Returns a list of cluster names and an error
71+
func (r *PatternReconciler) listManagedClusters(ctx context.Context) ([]string, error) {
72+
gvrMC := schema.GroupVersionResource{
73+
Group: "cluster.open-cluster-management.io",
74+
Version: "v1",
75+
Resource: "managedclusters",
76+
}
77+
78+
// ManagedCluster is a cluster-scoped resource, so no namespace needed
79+
mcList, err := r.dynamicClient.Resource(gvrMC).List(ctx, metav1.ListOptions{})
80+
if err != nil {
81+
return nil, fmt.Errorf("failed to list ManagedClusters: %w", err)
82+
}
83+
84+
var clusterNames []string
85+
for _, item := range mcList.Items {
86+
name := item.GetName()
87+
// Exclude local-cluster (hub cluster)
88+
if name != "local-cluster" {
89+
clusterNames = append(clusterNames, name)
90+
}
91+
}
92+
93+
return clusterNames, nil
94+
}
95+
96+
// deleteManagedClusters deletes all ManagedCluster resources (excluding local-cluster)
97+
// Returns the number of clusters deleted and an error
98+
func (r *PatternReconciler) deleteManagedClusters(ctx context.Context) (int, error) {
99+
gvrMC := schema.GroupVersionResource{
100+
Group: "cluster.open-cluster-management.io",
101+
Version: "v1",
102+
Resource: "managedclusters",
103+
}
104+
105+
// ManagedCluster is a cluster-scoped resource, so no namespace needed
106+
mcList, err := r.dynamicClient.Resource(gvrMC).List(ctx, metav1.ListOptions{})
107+
if err != nil {
108+
return 0, fmt.Errorf("failed to list ManagedClusters: %w", err)
109+
}
110+
111+
deletedCount := 0
112+
for _, item := range mcList.Items {
113+
name := item.GetName()
114+
// Exclude local-cluster (hub cluster)
115+
if name == "local-cluster" {
116+
continue
117+
}
118+
119+
// Delete the managed cluster
120+
err := r.dynamicClient.Resource(gvrMC).Delete(ctx, name, metav1.DeleteOptions{})
121+
if err != nil {
122+
// If already deleted, that's fine
123+
if kerrors.IsNotFound(err) {
124+
continue
125+
}
126+
return deletedCount, fmt.Errorf("failed to delete ManagedCluster %q: %w", name, err)
127+
}
128+
log.Printf("Deleted ManagedCluster: %q", name)
129+
deletedCount++
130+
}
131+
132+
return deletedCount, nil
133+
}

internal/controller/argo.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,16 @@ func newApplicationParameters(p *api.Pattern) []argoapi.HelmParameter {
426426
}
427427
}
428428
if !p.DeletionTimestamp.IsZero() {
429+
// Determine deletePattern value based on deletion phase
430+
// Phase 1 (deletingSpokeApps): deletePattern = "2" (delete apps from spoke)
431+
// Phase 2 (deletingHubApps): deletePattern = "1" (delete apps from hub)
432+
deletePatternValue := "2" // default to spoke deletion
433+
if p.Status.DeletionPhase == "deletingHubApps" {
434+
deletePatternValue = "1"
435+
}
429436
parameters = append(parameters, argoapi.HelmParameter{
430437
Name: "global.deletePattern",
431-
Value: "1",
438+
Value: deletePatternValue,
432439
ForceString: true,
433440
})
434441
}

0 commit comments

Comments
 (0)