diff --git a/internal/backup/pvc_action.go b/internal/backup/pvc_action.go index 2ffa2b1c..31b686f1 100644 --- a/internal/backup/pvc_action.go +++ b/internal/backup/pvc_action.go @@ -172,7 +172,7 @@ func (p *PVCBackupItemAction) Execute(item runtime.Unstructured, backup *velerov var itemToUpdate []velero.ResourceIdentifier if boolptr.IsSetToTrue(backup.Spec.SnapshotMoveData) { - operationID = label.GetValidName(string(util.AsyncOperationIDPrefixDataUpload) + string(backup.UID) + "." + string(pvc.UID)) + operationID = label.GetValidName(string(velerov1api.AsyncOperationIDPrefixDataUpload) + string(backup.UID) + "." + string(pvc.UID)) dataUploadLog := p.Log.WithFields(logrus.Fields{ "Source PVC": fmt.Sprintf("%s/%s", pvc.Namespace, pvc.Name), "VolumeSnapshot": fmt.Sprintf("%s/%s", upd.Namespace, upd.Name), @@ -305,10 +305,10 @@ func newDataUpload(backup *velerov1api.Backup, vs *snapshotv1api.VolumeSnapshot, }, }, Labels: map[string]string{ - velerov1api.BackupNameLabel: label.GetValidName(backup.Name), - velerov1api.BackupUIDLabel: string(backup.UID), - velerov1api.PVCUIDLabel: string(pvc.UID), - util.AsyncOperationIDLabel: operationID, + velerov1api.BackupNameLabel: label.GetValidName(backup.Name), + velerov1api.BackupUIDLabel: string(backup.UID), + velerov1api.PVCUIDLabel: string(pvc.UID), + velerov1api.AsyncOperationIDLabel: operationID, }, }, Spec: velerov2alpha1.DataUploadSpec{ @@ -342,7 +342,7 @@ 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", util.AsyncOperationIDLabel, operationID)} + listOptions := metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", velerov1api.AsyncOperationIDLabel, operationID)} dataUploadList, err := veleroClient.VeleroV2alpha1().DataUploads(backup.Namespace).List(context.Background(), listOptions) if err != nil { diff --git a/internal/backup/pvc_action_test.go b/internal/backup/pvc_action_test.go index 2c905330..82ec64a3 100644 --- a/internal/backup/pvc_action_test.go +++ b/internal/backup/pvc_action_test.go @@ -86,10 +86,10 @@ func TestExecute(t *testing.T) { GenerateName: "test-", Namespace: "velero", Labels: map[string]string{ - velerov1api.BackupNameLabel: "test", - velerov1api.BackupUIDLabel: "", - velerov1api.PVCUIDLabel: "", - util.AsyncOperationIDLabel: "du-.", + velerov1api.BackupNameLabel: "test", + velerov1api.BackupUIDLabel: "", + velerov1api.PVCUIDLabel: "", + velerov1api.AsyncOperationIDLabel: "du-.", }, OwnerReferences: []metav1.OwnerReference{ { @@ -193,7 +193,7 @@ func TestProgress(t *testing.T) { Namespace: "velero", Name: "testing", Labels: map[string]string{ - util.AsyncOperationIDLabel: "testing", + velerov1api.AsyncOperationIDLabel: "testing", }, }, Status: velerov2alpha1.DataUploadStatus{ @@ -268,7 +268,7 @@ func TestCancel(t *testing.T) { Namespace: "velero", Name: "testing", Labels: map[string]string{ - util.AsyncOperationIDLabel: "testing", + velerov1api.AsyncOperationIDLabel: "testing", }, }, }, @@ -283,7 +283,7 @@ func TestCancel(t *testing.T) { Namespace: "velero", Name: "testing", Labels: map[string]string{ - util.AsyncOperationIDLabel: "testing", + velerov1api.AsyncOperationIDLabel: "testing", }, }, Spec: velerov2alpha1.DataUploadSpec{ diff --git a/internal/restore/pvc_action.go b/internal/restore/pvc_action.go index e5a21e99..8a4fa437 100644 --- a/internal/restore/pvc_action.go +++ b/internal/restore/pvc_action.go @@ -158,7 +158,7 @@ func (p *PVCRestoreItemAction) Execute(input *velero.RestoreItemActionExecuteInp if boolptr.IsSetToTrue(backup.Spec.SnapshotMoveData) { logger.Info("Start DataMover restore.") - operationID = label.GetValidName(string(util.AsyncOperationIDPrefixDataDownload) + string(input.Restore.UID) + "." + string(pvcFromBackup.UID)) + operationID = label.GetValidName(string(velerov1api.AsyncOperationIDPrefixDataDownload) + string(input.Restore.UID) + "." + string(pvcFromBackup.UID)) dataDownload, err := restoreFromDataUploadResult(context.Background(), input.Restore, &pvc, operationID, pvcFromBackup.Namespace, p.Client, p.VeleroClient) if err != nil { @@ -268,8 +268,10 @@ func (p *PVCRestoreItemAction) AreAdditionalItemsReady(additionalItems []velero. func getDataUploadResult(ctx context.Context, restore *velerov1api.Restore, pvc *corev1api.PersistentVolumeClaim, sourceNamespace string, kubeClient kubernetes.Interface) (*velerov2alpha1.DataUploadResult, error) { - labelSelector := fmt.Sprintf("%s=%s,%s=%s", util.PVCNamespaceNameLabel, sourceNamespace+"."+pvc.Name, - velerov1api.RestoreUIDLabel, label.GetValidName(string(restore.UID))) + labelSelector := fmt.Sprintf("%s=%s,%s=%s,%s=%s", velerov1api.PVCNamespaceNameLabel, label.GetValidName(sourceNamespace+"."+pvc.Name), + velerov1api.RestoreUIDLabel, label.GetValidName(string(restore.UID)), + velerov1api.ResourceUsageLabel, label.GetValidName(string(velerov1api.VeleroResourceUsageDataUploadResult)), + ) cmList, err := kubeClient.CoreV1().ConfigMaps(restore.Namespace).List(ctx, metav1.ListOptions{LabelSelector: labelSelector}) if err != nil { return nil, errors.Wrapf(err, "error to get DataUpload result cm with labels %s", labelSelector) @@ -299,7 +301,7 @@ func getDataUploadResult(ctx context.Context, restore *velerov1api.Restore, pvc 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", util.AsyncOperationIDLabel, operationID), + LabelSelector: fmt.Sprintf("%s=%s", velerov1api.AsyncOperationIDLabel, operationID), }) if err != nil { return nil, errors.Wrap(err, "fail to list DataDownload") @@ -361,9 +363,9 @@ func newDataDownload(restore *velerov1api.Restore, dataUploadResult *velerov2alp }, }, Labels: map[string]string{ - velerov1api.RestoreNameLabel: label.GetValidName(restore.Name), - velerov1api.RestoreUIDLabel: string(restore.UID), - util.AsyncOperationIDLabel: operationID, + velerov1api.RestoreNameLabel: label.GetValidName(restore.Name), + velerov1api.RestoreUIDLabel: string(restore.UID), + velerov1api.AsyncOperationIDLabel: operationID, }, }, Spec: velerov2alpha1.DataDownloadSpec{ diff --git a/internal/restore/pvc_action_test.go b/internal/restore/pvc_action_test.go index 446e4ddb..98424226 100644 --- a/internal/restore/pvc_action_test.go +++ b/internal/restore/pvc_action_test.go @@ -31,6 +31,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation" "k8s.io/client-go/kubernetes/fake" "github.com/vmware-tanzu/velero-plugin-for-csi/internal/util" @@ -39,6 +40,7 @@ import ( 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" "github.com/vmware-tanzu/velero/pkg/util/boolptr" ) @@ -375,7 +377,7 @@ func TestProgress(t *testing.T) { Namespace: "velero", Name: "testing", Labels: map[string]string{ - util.AsyncOperationIDLabel: "testing", + velerov1api.AsyncOperationIDLabel: "testing", }, }, Status: velerov2alpha1.DataDownloadStatus{ @@ -447,7 +449,7 @@ func TestCancel(t *testing.T) { Namespace: "velero", Name: "testing", Labels: map[string]string{ - util.AsyncOperationIDLabel: "testing", + velerov1api.AsyncOperationIDLabel: "testing", }, }, }, @@ -462,7 +464,7 @@ func TestCancel(t *testing.T) { Namespace: "velero", Name: "testing", Labels: map[string]string{ - util.AsyncOperationIDLabel: "testing", + velerov1api.AsyncOperationIDLabel: "testing", }, }, Spec: velerov2alpha1.DataDownloadSpec{ @@ -485,7 +487,7 @@ func TestCancel(t *testing.T) { Namespace: "velero", Name: "testing", Labels: map[string]string{ - util.AsyncOperationIDLabel: "testing", + velerov1api.AsyncOperationIDLabel: "testing", }, }, Spec: velerov2alpha1.DataDownloadSpec{ @@ -570,20 +572,28 @@ func TestExecute(t *testing.T) { restore: builder.ForRestore("velero", "testRestore").Backup("testBackup").Result(), pvc: builder.ForPersistentVolumeClaim("velero", "testPVC").ObjectMeta(builder.WithAnnotations(util.VolumeSnapshotRestoreSize, "10Gi")).Result(), expectedPVC: builder.ForPersistentVolumeClaim("velero", "testPVC").Result(), - expectedErr: "fail get DataUploadResult for restore: testRestore: no DataUpload result cm found with labels velero.io/pvc-namespace-name=velero.testPVC,velero.io/restore-uid=", + expectedErr: "fail get DataUploadResult for restore: testRestore: no DataUpload result cm found with labels velero.io/pvc-namespace-name=velero.testPVC,velero.io/restore-uid=,velero.io/resource-usage=DataUpload", }, { name: "Restore from DataUploadResult", backup: builder.ForBackup("velero", "testBackup").SnapshotMoveData(true).Result(), restore: builder.ForRestore("velero", "testRestore").Backup("testBackup").ObjectMeta(builder.WithUID("uid")).Result(), pvc: builder.ForPersistentVolumeClaim("velero", "testPVC").ObjectMeta(builder.WithAnnotations(util.VolumeSnapshotRestoreSize, "10Gi")).Result(), - dataUploadResult: builder.ForConfigMap("velero", "testCM").Data("uid", "{}").ObjectMeta(builder.WithLabels(velerov1api.RestoreUIDLabel, "uid", util.PVCNamespaceNameLabel, "velero.testPVC")).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"}). ObjectMeta(builder.WithOwnerReference([]metav1.OwnerReference{{APIVersion: velerov1api.SchemeGroupVersion.String(), Kind: "Restore", Name: "testRestore", UID: "uid", Controller: boolptr.True()}}), - builder.WithLabelsMap(map[string]string{util.AsyncOperationIDLabel: "dd-uid.", velerov1api.RestoreNameLabel: "testRestore", velerov1api.RestoreUIDLabel: "uid"}), + builder.WithLabelsMap(map[string]string{velerov1api.AsyncOperationIDLabel: "dd-uid.", velerov1api.RestoreNameLabel: "testRestore", velerov1api.RestoreUIDLabel: "uid"}), builder.WithGenerateName("testRestore-")).Result(), }, + { + name: "Restore from DataUploadResult with long source PVC namespace and name", + backup: builder.ForBackup("migre209d0da-49c7-45ba-8d5a-3e59fd591ec1", "testBackup").SnapshotMoveData(true).Result(), + restore: builder.ForRestore("migre209d0da-49c7-45ba-8d5a-3e59fd591ec1", "testRestore").Backup("testBackup").ObjectMeta(builder.WithUID("uid")).Result(), + pvc: builder.ForPersistentVolumeClaim("migre209d0da-49c7-45ba-8d5a-3e59fd591ec1", "kibishii-data-kibishii-deployment-0").ObjectMeta(builder.WithAnnotations(util.VolumeSnapshotRestoreSize, "10Gi")).Result(), + dataUploadResult: builder.ForConfigMap("migre209d0da-49c7-45ba-8d5a-3e59fd591ec1", "testCM").Data("uid", "{}").ObjectMeta(builder.WithLabels(velerov1api.RestoreUIDLabel, "uid", velerov1api.PVCNamespaceNameLabel, "migre209d0da-49c7-45ba-8d5a-3e59fd591ec1.kibishii-data-ki152333", velerov1api.ResourceUsageLabel, label.GetValidName(string(velerov1api.VeleroResourceUsageDataUploadResult)))).Result(), + expectedPVC: builder.ForPersistentVolumeClaim("migre209d0da-49c7-45ba-8d5a-3e59fd591ec1", "kibishii-data-kibishii-deployment-0").ObjectMeta(builder.WithAnnotations("velero.io/vsi-volumesnapshot-restore-size", "10Gi")).Result(), + }, } for _, tc := range tests { @@ -633,7 +643,12 @@ func TestExecute(t *testing.T) { require.NoError(t, err) require.Equal(t, tc.expectedPVC.GetObjectMeta(), pvc.GetObjectMeta()) if pvc.Spec.Selector != nil && pvc.Spec.Selector.MatchLabels != nil { - require.Contains(t, pvc.Spec.Selector.MatchLabels[util.DynamicPVRestoreLabel], tc.pvc.Namespace+"."+tc.pvc.Name) + // This is used for long name and namespace case. + if len(tc.pvc.Namespace+"."+tc.pvc.Name) >= validation.DNS1035LabelMaxLength { + require.Contains(t, pvc.Spec.Selector.MatchLabels[util.DynamicPVRestoreLabel], label.GetValidName(tc.pvc.Namespace + "." + tc.pvc.Name)[:56]) + } else { + require.Contains(t, pvc.Spec.Selector.MatchLabels[util.DynamicPVRestoreLabel], tc.pvc.Namespace+"."+tc.pvc.Name) + } } } if tc.expectedDataDownload != nil { diff --git a/internal/util/labels_annotations.go b/internal/util/labels_annotations.go index f824c2c9..b0e1fb1b 100644 --- a/internal/util/labels_annotations.go +++ b/internal/util/labels_annotations.go @@ -43,22 +43,6 @@ const ( // timeout value for backup to plugins. ResourceTimeoutAnnotation = "velero.io/resource-timeout" - // AsyncOperationIDLabel is the label key used to identify the async operation ID - AsyncOperationIDLabel = "velero.io/async-operation-id" - - // TODO: need to use Velero server side label after it's added. - // PVCNameLabel is the label key used to identify the the PVC's namespace and name. - // The format is /. - PVCNamespaceNameLabel = "velero.io/pvc-namespace-name" - // DynamicPVRestoreLabel is the label key for dynamic PV restore DynamicPVRestoreLabel = "velero.io/dynamic-pv-restore" ) - -// TODO: need to use Velero server side type after it's added. -type AsyncOperationIDPrefix string - -const ( - AsyncOperationIDPrefixDataDownload AsyncOperationIDPrefix = "dd-" - AsyncOperationIDPrefixDataUpload AsyncOperationIDPrefix = "du-" -)