Skip to content

Commit 6ba5a87

Browse files
committed
fix(dataprotection): defer restore source resolution
1 parent 7a5a09d commit 6ba5a87

4 files changed

Lines changed: 24 additions & 66 deletions

File tree

pkg/controller/plan/restore.go

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -182,17 +182,16 @@ func (r *RestoreManager) BuildPrepareDataRestore(comp *component.SynthesizedComp
182182
sourceTargetName, sourceTarget := backupSourceTargetForRestore(backupObj)
183183
if r.SourceTargetName != "" {
184184
sourceTargetName = r.SourceTargetName
185-
sourceTarget = backupSourceTargetByName(backupObj, r.SourceTargetName)
186-
if sourceTarget == nil {
187-
return nil, intctrlutil.NewFatalError(fmt.Sprintf(`source target "%s" not found in backup "%s"`, r.SourceTargetName, backupObj.Name))
188-
}
185+
// Source-target validation and resolution belong to the DataProtection
186+
// Restore path. This layer only carries the public Restore intent.
187+
sourceTarget = nil
189188
}
190189
restore := &dpv1alpha1.Restore{
191190
ObjectMeta: r.GetRestoreObjectMeta(comp, dpv1alpha1.PrepareData, templateName),
192191
Spec: dpv1alpha1.RestoreSpec{
193192
Backup: dpv1alpha1.BackupRef{
194193
Name: backupObj.Name,
195-
Namespace: r.namespace,
194+
Namespace: backupObj.Namespace,
196195
SourceTargetName: sourceTargetName,
197196
},
198197
RestoreTime: r.RestoreTime,
@@ -254,7 +253,7 @@ func (r *RestoreManager) DoPostReady(comp *component.SynthesizedComponent,
254253
Spec: dpv1alpha1.RestoreSpec{
255254
Backup: dpv1alpha1.BackupRef{
256255
Name: backupObj.Name,
257-
Namespace: r.namespace,
256+
Namespace: backupObj.Namespace,
258257
SourceTargetName: sourceTargetName,
259258
},
260259
RestoreTime: r.RestoreTime,
@@ -306,24 +305,6 @@ func backupSourceTargetForRestore(backupObj *dpv1alpha1.Backup) (string, *dpv1al
306305
return "", nil
307306
}
308307

309-
func backupSourceTargetByName(backupObj *dpv1alpha1.Backup, sourceTargetName string) *dpv1alpha1.BackupStatusTarget {
310-
if backupObj == nil || sourceTargetName == "" {
311-
return nil
312-
}
313-
if backupObj.Status.Target != nil {
314-
if backupObj.Status.Target.Name == sourceTargetName {
315-
return backupObj.Status.Target
316-
}
317-
return nil
318-
}
319-
for i := range backupObj.Status.Targets {
320-
if backupObj.Status.Targets[i].Name == sourceTargetName {
321-
return &backupObj.Status.Targets[i]
322-
}
323-
}
324-
return nil
325-
}
326-
327308
func (r *RestoreManager) buildRequiredPolicy(sourceTarget *dpv1alpha1.BackupStatusTarget) *dpv1alpha1.RequiredPolicyForAllPodSelection {
328309
var requiredPolicy *dpv1alpha1.RequiredPolicyForAllPodSelection
329310
if sourceTarget != nil && sourceTarget.PodSelector.Strategy == dpv1alpha1.PodSelectionStrategyAll {

pkg/controller/plan/restore_test.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
dpv1alpha1 "github.com/apecloud/kubeblocks/apis/dataprotection/v1alpha1"
3232
"github.com/apecloud/kubeblocks/pkg/constant"
3333
"github.com/apecloud/kubeblocks/pkg/controller/component"
34-
intctrlutil "github.com/apecloud/kubeblocks/pkg/controllerutil"
3534
)
3635

3736
func newRestoreManagerForTest() *RestoreManager {
@@ -235,7 +234,7 @@ func TestRestoreManagerBuildPrepareDataRestore(t *testing.T) {
235234
SchedulingPolicy: &appsv1.SchedulingPolicy{NodeName: "node-a"},
236235
}
237236
backup := &dpv1alpha1.Backup{
238-
ObjectMeta: metav1.ObjectMeta{Name: "backup"},
237+
ObjectMeta: metav1.ObjectMeta{Name: "backup", Namespace: "backup-source"},
239238
Status: dpv1alpha1.BackupStatus{
240239
Targets: []dpv1alpha1.BackupStatusTarget{{
241240
BackupTarget: dpv1alpha1.BackupTarget{
@@ -263,7 +262,7 @@ func TestRestoreManagerBuildPrepareDataRestore(t *testing.T) {
263262
return
264263
}
265264
if restore.Spec.Backup.Name != "backup" ||
266-
restore.Spec.Backup.Namespace != "default" ||
265+
restore.Spec.Backup.Namespace != "backup-source" ||
267266
restore.Spec.Backup.SourceTargetName != "target-a" {
268267
t.Fatalf("unexpected backup ref: %#v", restore.Spec.Backup)
269268
}
@@ -338,7 +337,7 @@ func TestRestoreManagerBuildPrepareDataRestoreWithExplicitSourceTarget(t *testin
338337
}
339338
}
340339

341-
func TestRestoreManagerBuildPrepareDataRestoreRejectsUnknownSourceTarget(t *testing.T) {
340+
func TestRestoreManagerBuildPrepareDataRestorePassesUnknownSourceTargetToDataProtection(t *testing.T) {
342341
manager := newRestoreManagerForTest()
343342
manager.SourceTargetName = "missing-target"
344343
comp := &component.SynthesizedComponent{
@@ -366,12 +365,15 @@ func TestRestoreManagerBuildPrepareDataRestoreRejectsUnknownSourceTarget(t *test
366365
},
367366
}
368367

369-
_, err := manager.BuildPrepareDataRestore(comp, backup, nil)
370-
if err == nil {
371-
t.Fatal("expected unknown source target error")
368+
restore, err := manager.BuildPrepareDataRestore(comp, backup, nil)
369+
if err != nil {
370+
t.Fatalf("BuildPrepareDataRestore() error = %v", err)
371+
}
372+
if restore == nil {
373+
t.Fatal("restore is nil")
372374
}
373-
if !intctrlutil.IsTargetError(err, intctrlutil.ErrorTypeFatal) {
374-
t.Fatalf("expected fatal error, got %v", err)
375+
if restore.Spec.Backup.SourceTargetName != "missing-target" {
376+
t.Fatalf("source target = %q, want missing-target", restore.Spec.Backup.SourceTargetName)
375377
}
376378
}
377379

pkg/operations/horizontal_scaling.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,6 @@ func (hs horizontalScalingOpsHandler) createRestore(reqCtx intctrlutil.RequestCt
224224
}
225225
return nil
226226
}
227-
if len(backupObj.Status.Targets) > 1 && restoreMGR.SourceTargetName == "" {
228-
return intctrlutil.NewFatalError(fmt.Sprintf("scale-out from backup %s/%s requires sourceTargetName because it has multiple source targets", backupObj.Namespace, backupObj.Name))
229-
}
230227
// create restore
231228
restore, err := restoreMGR.BuildPrepareDataRestore(synthesizedComponent, backupObj, getTemplate(templateName))
232229
if err != nil {

pkg/operations/horizontal_scaling_test.go

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,14 @@ var _ = Describe("HorizontalScaling OpsRequest", func() {
268268
})
269269

270270
It("test to scale out replicas from a full backup", func() {
271+
backupNamespace := "backup-source-" + randomStr
272+
Expect(k8sClient.Create(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: backupNamespace}})).Should(Succeed())
273+
DeferCleanup(func() {
274+
_ = k8sClient.Delete(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: backupNamespace}})
275+
})
271276
By("create Backup")
272277
backupName := "backup-for-ops-" + randomStr
273-
backup := testdp.NewBackupFactory(testCtx.DefaultNamespace, backupName).
278+
backup := testdp.NewBackupFactory(backupNamespace, backupName).
274279
SetBackupPolicyName(testdp.BackupPolicyName).
275280
SetBackupMethod(testdp.VSBackupMethodName).
276281
Create(&testCtx).GetObject()
@@ -299,6 +304,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() {
299304
horizontalScaling := opsv1alpha1.HorizontalScaling{ScaleOut: &opsv1alpha1.ScaleOut{
300305
FromBackup: &opsv1alpha1.FromBackup{
301306
Name: backupName,
307+
Namespace: backupNamespace,
302308
SourceTargetName: "target-b",
303309
},
304310
}}
@@ -312,6 +318,7 @@ var _ = Describe("HorizontalScaling OpsRequest", func() {
312318
}, client.InNamespace(opsRes.OpsRequest.Namespace))).Should(Succeed())
313319
Expect(restoreList.Items).Should(HaveLen(2))
314320
for i := range restoreList.Items {
321+
Expect(restoreList.Items[i].Spec.Backup.Namespace).Should(Equal(backupNamespace))
315322
Expect(restoreList.Items[i].Spec.Backup.SourceTargetName).Should(Equal("target-b"))
316323
}
317324

@@ -347,35 +354,6 @@ var _ = Describe("HorizontalScaling OpsRequest", func() {
347354
checkOpsRequestPhaseIsSucceed(reqCtx, opsRes)
348355
})
349356

350-
It("fails scale-out from a multi-target backup without source target name", func() {
351-
backup := &dpv1alpha1.Backup{
352-
ObjectMeta: metav1.ObjectMeta{
353-
Namespace: testCtx.DefaultNamespace,
354-
Name: "multi-target-backup-" + randomStr,
355-
},
356-
Status: dpv1alpha1.BackupStatus{
357-
Targets: []dpv1alpha1.BackupStatusTarget{
358-
{BackupTarget: dpv1alpha1.BackupTarget{Name: "target-a"}},
359-
{BackupTarget: dpv1alpha1.BackupTarget{Name: "target-b"}},
360-
},
361-
},
362-
}
363-
restoreMGR := plan.NewRestoreManager(ctx, k8sClient, &appsv1.Cluster{
364-
ObjectMeta: metav1.ObjectMeta{Name: clusterName, Namespace: testCtx.DefaultNamespace},
365-
}, model.GetScheme(), nil, 1, 0)
366-
err := horizontalScalingOpsHandler{}.createRestore(
367-
intctrlutil.RequestCtx{Ctx: ctx},
368-
k8sClient,
369-
&OpsResource{OpsRequest: &opsv1alpha1.OpsRequest{}},
370-
nil,
371-
restoreMGR,
372-
&appsv1.ClusterComponentSpec{},
373-
backup,
374-
"")
375-
Expect(err).Should(HaveOccurred())
376-
Expect(err.Error()).Should(ContainSubstring("requires sourceTargetName"))
377-
})
378-
379357
It("test to scale in replicas with `scaleIn`", func() {
380358
By("scale in replicas from 3 to 1")
381359
horizontalScaling := opsv1alpha1.HorizontalScaling{ScaleIn: &opsv1alpha1.ScaleIn{}}

0 commit comments

Comments
 (0)