parent
b00633976b
commit
75b7599178
|
@ -0,0 +1 @@
|
||||||
|
Add UT for pkg/util
|
|
@ -30,6 +30,8 @@ import (
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
|
|
||||||
clientTesting "k8s.io/client-go/testing"
|
clientTesting "k8s.io/client-go/testing"
|
||||||
|
|
||||||
|
velerotest "github.com/vmware-tanzu/velero/pkg/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEnsureDeletePod(t *testing.T) {
|
func TestEnsureDeletePod(t *testing.T) {
|
||||||
|
@ -91,3 +93,253 @@ func TestEnsureDeletePod(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsPodRunning(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
pod *corev1api.Pod
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "pod is nil",
|
||||||
|
err: "invalid input pod",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pod is not scheduled",
|
||||||
|
pod: &corev1api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pod",
|
||||||
|
},
|
||||||
|
Status: corev1api.PodStatus{
|
||||||
|
Phase: "fake-phase",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "pod is not scheduled, name=fake-pod, namespace=fake-ns, phase=fake-phase",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pod is not running",
|
||||||
|
pod: &corev1api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pod",
|
||||||
|
},
|
||||||
|
Spec: corev1api.PodSpec{
|
||||||
|
NodeName: "fake-node",
|
||||||
|
},
|
||||||
|
Status: corev1api.PodStatus{
|
||||||
|
Phase: "fake-phase",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "pod is not in the expected status, name=fake-pod, namespace=fake-ns, phase=fake-phase: pod is not running",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pod is being deleted",
|
||||||
|
pod: &corev1api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pod",
|
||||||
|
DeletionTimestamp: &metav1.Time{Time: time.Now()},
|
||||||
|
},
|
||||||
|
Spec: corev1api.PodSpec{
|
||||||
|
NodeName: "fake-node",
|
||||||
|
},
|
||||||
|
Status: corev1api.PodStatus{
|
||||||
|
Phase: corev1api.PodRunning,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "pod is being terminated, name=fake-pod, namespace=fake-ns, phase=Running",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "success",
|
||||||
|
pod: &corev1api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pod",
|
||||||
|
},
|
||||||
|
Spec: corev1api.PodSpec{
|
||||||
|
NodeName: "fake-node",
|
||||||
|
},
|
||||||
|
Status: corev1api.PodStatus{
|
||||||
|
Phase: corev1api.PodRunning,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
err := IsPodRunning(test.pod)
|
||||||
|
if err != nil {
|
||||||
|
assert.EqualError(t, err, test.err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsPodScheduled(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
pod *corev1api.Pod
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "pod is nil",
|
||||||
|
err: "invalid input pod",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pod is not scheduled",
|
||||||
|
pod: &corev1api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pod",
|
||||||
|
},
|
||||||
|
Status: corev1api.PodStatus{
|
||||||
|
Phase: "fake-phase",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "pod is not scheduled, name=fake-pod, namespace=fake-ns, phase=fake-phase",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pod is not running or pending",
|
||||||
|
pod: &corev1api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pod",
|
||||||
|
},
|
||||||
|
Spec: corev1api.PodSpec{
|
||||||
|
NodeName: "fake-node",
|
||||||
|
},
|
||||||
|
Status: corev1api.PodStatus{
|
||||||
|
Phase: "fake-phase",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "pod is not in the expected status, name=fake-pod, namespace=fake-ns, phase=fake-phase: pod is not running or pending",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pod is being deleted",
|
||||||
|
pod: &corev1api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pod",
|
||||||
|
DeletionTimestamp: &metav1.Time{Time: time.Now()},
|
||||||
|
},
|
||||||
|
Spec: corev1api.PodSpec{
|
||||||
|
NodeName: "fake-node",
|
||||||
|
},
|
||||||
|
Status: corev1api.PodStatus{
|
||||||
|
Phase: corev1api.PodRunning,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "pod is being terminated, name=fake-pod, namespace=fake-ns, phase=Running",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "success on running",
|
||||||
|
pod: &corev1api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pod",
|
||||||
|
},
|
||||||
|
Spec: corev1api.PodSpec{
|
||||||
|
NodeName: "fake-node",
|
||||||
|
},
|
||||||
|
Status: corev1api.PodStatus{
|
||||||
|
Phase: corev1api.PodRunning,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "success on pending",
|
||||||
|
pod: &corev1api.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pod",
|
||||||
|
},
|
||||||
|
Spec: corev1api.PodSpec{
|
||||||
|
NodeName: "fake-node",
|
||||||
|
},
|
||||||
|
Status: corev1api.PodStatus{
|
||||||
|
Phase: corev1api.PodPending,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
err := IsPodScheduled(test.pod)
|
||||||
|
if err != nil {
|
||||||
|
assert.EqualError(t, err, test.err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeletePodIfAny(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
podName string
|
||||||
|
podNamespace string
|
||||||
|
kubeClientObj []runtime.Object
|
||||||
|
kubeReactors []reactor
|
||||||
|
logMessage string
|
||||||
|
logLevel string
|
||||||
|
logError string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "get fail",
|
||||||
|
podName: "fake-pod",
|
||||||
|
podNamespace: "fake-namespace",
|
||||||
|
logMessage: "Abort deleting pod, it doesn't exist fake-namespace/fake-pod",
|
||||||
|
logLevel: "level=debug",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "delete fail",
|
||||||
|
podName: "fake-pod",
|
||||||
|
podNamespace: "fake-namespace",
|
||||||
|
kubeReactors: []reactor{
|
||||||
|
{
|
||||||
|
verb: "delete",
|
||||||
|
resource: "pods",
|
||||||
|
reactorFunc: func(action clientTesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, nil, errors.New("fake-delete-error")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
logMessage: "Failed to delete pod fake-namespace/fake-pod",
|
||||||
|
logLevel: "level=error",
|
||||||
|
logError: "error=fake-delete-error",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
fakeKubeClient := fake.NewSimpleClientset(test.kubeClientObj...)
|
||||||
|
|
||||||
|
for _, reactor := range test.kubeReactors {
|
||||||
|
fakeKubeClient.Fake.PrependReactor(reactor.verb, reactor.resource, reactor.reactorFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
var kubeClient kubernetes.Interface = fakeKubeClient
|
||||||
|
|
||||||
|
logMessage := ""
|
||||||
|
DeletePodIfAny(context.Background(), kubeClient.CoreV1(), test.podName, test.podNamespace, velerotest.NewSingleLogger(&logMessage))
|
||||||
|
|
||||||
|
if len(test.logMessage) > 0 {
|
||||||
|
assert.Contains(t, logMessage, test.logMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(test.logLevel) > 0 {
|
||||||
|
assert.Contains(t, logMessage, test.logLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(test.logError) > 0 {
|
||||||
|
assert.Contains(t, logMessage, test.logError)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -352,3 +352,485 @@ func TestDeletePVCIfAny(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeletePVIfAny(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
pvName string
|
||||||
|
kubeClientObj []runtime.Object
|
||||||
|
kubeReactors []reactor
|
||||||
|
logMessage string
|
||||||
|
logLevel string
|
||||||
|
logError string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "get fail",
|
||||||
|
pvName: "fake-pv",
|
||||||
|
logMessage: "Abort deleting PV, it doesn't exist, fake-pv",
|
||||||
|
logLevel: "level=debug",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "delete fail",
|
||||||
|
pvName: "fake-pv",
|
||||||
|
kubeReactors: []reactor{
|
||||||
|
{
|
||||||
|
verb: "delete",
|
||||||
|
resource: "persistentvolumes",
|
||||||
|
reactorFunc: func(action clientTesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, nil, errors.New("fake-delete-error")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
logMessage: "Failed to delete PV fake-pv",
|
||||||
|
logLevel: "level=error",
|
||||||
|
logError: "error=fake-delete-error",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
fakeKubeClient := fake.NewSimpleClientset(test.kubeClientObj...)
|
||||||
|
|
||||||
|
for _, reactor := range test.kubeReactors {
|
||||||
|
fakeKubeClient.Fake.PrependReactor(reactor.verb, reactor.resource, reactor.reactorFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
var kubeClient kubernetes.Interface = fakeKubeClient
|
||||||
|
|
||||||
|
logMessage := ""
|
||||||
|
DeletePVIfAny(context.Background(), kubeClient.CoreV1(), test.pvName, velerotest.NewSingleLogger(&logMessage))
|
||||||
|
|
||||||
|
if len(test.logMessage) > 0 {
|
||||||
|
assert.Contains(t, logMessage, test.logMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(test.logLevel) > 0 {
|
||||||
|
assert.Contains(t, logMessage, test.logLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(test.logError) > 0 {
|
||||||
|
assert.Contains(t, logMessage, test.logError)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnsureDeletePVC(t *testing.T) {
|
||||||
|
pvcObject := &corev1api.PersistentVolumeClaim{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pvc",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
clientObj []runtime.Object
|
||||||
|
pvcName string
|
||||||
|
namespace string
|
||||||
|
reactors []reactor
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "delete fail",
|
||||||
|
pvcName: "fake-pvc",
|
||||||
|
namespace: "fake-ns",
|
||||||
|
err: "error to delete pvc fake-pvc: persistentvolumeclaims \"fake-pvc\" not found",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "wait fail",
|
||||||
|
pvcName: "fake-pvc",
|
||||||
|
namespace: "fake-ns",
|
||||||
|
clientObj: []runtime.Object{pvcObject},
|
||||||
|
reactors: []reactor{
|
||||||
|
{
|
||||||
|
verb: "get",
|
||||||
|
resource: "persistentvolumeclaims",
|
||||||
|
reactorFunc: func(action clientTesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, nil, errors.New("fake-get-error")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "error to retrieve pvc info for fake-pvc: error to get pvc fake-pvc: fake-get-error",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
fakeKubeClient := fake.NewSimpleClientset(test.clientObj...)
|
||||||
|
|
||||||
|
for _, reactor := range test.reactors {
|
||||||
|
fakeKubeClient.Fake.PrependReactor(reactor.verb, reactor.resource, reactor.reactorFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
var kubeClient kubernetes.Interface = fakeKubeClient
|
||||||
|
|
||||||
|
err := EnsureDeletePVC(context.Background(), kubeClient.CoreV1(), test.pvcName, test.namespace, time.Millisecond)
|
||||||
|
if err != nil {
|
||||||
|
assert.EqualError(t, err, test.err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRebindPVC(t *testing.T) {
|
||||||
|
pvcObject := &corev1api.PersistentVolumeClaim{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pvc",
|
||||||
|
Annotations: map[string]string{
|
||||||
|
KubeAnnBindCompleted: "true",
|
||||||
|
KubeAnnBoundByController: "true",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
clientObj []runtime.Object
|
||||||
|
pvc *corev1api.PersistentVolumeClaim
|
||||||
|
pv string
|
||||||
|
reactors []reactor
|
||||||
|
result *corev1api.PersistentVolumeClaim
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "path fail",
|
||||||
|
pvc: pvcObject,
|
||||||
|
pv: "fake-pv",
|
||||||
|
clientObj: []runtime.Object{pvcObject},
|
||||||
|
reactors: []reactor{
|
||||||
|
{
|
||||||
|
verb: "patch",
|
||||||
|
resource: "persistentvolumeclaims",
|
||||||
|
reactorFunc: func(action clientTesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, nil, errors.New("fake-patch-error")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "error patching PVC: fake-patch-error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
pvc: pvcObject,
|
||||||
|
pv: "fake-pv",
|
||||||
|
clientObj: []runtime.Object{pvcObject},
|
||||||
|
result: &corev1api.PersistentVolumeClaim{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pvc",
|
||||||
|
},
|
||||||
|
Spec: corev1api.PersistentVolumeClaimSpec{
|
||||||
|
VolumeName: "fake-pv",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
fakeKubeClient := fake.NewSimpleClientset(test.clientObj...)
|
||||||
|
|
||||||
|
for _, reactor := range test.reactors {
|
||||||
|
fakeKubeClient.Fake.PrependReactor(reactor.verb, reactor.resource, reactor.reactorFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
var kubeClient kubernetes.Interface = fakeKubeClient
|
||||||
|
|
||||||
|
result, err := RebindPVC(context.Background(), kubeClient.CoreV1(), test.pvc, test.pv)
|
||||||
|
if err != nil {
|
||||||
|
assert.EqualError(t, err, test.err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, test.result, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResetPVBinding(t *testing.T) {
|
||||||
|
pvObject := &corev1api.PersistentVolume{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fake-pv",
|
||||||
|
Annotations: map[string]string{
|
||||||
|
KubeAnnBoundByController: "true",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: corev1api.PersistentVolumeSpec{
|
||||||
|
ClaimRef: &corev1api.ObjectReference{
|
||||||
|
Kind: "fake-kind",
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
Name: "fake-pvc",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
clientObj []runtime.Object
|
||||||
|
pv *corev1api.PersistentVolume
|
||||||
|
labels map[string]string
|
||||||
|
reactors []reactor
|
||||||
|
result *corev1api.PersistentVolume
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "path fail",
|
||||||
|
pv: pvObject,
|
||||||
|
clientObj: []runtime.Object{pvObject},
|
||||||
|
reactors: []reactor{
|
||||||
|
{
|
||||||
|
verb: "patch",
|
||||||
|
resource: "persistentvolumes",
|
||||||
|
reactorFunc: func(action clientTesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, nil, errors.New("fake-patch-error")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "error patching PV: fake-patch-error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
pv: pvObject,
|
||||||
|
labels: map[string]string{
|
||||||
|
"fake-label-1": "fake-value-1",
|
||||||
|
"fake-label-2": "fake-value-2",
|
||||||
|
},
|
||||||
|
clientObj: []runtime.Object{pvObject},
|
||||||
|
result: &corev1api.PersistentVolume{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fake-pv",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"fake-label-1": "fake-value-1",
|
||||||
|
"fake-label-2": "fake-value-2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
fakeKubeClient := fake.NewSimpleClientset(test.clientObj...)
|
||||||
|
|
||||||
|
for _, reactor := range test.reactors {
|
||||||
|
fakeKubeClient.Fake.PrependReactor(reactor.verb, reactor.resource, reactor.reactorFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
var kubeClient kubernetes.Interface = fakeKubeClient
|
||||||
|
|
||||||
|
result, err := ResetPVBinding(context.Background(), kubeClient.CoreV1(), test.pv, test.labels)
|
||||||
|
if err != nil {
|
||||||
|
assert.EqualError(t, err, test.err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, test.result, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetPVReclaimPolicy(t *testing.T) {
|
||||||
|
pvObject := &corev1api.PersistentVolume{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fake-pv",
|
||||||
|
},
|
||||||
|
Spec: corev1api.PersistentVolumeSpec{
|
||||||
|
PersistentVolumeReclaimPolicy: corev1api.PersistentVolumeReclaimRetain,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
clientObj []runtime.Object
|
||||||
|
pv *corev1api.PersistentVolume
|
||||||
|
policy corev1api.PersistentVolumeReclaimPolicy
|
||||||
|
reactors []reactor
|
||||||
|
result *corev1api.PersistentVolume
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "policy not changed",
|
||||||
|
pv: pvObject,
|
||||||
|
policy: corev1api.PersistentVolumeReclaimRetain,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "path fail",
|
||||||
|
pv: pvObject,
|
||||||
|
policy: corev1api.PersistentVolumeReclaimDelete,
|
||||||
|
clientObj: []runtime.Object{pvObject},
|
||||||
|
reactors: []reactor{
|
||||||
|
{
|
||||||
|
verb: "patch",
|
||||||
|
resource: "persistentvolumes",
|
||||||
|
reactorFunc: func(action clientTesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||||
|
return true, nil, errors.New("fake-patch-error")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "error patching PV: fake-patch-error",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "succeed",
|
||||||
|
pv: pvObject,
|
||||||
|
policy: corev1api.PersistentVolumeReclaimDelete,
|
||||||
|
clientObj: []runtime.Object{pvObject},
|
||||||
|
result: &corev1api.PersistentVolume{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fake-pv",
|
||||||
|
},
|
||||||
|
Spec: corev1api.PersistentVolumeSpec{
|
||||||
|
PersistentVolumeReclaimPolicy: corev1api.PersistentVolumeReclaimDelete,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
fakeKubeClient := fake.NewSimpleClientset(test.clientObj...)
|
||||||
|
|
||||||
|
for _, reactor := range test.reactors {
|
||||||
|
fakeKubeClient.Fake.PrependReactor(reactor.verb, reactor.resource, reactor.reactorFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
var kubeClient kubernetes.Interface = fakeKubeClient
|
||||||
|
|
||||||
|
result, err := SetPVReclaimPolicy(context.Background(), kubeClient.CoreV1(), test.pv, test.policy)
|
||||||
|
if err != nil {
|
||||||
|
assert.EqualError(t, err, test.err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, test.result, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWaitPVBound(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
pvName string
|
||||||
|
pvcName string
|
||||||
|
pvcNamespace string
|
||||||
|
kubeClientObj []runtime.Object
|
||||||
|
kubeReactors []reactor
|
||||||
|
expectedPV *corev1api.PersistentVolume
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "get pv error",
|
||||||
|
pvName: "fake-pv",
|
||||||
|
err: "error to wait for bound of PV: failed to get pv fake-pv: persistentvolumes \"fake-pv\" not found",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pvc claimRef miss",
|
||||||
|
pvName: "fake-pv",
|
||||||
|
kubeClientObj: []runtime.Object{
|
||||||
|
&corev1api.PersistentVolume{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fake-pv",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "error to wait for bound of PV: timed out waiting for the condition",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pvc claimRef pvc name mismatch",
|
||||||
|
pvName: "fake-pv",
|
||||||
|
pvcName: "fake-pvc",
|
||||||
|
kubeClientObj: []runtime.Object{
|
||||||
|
&corev1api.PersistentVolume{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fake-pv",
|
||||||
|
},
|
||||||
|
Spec: corev1api.PersistentVolumeSpec{
|
||||||
|
ClaimRef: &corev1api.ObjectReference{
|
||||||
|
Kind: "fake-kind",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "error to wait for bound of PV: timed out waiting for the condition",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pvc claimRef pvc namespace mismatch",
|
||||||
|
pvName: "fake-pv",
|
||||||
|
pvcName: "fake-pvc",
|
||||||
|
pvcNamespace: "fake-ns",
|
||||||
|
kubeClientObj: []runtime.Object{
|
||||||
|
&corev1api.PersistentVolume{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fake-pv",
|
||||||
|
},
|
||||||
|
Spec: corev1api.PersistentVolumeSpec{
|
||||||
|
ClaimRef: &corev1api.ObjectReference{
|
||||||
|
Kind: "fake-kind",
|
||||||
|
Name: "fake-pvc",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: "error to wait for bound of PV: timed out waiting for the condition",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "success",
|
||||||
|
pvName: "fake-pv",
|
||||||
|
pvcName: "fake-pvc",
|
||||||
|
pvcNamespace: "fake-ns",
|
||||||
|
kubeClientObj: []runtime.Object{
|
||||||
|
&corev1api.PersistentVolume{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fake-pv",
|
||||||
|
},
|
||||||
|
Spec: corev1api.PersistentVolumeSpec{
|
||||||
|
ClaimRef: &corev1api.ObjectReference{
|
||||||
|
Kind: "fake-kind",
|
||||||
|
Name: "fake-pvc",
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedPV: &corev1api.PersistentVolume{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "fake-pv",
|
||||||
|
},
|
||||||
|
Spec: corev1api.PersistentVolumeSpec{
|
||||||
|
ClaimRef: &corev1api.ObjectReference{
|
||||||
|
Kind: "fake-kind",
|
||||||
|
Name: "fake-pvc",
|
||||||
|
Namespace: "fake-ns",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
fakeKubeClient := fake.NewSimpleClientset(test.kubeClientObj...)
|
||||||
|
|
||||||
|
for _, reactor := range test.kubeReactors {
|
||||||
|
fakeKubeClient.Fake.PrependReactor(reactor.verb, reactor.resource, reactor.reactorFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
var kubeClient kubernetes.Interface = fakeKubeClient
|
||||||
|
|
||||||
|
pv, err := WaitPVBound(context.Background(), kubeClient.CoreV1(), test.pvName, test.pvcName, test.pvcNamespace, time.Millisecond)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
assert.EqualError(t, err, test.err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, test.expectedPV, pv)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue