From e7dd7346e53ea8e68d6052fc511d1dff88f003a3 Mon Sep 17 00:00:00 2001 From: Xun Jiang Date: Thu, 9 Nov 2023 21:40:55 +0800 Subject: [PATCH] Remove velero generated client, because it's going to be deprecated Signed-off-by: Xun Jiang --- go.mod | 11 +++++-- internal/backup/pvc_action.go | 48 ++++++++++----------------- internal/backup/pvc_action_test.go | 49 +++++++++++++++------------ internal/restore/pvc_action.go | 51 ++++++++++------------------- internal/restore/pvc_action_test.go | 46 +++++++++++++++----------- internal/util/util.go | 20 ++++++++--- main.go | 8 ++--- 7 files changed, 118 insertions(+), 115 deletions(-) diff --git a/go.mod b/go.mod index 368a4583..fb1ca42e 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 toolchain go1.21.3 require ( - github.com/evanphx/json-patch v5.6.0+incompatible + github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.0 @@ -18,6 +18,11 @@ require ( k8s.io/client-go v0.25.6 ) +require ( + github.com/google/go-cmp v0.5.9 + sigs.k8s.io/controller-runtime v0.12.2 +) + require ( cloud.google.com/go v0.110.0 // indirect cloud.google.com/go/compute v1.19.1 // indirect @@ -61,7 +66,6 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.6.9 // indirect - github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/s2a-go v0.1.2 // indirect github.com/google/uuid v1.3.0 // indirect @@ -102,7 +106,9 @@ require ( github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rs/xid v1.4.0 // indirect + github.com/spf13/afero v1.6.0 // indirect github.com/spf13/cobra v1.4.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect github.com/zeebo/blake3 v0.2.3 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.14.0 // indirect @@ -135,7 +141,6 @@ require ( k8s.io/klog/v2 v2.70.1 // indirect k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect - sigs.k8s.io/controller-runtime v0.12.2 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect diff --git a/internal/backup/pvc_action.go b/internal/backup/pvc_action.go index 19181de4..7f448d48 100644 --- a/internal/backup/pvc_action.go +++ b/internal/backup/pvc_action.go @@ -18,10 +18,8 @@ package backup import ( "context" - "encoding/json" "fmt" - jsonpatch "github.com/evanphx/json-patch" snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" snapshotterClientSet "github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned" "github.com/pkg/errors" @@ -29,16 +27,17 @@ import ( corev1api "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" + "sigs.k8s.io/controller-runtime/pkg/client" + crclient "sigs.k8s.io/controller-runtime/pkg/client" "github.com/vmware-tanzu/velero-plugin-for-csi/internal/util" velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1" - veleroClientSet "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned" "github.com/vmware-tanzu/velero/pkg/kuberesource" "github.com/vmware-tanzu/velero/pkg/label" "github.com/vmware-tanzu/velero/pkg/plugin/velero" @@ -51,7 +50,7 @@ type PVCBackupItemAction struct { Log logrus.FieldLogger Client kubernetes.Interface SnapshotClient snapshotterClientSet.Interface - VeleroClient veleroClientSet.Interface + CRClient crclient.Client } // AppliesTo returns information indicating that the PVCBackupItemAction should be invoked to backup PVCs. @@ -195,7 +194,7 @@ func (p *PVCBackupItemAction) Execute(item runtime.Unstructured, backup *velerov dataUploadLog.Info("Starting data upload of backup") - dataUpload, err := createDataUpload(context.Background(), backup, p.VeleroClient, upd, &pvc, operationID) + dataUpload, err := createDataUpload(context.Background(), backup, p.CRClient, upd, &pvc, operationID) if err != nil { dataUploadLog.WithError(err).Error("failed to submit DataUpload") util.DeleteVolumeSnapshotIfAny(context.Background(), p.SnapshotClient, *upd, dataUploadLog) @@ -254,7 +253,7 @@ func (p *PVCBackupItemAction) Progress(operationID string, backup *velerov1api.B return progress, biav2.InvalidOperationIDError(operationID) } - dataUpload, err := getDataUpload(context.Background(), backup, p.VeleroClient, operationID) + dataUpload, err := getDataUpload(context.Background(), backup, p.CRClient, operationID) if err != nil { p.Log.Errorf("fail to get DataUpload for backup %s/%s: %s", backup.Namespace, backup.Name, err.Error()) return progress, err @@ -295,13 +294,13 @@ func (p *PVCBackupItemAction) Cancel(operationID string, backup *velerov1api.Bac return biav2.InvalidOperationIDError(operationID) } - dataUpload, err := getDataUpload(context.Background(), backup, p.VeleroClient, operationID) + dataUpload, err := getDataUpload(context.Background(), backup, p.CRClient, operationID) if err != nil { p.Log.Errorf("fail to get DataUpload for backup %s/%s: %s", backup.Namespace, backup.Name, err.Error()) return err } - return cancelDataUpload(context.Background(), p.VeleroClient, dataUpload) + return cancelDataUpload(context.Background(), p.CRClient, dataUpload) } func newDataUpload(backup *velerov1api.Backup, vs *snapshotv1api.VolumeSnapshot, @@ -347,11 +346,11 @@ func newDataUpload(backup *velerov1api.Backup, vs *snapshotv1api.VolumeSnapshot, return dataUpload } -func createDataUpload(ctx context.Context, backup *velerov1api.Backup, veleroClient veleroClientSet.Interface, +func createDataUpload(ctx context.Context, backup *velerov1api.Backup, crClient crclient.Client, vs *snapshotv1api.VolumeSnapshot, pvc *corev1api.PersistentVolumeClaim, operationID string) (*velerov2alpha1.DataUpload, error) { dataUpload := newDataUpload(backup, vs, pvc, operationID) - dataUpload, err := veleroClient.VeleroV2alpha1().DataUploads(dataUpload.Namespace).Create(ctx, dataUpload, metav1.CreateOptions{}) + err := crClient.Create(ctx, dataUpload) if err != nil { return nil, errors.Wrap(err, "fail to create DataUpload CR") } @@ -360,10 +359,11 @@ func createDataUpload(ctx context.Context, backup *velerov1api.Backup, veleroCli } func getDataUpload(ctx context.Context, backup *velerov1api.Backup, - veleroClient veleroClientSet.Interface, operationID string) (*velerov2alpha1.DataUpload, error) { - listOptions := metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", velerov1api.AsyncOperationIDLabel, operationID)} - - dataUploadList, err := veleroClient.VeleroV2alpha1().DataUploads(backup.Namespace).List(context.Background(), listOptions) + crClient crclient.Client, operationID string) (*velerov2alpha1.DataUpload, error) { + dataUploadList := new(velerov2alpha1.DataUploadList) + err := crClient.List(context.Background(), dataUploadList, &crclient.ListOptions{ + LabelSelector: labels.SelectorFromSet(map[string]string{velerov1api.AsyncOperationIDLabel: operationID}), + }) if err != nil { return nil, errors.Wrapf(err, "error to list DataUpload") } @@ -379,27 +379,13 @@ func getDataUpload(ctx context.Context, backup *velerov1api.Backup, return &dataUploadList.Items[0], nil } -func cancelDataUpload(ctx context.Context, veleroClient veleroClientSet.Interface, +func cancelDataUpload(ctx context.Context, crClient crclient.Client, dataUpload *velerov2alpha1.DataUpload) error { - oldData, err := json.Marshal(dataUpload) - if err != nil { - return errors.Wrap(err, "error marshalling original DataUpload") - } updatedDataUpload := dataUpload.DeepCopy() updatedDataUpload.Spec.Cancel = true - newData, err := json.Marshal(updatedDataUpload) - if err != nil { - return errors.Wrap(err, "err marshalling updated DataUpload") - } - - patchData, err := jsonpatch.CreateMergePatch(oldData, newData) - if err != nil { - return errors.Wrap(err, "error creating patch data for DataUpload") - } - - _, err = veleroClient.VeleroV2alpha1().DataUploads(dataUpload.Namespace).Patch(ctx, dataUpload.Name, types.MergePatchType, patchData, metav1.PatchOptions{}) + err := crClient.Patch(context.Background(), updatedDataUpload, client.MergeFrom(dataUpload)) if err != nil { return errors.Wrap(err, "error patch DataUpload") } diff --git a/internal/backup/pvc_action_test.go b/internal/backup/pvc_action_test.go index 2782ba84..b76b8209 100644 --- a/internal/backup/pvc_action_test.go +++ b/internal/backup/pvc_action_test.go @@ -18,10 +18,11 @@ package backup import ( "context" - "fmt" "testing" "time" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" v1 "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" snapshotfake "github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned/fake" @@ -31,17 +32,19 @@ import ( storagev1 "k8s.io/api/storage/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes/fake" + crclient "sigs.k8s.io/controller-runtime/pkg/client" "github.com/vmware-tanzu/velero-plugin-for-csi/internal/util" "github.com/vmware-tanzu/velero/pkg/apis/velero/shared" 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" - velerofake "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/fake" "github.com/vmware-tanzu/velero/pkg/plugin/velero" + velerotest "github.com/vmware-tanzu/velero/pkg/test" "github.com/vmware-tanzu/velero/pkg/util/boolptr" ) @@ -135,7 +138,7 @@ func TestExecute(t *testing.T) { t.Run(tc.name, func(*testing.T) { client := fake.NewSimpleClientset() snapshotClient := snapshotfake.NewSimpleClientset() - veleroClient := velerofake.NewSimpleClientset() + crClient := velerotest.NewFakeControllerRuntimeClient(t) logger := logrus.New() logger.Level = logrus.DebugLevel @@ -160,7 +163,7 @@ func TestExecute(t *testing.T) { Log: logger, Client: client, SnapshotClient: snapshotClient, - VeleroClient: veleroClient, + CRClient: crClient, } pvcMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&tc.pvc) @@ -197,16 +200,17 @@ func TestExecute(t *testing.T) { } if tc.expectedDataUpload != nil { - dataUploadList, err := veleroClient.VeleroV2alpha1().DataUploads(tc.backup.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", velerov1api.BackupNameLabel, tc.backup.Name)}) + dataUploadList := new(velerov2alpha1.DataUploadList) + err := crClient.List(context.Background(), dataUploadList, &crclient.ListOptions{LabelSelector: labels.SelectorFromSet(map[string]string{velerov1api.BackupNameLabel: tc.backup.Name})}) require.NoError(t, err) require.Equal(t, 1, len(dataUploadList.Items)) - require.Equal(t, *tc.expectedDataUpload, dataUploadList.Items[0]) + require.True(t, cmp.Equal(tc.expectedDataUpload, &dataUploadList.Items[0], cmpopts.IgnoreFields(velerov2alpha1.DataUpload{}, "ResourceVersion", "Name"))) } if tc.expectedPVC != nil { resultPVC := new(corev1.PersistentVolumeClaim) runtime.DefaultUnstructuredConverter.FromUnstructured(resultUnstructed.UnstructuredContent(), resultPVC) - require.Equal(t, *tc.expectedPVC, *resultPVC) + require.True(t, cmp.Equal(tc.expectedPVC, resultPVC, cmpopts.IgnoreFields(corev1.PersistentVolumeClaim{}, "Annotations"))) } }) } @@ -217,7 +221,7 @@ func TestProgress(t *testing.T) { tests := []struct { name string backup *velerov1api.Backup - dataUpload velerov2alpha1.DataUpload + dataUpload *velerov2alpha1.DataUpload operationID string expectedErr string expectedProgress velero.OperationProgress @@ -231,7 +235,7 @@ func TestProgress(t *testing.T) { { name: "DataUpload is found", backup: builder.ForBackup("velero", "test").Result(), - dataUpload: velerov2alpha1.DataUpload{ + dataUpload: &velerov2alpha1.DataUpload{ TypeMeta: metav1.TypeMeta{ Kind: "DataUpload", APIVersion: "v2alpha1", @@ -272,24 +276,26 @@ func TestProgress(t *testing.T) { t.Run(tc.name, func(*testing.T) { client := fake.NewSimpleClientset() snapshotClient := snapshotfake.NewSimpleClientset() - veleroClient := velerofake.NewSimpleClientset() + crClient := velerotest.NewFakeControllerRuntimeClient(t) logger := logrus.New() pvcBIA := PVCBackupItemAction{ Log: logger, Client: client, SnapshotClient: snapshotClient, - VeleroClient: veleroClient, + CRClient: crClient, } - _, err := veleroClient.VeleroV2alpha1().DataUploads(tc.dataUpload.Namespace).Create(context.Background(), &tc.dataUpload, metav1.CreateOptions{}) - require.NoError(t, err) + if tc.dataUpload != nil { + err := crClient.Create(context.Background(), tc.dataUpload) + require.NoError(t, err) + } progress, err := pvcBIA.Progress(tc.operationID, tc.backup) if tc.expectedErr != "" { require.Equal(t, tc.expectedErr, err.Error()) } - require.Equal(t, tc.expectedProgress, progress) + require.True(t, cmp.Equal(tc.expectedProgress, progress, cmpopts.IgnoreFields(velero.OperationProgress{}, "Started", "Updated"))) }) } } @@ -309,7 +315,7 @@ func TestCancel(t *testing.T) { dataUpload: velerov2alpha1.DataUpload{ TypeMeta: metav1.TypeMeta{ Kind: "DataUpload", - APIVersion: "v2alpha1", + APIVersion: velerov2alpha1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Namespace: "velero", @@ -324,7 +330,7 @@ func TestCancel(t *testing.T) { expectedDataUpload: velerov2alpha1.DataUpload{ TypeMeta: metav1.TypeMeta{ Kind: "DataUpload", - APIVersion: "v2alpha1", + APIVersion: velerov2alpha1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Namespace: "velero", @@ -344,17 +350,17 @@ func TestCancel(t *testing.T) { t.Run(tc.name, func(*testing.T) { client := fake.NewSimpleClientset() snapshotClient := snapshotfake.NewSimpleClientset() - veleroClient := velerofake.NewSimpleClientset() + crClient := velerotest.NewFakeControllerRuntimeClient(t) logger := logrus.New() pvcBIA := PVCBackupItemAction{ Log: logger, Client: client, SnapshotClient: snapshotClient, - VeleroClient: veleroClient, + CRClient: crClient, } - _, err := veleroClient.VeleroV2alpha1().DataUploads(tc.dataUpload.Namespace).Create(context.Background(), &tc.dataUpload, metav1.CreateOptions{}) + err := crClient.Create(context.Background(), &tc.dataUpload) require.NoError(t, err) err = pvcBIA.Cancel(tc.operationID, tc.backup) @@ -362,10 +368,11 @@ func TestCancel(t *testing.T) { require.Equal(t, err, tc.expectedErr) } - du, err := veleroClient.VeleroV2alpha1().DataUploads(tc.dataUpload.Namespace).Get(context.Background(), tc.dataUpload.Name, metav1.GetOptions{}) + du := new(velerov2alpha1.DataUpload) + err = crClient.Get(context.Background(), crclient.ObjectKey{Namespace: tc.dataUpload.Namespace, Name: tc.dataUpload.Name}, du) require.NoError(t, err) - require.Equal(t, *du, tc.expectedDataUpload) + require.True(t, cmp.Equal(tc.expectedDataUpload, *du, cmpopts.IgnoreFields(velerov2alpha1.DataUpload{}, "ResourceVersion"))) }) } } diff --git a/internal/restore/pvc_action.go b/internal/restore/pvc_action.go index 186ab79c..d6e643a1 100644 --- a/internal/restore/pvc_action.go +++ b/internal/restore/pvc_action.go @@ -21,7 +21,6 @@ import ( "encoding/json" "fmt" - jsonpatch "github.com/evanphx/json-patch" snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" snapshotterClientSet "github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned" "github.com/pkg/errors" @@ -30,15 +29,16 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" utilrand "k8s.io/apimachinery/pkg/util/rand" "k8s.io/client-go/kubernetes" + "sigs.k8s.io/controller-runtime/pkg/client" + crclient "sigs.k8s.io/controller-runtime/pkg/client" "github.com/vmware-tanzu/velero-plugin-for-csi/internal/util" velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" velerov2alpha1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1" - veleroClientSet "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned" "github.com/vmware-tanzu/velero/pkg/label" "github.com/vmware-tanzu/velero/pkg/plugin/velero" riav2 "github.com/vmware-tanzu/velero/pkg/plugin/velero/restoreitemaction/v2" @@ -62,7 +62,7 @@ type PVCRestoreItemAction struct { Log logrus.FieldLogger Client kubernetes.Interface SnapshotClient snapshotterClientSet.Interface - VeleroClient veleroClientSet.Interface + CRClient crclient.Client } // AppliesTo returns information indicating that the PVCRestoreItemAction should be run while restoring PVCs. @@ -162,8 +162,9 @@ func (p *PVCRestoreItemAction) Execute(input *velero.RestoreItemActionExecuteInp pvc.Spec.DataSource = nil pvc.Spec.DataSourceRef = nil } else { - backup, err := p.VeleroClient.VeleroV1().Backups(input.Restore.Namespace).Get(context.Background(), - input.Restore.Spec.BackupName, metav1.GetOptions{}) + backup := new(velerov1api.Backup) + err := p.CRClient.Get(context.TODO(), crclient.ObjectKey{Namespace: input.Restore.Namespace, Name: input.Restore.Spec.BackupName}, backup) + if err != nil { logger.Error("Fail to get backup for restore.") return nil, fmt.Errorf("fail to get backup for restore: %s", err.Error()) @@ -184,7 +185,7 @@ func (p *PVCRestoreItemAction) Execute(input *velero.RestoreItemActionExecuteInp operationID = label.GetValidName(string(velerov1api.AsyncOperationIDPrefixDataDownload) + string(input.Restore.UID) + "." + string(pvcFromBackup.UID)) dataDownload, err := restoreFromDataUploadResult(context.Background(), input.Restore, backup, &pvc, newNamespace, - operationID, p.Client, p.VeleroClient) + operationID, p.Client, p.CRClient) if err != nil { logger.Errorf("Fail to restore from DataUploadResult: %s", err.Error()) return nil, errors.WithStack(err) @@ -234,7 +235,7 @@ func (p *PVCRestoreItemAction) Progress(operationID string, restore *velerov1api "Namespace": restore.Namespace, }) - dataDownload, err := getDataDownload(context.Background(), restore.Namespace, operationID, p.VeleroClient) + dataDownload, err := getDataDownload(context.Background(), restore.Namespace, operationID, p.CRClient) if err != nil { logger.Errorf("fail to get DataDownload: %s", err.Error()) return progress, err @@ -281,13 +282,13 @@ func (p *PVCRestoreItemAction) Cancel(operationID string, restore *velerov1api.R "Namespace": restore.Namespace, }) - dataDownload, err := getDataDownload(context.Background(), restore.Namespace, operationID, p.VeleroClient) + dataDownload, err := getDataDownload(context.Background(), restore.Namespace, operationID, p.CRClient) if err != nil { logger.Errorf("fail to get DataDownload: %s", err.Error()) return err } - err = cancelDataDownload(context.Background(), p.VeleroClient, dataDownload) + err = cancelDataDownload(context.Background(), p.CRClient, dataDownload) if err != nil { logger.Errorf("fail to cancel DataDownload %s: %s", dataDownload.Name, err.Error()) } @@ -331,10 +332,9 @@ func getDataUploadResult(ctx context.Context, restore *velerov1api.Restore, pvc return &result, nil } -func getDataDownload(ctx context.Context, namespace string, operationID string, veleroClient veleroClientSet.Interface) (*velerov2alpha1.DataDownload, error) { - dataDownloadList, err := veleroClient.VeleroV2alpha1().DataDownloads(namespace).List(ctx, metav1.ListOptions{ - LabelSelector: fmt.Sprintf("%s=%s", velerov1api.AsyncOperationIDLabel, operationID), - }) +func getDataDownload(ctx context.Context, namespace string, operationID string, crClient crclient.Client) (*velerov2alpha1.DataDownload, error) { + dataDownloadList := new(velerov2alpha1.DataDownloadList) + err := crClient.List(ctx, dataDownloadList, &crclient.ListOptions{LabelSelector: labels.SelectorFromSet(map[string]string{velerov1api.AsyncOperationIDLabel: operationID})}) if err != nil { return nil, errors.Wrap(err, "fail to list DataDownload") } @@ -350,28 +350,13 @@ func getDataDownload(ctx context.Context, namespace string, operationID string, return &dataDownloadList.Items[0], nil } -func cancelDataDownload(ctx context.Context, veleroClient veleroClientSet.Interface, +func cancelDataDownload(ctx context.Context, crClient crclient.Client, dataDownload *velerov2alpha1.DataDownload) error { - oldData, err := json.Marshal(dataDownload) - if err != nil { - return errors.Wrap(err, "fail to marshal origin DataDownload") - } updatedDataDownload := dataDownload.DeepCopy() updatedDataDownload.Spec.Cancel = true - newData, err := json.Marshal(updatedDataDownload) - if err != nil { - return errors.Wrap(err, "fail to marshal updated DataDownload") - } - - patchData, err := jsonpatch.CreateMergePatch(oldData, newData) - if err != nil { - return errors.Wrap(err, "fail to create merge patch for DataDownload") - } - - _, err = veleroClient.VeleroV2alpha1().DataDownloads(dataDownload.Namespace).Patch(ctx, dataDownload.Name, - types.MergePatchType, patchData, metav1.PatchOptions{}) + err := crClient.Patch(context.Background(), updatedDataDownload, client.MergeFrom(dataDownload)) return err } @@ -444,7 +429,7 @@ func restoreFromVolumeSnapshot(pvc *corev1api.PersistentVolumeClaim, newNamespac } func restoreFromDataUploadResult(ctx context.Context, restore *velerov1api.Restore, backup *velerov1api.Backup, pvc *corev1api.PersistentVolumeClaim, - newNamespace, operationID string, kubeClient kubernetes.Interface, veleroClient veleroClientSet.Interface) (*velerov2alpha1.DataDownload, error) { + newNamespace, operationID string, kubeClient kubernetes.Interface, crClient crclient.Client) (*velerov2alpha1.DataDownload, error) { dataUploadResult, err := getDataUploadResult(ctx, restore, pvc, kubeClient) if err != nil { return nil, errors.Wrapf(err, "fail get DataUploadResult for restore: %s", restore.Name) @@ -459,7 +444,7 @@ func restoreFromDataUploadResult(ctx context.Context, restore *velerov1api.Resto pvc.Spec.Selector.MatchLabels[util.DynamicPVRestoreLabel] = label.GetValidName(fmt.Sprintf("%s.%s.%s", newNamespace, pvc.Name, utilrand.String(GenerateNameRandomLength))) dataDownload := newDataDownload(restore, backup, dataUploadResult, pvc, newNamespace, operationID) - _, err = veleroClient.VeleroV2alpha1().DataDownloads(restore.Namespace).Create(ctx, dataDownload, metav1.CreateOptions{}) + crClient.Create(ctx, dataDownload) if err != nil { return nil, errors.Wrapf(err, "fail to create DataDownload") } diff --git a/internal/restore/pvc_action_test.go b/internal/restore/pvc_action_test.go index f96b7b39..2062c29f 100644 --- a/internal/restore/pvc_action_test.go +++ b/internal/restore/pvc_action_test.go @@ -21,6 +21,8 @@ import ( "testing" "time" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1" snapshotfake "github.com/kubernetes-csi/external-snapshotter/client/v4/clientset/versioned/fake" "github.com/sirupsen/logrus" @@ -30,18 +32,20 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/client-go/kubernetes/fake" + crclient "sigs.k8s.io/controller-runtime/pkg/client" "github.com/vmware-tanzu/velero-plugin-for-csi/internal/util" "github.com/vmware-tanzu/velero/pkg/apis/velero/shared" 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" - velerofake "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/fake" "github.com/vmware-tanzu/velero/pkg/label" "github.com/vmware-tanzu/velero/pkg/plugin/velero" + velerotest "github.com/vmware-tanzu/velero/pkg/test" "github.com/vmware-tanzu/velero/pkg/util/boolptr" ) @@ -371,7 +375,7 @@ func TestProgress(t *testing.T) { dataDownload: &velerov2alpha1.DataDownload{ TypeMeta: metav1.TypeMeta{ Kind: "DataUpload", - APIVersion: "v2alpha1", + APIVersion: velerov2alpha1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Namespace: "velero", @@ -408,11 +412,11 @@ func TestProgress(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(*testing.T) { pvcRIA := PVCRestoreItemAction{ - Log: logrus.New(), - VeleroClient: velerofake.NewSimpleClientset(), + Log: logrus.New(), + CRClient: velerotest.NewFakeControllerRuntimeClient(t), } if tc.dataDownload != nil { - _, err := pvcRIA.VeleroClient.VeleroV2alpha1().DataDownloads(tc.dataDownload.Namespace).Create(context.Background(), tc.dataDownload, metav1.CreateOptions{}) + err := pvcRIA.CRClient.Create(context.Background(), tc.dataDownload) require.NoError(t, err) } @@ -423,7 +427,7 @@ func TestProgress(t *testing.T) { } require.NoError(t, err) - require.Equal(t, tc.expectedProgress, progress) + require.True(t, cmp.Equal(tc.expectedProgress, progress, cmpopts.IgnoreFields(velero.OperationProgress{}, "Started", "Updated"))) }) } } @@ -443,7 +447,7 @@ func TestCancel(t *testing.T) { dataDownload: &velerov2alpha1.DataDownload{ TypeMeta: metav1.TypeMeta{ Kind: "DataDownload", - APIVersion: "v2alpha1", + APIVersion: velerov2alpha1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Namespace: "velero", @@ -458,7 +462,7 @@ func TestCancel(t *testing.T) { expectedDataDownload: velerov2alpha1.DataDownload{ TypeMeta: metav1.TypeMeta{ Kind: "DataDownload", - APIVersion: "v2alpha1", + APIVersion: velerov2alpha1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Namespace: "velero", @@ -481,7 +485,7 @@ func TestCancel(t *testing.T) { expectedDataDownload: velerov2alpha1.DataDownload{ TypeMeta: metav1.TypeMeta{ Kind: "DataDownload", - APIVersion: "v2alpha1", + APIVersion: velerov2alpha1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Namespace: "velero", @@ -500,11 +504,11 @@ func TestCancel(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(*testing.T) { pvcRIA := PVCRestoreItemAction{ - Log: logrus.New(), - VeleroClient: velerofake.NewSimpleClientset(), + Log: logrus.New(), + CRClient: velerotest.NewFakeControllerRuntimeClient(t), } if tc.dataDownload != nil { - _, err := pvcRIA.VeleroClient.VeleroV2alpha1().DataDownloads(tc.dataDownload.Namespace).Create(context.Background(), tc.dataDownload, metav1.CreateOptions{}) + err := pvcRIA.CRClient.Create(context.Background(), tc.dataDownload) require.NoError(t, err) } @@ -515,10 +519,11 @@ func TestCancel(t *testing.T) { } require.NoError(t, err) - resultDataDownload, err := pvcRIA.VeleroClient.VeleroV2alpha1().DataDownloads(tc.dataDownload.Namespace).Get(context.Background(), tc.dataDownload.Name, metav1.GetOptions{}) + resultDataDownload := new(velerov2alpha1.DataDownload) + err = pvcRIA.CRClient.Get(context.Background(), crclient.ObjectKey{Namespace: tc.dataDownload.Namespace, Name: tc.dataDownload.Name}, resultDataDownload) require.NoError(t, err) - require.Equal(t, tc.expectedDataDownload, *resultDataDownload) + require.True(t, cmp.Equal(tc.expectedDataDownload, *resultDataDownload, cmpopts.IgnoreFields(velerov2alpha1.DataDownload{}, "ResourceVersion", "Name"))) }) } } @@ -590,7 +595,7 @@ func TestExecute(t *testing.T) { pvc: builder.ForPersistentVolumeClaim("velero", "testPVC").ObjectMeta(builder.WithAnnotations(util.VolumeSnapshotRestoreSize, "10Gi", util.DataUploadNameAnnotation, "velero/")).Result(), dataUploadResult: builder.ForConfigMap("velero", "testCM").Data("uid", "{}").ObjectMeta(builder.WithLabels(velerov1api.RestoreUIDLabel, "uid", velerov1api.PVCNamespaceNameLabel, "velero.testPVC", velerov1api.ResourceUsageLabel, label.GetValidName(string(velerov1api.VeleroResourceUsageDataUploadResult)))).Result(), expectedPVC: builder.ForPersistentVolumeClaim("velero", "testPVC").ObjectMeta(builder.WithAnnotations("velero.io/vsi-volumesnapshot-restore-size", "10Gi")).Result(), - expectedDataDownload: builder.ForDataDownload("velero", "").TargetVolume(velerov2alpha1.TargetVolumeSpec{PVC: "testPVC", Namespace: "velero"}). + expectedDataDownload: builder.ForDataDownload("velero", "name").TargetVolume(velerov2alpha1.TargetVolumeSpec{PVC: "testPVC", Namespace: "velero"}). ObjectMeta(builder.WithOwnerReference([]metav1.OwnerReference{{APIVersion: velerov1api.SchemeGroupVersion.String(), Kind: "Restore", Name: "testRestore", UID: "uid", Controller: boolptr.True()}}), builder.WithLabelsMap(map[string]string{velerov1api.AsyncOperationIDLabel: "dd-uid.", velerov1api.RestoreNameLabel: "testRestore", velerov1api.RestoreUIDLabel: "uid"}), builder.WithGenerateName("testRestore-")).Result(), @@ -631,7 +636,7 @@ func TestExecute(t *testing.T) { Log: logrus.New(), Client: fake.NewSimpleClientset(), SnapshotClient: snapshotfake.NewSimpleClientset(), - VeleroClient: velerofake.NewSimpleClientset(), + CRClient: velerotest.NewFakeControllerRuntimeClient(t), } input := new(velero.RestoreItemActionExecuteInput) @@ -650,7 +655,7 @@ func TestExecute(t *testing.T) { } if tc.backup != nil { - _, err := pvcRIA.VeleroClient.VeleroV1().Backups(tc.backup.Namespace).Create(context.Background(), tc.backup, metav1.CreateOptions{}) + err := pvcRIA.CRClient.Create(context.Background(), tc.backup) require.NoError(t, err) } @@ -686,9 +691,12 @@ func TestExecute(t *testing.T) { } } if tc.expectedDataDownload != nil { - dataDownload, err := pvcRIA.VeleroClient.VeleroV2alpha1().DataDownloads(tc.expectedDataDownload.Namespace).Get(context.Background(), tc.expectedDataDownload.Name, metav1.GetOptions{}) + dataDownloadList := new(velerov2alpha1.DataDownloadList) + err := pvcRIA.CRClient.List(context.Background(), dataDownloadList, &crclient.ListOptions{ + LabelSelector: labels.SelectorFromSet(tc.expectedDataDownload.Labels), + }) require.NoError(t, err) - require.Equal(t, tc.expectedDataDownload, dataDownload) + require.True(t, cmp.Equal(tc.expectedDataDownload, &dataDownloadList.Items[0], cmpopts.IgnoreFields(velerov2alpha1.DataDownload{}, "ResourceVersion", "Name"))) } }) } diff --git a/internal/util/util.go b/internal/util/util.go index 793ab09f..fd54c9ef 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -30,14 +30,16 @@ import ( corev1api "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes" corev1client "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/clientcmd" + crclient "sigs.k8s.io/controller-runtime/pkg/client" velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - veleroClientSet "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned" + velerov2alpha1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1" "github.com/vmware-tanzu/velero/pkg/label" "github.com/vmware-tanzu/velero/pkg/podvolume" ) @@ -285,7 +287,7 @@ func GetClients() (*kubernetes.Clientset, snapshotterClientSet.Interface, error) return client, snapshotterClient, err } -func GetFullClients() (*kubernetes.Clientset, snapshotterClientSet.Interface, *veleroClientSet.Clientset, error) { +func GetFullClients() (*kubernetes.Clientset, snapshotterClientSet.Interface, crclient.Client, error) { loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() configOverrides := &clientcmd.ConfigOverrides{} kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides) @@ -304,12 +306,22 @@ func GetFullClients() (*kubernetes.Clientset, snapshotterClientSet.Interface, *v return nil, nil, nil, errors.WithStack(err) } - veleroClient, err := veleroClientSet.NewForConfig(clientConfig) + scheme := runtime.NewScheme() + if err := velerov1api.AddToScheme(scheme); err != nil { + return nil, nil, nil, errors.WithStack(err) + } + if err := velerov2alpha1api.AddToScheme(scheme); err != nil { + return nil, nil, nil, errors.WithStack(err) + } + + crClient, err := crclient.New(clientConfig, crclient.Options{ + Scheme: scheme, + }) if err != nil { return nil, nil, nil, errors.WithStack(err) } - return client, snapshotterClient, veleroClient, nil + return client, snapshotterClient, crClient, nil } // IsVolumeSnapshotClassHasListerSecret returns whether a volumesnapshotclass has a snapshotlister secret diff --git a/main.go b/main.go index 18f40f7a..7699e3d6 100644 --- a/main.go +++ b/main.go @@ -44,7 +44,7 @@ func main() { } func newPVCBackupItemAction(logger logrus.FieldLogger) (interface{}, error) { - client, snapshotClient, veleroClient, err := util.GetFullClients() + client, snapshotClient, crClient, err := util.GetFullClients() if err != nil { return nil, errors.WithStack(err) } @@ -53,7 +53,7 @@ func newPVCBackupItemAction(logger logrus.FieldLogger) (interface{}, error) { Log: logger, Client: client, SnapshotClient: snapshotClient, - VeleroClient: veleroClient, + CRClient: crClient, }, nil } @@ -70,7 +70,7 @@ func newVolumeSnapContentBackupItemAction(logger logrus.FieldLogger) (interface{ } func newPVCRestoreItemAction(logger logrus.FieldLogger) (interface{}, error) { - client, snapshotClient, veleroClient, err := util.GetFullClients() + client, snapshotClient, crClient, err := util.GetFullClients() if err != nil { return nil, errors.WithStack(err) } @@ -79,7 +79,7 @@ func newPVCRestoreItemAction(logger logrus.FieldLogger) (interface{}, error) { Log: logger, Client: client, SnapshotClient: snapshotClient, - VeleroClient: veleroClient, + CRClient: crClient, }, nil }