Skip to content

Commit

Permalink
add unit test for GarbageCollectorRunner
Browse files Browse the repository at this point in the history
Signed-off-by: Ryotaro Banno <[email protected]>
  • Loading branch information
ushitora-anqou committed Dec 2, 2024
1 parent 44add37 commit 320f305
Showing 1 changed file with 178 additions and 0 deletions.
178 changes: 178 additions & 0 deletions internal/controller/garbage_collector_runner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package controller

import (
"time"

mantlev1 "github.com/cybozu-go/mantle/api/v1"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
)

var _ = Describe("garbage collector", func() {
var err error

Context("isMantleRestoreAlreadyDeleted", func() {
doTest :=
func(
ctx SpecContext,
buildMR func(ns string) *mantlev1.MantleRestore,
buildPV func(ns string, mr *mantlev1.MantleRestore) *corev1.PersistentVolume,
expectError, expectDeleted bool,
) {
runner := NewGarbageCollectorRunner(k8sClient, 1*time.Second)
ns := resMgr.CreateNamespace()
mr := buildMR(ns)
if mr != nil {
err = k8sClient.Create(ctx, mr)
Expect(err).NotTo(HaveOccurred())
err = k8sClient.Get(ctx, types.NamespacedName{Name: mr.GetName(), Namespace: mr.GetNamespace()}, mr)
Expect(err).NotTo(HaveOccurred())
}
pv := buildPV(ns, mr)

deleted, err := runner.isMantleRestoreAlreadyDeleted(ctx, pv)
if expectError {
Expect(err).To(HaveOccurred())
} else {
Expect(err).NotTo(HaveOccurred())
}
Expect(deleted).To(Equal(expectDeleted))
}

makeMR := func(ns string) *mantlev1.MantleRestore {
var mr mantlev1.MantleRestore
mr.SetName("mr")
mr.SetNamespace(ns)
mr.Spec.Backup = "dummy"
return &mr
}

makePV := func(ns string, mr *mantlev1.MantleRestore) *corev1.PersistentVolume {
var pv corev1.PersistentVolume
pv.SetAnnotations(map[string]string{
PVAnnotationRestoredBy: string(mr.GetUID()),
PVAnnotationRestoredByName: "mr",
PVAnnotationRestoredByNamespace: ns,
})
return &pv
}

DescribeTable("isMantleRestoreAlreadyDeleted",
doTest,
Entry("MantleRestore exists", makeMR, makePV, false, false),
Entry(
"MantleRestore does NOT exist",
func(ns string) *mantlev1.MantleRestore { return nil },
func(ns string, mr *mantlev1.MantleRestore) *corev1.PersistentVolume {
var pv corev1.PersistentVolume
pv.SetAnnotations(map[string]string{
PVAnnotationRestoredBy: "uid",
PVAnnotationRestoredByName: "mr",
PVAnnotationRestoredByNamespace: ns,
})
return &pv
},
false, true,
),
Entry(
"MantleRestore exists, but the PV's annotation has unexpected MR's UID",
makeMR,
func(ns string, mr *mantlev1.MantleRestore) *corev1.PersistentVolume {
pv := makePV(ns, mr)
pv.Annotations[PVAnnotationRestoredBy] = "unexpected-uid"
return pv
},
false, true,
),
Entry(
"PV annotation of restored-by missing",
makeMR,
func(ns string, mr *mantlev1.MantleRestore) *corev1.PersistentVolume {
pv := makePV(ns, mr)
delete(pv.Annotations, PVAnnotationRestoredBy)
return pv
},
true, false,
),
Entry(
"PV annotation of restored-by-name missing",
makeMR,
func(ns string, mr *mantlev1.MantleRestore) *corev1.PersistentVolume {
pv := makePV(ns, mr)
delete(pv.Annotations, PVAnnotationRestoredByName)
return pv
},
true, false,
),
Entry(
"PV annotation of restored-by-namespace missing",
makeMR,
func(ns string, mr *mantlev1.MantleRestore) *corev1.PersistentVolume {
pv := makePV(ns, mr)
delete(pv.Annotations, PVAnnotationRestoredByNamespace)
return pv
},
true, false,
),
)
})

Context("deleteOrphanPVs", func() {
It("should remove only orphan PVs", func(ctx SpecContext) {
runner := NewGarbageCollectorRunner(k8sClient, 1*time.Second)
ns := resMgr.CreateNamespace()

mr1 := mantlev1.MantleRestore{}
mr1.SetName("mr1")
mr1.SetNamespace(ns)
mr1.Spec.Backup = "dummy"
err = k8sClient.Create(ctx, &mr1)
Expect(err).NotTo(HaveOccurred())
err = k8sClient.Get(ctx, types.NamespacedName{Name: mr1.GetName(), Namespace: mr1.GetNamespace()}, &mr1)
Expect(err).NotTo(HaveOccurred())

pv1, _, err := resMgr.CreateUniquePVAndPVC(ctx, ns)
Expect(err).NotTo(HaveOccurred())
pv1.SetLabels(map[string]string{
labelRestoringPVKey: labelRestoringPVValue,
})
pv1.SetAnnotations(map[string]string{
PVAnnotationRestoredBy: string(mr1.GetUID()),
PVAnnotationRestoredByName: mr1.GetName(),
PVAnnotationRestoredByNamespace: mr1.GetNamespace(),
})
err = k8sClient.Update(ctx, pv1)
Expect(err).NotTo(HaveOccurred())

pv2, _, err := resMgr.CreateUniquePVAndPVC(ctx, ns)
Expect(err).NotTo(HaveOccurred())
pv2.SetLabels(map[string]string{
labelRestoringPVKey: labelRestoringPVValue,
})
pv2.SetAnnotations(map[string]string{
PVAnnotationRestoredBy: "non-existing-uid",
PVAnnotationRestoredByName: "non-existing-name",
PVAnnotationRestoredByNamespace: "non-existing-namespace",
})
err = k8sClient.Update(ctx, pv2)
Expect(err).NotTo(HaveOccurred())

// No MantleRestore exists for pv2, so pv2 is orphan and should be removed.

// Perform deleteOrphanPVs.
err = runner.deleteOrphanPVs(ctx)
Expect(err).NotTo(HaveOccurred())

// pv1 should NOT be deleted.
err = k8sClient.Get(ctx, types.NamespacedName{Name: pv1.GetName()}, pv1)
Expect(err).NotTo(HaveOccurred())
Expect(pv1.DeletionTimestamp.IsZero()).To(BeTrue())
// pv2 should be deleted.
err = k8sClient.Get(ctx, types.NamespacedName{Name: pv2.GetName()}, pv2)
Expect(err).NotTo(HaveOccurred())
Expect(pv2.DeletionTimestamp.IsZero()).To(BeFalse())
})
})
})

0 comments on commit 320f305

Please sign in to comment.