@@ -249,6 +249,207 @@ var _ = Describe("Restore", func() {
249249 restore .Status .Phase = dpv1alpha1 .RestorePhaseCompleted
250250 })()).ShouldNot (HaveOccurred ())
251251
252+ By ("clean up annotations after cluster running" )
253+ _ = restoreMGR .DoRestore (synthesizedComponent , compObj , true )
254+ Eventually (testapps .CheckObj (& testCtx , client .ObjectKeyFromObject (cluster ), func (g Gomega , tmpCluster * appsv1.Cluster ) {
255+ g .Expect (tmpCluster .Annotations [constant .RestoreFromBackupAnnotationKey ]).Should (BeEmpty ())
256+ })).Should (Succeed ())
257+ })
258+ })
259+ Context ("Cluster InstanceTemplate ranges Restore" , func () {
260+ const (
261+ compDefName = "test-compdef-1"
262+ defaultCompName = "mysql"
263+ topologyKey = "testTopologyKey"
264+ labelKey = "testNodeLabelKey"
265+ labelValue = "testLabelValue"
266+ )
267+
268+ var (
269+ compDef * appsv1.ComponentDefinition
270+ cluster * appsv1.Cluster
271+ synthesizedComponent * component.SynthesizedComponent
272+ compObj * appsv1.Component
273+ pvc * corev1.PersistentVolumeClaim
274+ backup * dpv1alpha1.Backup
275+ fullBackupActionSet * dpv1alpha1.ActionSet
276+ fullBackupActionSetName string
277+ startIndex = int32 (10 )
278+ )
279+
280+ BeforeEach (func () {
281+ By ("By creating backup policyTemplate " )
282+ compDef = testapps .NewComponentDefinitionFactory (compDefName ).
283+ SetDefaultSpec ().
284+ Create (& testCtx ).GetObject ()
285+
286+ testdp .NewBackupPolicyTemplateFactory ("backup-policy-template" ).
287+ SetCompDefs (compDef .Name ).
288+ WithRandomName ().
289+ AddBackupMethod (testdp .BackupMethodName , false , fullBackupActionSetName ).
290+ SetBackupMethodVolumeMounts (testapps .DataVolumeName , "/data" ).Create (& testCtx ).Get ()
291+
292+ pvcSpec := testapps .NewPVCSpec ("1Gi" )
293+ cluster = testapps .NewClusterFactory (testCtx .DefaultNamespace , clusterName , "" ).
294+ AddMultipleTemplateComponentRange (defaultCompName , compDefName ).
295+ SetReplicas (3 ).
296+ AddVolumeClaimTemplate (testapps .DataVolumeName , pvcSpec ).
297+ Create (& testCtx ).GetObject ()
298+
299+ By ("By mocking a pvc" )
300+ pvc = testapps .NewPersistentVolumeClaimFactory (
301+ testCtx .DefaultNamespace , "data-" + clusterName + "-" + defaultCompName + "-0" , clusterName , defaultCompName , "data" ).
302+ SetStorage ("1Gi" ).
303+ Create (& testCtx ).GetObject ()
304+
305+ By ("By mocking a pod" )
306+ volume := corev1.Volume {Name : pvc .Name , VolumeSource : corev1.VolumeSource {
307+ PersistentVolumeClaim : & corev1.PersistentVolumeClaimVolumeSource {ClaimName : pvc .Name }}}
308+ _ = testapps .NewPodFactory (testCtx .DefaultNamespace , clusterName + "-" + defaultCompName + "-0" ).
309+ AddAppInstanceLabel (clusterName ).
310+ AddAppComponentLabel (defaultCompName ).
311+ AddAppManagedByLabel ().
312+ AddVolume (volume ).
313+ AddContainer (corev1.Container {Name : testapps .DefaultMySQLContainerName , Image : testapps .ApeCloudMySQLImage }).
314+ AddNodeName ("fake-node-name" ).
315+ Create (& testCtx ).GetObject ()
316+
317+ By ("create actionset of full backup" )
318+ fullBackupActionSet = testapps .CreateCustomizedObj (& testCtx , "backup/actionset.yaml" , & dpv1alpha1.ActionSet {}, testapps .RandomizedObjName ())
319+ fullBackupActionSetName = fullBackupActionSet .Name
320+ synthesizedComponent = & component.SynthesizedComponent {
321+ PodSpec : & compDef .Spec .Runtime ,
322+ VolumeClaimTemplates : intctrlutil .ToCoreV1PVCTs (cluster .Spec .ComponentSpecs [0 ].VolumeClaimTemplates ),
323+ Name : defaultCompName ,
324+ Replicas : 3 ,
325+ Roles : []appsv1.ReplicaRole {
326+ {
327+ Name : "leader" ,
328+ UpdatePriority : 2 ,
329+ },
330+ {
331+ Name : "follower" ,
332+ UpdatePriority : 1 ,
333+ },
334+ },
335+ Instances : []appsv1.InstanceTemplate {{
336+ Name : "foo" ,
337+ Replicas : func () * int32 { replicas := int32 (1 ); return & replicas }(),
338+ Ordinals : appsv1.Ordinals {
339+ Ranges : []appsv1.Range {
340+ {Start : startIndex , End : 20 },
341+ },
342+ },
343+ }},
344+ }
345+ By ("create component object" )
346+ compObj = testapps .NewComponentFactory (testCtx .DefaultNamespace , cluster .Name + "-" + synthesizedComponent .Name , "" ).
347+ AddAnnotations (constant .KBAppClusterUIDKey , string (cluster .UID )).
348+ AddLabels (constant .AppInstanceLabelKey , cluster .Name ).
349+ SetReplicas (1 ).
350+ Create (& testCtx ).
351+ GetObject ()
352+
353+ By ("By creating remote pvc: " )
354+ remotePVC := testapps .NewPersistentVolumeClaimFactory (
355+ testCtx .DefaultNamespace , "remote-pvc" , clusterName , defaultCompName , "log" ).
356+ SetStorage ("1Gi" ).
357+ Create (& testCtx ).GetObject ()
358+
359+ By ("By creating base backup: " )
360+ backupLabels := map [string ]string {
361+ constant .AppInstanceLabelKey : sourceCluster ,
362+ constant .KBAppComponentLabelKey : defaultCompName ,
363+ }
364+ backup = testdp .NewBackupFactory (testCtx .DefaultNamespace , backupName ).
365+ WithRandomName ().SetLabels (backupLabels ).
366+ SetBackupPolicyName ("test-fake" ).
367+ SetBackupMethod (testdp .VSBackupMethodName ).
368+ Create (& testCtx ).GetObject ()
369+ baseStartTime := & startTime
370+ baseStopTime := & now
371+ backup .Status = dpv1alpha1.BackupStatus {
372+ Phase : dpv1alpha1 .BackupPhaseCompleted ,
373+ StartTimestamp : baseStartTime ,
374+ CompletionTimestamp : baseStopTime ,
375+ PersistentVolumeClaimName : remotePVC .Name ,
376+ }
377+ testdp .MockBackupStatusMethod (backup , testdp .VSBackupMethodName , testapps .DataVolumeName , testdp .ActionSetName )
378+ patchBackupStatus (backup .Status , client .ObjectKeyFromObject (backup ))
379+ })
380+
381+ It ("Test restore" , func () {
382+ By ("restore from backup" )
383+ restoreFromBackup := fmt .Sprintf (`{"%s": {"name":"%s"}}` , defaultCompName , backup .Name )
384+ Expect (testapps .ChangeObj (& testCtx , cluster , func (tmpCluster * appsv1.Cluster ) {
385+ tmpCluster .Annotations = map [string ]string {
386+ constant .RestoreFromBackupAnnotationKey : restoreFromBackup ,
387+ }
388+ })).Should (Succeed ())
389+ Expect (k8sClient .Get (ctx , client .ObjectKeyFromObject (cluster ), cluster )).Should (Succeed ())
390+ restoreMGR := NewRestoreManager (ctx , k8sClient , cluster , scheme .Scheme , nil , 3 , 0 )
391+
392+ By ("restore from template" )
393+ err := restoreMGR .DoRestore (synthesizedComponent , compObj , true )
394+ Expect (intctrlutil .IsTargetError (err , intctrlutil .ErrorTypeNeedWaiting )).Should (BeTrue ())
395+
396+ By ("verify template restore" )
397+ restore := & dpv1alpha1.Restore {}
398+ restoreMeta := restoreMGR .GetRestoreObjectMeta (synthesizedComponent , dpv1alpha1 .PrepareData , "foo" )
399+ namedspace := types.NamespacedName {Name : restoreMeta .Name , Namespace : restoreMeta .Namespace }
400+ Expect (k8sClient .Get (ctx , namedspace , restore )).Should (Succeed ())
401+ Expect (restore .Spec .PrepareDataConfig .RestoreVolumeClaimsTemplate .StartingIndex ).Should (Equal (startIndex ))
402+ Expect (restore .Spec .PrepareDataConfig .RestoreVolumeClaimsTemplate .Replicas ).Should (Equal (int32 (1 )))
403+
404+ By ("mock template restore of prepareData stage to Completed" )
405+ Expect (testapps .GetAndChangeObjStatus (& testCtx , namedspace , func (restore * dpv1alpha1.Restore ) {
406+ restore .Status .Phase = dpv1alpha1 .RestorePhaseCompleted
407+ })()).ShouldNot (HaveOccurred ())
408+
409+ By ("restore from default" )
410+ err = restoreMGR .DoRestore (synthesizedComponent , compObj , true )
411+ Expect (intctrlutil .IsTargetError (err , intctrlutil .ErrorTypeNeedWaiting )).Should (BeTrue ())
412+
413+ By ("verify default restore" )
414+ defaultMeta := restoreMGR .GetRestoreObjectMeta (synthesizedComponent , dpv1alpha1 .PrepareData , "" )
415+ defaultNs := types.NamespacedName {Name : defaultMeta .Name , Namespace : defaultMeta .Namespace }
416+ defaultRestore := & dpv1alpha1.Restore {}
417+ Expect (k8sClient .Get (ctx , defaultNs , defaultRestore )).Should (Succeed ())
418+ Expect (defaultRestore .Spec .PrepareDataConfig .RestoreVolumeClaimsTemplate .StartingIndex ).Should (Equal (int32 (0 )))
419+ Expect (defaultRestore .Spec .PrepareDataConfig .RestoreVolumeClaimsTemplate .Replicas ).Should (Equal (int32 (2 )))
420+
421+ By ("mock default restore of prepareData stage to Completed" )
422+ Expect (testapps .GetAndChangeObjStatus (& testCtx , defaultNs , func (restore * dpv1alpha1.Restore ) {
423+ restore .Status .Phase = dpv1alpha1 .RestorePhaseCompleted
424+ })()).ShouldNot (HaveOccurred ())
425+
426+ By ("mock component and cluster phase to Running" )
427+ Expect (testapps .ChangeObjStatus (& testCtx , cluster , func () {
428+ cluster .Status .Phase = appsv1 .RunningClusterPhase
429+ cluster .Status .Components = map [string ]appsv1.ClusterComponentStatus {
430+ defaultCompName : {
431+ Phase : appsv1 .RunningComponentPhase ,
432+ },
433+ }
434+ })).Should (Succeed ())
435+ Expect (testapps .ChangeObjStatus (& testCtx , compObj , func () {
436+ compObj .Status .Phase = appsv1 .RunningComponentPhase
437+ })).Should (Succeed ())
438+
439+ By ("wait for postReady restore created and mock it to Completed" )
440+ restoreMGR .Cluster = cluster
441+ _ = restoreMGR .DoRestore (synthesizedComponent , compObj , true )
442+
443+ // check if restore CR of postReady stage is created.
444+ restoreMeta = restoreMGR .GetRestoreObjectMeta (synthesizedComponent , dpv1alpha1 .PostReady , "" )
445+ namedspace = types.NamespacedName {Name : restoreMeta .Name , Namespace : restoreMeta .Namespace }
446+ Eventually (testapps .CheckObjExists (& testCtx , namedspace ,
447+ & dpv1alpha1.Restore {}, true )).Should (Succeed ())
448+ // set restore to Completed
449+ Expect (testapps .GetAndChangeObjStatus (& testCtx , namedspace , func (restore * dpv1alpha1.Restore ) {
450+ restore .Status .Phase = dpv1alpha1 .RestorePhaseCompleted
451+ })()).ShouldNot (HaveOccurred ())
452+
252453 By ("clean up annotations after cluster running" )
253454 _ = restoreMGR .DoRestore (synthesizedComponent , compObj , true )
254455 Eventually (testapps .CheckObj (& testCtx , client .ObjectKeyFromObject (cluster ), func (g Gomega , tmpCluster * appsv1.Cluster ) {
0 commit comments