Add more UT for the CSI plugins.
Signed-off-by: Xun Jiang <blackpigletbruce@gmail.com>pull/7661/head
parent
c888f51817
commit
30995bcbd2
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
Copyright the Velero contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
factorymocks "github.com/vmware-tanzu/velero/pkg/client/mocks"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/vmware-tanzu/velero/pkg/test"
|
||||
)
|
||||
|
||||
func TestVSExecute(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
item runtime.Unstructured
|
||||
vs *snapshotv1api.VolumeSnapshot
|
||||
backup *velerov1api.Backup
|
||||
createVS bool
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "VolumeSnapshot doesn't have backup label",
|
||||
item: velerotest.UnstructuredOrDie(
|
||||
`
|
||||
{
|
||||
"apiVersion": "snapshot.storage.k8s.io/v1",
|
||||
"kind": "VolumeSnapshot",
|
||||
"metadata": {
|
||||
"namespace": "ns",
|
||||
"name": "foo"
|
||||
}
|
||||
}
|
||||
`,
|
||||
),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "VolumeSnapshot doesn't exist in the cluster",
|
||||
vs: builder.ForVolumeSnapshot("foo", "bar").
|
||||
ObjectMeta(builder.WithLabelsMap(
|
||||
map[string]string{velerov1api.BackupNameLabel: "backup"},
|
||||
)).Status().
|
||||
BoundVolumeSnapshotContentName("vsc").
|
||||
Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Normal case, VolumeSnapshot should be deleted",
|
||||
vs: builder.ForVolumeSnapshot("foo", "bar").
|
||||
ObjectMeta(builder.WithLabelsMap(
|
||||
map[string]string{velerov1api.BackupNameLabel: "backup"},
|
||||
)).Status().
|
||||
BoundVolumeSnapshotContentName("vsc").
|
||||
Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectErr: false,
|
||||
createVS: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
crClient := velerotest.NewFakeControllerRuntimeClient(t)
|
||||
logger := logrus.StandardLogger()
|
||||
|
||||
p := volumeSnapshotDeleteItemAction{log: logger, crClient: crClient}
|
||||
|
||||
if test.vs != nil {
|
||||
vsMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(test.vs)
|
||||
require.NoError(t, err)
|
||||
test.item = &unstructured.Unstructured{Object: vsMap}
|
||||
}
|
||||
|
||||
if test.createVS {
|
||||
require.NoError(t, crClient.Create(context.TODO(), test.vs))
|
||||
}
|
||||
|
||||
err := p.Execute(
|
||||
&velero.DeleteItemActionExecuteInput{
|
||||
Item: test.item,
|
||||
Backup: test.backup,
|
||||
},
|
||||
)
|
||||
|
||||
if test.expectErr == false {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVSAppliesTo(t *testing.T) {
|
||||
p := volumeSnapshotDeleteItemAction{
|
||||
log: logrus.StandardLogger(),
|
||||
}
|
||||
selector, err := p.AppliesTo()
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshots.snapshot.storage.k8s.io"},
|
||||
},
|
||||
selector,
|
||||
)
|
||||
}
|
||||
|
||||
func TestNewVolumeSnapshotDeleteItemAction(t *testing.T) {
|
||||
logger := logrus.StandardLogger()
|
||||
crClient := velerotest.NewFakeControllerRuntimeClient(t)
|
||||
|
||||
f := &factorymocks.Factory{}
|
||||
f.On("KubebuilderClient").Return(nil, fmt.Errorf(""))
|
||||
plugin := NewVolumeSnapshotDeleteItemAction(f)
|
||||
_, err := plugin(logger)
|
||||
require.Error(t, err)
|
||||
|
||||
f1 := &factorymocks.Factory{}
|
||||
f1.On("KubebuilderClient").Return(crClient, nil)
|
||||
plugin1 := NewVolumeSnapshotDeleteItemAction(f1)
|
||||
_, err1 := plugin1(logger)
|
||||
require.NoError(t, err1)
|
||||
}
|
|
@ -45,7 +45,7 @@ type volumeSnapshotContentDeleteItemAction struct {
|
|||
// while restoring VolumeSnapshotContent.snapshot.storage.k8s.io resources
|
||||
func (p *volumeSnapshotContentDeleteItemAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshotcontent.snapshot.storage.k8s.io"},
|
||||
IncludedResources: []string{"volumesnapshotcontents.snapshot.storage.k8s.io"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
Copyright the Velero contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
factorymocks "github.com/vmware-tanzu/velero/pkg/client/mocks"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/vmware-tanzu/velero/pkg/test"
|
||||
)
|
||||
|
||||
func TestVSCExecute(t *testing.T) {
|
||||
snapshotHandleStr := "test"
|
||||
tests := []struct {
|
||||
name string
|
||||
item runtime.Unstructured
|
||||
vsc *snapshotv1api.VolumeSnapshotContent
|
||||
backup *velerov1api.Backup
|
||||
createVSC bool
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "VolumeSnapshotContent doesn't have backup label",
|
||||
item: velerotest.UnstructuredOrDie(
|
||||
`
|
||||
{
|
||||
"apiVersion": "snapshot.storage.k8s.io/v1",
|
||||
"kind": "VolumeSnapshotContent",
|
||||
"metadata": {
|
||||
"namespace": "ns",
|
||||
"name": "foo"
|
||||
}
|
||||
}
|
||||
`,
|
||||
),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "VolumeSnapshotContent doesn't exist in the cluster, no error",
|
||||
vsc: builder.ForVolumeSnapshotContent("bar").ObjectMeta(builder.WithLabelsMap(map[string]string{velerov1api.BackupNameLabel: "backup"})).Status(&snapshotv1api.VolumeSnapshotContentStatus{SnapshotHandle: &snapshotHandleStr}).Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Normal case, VolumeSnapshot should be deleted",
|
||||
vsc: builder.ForVolumeSnapshotContent("bar").ObjectMeta(builder.WithLabelsMap(map[string]string{velerov1api.BackupNameLabel: "backup"})).Status(&snapshotv1api.VolumeSnapshotContentStatus{SnapshotHandle: &snapshotHandleStr}).Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectErr: false,
|
||||
createVSC: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
crClient := velerotest.NewFakeControllerRuntimeClient(t)
|
||||
logger := logrus.StandardLogger()
|
||||
|
||||
p := volumeSnapshotContentDeleteItemAction{log: logger, crClient: crClient}
|
||||
|
||||
if test.vsc != nil {
|
||||
vscMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(test.vsc)
|
||||
require.NoError(t, err)
|
||||
test.item = &unstructured.Unstructured{Object: vscMap}
|
||||
}
|
||||
|
||||
if test.createVSC {
|
||||
require.NoError(t, crClient.Create(context.TODO(), test.vsc))
|
||||
}
|
||||
|
||||
err := p.Execute(
|
||||
&velero.DeleteItemActionExecuteInput{
|
||||
Item: test.item,
|
||||
Backup: test.backup,
|
||||
},
|
||||
)
|
||||
|
||||
if test.expectErr == false {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVSCAppliesTo(t *testing.T) {
|
||||
p := volumeSnapshotContentDeleteItemAction{
|
||||
log: logrus.StandardLogger(),
|
||||
}
|
||||
selector, err := p.AppliesTo()
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshotcontents.snapshot.storage.k8s.io"},
|
||||
},
|
||||
selector,
|
||||
)
|
||||
}
|
||||
|
||||
func TestNewVolumeSnapshotContentDeleteItemAction(t *testing.T) {
|
||||
logger := logrus.StandardLogger()
|
||||
crClient := velerotest.NewFakeControllerRuntimeClient(t)
|
||||
|
||||
f := &factorymocks.Factory{}
|
||||
f.On("KubebuilderClient").Return(nil, fmt.Errorf(""))
|
||||
plugin := NewVolumeSnapshotContentDeleteItemAction(f)
|
||||
_, err := plugin(logger)
|
||||
require.Error(t, err)
|
||||
|
||||
f1 := &factorymocks.Factory{}
|
||||
f1.On("KubebuilderClient").Return(crClient, nil)
|
||||
plugin1 := NewVolumeSnapshotContentDeleteItemAction(f1)
|
||||
_, err1 := plugin1(logger)
|
||||
require.NoError(t, err1)
|
||||
}
|
|
@ -122,8 +122,6 @@ const (
|
|||
VolumeSnapshotHandleAnnotation = "velero.io/csi-volumesnapshot-handle"
|
||||
VolumeSnapshotRestoreSize = "velero.io/csi-volumesnapshot-restore-size"
|
||||
DriverNameAnnotation = "velero.io/csi-driver-name"
|
||||
DeleteSecretNameAnnotation = "velero.io/csi-deletesnapshotsecret-name" // #nosec G101
|
||||
DeleteSecretNamespaceAnnotation = "velero.io/csi-deletesnapshotsecret-namespace" // #nosec G101
|
||||
VSCDeletionPolicyAnnotation = "velero.io/csi-vsc-deletion-policy"
|
||||
VolumeSnapshotClassSelectorLabel = "velero.io/csi-volumesnapshot-class"
|
||||
VolumeSnapshotClassDriverBackupAnnotationPrefix = "velero.io/csi-volumesnapshot-class"
|
||||
|
|
|
@ -18,6 +18,7 @@ package csi
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -40,6 +41,7 @@ import (
|
|||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
factorymocks "github.com/vmware-tanzu/velero/pkg/client/mocks"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/vmware-tanzu/velero/pkg/test"
|
||||
"github.com/vmware-tanzu/velero/pkg/util/boolptr"
|
||||
|
@ -365,3 +367,37 @@ func TestCancel(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPVCAppliesTo(t *testing.T) {
|
||||
p := pvcBackupItemAction{
|
||||
log: logrus.StandardLogger(),
|
||||
}
|
||||
selector, err := p.AppliesTo()
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
velero.ResourceSelector{
|
||||
IncludedResources: []string{"persistentvolumeclaims"},
|
||||
},
|
||||
selector,
|
||||
)
|
||||
}
|
||||
|
||||
func TestNewPVCBackupItemAction(t *testing.T) {
|
||||
logger := logrus.StandardLogger()
|
||||
crClient := velerotest.NewFakeControllerRuntimeClient(t)
|
||||
|
||||
f := &factorymocks.Factory{}
|
||||
f.On("KubebuilderClient").Return(nil, fmt.Errorf(""))
|
||||
plugin := NewPvcBackupItemAction(f)
|
||||
_, err := plugin(logger)
|
||||
require.Error(t, err)
|
||||
|
||||
f1 := &factorymocks.Factory{}
|
||||
f1.On("KubebuilderClient").Return(crClient, nil)
|
||||
plugin1 := NewPvcBackupItemAction(f1)
|
||||
_, err1 := plugin1(logger)
|
||||
require.NoError(t, err1)
|
||||
}
|
||||
|
|
|
@ -84,10 +84,15 @@ func (p *volumeSnapshotBackupItemAction) Execute(
|
|||
return nil, nil, "", nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
volumeSnapshotClassName := ""
|
||||
if vs.Spec.VolumeSnapshotClassName != nil {
|
||||
volumeSnapshotClassName = *vs.Spec.VolumeSnapshotClassName
|
||||
}
|
||||
|
||||
additionalItems := []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: kuberesource.VolumeSnapshotClasses,
|
||||
Name: *vs.Spec.VolumeSnapshotClassName,
|
||||
Name: volumeSnapshotClassName,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -128,6 +133,10 @@ func (p *volumeSnapshotBackupItemAction) Execute(
|
|||
WithField("Backup", fmt.Sprintf("%s/%s", backup.Namespace, backup.Name)).
|
||||
WithField("BackupPhase", backup.Status.Phase).Debugf("Clean VolumeSnapshots.")
|
||||
|
||||
if vsc == nil {
|
||||
vsc = &snapshotv1api.VolumeSnapshotContent{}
|
||||
}
|
||||
|
||||
csi.DeleteVolumeSnapshot(*vs, *vsc, backup, p.crClient, p.log)
|
||||
return item, nil, "", nil, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
Copyright the Velero contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
factorymocks "github.com/vmware-tanzu/velero/pkg/client/mocks"
|
||||
"github.com/vmware-tanzu/velero/pkg/kuberesource"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/vmware-tanzu/velero/pkg/test"
|
||||
)
|
||||
|
||||
func TestVSExecute(t *testing.T) {
|
||||
snapshotHandle := "handle"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
backup *velerov1api.Backup
|
||||
vs *snapshotv1api.VolumeSnapshot
|
||||
vsc *snapshotv1api.VolumeSnapshotContent
|
||||
expectedErr string
|
||||
expectedAdditionalItems []velero.ResourceIdentifier
|
||||
expectedItemToUpdate []velero.ResourceIdentifier
|
||||
}{
|
||||
{
|
||||
name: "VS not created by backup, has no status. Backup is finalizing",
|
||||
backup: builder.ForBackup("velero", "backup").
|
||||
Phase(velerov1api.BackupPhaseFinalizing).Result(),
|
||||
vs: builder.ForVolumeSnapshot("velero", "vs").
|
||||
VolumeSnapshotClass("class").Result(),
|
||||
expectedErr: "",
|
||||
},
|
||||
{
|
||||
name: "VS is not created by the backup, associated VSC not exists",
|
||||
backup: builder.ForBackup("velero", "backup").
|
||||
Phase(velerov1api.BackupPhaseInProgress).Result(),
|
||||
vs: builder.ForVolumeSnapshot("velero", "vs").
|
||||
VolumeSnapshotClass("class").Status().
|
||||
BoundVolumeSnapshotContentName("vsc").Result(),
|
||||
expectedErr: `error getting volume snapshot content from API: volumesnapshotcontents.snapshot.storage.k8s.io "vsc" not found`,
|
||||
},
|
||||
{
|
||||
name: "Normal case",
|
||||
backup: builder.ForBackup("velero", "backup").
|
||||
Phase(velerov1api.BackupPhaseInProgress).Result(),
|
||||
vs: builder.ForVolumeSnapshot("velero", "vs").
|
||||
ObjectMeta(builder.WithLabels(
|
||||
velerov1api.BackupNameLabel, "backup")).
|
||||
VolumeSnapshotClass("class").Status().
|
||||
BoundVolumeSnapshotContentName("vsc").Result(),
|
||||
vsc: builder.ForVolumeSnapshotContent("vsc").Status(
|
||||
&snapshotv1api.VolumeSnapshotContentStatus{
|
||||
SnapshotHandle: &snapshotHandle,
|
||||
},
|
||||
).Result(),
|
||||
expectedErr: "",
|
||||
expectedAdditionalItems: []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: kuberesource.VolumeSnapshotClasses,
|
||||
Name: "class",
|
||||
},
|
||||
{
|
||||
GroupResource: kuberesource.VolumeSnapshotContents,
|
||||
Name: "vsc",
|
||||
},
|
||||
},
|
||||
expectedItemToUpdate: []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: kuberesource.VolumeSnapshots,
|
||||
Namespace: "velero",
|
||||
Name: "vs",
|
||||
},
|
||||
{
|
||||
GroupResource: kuberesource.VolumeSnapshotContents,
|
||||
Name: "vsc",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(*testing.T) {
|
||||
vsBIA := volumeSnapshotBackupItemAction{
|
||||
log: logrus.New(),
|
||||
crClient: velerotest.NewFakeControllerRuntimeClient(t, tc.vs),
|
||||
}
|
||||
|
||||
item, err := runtime.DefaultUnstructuredConverter.ToUnstructured(tc.vs)
|
||||
require.NoError(t, err)
|
||||
|
||||
if tc.vsc != nil {
|
||||
require.NoError(t, vsBIA.crClient.Create(context.TODO(), tc.vsc))
|
||||
}
|
||||
|
||||
_, additionalItems, _, itemToUpdate, err := vsBIA.Execute(&unstructured.UnstructuredList{Object: item}, tc.backup)
|
||||
if tc.expectedErr == "" {
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
require.Equal(t, tc.expectedErr, err.Error())
|
||||
}
|
||||
|
||||
require.ElementsMatch(t, tc.expectedAdditionalItems, additionalItems)
|
||||
require.ElementsMatch(t, tc.expectedItemToUpdate, itemToUpdate)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVSProgress(t *testing.T) {
|
||||
errorStr := "error"
|
||||
readyToUse := true
|
||||
tests := []struct {
|
||||
name string
|
||||
backup *velerov1api.Backup
|
||||
vs *snapshotv1api.VolumeSnapshot
|
||||
vsc *snapshotv1api.VolumeSnapshotContent
|
||||
operationID string
|
||||
expectedErr bool
|
||||
expectedProgress *velero.OperationProgress
|
||||
}{
|
||||
{
|
||||
name: "Empty OperationID",
|
||||
operationID: "",
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "OperationID doesn't have slash",
|
||||
operationID: "invalid",
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "OperationID doesn't have valid timestamp",
|
||||
operationID: "ns/name/invalid",
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "OperationID represents VS does not exist",
|
||||
operationID: "ns/name/2024-04-11T18:49:00+08:00",
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "VS status is nil",
|
||||
operationID: "ns/name/2024-04-11T18:49:00+08:00",
|
||||
vs: builder.ForVolumeSnapshot("ns", "name").Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "VS status has error",
|
||||
operationID: "ns/name/2024-04-11T18:49:00+08:00",
|
||||
vs: builder.ForVolumeSnapshot("ns", "name").Status().
|
||||
StatusError(snapshotv1api.VolumeSnapshotError{
|
||||
Message: &errorStr,
|
||||
}).Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "Fail to get VSC",
|
||||
operationID: "ns/name/2024-04-11T18:49:00+08:00",
|
||||
vs: builder.ForVolumeSnapshot("ns", "name").Status().
|
||||
ReadyToUse(true).BoundVolumeSnapshotContentName("vsc").Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "VSC status is nil",
|
||||
operationID: "ns/name/2024-04-11T18:49:00+08:00",
|
||||
vs: builder.ForVolumeSnapshot("ns", "name").Status().
|
||||
ReadyToUse(true).BoundVolumeSnapshotContentName("vsc").Result(),
|
||||
vsc: builder.ForVolumeSnapshotContent("vsc").Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "VSC is ReadyToUse",
|
||||
operationID: "ns/name/2024-04-11T18:49:00+08:00",
|
||||
vs: builder.ForVolumeSnapshot("ns", "name").Status().
|
||||
ReadyToUse(true).BoundVolumeSnapshotContentName("vsc").Result(),
|
||||
vsc: builder.ForVolumeSnapshotContent("vsc").
|
||||
Status(&snapshotv1api.VolumeSnapshotContentStatus{
|
||||
ReadyToUse: &readyToUse,
|
||||
}).Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectedErr: false,
|
||||
expectedProgress: &velero.OperationProgress{Completed: true},
|
||||
},
|
||||
{
|
||||
name: "VSC status has error",
|
||||
operationID: "ns/name/2024-04-11T18:49:00+08:00",
|
||||
vs: builder.ForVolumeSnapshot("ns", "name").Status().
|
||||
ReadyToUse(true).BoundVolumeSnapshotContentName("vsc").Result(),
|
||||
vsc: builder.ForVolumeSnapshotContent("vsc").
|
||||
Status(&snapshotv1api.VolumeSnapshotContentStatus{
|
||||
Error: &snapshotv1api.VolumeSnapshotError{
|
||||
Message: &errorStr,
|
||||
},
|
||||
}).Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectedErr: false,
|
||||
expectedProgress: &velero.OperationProgress{
|
||||
Completed: true,
|
||||
Err: "error",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(*testing.T) {
|
||||
crClient := velerotest.NewFakeControllerRuntimeClient(t)
|
||||
logger := logrus.New()
|
||||
|
||||
vsBIA := volumeSnapshotBackupItemAction{
|
||||
log: logger,
|
||||
crClient: crClient,
|
||||
}
|
||||
|
||||
if tc.vs != nil {
|
||||
err := crClient.Create(context.Background(), tc.vs)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
if tc.vsc != nil {
|
||||
require.NoError(t, crClient.Create(context.TODO(), tc.vsc))
|
||||
}
|
||||
|
||||
progress, err := vsBIA.Progress(tc.operationID, tc.backup)
|
||||
if tc.expectedErr == false {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
if tc.expectedProgress != nil {
|
||||
require.True(
|
||||
t,
|
||||
cmp.Equal(
|
||||
*tc.expectedProgress,
|
||||
progress,
|
||||
cmpopts.IgnoreFields(
|
||||
velero.OperationProgress{},
|
||||
"Started",
|
||||
"Updated",
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVSAppliesTo(t *testing.T) {
|
||||
p := volumeSnapshotBackupItemAction{
|
||||
log: logrus.StandardLogger(),
|
||||
}
|
||||
selector, err := p.AppliesTo()
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshots.snapshot.storage.k8s.io"},
|
||||
},
|
||||
selector,
|
||||
)
|
||||
}
|
||||
|
||||
func TestNewVolumeSnapshotBackupItemAction(t *testing.T) {
|
||||
logger := logrus.StandardLogger()
|
||||
crClient := velerotest.NewFakeControllerRuntimeClient(t)
|
||||
|
||||
f := &factorymocks.Factory{}
|
||||
f.On("KubebuilderClient").Return(nil, fmt.Errorf(""))
|
||||
plugin := NewVolumeSnapshotBackupItemAction(f)
|
||||
_, err := plugin(logger)
|
||||
require.Error(t, err)
|
||||
|
||||
f1 := &factorymocks.Factory{}
|
||||
f1.On("KubebuilderClient").Return(crClient, nil)
|
||||
plugin1 := NewVolumeSnapshotBackupItemAction(f1)
|
||||
_, err1 := plugin1(logger)
|
||||
require.NoError(t, err1)
|
||||
}
|
|
@ -45,7 +45,7 @@ func (p *volumeSnapshotClassBackupItemAction) AppliesTo() (
|
|||
error,
|
||||
) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshotclass.snapshot.storage.k8s.io"},
|
||||
IncludedResources: []string{"volumesnapshotclasses.snapshot.storage.k8s.io"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
Copyright the Velero contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
"github.com/vmware-tanzu/velero/pkg/kuberesource"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
func TestVSClassExecute(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
item runtime.Unstructured
|
||||
vsClass *snapshotv1api.VolumeSnapshotClass
|
||||
backup *velerov1api.Backup
|
||||
expectErr bool
|
||||
expectedItems []velero.ResourceIdentifier
|
||||
}{
|
||||
{
|
||||
name: "No Secret in the VS Class, no return additional items",
|
||||
vsClass: builder.ForVolumeSnapshotClass("test").Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Normal case, additional items should return",
|
||||
vsClass: builder.ForVolumeSnapshotClass("test").ObjectMeta(builder.WithAnnotationsMap(
|
||||
map[string]string{
|
||||
velerov1api.PrefixedListSecretNameAnnotation: "name",
|
||||
velerov1api.PrefixedListSecretNamespaceAnnotation: "namespace",
|
||||
},
|
||||
)).Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectErr: false,
|
||||
expectedItems: []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: kuberesource.Secrets,
|
||||
Namespace: "namespace",
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
p, err := NewVolumeSnapshotClassBackupItemAction(logrus.StandardLogger())
|
||||
require.NoError(t, err)
|
||||
|
||||
action := p.(*volumeSnapshotClassBackupItemAction)
|
||||
|
||||
if test.vsClass != nil {
|
||||
vsMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(test.vsClass)
|
||||
require.NoError(t, err)
|
||||
test.item = &unstructured.Unstructured{Object: vsMap}
|
||||
}
|
||||
|
||||
_, additionalItems, _, _, err := action.Execute(
|
||||
test.item,
|
||||
test.backup,
|
||||
)
|
||||
|
||||
if test.expectErr == false {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
if len(test.expectedItems) > 0 {
|
||||
require.Equal(t, test.expectedItems, additionalItems)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVSClassAppliesTo(t *testing.T) {
|
||||
p := volumeSnapshotClassBackupItemAction{
|
||||
log: logrus.StandardLogger(),
|
||||
}
|
||||
selector, err := p.AppliesTo()
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshotclasses.snapshot.storage.k8s.io"},
|
||||
},
|
||||
selector,
|
||||
)
|
||||
}
|
|
@ -43,7 +43,7 @@ type volumeSnapshotContentBackupItemAction struct {
|
|||
// backup VolumeSnapshotContents.
|
||||
func (p *volumeSnapshotContentBackupItemAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshotcontent.snapshot.storage.k8s.io"},
|
||||
IncludedResources: []string{"volumesnapshotcontents.snapshot.storage.k8s.io"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
Copyright the Velero contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
"github.com/vmware-tanzu/velero/pkg/kuberesource"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/vmware-tanzu/velero/pkg/test"
|
||||
)
|
||||
|
||||
func TestVSCExecute(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
item runtime.Unstructured
|
||||
vsc *snapshotv1api.VolumeSnapshotContent
|
||||
backup *velerov1api.Backup
|
||||
expectErr bool
|
||||
expectedItems []velero.ResourceIdentifier
|
||||
}{
|
||||
{
|
||||
name: "Invalid VolumeSnapshotClass",
|
||||
item: velerotest.UnstructuredOrDie(
|
||||
`
|
||||
{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
"metadata": {
|
||||
"namespace": "ns",
|
||||
"name": "foo"
|
||||
}
|
||||
}
|
||||
`,
|
||||
),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Normal case, additional items should return",
|
||||
vsc: builder.ForVolumeSnapshotContent("test").ObjectMeta(builder.WithAnnotationsMap(
|
||||
map[string]string{
|
||||
velerov1api.PrefixedSecretNameAnnotation: "name",
|
||||
velerov1api.PrefixedSecretNamespaceAnnotation: "namespace",
|
||||
},
|
||||
)).Result(),
|
||||
backup: builder.ForBackup("velero", "backup").Result(),
|
||||
expectErr: false,
|
||||
expectedItems: []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: kuberesource.Secrets,
|
||||
Namespace: "namespace",
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
p, err := NewVolumeSnapshotContentBackupItemAction(logrus.StandardLogger())
|
||||
require.NoError(t, err)
|
||||
|
||||
action := p.(*volumeSnapshotContentBackupItemAction)
|
||||
|
||||
if test.vsc != nil {
|
||||
vsMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(test.vsc)
|
||||
require.NoError(t, err)
|
||||
test.item = &unstructured.Unstructured{Object: vsMap}
|
||||
}
|
||||
|
||||
_, additionalItems, _, _, err := action.Execute(
|
||||
test.item,
|
||||
test.backup,
|
||||
)
|
||||
|
||||
if test.expectErr == false {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
if len(test.expectedItems) > 0 {
|
||||
require.Equal(t, test.expectedItems, additionalItems)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVSCAppliesTo(t *testing.T) {
|
||||
p := volumeSnapshotContentBackupItemAction{
|
||||
log: logrus.StandardLogger(),
|
||||
}
|
||||
selector, err := p.AppliesTo()
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshotcontents.snapshot.storage.k8s.io"},
|
||||
},
|
||||
selector,
|
||||
)
|
||||
}
|
|
@ -93,3 +93,15 @@ func (v *VolumeSnapshotBuilder) VolumeSnapshotClass(name string) *VolumeSnapshot
|
|||
v.object.Spec.VolumeSnapshotClassName = &name
|
||||
return v
|
||||
}
|
||||
|
||||
// StatusError set the built VolumeSnapshot's status.Error value.
|
||||
func (v *VolumeSnapshotBuilder) StatusError(snapshotError snapshotv1api.VolumeSnapshotError) *VolumeSnapshotBuilder {
|
||||
v.object.Status.Error = &snapshotError
|
||||
return v
|
||||
}
|
||||
|
||||
// ReadyToUse set the built VolumeSnapshot's status.ReadyToUse value.
|
||||
func (v *VolumeSnapshotBuilder) ReadyToUse(readyToUse bool) *VolumeSnapshotBuilder {
|
||||
v.object.Status.ReadyToUse = &readyToUse
|
||||
return v
|
||||
}
|
||||
|
|
|
@ -84,3 +84,13 @@ func (v *VolumeSnapshotContentBuilder) ObjectMeta(opts ...ObjectMetaOpt) *Volume
|
|||
|
||||
return v
|
||||
}
|
||||
|
||||
func (v *VolumeSnapshotContentBuilder) Driver(driver string) *VolumeSnapshotContentBuilder {
|
||||
v.object.Spec.Driver = driver
|
||||
return v
|
||||
}
|
||||
|
||||
func (v *VolumeSnapshotContentBuilder) Source(source snapshotv1api.VolumeSnapshotContentSource) *VolumeSnapshotContentBuilder {
|
||||
v.object.Spec.Source = source
|
||||
return v
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package csi
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -40,6 +41,7 @@ import (
|
|||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
factorymocks "github.com/vmware-tanzu/velero/pkg/client/mocks"
|
||||
"github.com/vmware-tanzu/velero/pkg/label"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/vmware-tanzu/velero/pkg/test"
|
||||
|
@ -711,3 +713,37 @@ func TestExecute(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPVCAppliesTo(t *testing.T) {
|
||||
p := pvcRestoreItemAction{
|
||||
log: logrus.StandardLogger(),
|
||||
}
|
||||
selector, err := p.AppliesTo()
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
velero.ResourceSelector{
|
||||
IncludedResources: []string{"persistentvolumeclaims"},
|
||||
},
|
||||
selector,
|
||||
)
|
||||
}
|
||||
|
||||
func TestNewPvcRestoreItemAction(t *testing.T) {
|
||||
logger := logrus.StandardLogger()
|
||||
crClient := velerotest.NewFakeControllerRuntimeClient(t)
|
||||
|
||||
f := &factorymocks.Factory{}
|
||||
f.On("KubebuilderClient").Return(nil, fmt.Errorf(""))
|
||||
plugin := NewPvcRestoreItemAction(f)
|
||||
_, err := plugin(logger)
|
||||
require.Error(t, err)
|
||||
|
||||
f1 := &factorymocks.Factory{}
|
||||
f1.On("KubebuilderClient").Return(crClient, nil)
|
||||
plugin1 := NewPvcRestoreItemAction(f1)
|
||||
_, err1 := plugin1(logger)
|
||||
require.NoError(t, err1)
|
||||
}
|
||||
|
|
|
@ -76,13 +76,14 @@ func (p *volumeSnapshotRestoreItemAction) Execute(
|
|||
input *velero.RestoreItemActionExecuteInput,
|
||||
) (*velero.RestoreItemActionExecuteOutput, error) {
|
||||
p.log.Info("Starting VolumeSnapshotRestoreItemAction")
|
||||
|
||||
if boolptr.IsSetToFalse(input.Restore.Spec.RestorePVs) {
|
||||
p.log.Infof("Restore %s/%s did not request for PVs to be restored.",
|
||||
input.Restore.Namespace, input.Restore.Name)
|
||||
return &velero.RestoreItemActionExecuteOutput{SkipRestore: true}, nil
|
||||
}
|
||||
var vs snapshotv1api.VolumeSnapshot
|
||||
|
||||
var vs snapshotv1api.VolumeSnapshot
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(
|
||||
input.Item.UnstructuredContent(), &vs); err != nil {
|
||||
return &velero.RestoreItemActionExecuteOutput{},
|
||||
|
@ -101,7 +102,7 @@ func (p *volumeSnapshotRestoreItemAction) Execute(
|
|||
snapHandle, exists := vs.Annotations[velerov1api.VolumeSnapshotHandleAnnotation]
|
||||
if !exists {
|
||||
return nil, errors.Errorf(
|
||||
"Volumesnapshot %s/%s does not have a %s annotation",
|
||||
"VolumeSnapshot %s/%s does not have a %s annotation",
|
||||
vs.Namespace,
|
||||
vs.Name,
|
||||
velerov1api.VolumeSnapshotHandleAnnotation,
|
||||
|
@ -111,7 +112,7 @@ func (p *volumeSnapshotRestoreItemAction) Execute(
|
|||
csiDriverName, exists := vs.Annotations[velerov1api.DriverNameAnnotation]
|
||||
if !exists {
|
||||
return nil, errors.Errorf(
|
||||
"Volumesnapshot %s/%s does not have a %s annotation",
|
||||
"VolumeSnapshot %s/%s does not have a %s annotation",
|
||||
vs.Namespace, vs.Name, velerov1api.DriverNameAnnotation)
|
||||
}
|
||||
|
||||
|
@ -129,9 +130,10 @@ func (p *volumeSnapshotRestoreItemAction) Execute(
|
|||
DeletionPolicy: snapshotv1api.VolumeSnapshotContentRetain,
|
||||
Driver: csiDriverName,
|
||||
VolumeSnapshotRef: core_v1.ObjectReference{
|
||||
Kind: "VolumeSnapshot",
|
||||
Namespace: newNamespace,
|
||||
Name: vs.Name,
|
||||
APIVersion: "snapshot.storage.k8s.io/v1",
|
||||
Kind: "VolumeSnapshot",
|
||||
Namespace: newNamespace,
|
||||
Name: vs.Name,
|
||||
},
|
||||
Source: snapshotv1api.VolumeSnapshotContentSource{
|
||||
SnapshotHandle: &snapHandle,
|
||||
|
@ -149,7 +151,7 @@ func (p *volumeSnapshotRestoreItemAction) Execute(
|
|||
// See: https://github.com/kubernetes-csi/external-snapshotter/issues/274
|
||||
if err := p.crClient.Create(context.TODO(), &vsc); err != nil {
|
||||
return nil, errors.Wrapf(err,
|
||||
"failed to create volumesnapshotcontents %s",
|
||||
"failed to create VolumeSnapshotContents %s",
|
||||
vsc.GenerateName)
|
||||
}
|
||||
p.log.Infof("Created VolumesnapshotContents %s with static binding to volumesnapshot %s/%s",
|
||||
|
@ -169,7 +171,8 @@ func (p *volumeSnapshotRestoreItemAction) Execute(
|
|||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
p.log.Infof("Returning from VolumeSnapshotRestoreItemAction with no additionalItems")
|
||||
p.log.Infof(`Returning from VolumeSnapshotRestoreItemAction with
|
||||
no additionalItems`)
|
||||
|
||||
return &velero.RestoreItemActionExecuteOutput{
|
||||
UpdatedItem: &unstructured.Unstructured{Object: vsMap},
|
||||
|
|
|
@ -17,11 +17,25 @@ limitations under the License.
|
|||
package csi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
factorymocks "github.com/vmware-tanzu/velero/pkg/client/mocks"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/vmware-tanzu/velero/pkg/test"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -87,3 +101,144 @@ func TestResetVolumeSnapshotSpecForRestore(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVSExecute(t *testing.T) {
|
||||
snapshotHandle := "vsc"
|
||||
tests := []struct {
|
||||
name string
|
||||
item runtime.Unstructured
|
||||
vs *snapshotv1api.VolumeSnapshot
|
||||
restore *velerov1api.Restore
|
||||
expectErr bool
|
||||
createVS bool
|
||||
expectedVSC *snapshotv1api.VolumeSnapshotContent
|
||||
}{
|
||||
{
|
||||
name: "Restore's RestorePVs is false",
|
||||
restore: builder.ForRestore("velero", "restore").RestorePVs(false).Result(),
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Namespace remapping and VS already exists in cluster. Nothing change",
|
||||
vs: builder.ForVolumeSnapshot("ns", "name").Result(),
|
||||
restore: builder.ForRestore("velero", "restore").NamespaceMappings("ns", "newNS").Result(),
|
||||
createVS: true,
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "VS doesn't have VolumeSnapshotHandleAnnotation annotation",
|
||||
vs: builder.ForVolumeSnapshot("ns", "name").Result(),
|
||||
restore: builder.ForRestore("velero", "restore").NamespaceMappings("ns", "newNS").Result(),
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "VS doesn't have DriverNameAnnotation annotation",
|
||||
vs: builder.ForVolumeSnapshot("ns", "name").ObjectMeta(
|
||||
builder.WithAnnotations(velerov1api.VolumeSnapshotHandleAnnotation, ""),
|
||||
).Result(),
|
||||
restore: builder.ForRestore("velero", "restore").NamespaceMappings("ns", "newNS").Result(),
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "Normal case, VSC should be created",
|
||||
vs: builder.ForVolumeSnapshot("ns", "test").ObjectMeta(builder.WithAnnotationsMap(
|
||||
map[string]string{
|
||||
velerov1api.VolumeSnapshotHandleAnnotation: "vsc",
|
||||
velerov1api.DriverNameAnnotation: "pd.csi.storage.gke.io",
|
||||
},
|
||||
)).Result(),
|
||||
restore: builder.ForRestore("velero", "restore").Result(),
|
||||
expectErr: false,
|
||||
expectedVSC: builder.ForVolumeSnapshotContent("vsc").ObjectMeta(
|
||||
builder.WithLabels(velerov1api.RestoreNameLabel, "restore"),
|
||||
).VolumeSnapshotRef("ns", "test").
|
||||
DeletionPolicy(snapshotv1api.VolumeSnapshotContentRetain).
|
||||
Driver("pd.csi.storage.gke.io").
|
||||
Source(snapshotv1api.VolumeSnapshotContentSource{
|
||||
SnapshotHandle: &snapshotHandle,
|
||||
}).
|
||||
Result(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
p := volumeSnapshotRestoreItemAction{
|
||||
log: logrus.StandardLogger(),
|
||||
crClient: velerotest.NewFakeControllerRuntimeClient(t),
|
||||
}
|
||||
|
||||
if test.vs != nil {
|
||||
vsMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(test.vs)
|
||||
require.NoError(t, err)
|
||||
test.item = &unstructured.Unstructured{Object: vsMap}
|
||||
|
||||
if test.createVS == true {
|
||||
if newNS, ok := test.restore.Spec.NamespaceMapping[test.vs.Namespace]; ok {
|
||||
test.vs.SetNamespace(newNS)
|
||||
}
|
||||
require.NoError(t, p.crClient.Create(context.TODO(), test.vs))
|
||||
}
|
||||
}
|
||||
|
||||
_, err := p.Execute(
|
||||
&velero.RestoreItemActionExecuteInput{
|
||||
Item: test.item,
|
||||
Restore: test.restore,
|
||||
},
|
||||
)
|
||||
|
||||
if test.expectErr == false {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
if test.expectedVSC != nil {
|
||||
vscList := new(snapshotv1api.VolumeSnapshotContentList)
|
||||
require.NoError(t, p.crClient.List(context.TODO(), vscList))
|
||||
require.True(t, cmp.Equal(
|
||||
*test.expectedVSC,
|
||||
vscList.Items[0],
|
||||
cmpopts.IgnoreFields(
|
||||
snapshotv1api.VolumeSnapshotContent{},
|
||||
"Kind", "APIVersion", "GenerateName", "Name",
|
||||
"ResourceVersion",
|
||||
),
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVSAppliesTo(t *testing.T) {
|
||||
p := volumeSnapshotRestoreItemAction{
|
||||
log: logrus.StandardLogger(),
|
||||
}
|
||||
selector, err := p.AppliesTo()
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshots.snapshot.storage.k8s.io"},
|
||||
},
|
||||
selector,
|
||||
)
|
||||
}
|
||||
|
||||
func TestNewVolumeSnapshotRestoreItemAction(t *testing.T) {
|
||||
logger := logrus.StandardLogger()
|
||||
crClient := velerotest.NewFakeControllerRuntimeClient(t)
|
||||
|
||||
f := &factorymocks.Factory{}
|
||||
f.On("KubebuilderClient").Return(nil, fmt.Errorf(""))
|
||||
plugin := NewVolumeSnapshotRestoreItemAction(f)
|
||||
_, err := plugin(logger)
|
||||
require.Error(t, err)
|
||||
|
||||
f1 := &factorymocks.Factory{}
|
||||
f1.On("KubebuilderClient").Return(crClient, nil)
|
||||
plugin1 := NewVolumeSnapshotRestoreItemAction(f1)
|
||||
_, err1 := plugin1(logger)
|
||||
require.NoError(t, err1)
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ type volumeSnapshotClassRestoreItemAction struct {
|
|||
// should be invoked while restoring volumesnapshotclass.snapshot.storage.k8s.io resources.
|
||||
func (p *volumeSnapshotClassRestoreItemAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshotclass.snapshot.storage.k8s.io"},
|
||||
IncludedResources: []string{"volumesnapshotclasses.snapshot.storage.k8s.io"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
Copyright the Velero contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
"github.com/vmware-tanzu/velero/pkg/kuberesource"
|
||||
|
||||
//"github.com/vmware-tanzu/velero/pkg/kuberesource"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
func TestVSClassExecute(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
item runtime.Unstructured
|
||||
vsClass *snapshotv1api.VolumeSnapshotClass
|
||||
restore *velerov1api.Restore
|
||||
expectErr bool
|
||||
expectedItems []velero.ResourceIdentifier
|
||||
}{
|
||||
{
|
||||
name: "Restore's RestorePVs is false",
|
||||
restore: builder.ForRestore("velero", "restore").RestorePVs(false).Result(),
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "No Secret in the VS Class, no return additional items",
|
||||
vsClass: builder.ForVolumeSnapshotClass("test").Result(),
|
||||
restore: builder.ForRestore("velero", "restore").Result(),
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Normal case, additional items should return",
|
||||
vsClass: builder.ForVolumeSnapshotClass("test").ObjectMeta(builder.WithAnnotationsMap(
|
||||
map[string]string{
|
||||
velerov1api.PrefixedListSecretNameAnnotation: "name",
|
||||
velerov1api.PrefixedListSecretNamespaceAnnotation: "namespace",
|
||||
},
|
||||
)).Result(),
|
||||
restore: builder.ForRestore("velero", "restore").Result(),
|
||||
expectErr: false,
|
||||
expectedItems: []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: kuberesource.Secrets,
|
||||
Namespace: "namespace",
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
p, err := NewVolumeSnapshotClassRestoreItemAction(logrus.StandardLogger())
|
||||
require.NoError(t, err)
|
||||
|
||||
action := p.(*volumeSnapshotClassRestoreItemAction)
|
||||
|
||||
if test.vsClass != nil {
|
||||
vsMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(test.vsClass)
|
||||
require.NoError(t, err)
|
||||
test.item = &unstructured.Unstructured{Object: vsMap}
|
||||
}
|
||||
|
||||
output, err := action.Execute(
|
||||
&velero.RestoreItemActionExecuteInput{
|
||||
Item: test.item,
|
||||
Restore: test.restore,
|
||||
},
|
||||
)
|
||||
|
||||
if test.expectErr == false {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
if len(test.expectedItems) > 0 {
|
||||
require.Equal(t, test.expectedItems, output.AdditionalItems)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVSClassAppliesTo(t *testing.T) {
|
||||
p := volumeSnapshotClassRestoreItemAction{
|
||||
log: logrus.StandardLogger(),
|
||||
}
|
||||
selector, err := p.AppliesTo()
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshotclasses.snapshot.storage.k8s.io"},
|
||||
},
|
||||
selector,
|
||||
)
|
||||
}
|
|
@ -42,7 +42,7 @@ func (p *volumeSnapshotContentRestoreItemAction) AppliesTo() (
|
|||
velero.ResourceSelector, error,
|
||||
) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshotcontent.snapshot.storage.k8s.io"},
|
||||
IncludedResources: []string{"volumesnapshotcontents.snapshot.storage.k8s.io"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -69,8 +69,8 @@ func (p *volumeSnapshotContentRestoreItemAction) Execute(
|
|||
additionalItems = append(additionalItems,
|
||||
velero.ResourceIdentifier{
|
||||
GroupResource: schema.GroupResource{Group: "", Resource: "secrets"},
|
||||
Name: snapCont.Annotations[velerov1api.DeleteSecretNameAnnotation],
|
||||
Namespace: snapCont.Annotations[velerov1api.DeleteSecretNamespaceAnnotation],
|
||||
Name: snapCont.Annotations[velerov1api.PrefixedSecretNameAnnotation],
|
||||
Namespace: snapCont.Annotations[velerov1api.PrefixedSecretNamespaceAnnotation],
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
Copyright the Velero contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package csi
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
"github.com/vmware-tanzu/velero/pkg/kuberesource"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
func TestVSCExecute(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
item runtime.Unstructured
|
||||
vsc *snapshotv1api.VolumeSnapshotContent
|
||||
restore *velerov1api.Restore
|
||||
expectErr bool
|
||||
expectedItems []velero.ResourceIdentifier
|
||||
}{
|
||||
{
|
||||
name: "Restore's RestorePVs is false",
|
||||
restore: builder.ForRestore("velero", "restore").RestorePVs(false).Result(),
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "Normal case, additional items should return",
|
||||
vsc: builder.ForVolumeSnapshotContent("test").ObjectMeta(builder.WithAnnotationsMap(
|
||||
map[string]string{
|
||||
velerov1api.PrefixedSecretNameAnnotation: "name",
|
||||
velerov1api.PrefixedSecretNamespaceAnnotation: "namespace",
|
||||
},
|
||||
)).Result(),
|
||||
restore: builder.ForRestore("velero", "restore").Result(),
|
||||
expectErr: false,
|
||||
expectedItems: []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: kuberesource.Secrets,
|
||||
Namespace: "namespace",
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
p, err := NewVolumeSnapshotContentRestoreItemAction(logrus.StandardLogger())
|
||||
require.NoError(t, err)
|
||||
|
||||
action := p.(*volumeSnapshotContentRestoreItemAction)
|
||||
|
||||
if test.vsc != nil {
|
||||
vsMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(test.vsc)
|
||||
require.NoError(t, err)
|
||||
test.item = &unstructured.Unstructured{Object: vsMap}
|
||||
}
|
||||
|
||||
output, err := action.Execute(
|
||||
&velero.RestoreItemActionExecuteInput{
|
||||
Item: test.item,
|
||||
Restore: test.restore,
|
||||
},
|
||||
)
|
||||
|
||||
if test.expectErr == false {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
if len(test.expectedItems) > 0 {
|
||||
require.Equal(t, test.expectedItems, output.AdditionalItems)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVSCAppliesTo(t *testing.T) {
|
||||
p := volumeSnapshotContentRestoreItemAction{
|
||||
log: logrus.StandardLogger(),
|
||||
}
|
||||
selector, err := p.AppliesTo()
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(
|
||||
t,
|
||||
velero.ResourceSelector{
|
||||
IncludedResources: []string{"volumesnapshotcontents.snapshot.storage.k8s.io"},
|
||||
},
|
||||
selector,
|
||||
)
|
||||
}
|
|
@ -447,14 +447,6 @@ func IsVolumeSnapshotContentHasDeleteSecret(vsc *snapshotv1api.VolumeSnapshotCon
|
|||
return nameExists && nsExists
|
||||
}
|
||||
|
||||
// IsVolumeSnapshotHasVSCDeleteSecret returns whether a volumesnapshot should set the deletesnapshot secret
|
||||
// for the static volumesnapshotcontent that is created on restore
|
||||
func IsVolumeSnapshotHasVSCDeleteSecret(vs *snapshotv1api.VolumeSnapshot) bool {
|
||||
_, nameExists := vs.Annotations[velerov1api.DeleteSecretNameAnnotation]
|
||||
_, nsExists := vs.Annotations[velerov1api.DeleteSecretNamespaceAnnotation]
|
||||
return nameExists && nsExists
|
||||
}
|
||||
|
||||
// IsVolumeSnapshotExists returns whether a specific volumesnapshot object exists.
|
||||
func IsVolumeSnapshotExists(
|
||||
ns,
|
||||
|
|
|
@ -1257,94 +1257,6 @@ func TestIsVolumeSnapshotContentHasDeleteSecret(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestIsVolumeSnapshotHasVSCDeleteSecret(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
vs snapshotv1api.VolumeSnapshot
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "should find both annotations",
|
||||
vs: snapshotv1api.VolumeSnapshot{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "vs-1",
|
||||
Annotations: map[string]string{
|
||||
"velero.io/csi-deletesnapshotsecret-name": "snapDelSecret",
|
||||
"velero.io/csi-deletesnapshotsecret-namespace": "awesome-ns",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "should not find both annotations name is missing",
|
||||
vs: snapshotv1api.VolumeSnapshot{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "vs-1",
|
||||
Annotations: map[string]string{
|
||||
"foo": "snapDelSecret",
|
||||
"velero.io/csi-deletesnapshotsecret-namespace": "awesome-ns",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "should not find both annotations namespace is missing",
|
||||
vs: snapshotv1api.VolumeSnapshot{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "vs-1",
|
||||
Annotations: map[string]string{
|
||||
"velero.io/csi-deletesnapshotsecret-name": "snapDelSecret",
|
||||
"foo": "awesome-ns",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "should not find annotation non-empty annotation",
|
||||
vs: snapshotv1api.VolumeSnapshot{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "vs-1",
|
||||
Annotations: map[string]string{
|
||||
"foo": "snapDelSecret",
|
||||
"bar": "awesome-ns",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "should not find annotation empty annotation",
|
||||
vs: snapshotv1api.VolumeSnapshot{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "vs-1",
|
||||
Annotations: map[string]string{},
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "should not find annotation nil annotation",
|
||||
vs: snapshotv1api.VolumeSnapshot{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "vs-1",
|
||||
Annotations: nil,
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
actual := IsVolumeSnapshotHasVSCDeleteSecret(&tc.vs)
|
||||
assert.Equal(t, tc.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsVolumeSnapshotExists(t *testing.T) {
|
||||
vsExists := &snapshotv1api.VolumeSnapshot{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
|
|
Loading…
Reference in New Issue