@@ -242,4 +242,56 @@ var _ = Describe("ImpVMSnapshot controller", func() {
242242 Expect (k8sClient .Get (ctx , types.NamespacedName {Name : parentName , Namespace : "default" }, updated )).To (Succeed ())
243243 Expect (updated .Status .BaseSnapshot ).To (Equal (childName ))
244244 })
245+
246+ It ("TestOperatorSnapshotReconciler_baseSnapshotExemptFromPruning — baseSnapshot child is never pruned" , func () {
247+ parentName := "snap-parent-exempt"
248+ baseChildName := "snap-parent-exec-0"
249+ otherChildName := "snap-parent-exec-1"
250+ parent := makeParentSnap (parentName , "default" , func (s * impv1alpha1.ImpVMSnapshotSpec ) {
251+ s .Retention = 1
252+ s .BaseSnapshot = baseChildName
253+ })
254+ Expect (k8sClient .Create (ctx , parent )).To (Succeed ())
255+ DeferCleanup (func () {
256+ list := & impv1alpha1.ImpVMSnapshotList {}
257+ _ = k8sClient .List (ctx , list , client .InNamespace ("default" ), client.MatchingLabels {impv1alpha1 .LabelSnapshotParent : parentName })
258+ for i := range list .Items {
259+ _ = k8sClient .Delete (ctx , & list .Items [i ])
260+ }
261+ _ = k8sClient .Delete (ctx , parent )
262+ })
263+
264+ fetched := & impv1alpha1.ImpVMSnapshot {}
265+ Expect (k8sClient .Get (ctx , types.NamespacedName {Name : parentName , Namespace : "default" }, fetched )).To (Succeed ())
266+
267+ now := metav1 .Now ()
268+ // Create baseSnapshot child (oldest, snap-parent-exec-0).
269+ baseChild := makeChildSnap (baseChildName , "default" , parentName , fetched .UID )
270+ Expect (k8sClient .Create (ctx , baseChild )).To (Succeed ())
271+ baseChild .Status .Phase = "Succeeded"
272+ baseChild .Status .TerminatedAt = & now
273+ Expect (k8sClient .Status ().Update (ctx , baseChild )).To (Succeed ())
274+
275+ // Create a second terminated child (newer, snap-parent-exec-1).
276+ otherChild := makeChildSnap (otherChildName , "default" , parentName , fetched .UID )
277+ Expect (k8sClient .Create (ctx , otherChild )).To (Succeed ())
278+ otherChild .Status .Phase = "Succeeded"
279+ otherChild .Status .TerminatedAt = & now
280+ Expect (k8sClient .Status ().Update (ctx , otherChild )).To (Succeed ())
281+
282+ r := newSnapshotReconciler ()
283+ _ , err := r .Reconcile (ctx , reconcile.Request {
284+ NamespacedName : types.NamespacedName {Name : parentName , Namespace : "default" },
285+ })
286+ Expect (err ).NotTo (HaveOccurred ())
287+
288+ // The elected baseSnapshot child must survive pruning even though it is the oldest.
289+ surviving := & impv1alpha1.ImpVMSnapshot {}
290+ Expect (k8sClient .Get (ctx , types.NamespacedName {Name : baseChildName , Namespace : "default" }, surviving )).To (Succeed ())
291+
292+ // status.baseSnapshot should also be elected.
293+ updatedParent := & impv1alpha1.ImpVMSnapshot {}
294+ Expect (k8sClient .Get (ctx , types.NamespacedName {Name : parentName , Namespace : "default" }, updatedParent )).To (Succeed ())
295+ Expect (updatedParent .Status .BaseSnapshot ).To (Equal (baseChildName ))
296+ })
245297})
0 commit comments