Skip to content

Commit 0ed0f2e

Browse files
authored
chore: move cluster backup cleanup into dp (#10226)
1 parent 23a801e commit 0ed0f2e

15 files changed

Lines changed: 503 additions & 85 deletions

cmd/dataprotection/main.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,14 @@ func main() {
337337
os.Exit(1)
338338
}
339339

340+
if err = (&dpcontrollers.ClusterBackupReconciler{
341+
Client: mgr.GetClient(),
342+
Recorder: mgr.GetEventRecorderFor("cluster-backup-controller"),
343+
}).SetupWithManager(mgr); err != nil {
344+
setupLog.Error(err, "unable to create controller", "controller", "ClusterBackup")
345+
os.Exit(1)
346+
}
347+
340348
if err = (&dpcontrollers.BackupScheduleReconciler{
341349
Client: dputils.NewCompatClient(mgr.GetClient()),
342350
Scheme: mgr.GetScheme(),

config/rbac/role.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ rules:
9595
resources:
9696
- clusters/finalizers
9797
verbs:
98+
- patch
9899
- update
99100
- apiGroups:
100101
- apps.kubeblocks.io

controllers/apps/cluster/cluster_controller_test.go

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,10 @@ import (
3636
"sigs.k8s.io/controller-runtime/pkg/client"
3737

3838
appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1"
39-
dpv1alpha1 "github.com/apecloud/kubeblocks/apis/dataprotection/v1alpha1"
4039
"github.com/apecloud/kubeblocks/pkg/constant"
4140
"github.com/apecloud/kubeblocks/pkg/controller/builder"
4241
"github.com/apecloud/kubeblocks/pkg/generics"
4342
testapps "github.com/apecloud/kubeblocks/pkg/testutil/apps"
44-
testdp "github.com/apecloud/kubeblocks/pkg/testutil/dataprotection"
4543
viper "github.com/apecloud/kubeblocks/pkg/viperx"
4644
)
4745

@@ -740,34 +738,16 @@ var _ = Describe("Cluster Controller", func() {
740738
}
741739

742740
deleteClusterWithBackup := func(terminationPolicy appsv1.TerminationPolicyType) {
743-
By("mocking a retained backup")
744-
backupPolicyName := "test-backup-policy"
745-
backupName := "test-backup"
746-
backupMethod := "test-backup-method"
747-
backup := testdp.NewBackupFactory(testCtx.DefaultNamespace, backupName).
748-
SetBackupPolicyName(backupPolicyName).
749-
SetBackupMethod(backupMethod).
750-
SetLabels(map[string]string{
751-
constant.AppManagedByLabelKey: constant.AppName,
752-
constant.AppInstanceLabelKey: clusterObj.Name,
753-
}).
754-
WithRandomName().
755-
Create(&testCtx).GetObject()
756-
backupKey := client.ObjectKeyFromObject(backup)
757-
Eventually(testapps.CheckObjExists(&testCtx, backupKey, &dpv1alpha1.Backup{}, true)).Should(Succeed())
758-
759741
By("delete the cluster")
760742
testapps.DeleteObject(&testCtx, clusterKey, &appsv1.Cluster{})
761743

762744
By("wait for the cluster to terminate")
763745
Eventually(testapps.CheckObjExists(&testCtx, clusterKey, &appsv1.Cluster{}, false)).Should(Succeed())
764746

765-
By(fmt.Sprintf("checking the backup with TerminationPolicyType=%s", terminationPolicy))
766-
if terminationPolicy == appsv1.WipeOut {
767-
Eventually(testapps.CheckObjExists(&testCtx, backupKey, &dpv1alpha1.Backup{}, false)).Should(Succeed())
768-
} else {
769-
Consistently(testapps.CheckObjExists(&testCtx, backupKey, &dpv1alpha1.Backup{}, true)).Should(Succeed())
770-
}
747+
By(fmt.Sprintf("checking backup cleanup is out of scope for apps with TerminationPolicyType=%s", terminationPolicy))
748+
// Backup cleanup is owned by the dataprotection controllers and covered by
749+
// dataprotection integration tests, so apps tests only verify that backup
750+
// presence does not block cluster deletion here.
771751

772752
By("check all other resources deleted")
773753
transCtx := &clusterTransformContext{

controllers/apps/cluster/transformer_cluster_deletion.go

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,11 @@ import (
3131
"sigs.k8s.io/controller-runtime/pkg/client"
3232

3333
appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1"
34-
dpv1alpha1 "github.com/apecloud/kubeblocks/apis/dataprotection/v1alpha1"
3534
appsutil "github.com/apecloud/kubeblocks/controllers/apps/util"
3635
"github.com/apecloud/kubeblocks/pkg/constant"
3736
"github.com/apecloud/kubeblocks/pkg/controller/graph"
3837
"github.com/apecloud/kubeblocks/pkg/controller/model"
3938
intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil"
40-
dptypes "github.com/apecloud/kubeblocks/pkg/dataprotection/types"
4139
)
4240

4341
// clusterDeletionTransformer handles cluster deletion
@@ -86,21 +84,6 @@ func (t *clusterDeletionTransformer) Transform(ctx graph.TransformContext, dag *
8684
// then list all the others objects owned by this cluster in cache, and delete them all
8785
ml := getAppInstanceML(*cluster)
8886

89-
toDeleteObjs := func(objs owningObjects) []client.Object {
90-
var delObjs []client.Object
91-
for _, obj := range objs {
92-
if obj.GetObjectKind().GroupVersionKind().Kind == dptypes.BackupKind {
93-
backupObj := obj.(*dpv1alpha1.Backup)
94-
// retain backup for data protection even if the cluster is wiped out.
95-
if backupObj.Spec.DeletionPolicy == dpv1alpha1.BackupDeletionPolicyRetain {
96-
continue
97-
}
98-
}
99-
delObjs = append(delObjs, obj)
100-
}
101-
return delObjs
102-
}
103-
10487
// add namespaced objects deletion vertex
10588
namespacedObjs, err := getOwningNamespacedObjects(transCtx.Context, transCtx.Client, cluster.Namespace, ml, toDeleteNamespacedKinds)
10689
if err != nil {
@@ -109,12 +92,10 @@ func (t *clusterDeletionTransformer) Transform(ctx graph.TransformContext, dag *
10992
return err
11093
}
11194
}
112-
if cluster.Spec.TerminationPolicy != appsv1.WipeOut {
113-
if err = getFailedBackups(transCtx.Context, transCtx.Client, cluster.Namespace, ml, namespacedObjs); err != nil {
114-
return err
115-
}
95+
delObjs := make([]client.Object, 0, len(namespacedObjs))
96+
for _, obj := range namespacedObjs {
97+
delObjs = append(delObjs, obj)
11698
}
117-
delObjs := toDeleteObjs(namespacedObjs)
11899

119100
// add non-namespaced objects deletion vertex
120101
nonNamespacedObjs, err := getOwningNonNamespacedObjects(transCtx.Context, transCtx.Client, ml, toDeleteNonNamespacedKinds)
@@ -124,7 +105,9 @@ func (t *clusterDeletionTransformer) Transform(ctx graph.TransformContext, dag *
124105
return err
125106
}
126107
}
127-
delObjs = append(delObjs, toDeleteObjs(nonNamespacedObjs)...)
108+
for _, obj := range nonNamespacedObjs {
109+
delObjs = append(delObjs, obj)
110+
}
128111

129112
delKindMap := map[string]sets.Empty{}
130113
for _, o := range delObjs {
@@ -166,11 +149,7 @@ func kindsForDelete() ([]client.ObjectList, []client.ObjectList) {
166149
}
167150

168151
func kindsForWipeOut() ([]client.ObjectList, []client.ObjectList) {
169-
namespacedKinds, nonNamespacedKinds := kindsForDelete()
170-
namespacedKindsPlus := []client.ObjectList{
171-
&dpv1alpha1.BackupList{},
172-
}
173-
return append(namespacedKinds, namespacedKindsPlus...), nonNamespacedKinds
152+
return kindsForDelete()
174153
}
175154

176155
func deleteCompNShardingInOrder4Terminate(transCtx *clusterTransformContext, dag *graph.DAG) (sets.Set[string], error) {

controllers/apps/cluster/transformer_cluster_deletion_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"sigs.k8s.io/controller-runtime/pkg/client"
3232

3333
appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1"
34+
dpv1alpha1 "github.com/apecloud/kubeblocks/apis/dataprotection/v1alpha1"
3435
appsutil "github.com/apecloud/kubeblocks/controllers/apps/util"
3536
"github.com/apecloud/kubeblocks/pkg/constant"
3637
"github.com/apecloud/kubeblocks/pkg/controller/graph"
@@ -164,4 +165,51 @@ var _ = Describe("clusterDeletionTransformer", func() {
164165
Expect(err).Should(Equal(graph.ErrPrematureStop))
165166
Expect(dag.Vertices()).Should(HaveLen(1))
166167
})
168+
169+
It("does not delete backups on wipeout", func() {
170+
cluster.Spec.TerminationPolicy = appsv1.WipeOut
171+
reader = &appsutil.MockReader{
172+
Objects: []client.Object{
173+
clusterDef,
174+
&dpv1alpha1.Backup{
175+
ObjectMeta: metav1.ObjectMeta{
176+
Namespace: testCtx.DefaultNamespace,
177+
Name: "test-cluster-backup",
178+
Labels: map[string]string{constant.AppInstanceLabelKey: cluster.Name},
179+
},
180+
},
181+
},
182+
}
183+
transCtx.Client = model.NewGraphClient(reader)
184+
dag = newDag(transCtx.Client.(model.GraphClient))
185+
186+
transformer := &clusterDeletionTransformer{}
187+
err := transformer.Transform(transCtx, dag)
188+
Expect(err).Should(Equal(graph.ErrPrematureStop))
189+
Expect(dag.Vertices()).Should(HaveLen(1))
190+
})
191+
192+
It("does not special-case failed backups on non-wipeout deletion", func() {
193+
cluster.Spec.TerminationPolicy = appsv1.Delete
194+
reader = &appsutil.MockReader{
195+
Objects: []client.Object{
196+
clusterDef,
197+
&dpv1alpha1.Backup{
198+
ObjectMeta: metav1.ObjectMeta{
199+
Namespace: testCtx.DefaultNamespace,
200+
Name: "test-cluster-failed-backup",
201+
Labels: map[string]string{constant.AppInstanceLabelKey: cluster.Name},
202+
},
203+
Status: dpv1alpha1.BackupStatus{Phase: dpv1alpha1.BackupPhaseFailed},
204+
},
205+
},
206+
}
207+
transCtx.Client = model.NewGraphClient(reader)
208+
dag = newDag(transCtx.Client.(model.GraphClient))
209+
210+
transformer := &clusterDeletionTransformer{}
211+
err := transformer.Transform(transCtx, dag)
212+
Expect(err).Should(Equal(graph.ErrPrematureStop))
213+
Expect(dag.Vertices()).Should(HaveLen(1))
214+
})
167215
})

controllers/apps/cluster/utils.go

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,9 @@ import (
3030
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
3131

3232
appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1"
33-
dpv1alpha1 "github.com/apecloud/kubeblocks/apis/dataprotection/v1alpha1"
3433
"github.com/apecloud/kubeblocks/pkg/constant"
3534
"github.com/apecloud/kubeblocks/pkg/controller/component"
3635
"github.com/apecloud/kubeblocks/pkg/controller/model"
37-
dptypes "github.com/apecloud/kubeblocks/pkg/dataprotection/types"
3836
)
3937

4038
type gvkNObjKey struct {
@@ -64,32 +62,6 @@ func getAppInstanceML(cluster appsv1.Cluster) client.MatchingLabels {
6462
}
6563
}
6664

67-
func getFailedBackups(ctx context.Context,
68-
cli client.Reader,
69-
namespace string,
70-
labels client.MatchingLabels,
71-
owningNamespacedObjects owningObjects) error {
72-
backupList := &dpv1alpha1.BackupList{}
73-
if err := cli.List(ctx, backupList, client.InNamespace(namespace), labels); err != nil {
74-
return err
75-
}
76-
77-
for i := range backupList.Items {
78-
backup := &backupList.Items[i]
79-
if backup.Status.Phase != dpv1alpha1.BackupPhaseFailed {
80-
continue
81-
}
82-
if backup.Labels[dptypes.BackupTypeLabelKey] != string(dpv1alpha1.BackupTypeContinuous) {
83-
gvr, err := getGVKName(backup, model.GetScheme())
84-
if err != nil {
85-
return err
86-
}
87-
owningNamespacedObjects[*gvr] = backup
88-
}
89-
}
90-
return nil
91-
}
92-
9365
func getOwningNamespacedObjects(ctx context.Context,
9466
cli client.Reader,
9567
namespace string,

controllers/dataprotection/backup_controller_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ var _ = Describe("Backup Controller test", func() {
6565
inNS := client.InNamespace(testCtx.DefaultNamespace)
6666
ml := client.HasLabels{testCtx.TestObjLabelKey}
6767

68-
testapps.ClearResources(&testCtx, generics.ClusterSignature, inNS, ml)
68+
testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ClusterSignature, true, inNS, ml)
6969
testapps.ClearResources(&testCtx, generics.PodSignature, inNS, ml)
7070
testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.BackupSignature, true, inNS)
7171
testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.BackupRepoSignature, true, ml)

controllers/dataprotection/backupschedule_controller_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ var _ = Describe("Backup Schedule Controller", func() {
4949
inNS := client.InNamespace(testCtx.DefaultNamespace)
5050
ml := client.HasLabels{testCtx.TestObjLabelKey}
5151

52-
testapps.ClearResources(&testCtx, generics.ClusterSignature, inNS, ml)
52+
testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.ClusterSignature, true, inNS, ml)
5353
testapps.ClearResources(&testCtx, generics.PodSignature, inNS, ml)
5454
testapps.ClearResources(&testCtx, generics.SecretSignature, inNS, ml)
5555
testapps.ClearResourcesWithRemoveFinalizerOption(&testCtx, generics.BackupPolicySignature, true, inNS)

0 commit comments

Comments
 (0)