mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-09-04 07:07:11 +00:00
Merge branch 'main' into data-mover-ms-new-exposer
This commit is contained in:
@@ -21,7 +21,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1"
|
||||
@@ -464,7 +463,7 @@ func (b *backupReconciler) prepareBackupRequest(backup *velerov1api.Backup, logg
|
||||
}
|
||||
|
||||
// validate the included/excluded namespaces
|
||||
for _, err := range b.validateNamespaceIncludesExcludes(request.Spec.IncludedNamespaces, request.Spec.ExcludedNamespaces) {
|
||||
for _, err := range collections.ValidateNamespaceIncludesExcludes(request.Spec.IncludedNamespaces, request.Spec.ExcludedNamespaces) {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, fmt.Sprintf("Invalid included/excluded namespace lists: %v", err))
|
||||
}
|
||||
|
||||
@@ -473,20 +472,11 @@ func (b *backupReconciler) prepareBackupRequest(backup *velerov1api.Backup, logg
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, "encountered labelSelector as well as orLabelSelectors in backup spec, only one can be specified")
|
||||
}
|
||||
|
||||
if request.Spec.ResourcePolicy != nil && strings.EqualFold(request.Spec.ResourcePolicy.Kind, resourcepolicies.ConfigmapRefType) {
|
||||
policiesConfigmap := &corev1api.ConfigMap{}
|
||||
err := b.kbClient.Get(context.Background(), kbclient.ObjectKey{Namespace: request.Namespace, Name: request.Spec.ResourcePolicy.Name}, policiesConfigmap)
|
||||
if err != nil {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, fmt.Sprintf("failed to get resource policies %s/%s configmap with err %v", request.Namespace, request.Spec.ResourcePolicy.Name, err))
|
||||
}
|
||||
res, err := resourcepolicies.GetResourcePoliciesFromConfig(policiesConfigmap)
|
||||
if err != nil {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, errors.Wrapf(err, fmt.Sprintf("resource policies %s/%s", request.Namespace, request.Spec.ResourcePolicy.Name)).Error())
|
||||
} else if err = res.Validate(); err != nil {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, errors.Wrapf(err, fmt.Sprintf("resource policies %s/%s", request.Namespace, request.Spec.ResourcePolicy.Name)).Error())
|
||||
}
|
||||
request.ResPolicies = res
|
||||
resourcePolicies, err := resourcepolicies.GetResourcePoliciesFromBackup(*request.Backup, b.kbClient, logger)
|
||||
if err != nil {
|
||||
request.Status.ValidationErrors = append(request.Status.ValidationErrors, err.Error())
|
||||
}
|
||||
request.ResPolicies = resourcePolicies
|
||||
|
||||
return request
|
||||
}
|
||||
@@ -596,24 +586,6 @@ func (b *backupReconciler) validateAndGetSnapshotLocations(backup *velerov1api.B
|
||||
return providerLocations, nil
|
||||
}
|
||||
|
||||
func (b *backupReconciler) validateNamespaceIncludesExcludes(includedNamespaces, excludedNamespaces []string) []error {
|
||||
var errs []error
|
||||
if errs = collections.ValidateNamespaceIncludesExcludes(includedNamespaces, excludedNamespaces); len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
namespace := &corev1api.Namespace{}
|
||||
for _, name := range collections.NewIncludesExcludes().Includes(includedNamespaces...).GetIncludes() {
|
||||
if name == "" || name == "*" {
|
||||
continue
|
||||
}
|
||||
if err := b.kbClient.Get(context.Background(), kbclient.ObjectKey{Name: name}, namespace); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
// runBackup runs and uploads a validated backup. Any error returned from this function
|
||||
// causes the backup to be Failed; if no error is returned, the backup's status's Errors
|
||||
// field is checked to see if the backup was a partial failure.
|
||||
|
||||
@@ -85,6 +85,7 @@ func (b *fakeBackupper) FinalizeBackup(
|
||||
outBackupFile io.Writer,
|
||||
backupItemActionResolver framework.BackupItemActionResolverV2,
|
||||
asyncBIAOperations []*itemoperation.BackupOperation,
|
||||
backupStore persistence.BackupStore,
|
||||
) error {
|
||||
args := b.Called(logger, backup, inBackupFile, outBackupFile, backupItemActionResolver, asyncBIAOperations)
|
||||
return args.Error(0)
|
||||
@@ -190,16 +191,10 @@ func TestProcessBackupValidationFailures(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "use old filter parameters and new filter parameters together",
|
||||
backup: defaultBackup().IncludeClusterResources(true).IncludedNamespaceScopedResources("Deployment").IncludedNamespaces("foo").Result(),
|
||||
backup: defaultBackup().IncludeClusterResources(true).IncludedNamespaceScopedResources("Deployment").IncludedNamespaces("default").Result(),
|
||||
backupLocation: defaultBackupLocation,
|
||||
expectedErrs: []string{"include-resources, exclude-resources and include-cluster-resources are old filter parameters.\ninclude-cluster-scoped-resources, exclude-cluster-scoped-resources, include-namespace-scoped-resources and exclude-namespace-scoped-resources are new filter parameters.\nThey cannot be used together"},
|
||||
},
|
||||
{
|
||||
name: "nonexisting namespace",
|
||||
backup: defaultBackup().IncludedNamespaces("non-existing").Result(),
|
||||
backupLocation: defaultBackupLocation,
|
||||
expectedErrs: []string{"Invalid included/excluded namespace lists: namespaces \"non-existing\" not found"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@@ -214,11 +209,10 @@ func TestProcessBackupValidationFailures(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var fakeClient kbclient.Client
|
||||
namespace := builder.ForNamespace("foo").Result()
|
||||
if test.backupLocation != nil {
|
||||
fakeClient = velerotest.NewFakeControllerRuntimeClient(t, test.backupLocation, namespace)
|
||||
fakeClient = velerotest.NewFakeControllerRuntimeClient(t, test.backupLocation)
|
||||
} else {
|
||||
fakeClient = velerotest.NewFakeControllerRuntimeClient(t, namespace)
|
||||
fakeClient = velerotest.NewFakeControllerRuntimeClient(t)
|
||||
}
|
||||
|
||||
c := &backupReconciler{
|
||||
@@ -1574,43 +1568,6 @@ func TestValidateAndGetSnapshotLocations(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateNamespaceIncludesExcludes(t *testing.T) {
|
||||
namespace := builder.ForNamespace("default").Result()
|
||||
reconciler := &backupReconciler{
|
||||
kbClient: velerotest.NewFakeControllerRuntimeClient(t, namespace),
|
||||
}
|
||||
|
||||
// empty string as includedNamespaces
|
||||
includedNamespaces := []string{""}
|
||||
excludedNamespaces := []string{"test"}
|
||||
errs := reconciler.validateNamespaceIncludesExcludes(includedNamespaces, excludedNamespaces)
|
||||
assert.Empty(t, errs)
|
||||
|
||||
// "*" as includedNamespaces
|
||||
includedNamespaces = []string{"*"}
|
||||
excludedNamespaces = []string{"test"}
|
||||
errs = reconciler.validateNamespaceIncludesExcludes(includedNamespaces, excludedNamespaces)
|
||||
assert.Empty(t, errs)
|
||||
|
||||
// invalid namespaces
|
||||
includedNamespaces = []string{"1@#"}
|
||||
excludedNamespaces = []string{"2@#"}
|
||||
errs = reconciler.validateNamespaceIncludesExcludes(includedNamespaces, excludedNamespaces)
|
||||
assert.Len(t, errs, 2)
|
||||
|
||||
// not exist namespaces
|
||||
includedNamespaces = []string{"non-existing-namespace"}
|
||||
excludedNamespaces = []string{}
|
||||
errs = reconciler.validateNamespaceIncludesExcludes(includedNamespaces, excludedNamespaces)
|
||||
assert.Len(t, errs, 1)
|
||||
|
||||
// valid namespaces
|
||||
includedNamespaces = []string{"default"}
|
||||
excludedNamespaces = []string{}
|
||||
errs = reconciler.validateNamespaceIncludesExcludes(includedNamespaces, excludedNamespaces)
|
||||
assert.Empty(t, errs)
|
||||
}
|
||||
|
||||
// Test_getLastSuccessBySchedule verifies that the getLastSuccessBySchedule helper function correctly returns
|
||||
// the completion timestamp of the most recent completed backup for each schedule, including an entry for ad-hoc
|
||||
// or non-scheduled backups.
|
||||
|
||||
@@ -184,6 +184,7 @@ func (r *backupFinalizerReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
||||
outBackupFile,
|
||||
backupItemActionsResolver,
|
||||
operations,
|
||||
backupStore,
|
||||
)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("error finalizing Backup")
|
||||
|
||||
@@ -225,7 +225,7 @@ func TestBackupFinalizerReconcile(t *testing.T) {
|
||||
backupStore.On("GetBackupVolumeInfos", mock.Anything).Return(nil, nil)
|
||||
backupStore.On("PutBackupVolumeInfos", mock.Anything, mock.Anything).Return(nil)
|
||||
pluginManager.On("GetBackupItemActionsV2").Return(nil, nil)
|
||||
backupper.On("FinalizeBackup", mock.Anything, mock.Anything, mock.Anything, mock.Anything, framework.BackupItemActionResolverV2{}, mock.Anything).Return(nil)
|
||||
backupper.On("FinalizeBackup", mock.Anything, mock.Anything, mock.Anything, mock.Anything, framework.BackupItemActionResolverV2{}, mock.Anything, mock.Anything).Return(nil)
|
||||
_, err := reconciler.Reconcile(context.TODO(), ctrl.Request{NamespacedName: types.NamespacedName{Namespace: test.backup.Namespace, Name: test.backup.Name}})
|
||||
gotErr := err != nil
|
||||
assert.Equal(t, test.expectError, gotErr)
|
||||
|
||||
@@ -40,6 +40,7 @@ import (
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt"
|
||||
"github.com/vmware-tanzu/velero/pkg/util/kube"
|
||||
|
||||
corev1api "k8s.io/api/core/v1"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
@@ -272,6 +273,20 @@ func (b *backupSyncReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
||||
for _, snapCont := range snapConts {
|
||||
// TODO: Reset ResourceVersion prior to persisting VolumeSnapshotContents
|
||||
snapCont.ResourceVersion = ""
|
||||
// Make the VolumeSnapshotContent static
|
||||
snapCont.Spec.Source = snapshotv1api.VolumeSnapshotContentSource{
|
||||
SnapshotHandle: snapCont.Status.SnapshotHandle,
|
||||
}
|
||||
// Set VolumeSnapshotRef to none exist one, because VolumeSnapshotContent
|
||||
// validation webhook will check whether name and namespace are nil.
|
||||
// external-snapshotter needs Source pointing to snapshot and VolumeSnapshot
|
||||
// reference's UID to nil to determine the VolumeSnapshotContent is deletable.
|
||||
snapCont.Spec.VolumeSnapshotRef = corev1api.ObjectReference{
|
||||
APIVersion: snapshotv1api.SchemeGroupVersion.String(),
|
||||
Kind: "VolumeSnapshot",
|
||||
Namespace: "ns-" + string(snapCont.UID),
|
||||
Name: "name-" + string(snapCont.UID),
|
||||
}
|
||||
err := b.client.Create(ctx, snapCont, &client.CreateOptions{})
|
||||
switch {
|
||||
case err != nil && apierrors.IsAlreadyExists(err):
|
||||
|
||||
@@ -334,10 +334,19 @@ func (r *DataDownloadReconciler) runCancelableDataPath(ctx context.Context, fsRe
|
||||
}
|
||||
|
||||
log.WithField("path", path.ByPath).Debug("Found host path")
|
||||
if err := fsRestore.Init(ctx, dd.Spec.BackupStorageLocation, dd.Spec.SourceNamespace, datamover.GetUploaderType(dd.Spec.DataMover),
|
||||
velerov1api.BackupRepositoryTypeKopia, "", r.repositoryEnsurer, r.credentialGetter); err != nil {
|
||||
|
||||
if err := fsRestore.Init(ctx, &datapath.FSBRInitParam{
|
||||
BSLName: dd.Spec.BackupStorageLocation,
|
||||
SourceNamespace: dd.Spec.SourceNamespace,
|
||||
UploaderType: datamover.GetUploaderType(dd.Spec.DataMover),
|
||||
RepositoryType: velerov1api.BackupRepositoryTypeKopia,
|
||||
RepoIdentifier: "",
|
||||
RepositoryEnsurer: r.repositoryEnsurer,
|
||||
CredentialGetter: r.credentialGetter,
|
||||
}); err != nil {
|
||||
return r.errorOut(ctx, dd, err, "error to initialize data path", log)
|
||||
}
|
||||
|
||||
log.WithField("path", path.ByPath).Info("fs init")
|
||||
|
||||
if err := fsRestore.StartRestore(dd.Spec.SnapshotID, path, dd.Spec.DataMoverConfig); err != nil {
|
||||
|
||||
@@ -338,23 +338,38 @@ func (r *DataUploadReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
||||
|
||||
func (r *DataUploadReconciler) runCancelableDataUpload(ctx context.Context, fsBackup datapath.AsyncBR, du *velerov2alpha1api.DataUpload, res *exposer.ExposeResult, log logrus.FieldLogger) (reconcile.Result, error) {
|
||||
log.Info("Run cancelable dataUpload")
|
||||
|
||||
path, err := exposer.GetPodVolumeHostPath(ctx, res.ByPod.HostingPod, res.ByPod.VolumeName, r.client, r.fileSystem, log)
|
||||
if err != nil {
|
||||
return r.errorOut(ctx, du, err, "error exposing host path for pod volume", log)
|
||||
}
|
||||
|
||||
log.WithField("path", path.ByPath).Debug("Found host path")
|
||||
if err := fsBackup.Init(ctx, du.Spec.BackupStorageLocation, du.Spec.SourceNamespace, datamover.GetUploaderType(du.Spec.DataMover),
|
||||
velerov1api.BackupRepositoryTypeKopia, "", r.repoEnsurer, r.credentialGetter); err != nil {
|
||||
|
||||
if err := fsBackup.Init(ctx, &datapath.FSBRInitParam{
|
||||
BSLName: du.Spec.BackupStorageLocation,
|
||||
SourceNamespace: du.Spec.SourceNamespace,
|
||||
UploaderType: datamover.GetUploaderType(du.Spec.DataMover),
|
||||
RepositoryType: velerov1api.BackupRepositoryTypeKopia,
|
||||
RepoIdentifier: "",
|
||||
RepositoryEnsurer: r.repoEnsurer,
|
||||
CredentialGetter: r.credentialGetter,
|
||||
}); err != nil {
|
||||
return r.errorOut(ctx, du, err, "error to initialize data path", log)
|
||||
}
|
||||
|
||||
log.WithField("path", path.ByPath).Info("fs init")
|
||||
|
||||
tags := map[string]string{
|
||||
velerov1api.AsyncOperationIDLabel: du.Labels[velerov1api.AsyncOperationIDLabel],
|
||||
}
|
||||
|
||||
if err := fsBackup.StartBackup(path, datamover.GetRealSource(du.Spec.SourceNamespace, du.Spec.SourcePVC), "", false, tags, du.Spec.DataMoverConfig); err != nil {
|
||||
if err := fsBackup.StartBackup(path, du.Spec.DataMoverConfig, &datapath.FSBRStartParam{
|
||||
RealSource: datamover.GetRealSource(du.Spec.SourceNamespace, du.Spec.SourcePVC),
|
||||
ParentSnapshot: "",
|
||||
ForceFull: false,
|
||||
Tags: tags,
|
||||
}); err != nil {
|
||||
return r.errorOut(ctx, du, err, "error starting data path backup", log)
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ import (
|
||||
"github.com/vmware-tanzu/velero/pkg/datapath"
|
||||
"github.com/vmware-tanzu/velero/pkg/exposer"
|
||||
"github.com/vmware-tanzu/velero/pkg/metrics"
|
||||
"github.com/vmware-tanzu/velero/pkg/repository"
|
||||
velerotest "github.com/vmware-tanzu/velero/pkg/test"
|
||||
"github.com/vmware-tanzu/velero/pkg/uploader"
|
||||
"github.com/vmware-tanzu/velero/pkg/util/boolptr"
|
||||
@@ -307,11 +306,11 @@ type fakeDataUploadFSBR struct {
|
||||
clock clock.WithTickerAndDelayedExecution
|
||||
}
|
||||
|
||||
func (f *fakeDataUploadFSBR) Init(ctx context.Context, bslName string, sourceNamespace string, uploaderType string, repositoryType string, repoIdentifier string, repositoryEnsurer *repository.Ensurer, credentialGetter *credentials.CredentialGetter) error {
|
||||
func (f *fakeDataUploadFSBR) Init(ctx context.Context, param interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeDataUploadFSBR) StartBackup(source datapath.AccessPoint, realSource string, parentSnapshot string, forceFull bool, tags map[string]string, uploaderConfigs map[string]string) error {
|
||||
func (f *fakeDataUploadFSBR) StartBackup(source datapath.AccessPoint, uploaderConfigs map[string]string, param interface{}) error {
|
||||
du := f.du
|
||||
original := f.du.DeepCopy()
|
||||
du.Status.Phase = velerov2alpha1api.DataUploadPhaseCompleted
|
||||
|
||||
@@ -159,8 +159,15 @@ func (r *PodVolumeBackupReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
||||
|
||||
log.WithField("path", path.ByPath).Debugf("Found host path")
|
||||
|
||||
if err := fsBackup.Init(ctx, pvb.Spec.BackupStorageLocation, pvb.Spec.Pod.Namespace, pvb.Spec.UploaderType,
|
||||
podvolume.GetPvbRepositoryType(&pvb), pvb.Spec.RepoIdentifier, r.repositoryEnsurer, r.credentialGetter); err != nil {
|
||||
if err := fsBackup.Init(ctx, &datapath.FSBRInitParam{
|
||||
BSLName: pvb.Spec.BackupStorageLocation,
|
||||
SourceNamespace: pvb.Spec.Pod.Namespace,
|
||||
UploaderType: pvb.Spec.UploaderType,
|
||||
RepositoryType: podvolume.GetPvbRepositoryType(&pvb),
|
||||
RepoIdentifier: pvb.Spec.RepoIdentifier,
|
||||
RepositoryEnsurer: r.repositoryEnsurer,
|
||||
CredentialGetter: r.credentialGetter,
|
||||
}); err != nil {
|
||||
return r.errorOut(ctx, &pvb, err, "error to initialize data path", log)
|
||||
}
|
||||
|
||||
@@ -179,7 +186,12 @@ func (r *PodVolumeBackupReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
||||
}
|
||||
}
|
||||
|
||||
if err := fsBackup.StartBackup(path, "", parentSnapshotID, false, pvb.Spec.Tags, pvb.Spec.UploaderSettings); err != nil {
|
||||
if err := fsBackup.StartBackup(path, pvb.Spec.UploaderSettings, &datapath.FSBRStartParam{
|
||||
RealSource: "",
|
||||
ParentSnapshot: parentSnapshotID,
|
||||
ForceFull: false,
|
||||
Tags: pvb.Spec.Tags,
|
||||
}); err != nil {
|
||||
return r.errorOut(ctx, &pvb, err, "error starting data path backup", log)
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ import (
|
||||
"github.com/vmware-tanzu/velero/pkg/builder"
|
||||
"github.com/vmware-tanzu/velero/pkg/datapath"
|
||||
"github.com/vmware-tanzu/velero/pkg/metrics"
|
||||
"github.com/vmware-tanzu/velero/pkg/repository"
|
||||
velerotest "github.com/vmware-tanzu/velero/pkg/test"
|
||||
)
|
||||
|
||||
@@ -99,11 +98,11 @@ type fakeFSBR struct {
|
||||
clock clock.WithTickerAndDelayedExecution
|
||||
}
|
||||
|
||||
func (b *fakeFSBR) Init(ctx context.Context, bslName string, sourceNamespace string, uploaderType string, repositoryType string, repoIdentifier string, repositoryEnsurer *repository.Ensurer, credentialGetter *credentials.CredentialGetter) error {
|
||||
func (b *fakeFSBR) Init(ctx context.Context, param interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *fakeFSBR) StartBackup(source datapath.AccessPoint, realSource string, parentSnapshot string, forceFull bool, tags map[string]string, uploaderConfigs map[string]string) error {
|
||||
func (b *fakeFSBR) StartBackup(source datapath.AccessPoint, uploaderConfigs map[string]string, param interface{}) error {
|
||||
pvb := b.pvb
|
||||
|
||||
original := b.pvb.DeepCopy()
|
||||
|
||||
@@ -141,8 +141,15 @@ func (c *PodVolumeRestoreReconciler) Reconcile(ctx context.Context, req ctrl.Req
|
||||
|
||||
log.WithField("path", volumePath.ByPath).Debugf("Found host path")
|
||||
|
||||
if err := fsRestore.Init(ctx, pvr.Spec.BackupStorageLocation, pvr.Spec.SourceNamespace, pvr.Spec.UploaderType,
|
||||
podvolume.GetPvrRepositoryType(pvr), pvr.Spec.RepoIdentifier, c.repositoryEnsurer, c.credentialGetter); err != nil {
|
||||
if err := fsRestore.Init(ctx, &datapath.FSBRInitParam{
|
||||
BSLName: pvr.Spec.BackupStorageLocation,
|
||||
SourceNamespace: pvr.Spec.SourceNamespace,
|
||||
UploaderType: pvr.Spec.UploaderType,
|
||||
RepositoryType: podvolume.GetPvrRepositoryType(pvr),
|
||||
RepoIdentifier: pvr.Spec.RepoIdentifier,
|
||||
RepositoryEnsurer: c.repositoryEnsurer,
|
||||
CredentialGetter: c.credentialGetter,
|
||||
}); err != nil {
|
||||
return c.errorOut(ctx, pvr, err, "error to initialize data path", log)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
storagev1api "k8s.io/api/storage/v1"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -304,6 +306,27 @@ func (ctx *finalizerContext) patchDynamicPVWithVolumeInfo() (errs results.Result
|
||||
return false, err
|
||||
}
|
||||
|
||||
// We are handling a common but specific scenario where a PVC is in a pending state and uses a storage class with
|
||||
// VolumeBindingMode set to WaitForFirstConsumer. In this case, the PV patch step is skipped to avoid
|
||||
// failures due to the PVC not being bound, which could cause a timeout and result in a failed restore.
|
||||
if pvc != nil && pvc.Status.Phase == v1.ClaimPending {
|
||||
// check if storage class used has VolumeBindingMode as WaitForFirstConsumer
|
||||
scName := *pvc.Spec.StorageClassName
|
||||
sc := &storagev1api.StorageClass{}
|
||||
err = ctx.crClient.Get(context.Background(), client.ObjectKey{Name: scName}, sc)
|
||||
|
||||
if err != nil {
|
||||
errs.Add(restoredNamespace, err)
|
||||
return false, err
|
||||
}
|
||||
// skip PV patch step for this scenario
|
||||
// because pvc would not be bound and the PV patch step would fail due to timeout thus failing the restore
|
||||
if *sc.VolumeBindingMode == storagev1api.VolumeBindingWaitForFirstConsumer {
|
||||
log.Warnf("skipping PV patch to restore custom reclaim policy, if any: StorageClass %s used by PVC %s has VolumeBindingMode set to WaitForFirstConsumer, and the PVC is also in a pending state", scName, pvc.Name)
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
if pvc.Status.Phase != v1.ClaimBound || pvc.Spec.VolumeName == "" {
|
||||
log.Debugf("PVC: %s not ready", pvc.Name)
|
||||
return false, nil
|
||||
|
||||
Reference in New Issue
Block a user