diff --git a/pkg/application/inject/fuse/injector.go b/pkg/application/inject/fuse/injector.go index 2fd469bd64e..2d4c5584a80 100644 --- a/pkg/application/inject/fuse/injector.go +++ b/pkg/application/inject/fuse/injector.go @@ -258,5 +258,5 @@ func (s *Injector) shouldInject(pod common.FluidObject) (should bool, err error) } func (s *Injector) getServerlessPlatformFromMeta(metaObj metav1.ObjectMeta) string { - return utils.GetServerlessPlatfrom(metaObj.Labels) + return utils.GetServerlessPlatform(metaObj.Labels) } diff --git a/pkg/common/constants.go b/pkg/common/constants.go index f5bd0e6acd5..c816d4f71a9 100644 --- a/pkg/common/constants.go +++ b/pkg/common/constants.go @@ -212,3 +212,7 @@ const ( K8sZoneLabelKey = "topology.kubernetes.io/zone" K8sRegionLabelKey = "topology.kubernetes.io/region" ) + +const ( + SkipPrecheckAnnotationKey = "sidecar.fluid.io/skip-precheck" +) diff --git a/pkg/ddc/base/runtime_helper.go b/pkg/ddc/base/runtime_helper.go index 3e0089d3ed8..8f053ebce8a 100644 --- a/pkg/ddc/base/runtime_helper.go +++ b/pkg/ddc/base/runtime_helper.go @@ -20,12 +20,11 @@ import ( "fmt" "time" + "github.com/fluid-cloudnative/fluid/pkg/common" "github.com/fluid-cloudnative/fluid/pkg/utils" "github.com/fluid-cloudnative/fluid/pkg/utils/kubeclient" "github.com/pkg/errors" appsv1 "k8s.io/api/apps/v1" - - "github.com/fluid-cloudnative/fluid/pkg/common" ) // GetFuseContainerTemplate collects the fuse container spec from the runtime's fuse daemonSet spec. The function summarizes fuse related information into @@ -52,9 +51,9 @@ func (info *RuntimeInfo) GetFuseContainerTemplate() (template *common.FuseInject template.FuseContainer.Name = common.FuseContainerName - hostMountPath, mountType, subPath, err := kubeclient.GetMountInfoFromVolumeClaim(info.client, info.name, info.namespace) + hostMountPath, mountType, subPath, err := info.getMountInfo() if err != nil { - return template, errors.Wrapf(err, "failed get mount info from PVC \"%s/%s\"", info.namespace, info.name) + return template, errors.Wrapf(err, "failed to get mount info by runtimeInfo %s/%s", info.namespace, info.name) } fuseVolMount, err := kubeclient.GetFuseMountInContainer(mountType, ds.Spec.Template.Spec.Containers[0]) @@ -87,3 +86,21 @@ func (info *RuntimeInfo) getFuseDaemonset() (ds *appsv1.DaemonSet, err error) { } return kubeclient.GetDaemonset(info.client, fuseName, info.GetNamespace()) } + +func (info *RuntimeInfo) getMountInfo() (path, mountType, subpath string, err error) { + pv, err := kubeclient.GetPersistentVolume(info.client, info.GetPersistentVolumeName()) + if err != nil { + err = errors.Wrapf(err, "cannot find pvc \"%s/%s\"'s bounded PV", info.namespace, info.name) + return + } + + if pv.Spec.CSI != nil && len(pv.Spec.CSI.VolumeAttributes) > 0 { + path = pv.Spec.CSI.VolumeAttributes[common.VolumeAttrFluidPath] + mountType = pv.Spec.CSI.VolumeAttributes[common.VolumeAttrMountType] + subpath = pv.Spec.CSI.VolumeAttributes[common.VolumeAttrFluidSubPath] + } else { + err = fmt.Errorf("the pv %s is not created by fluid", pv.Name) + } + + return +} diff --git a/pkg/ddc/base/runtime_helper_test.go b/pkg/ddc/base/runtime_helper_test.go index f17e327efa5..26d0e8be8e4 100644 --- a/pkg/ddc/base/runtime_helper_test.go +++ b/pkg/ddc/base/runtime_helper_test.go @@ -22,13 +22,11 @@ import ( datav1alpha1 "github.com/fluid-cloudnative/fluid/api/v1alpha1" "github.com/fluid-cloudnative/fluid/pkg/common" "github.com/fluid-cloudnative/fluid/pkg/utils/fake" - "sigs.k8s.io/controller-runtime/pkg/client" - appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" ) // func TestGetTemplateToInjectForFuse(t *testing.T) { @@ -1169,3 +1167,180 @@ func TestGetFuseDaemonset(t *testing.T) { } } } + +func TestGetMountInfoFromVolumeClaim(t *testing.T) { + namespace := "default" + testPVCInputs := []*corev1.PersistentVolumeClaim{{ + ObjectMeta: metav1.ObjectMeta{Name: "fluid-dataset", + Namespace: namespace}, + Spec: corev1.PersistentVolumeClaimSpec{ + VolumeName: "default-fluid-dataset", + }, + }, { + ObjectMeta: metav1.ObjectMeta{Name: "nonfluidpvc", + Annotations: common.ExpectedFluidAnnotations, + Namespace: namespace}, + Spec: corev1.PersistentVolumeClaimSpec{ + VolumeName: "nonfluidpv", + }, + }, { + ObjectMeta: metav1.ObjectMeta{Name: "nopv", + Annotations: common.ExpectedFluidAnnotations, + Namespace: namespace}, + Spec: corev1.PersistentVolumeClaimSpec{ + VolumeName: "nopv", + }, + }, { + ObjectMeta: metav1.ObjectMeta{Name: "fluid-dataset-subpath", + Annotations: common.ExpectedFluidAnnotations, + Namespace: namespace}, + Spec: corev1.PersistentVolumeClaimSpec{ + VolumeName: "default-fluid-dataset-subpath", + }, + }} + + objs := []runtime.Object{} + + for _, pvc := range testPVCInputs { + objs = append(objs, pvc.DeepCopy()) + } + + testPVInputs := []*corev1.PersistentVolume{{ + ObjectMeta: metav1.ObjectMeta{Name: "default-fluid-dataset"}, + Spec: corev1.PersistentVolumeSpec{ + PersistentVolumeSource: corev1.PersistentVolumeSource{ + CSI: &corev1.CSIPersistentVolumeSource{ + Driver: "fuse.csi.fluid.io", + VolumeAttributes: map[string]string{ + common.VolumeAttrFluidPath: "/runtime-mnt/jindo/big-data/nofounddataset/jindofs-fuse", + common.VolumeAttrMountType: common.JindoRuntime, + }, + }, + }, + }, + }, { + ObjectMeta: metav1.ObjectMeta{Name: "nonfluidpv", Annotations: common.ExpectedFluidAnnotations}, + Spec: corev1.PersistentVolumeSpec{}, + }, { + ObjectMeta: metav1.ObjectMeta{Name: "default-fluid-dataset-subpath"}, + Spec: corev1.PersistentVolumeSpec{ + PersistentVolumeSource: corev1.PersistentVolumeSource{ + CSI: &corev1.CSIPersistentVolumeSource{ + Driver: "fuse.csi.fluid.io", + VolumeAttributes: map[string]string{ + common.VolumeAttrFluidPath: "/runtime-mnt/jindo/big-data/nofounddataset/jindofs-fuse", + common.VolumeAttrMountType: common.JindoRuntime, + common.VolumeAttrFluidSubPath: "subtest", + }, + }, + }, + }, + }} + + for _, pv := range testPVInputs { + objs = append(objs, pv.DeepCopy()) + } + + type args struct { + name string + namespace string + } + tests := []struct { + name string + args args + wantError bool + wantPath string + wantType string + wantSubPath string + }{{ + name: "volumeClaim doesn't exist", + args: args{ + name: "notExist", + namespace: namespace, + }, + wantError: true, + }, { + name: "non fluid pv", + args: args{ + name: "nonfluidpvc", + namespace: namespace, + }, + wantError: true, + }, { + name: " fluid pv", + args: args{ + name: "fluid-dataset", + namespace: namespace, + }, + wantError: false, + wantPath: "/runtime-mnt/jindo/big-data/nofounddataset/jindofs-fuse", + wantType: common.JindoRuntime, + }, { + name: "no pv", + args: args{ + name: "nopv", + namespace: namespace, + }, + wantError: true, + }, { + name: "sub pv", + args: args{ + name: "fluid-dataset-subpath", + namespace: namespace, + }, + wantError: false, + wantPath: "/runtime-mnt/jindo/big-data/nofounddataset/jindofs-fuse", + wantType: common.JindoRuntime, + wantSubPath: "subtest", + }} + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testScheme := runtime.NewScheme() + _ = corev1.AddToScheme(testScheme) + runtimeInfo := RuntimeInfo{ + name: tt.args.name, + namespace: tt.args.namespace, + runtimeType: common.JindoRuntime, + client: fake.NewFakeClientWithScheme(testScheme, objs...), + } + + path, mountType, subpath, err := runtimeInfo.getMountInfo() + got := err != nil + + if got != tt.wantError { + t.Errorf("testcase %v getMountInfo() for %v in %v = %v, err = %v", tt.name, + tt.args.name, + tt.args.namespace, + got, + err) + } + + if path != tt.wantPath { + t.Errorf("testcase %v GetMountInfoFromVolumeClaim() for %v in %v got path %v, want path = %v", tt.name, + tt.args.name, + tt.args.namespace, + path, + tt.wantPath) + } + + if mountType != tt.wantType { + t.Errorf("testcase %v GetMountInfoFromVolumeClaim() for %v in %v got mountType %v, want mountType = %v", tt.name, + tt.args.name, + tt.args.namespace, + mountType, + tt.wantType) + } + + if subpath != tt.wantSubPath { + t.Errorf("testcase %v GetMountInfoFromVolumeClaim() for %v in %v got subpath %v, want subpath = %v", tt.name, + tt.args.name, + tt.args.namespace, + subpath, + tt.wantSubPath) + } + + }) + } + +} diff --git a/pkg/utils/annotations.go b/pkg/utils/annotations.go index 9b48d264de0..289428df7d9 100644 --- a/pkg/utils/annotations.go +++ b/pkg/utils/annotations.go @@ -75,7 +75,7 @@ const ( PlatformUnprivileged = "Unprivileged" ) -func GetServerlessPlatfrom(infos map[string]string) (platform string) { +func GetServerlessPlatform(infos map[string]string) (platform string) { if matchedKey(infos, ServerlessPlatformKey) { return infos[ServerlessPlatformKey] } @@ -129,6 +129,10 @@ func serverlessPlatformMatched(infos map[string]string) (match bool) { return matchedKey(infos, ServerlessPlatformKey) } +func SkipPrecheckEnable(infos map[string]string) (match bool) { + return enabled(infos, common.SkipPrecheckAnnotationKey) +} + // enabled checks if the given name has a value of "true" func enabled(infos map[string]string, name string) (match bool) { return matchedValue(infos, name, common.True) diff --git a/pkg/utils/kubeclient/volume_claim.go b/pkg/utils/kubeclient/volume_claim.go index bede75ddb72..a57f5edea3e 100644 --- a/pkg/utils/kubeclient/volume_claim.go +++ b/pkg/utils/kubeclient/volume_claim.go @@ -18,10 +18,6 @@ package kubeclient import ( "context" - "fmt" - - "github.com/fluid-cloudnative/fluid/pkg/common" - "github.com/pkg/errors" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -37,30 +33,3 @@ func GetPersistentVolumeClaim(client client.Client, name, namespace string) (pvc pvc) return } - -// GetMountInfoFromVolumeClaim gets the mountPath and type for CSI plugin -func GetMountInfoFromVolumeClaim(client client.Client, name, namespace string) (path string, mountType string, subpath string, err error) { - pvc, err := GetPersistentVolumeClaim(client, name, namespace) - if err != nil { - err = errors.Wrapf(err, "failed to get persistent volume claim") - return - } - - pv, err := GetPersistentVolume(client, pvc.Spec.VolumeName) - if err != nil { - err = errors.Wrapf(err, "cannot find pvc \"%s/%s\"'s bounded PV", pvc.Namespace, pvc.Name) - return - } - - if pv.Spec.CSI != nil && len(pv.Spec.CSI.VolumeAttributes) > 0 { - path = pv.Spec.CSI.VolumeAttributes[common.VolumeAttrFluidPath] - mountType = pv.Spec.CSI.VolumeAttributes[common.VolumeAttrMountType] - subpath = pv.Spec.CSI.VolumeAttributes[common.VolumeAttrFluidSubPath] - } else { - err = fmt.Errorf("the pvc %s in %s is not created by fluid", - name, - namespace) - } - - return -} diff --git a/pkg/utils/kubeclient/volume_claim_test.go b/pkg/utils/kubeclient/volume_claim_test.go index 00065fc8f86..6f5d7ed8527 100644 --- a/pkg/utils/kubeclient/volume_claim_test.go +++ b/pkg/utils/kubeclient/volume_claim_test.go @@ -416,173 +416,3 @@ func TestRemoveProtectionFinalizer(t *testing.T) { } } - -func TestGetMountInfoFromVolumeClaim(t *testing.T) { - namespace := "default" - testPVCInputs := []*v1.PersistentVolumeClaim{{ - ObjectMeta: metav1.ObjectMeta{Name: "fluidpvc", - Namespace: namespace}, - Spec: v1.PersistentVolumeClaimSpec{ - VolumeName: "fluidpv", - }, - }, { - ObjectMeta: metav1.ObjectMeta{Name: "nonfluidpvc", - Annotations: common.ExpectedFluidAnnotations, - Namespace: namespace}, - Spec: v1.PersistentVolumeClaimSpec{ - VolumeName: "nonfluidpv", - }, - }, { - ObjectMeta: metav1.ObjectMeta{Name: "nopv", - Annotations: common.ExpectedFluidAnnotations, - Namespace: namespace}, - Spec: v1.PersistentVolumeClaimSpec{ - VolumeName: "nopv", - }, - }, { - ObjectMeta: metav1.ObjectMeta{Name: "subpvc", - Annotations: common.ExpectedFluidAnnotations, - Namespace: namespace}, - Spec: v1.PersistentVolumeClaimSpec{ - VolumeName: "subpv", - }, - }} - - objs := []runtime.Object{} - - for _, pvc := range testPVCInputs { - objs = append(objs, pvc.DeepCopy()) - } - - testPVInputs := []*v1.PersistentVolume{{ - ObjectMeta: metav1.ObjectMeta{Name: "fluidpv"}, - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeSource: v1.PersistentVolumeSource{ - CSI: &v1.CSIPersistentVolumeSource{ - Driver: "fuse.csi.fluid.io", - VolumeAttributes: map[string]string{ - common.VolumeAttrFluidPath: "/runtime-mnt/jindo/big-data/nofounddataset/jindofs-fuse", - common.VolumeAttrMountType: common.JindoRuntime, - }, - }, - }, - }, - }, { - ObjectMeta: metav1.ObjectMeta{Name: "nonfluidpv", Annotations: common.ExpectedFluidAnnotations}, - Spec: v1.PersistentVolumeSpec{}, - }, { - ObjectMeta: metav1.ObjectMeta{Name: "subpv"}, - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeSource: v1.PersistentVolumeSource{ - CSI: &v1.CSIPersistentVolumeSource{ - Driver: "fuse.csi.fluid.io", - VolumeAttributes: map[string]string{ - common.VolumeAttrFluidPath: "/runtime-mnt/jindo/big-data/nofounddataset/jindofs-fuse", - common.VolumeAttrMountType: common.JindoRuntime, - common.VolumeAttrFluidSubPath: "subtest", - }, - }, - }, - }, - }} - - for _, pv := range testPVInputs { - objs = append(objs, pv.DeepCopy()) - } - - client := fake.NewFakeClientWithScheme(testScheme, objs...) - - type args struct { - name string - namespace string - } - tests := []struct { - name string - args args - wantError bool - wantPath string - wantType string - wantSubPath string - }{{ - name: "volumeClaim doesn't exist", - args: args{ - name: "notExist", - namespace: namespace, - }, - wantError: true, - }, { - name: "non fluid pv", - args: args{ - name: "nonfluidpvc", - namespace: namespace, - }, - wantError: true, - }, { - name: " fluid pv", - args: args{ - name: "fluidpvc", - namespace: namespace, - }, - wantError: false, - wantPath: "/runtime-mnt/jindo/big-data/nofounddataset/jindofs-fuse", - wantType: common.JindoRuntime, - }, { - name: "no pv", - args: args{ - name: "nopv", - namespace: namespace, - }, - wantError: true, - }, { - name: "sub pv", - args: args{ - name: "subpvc", - namespace: namespace, - }, - wantError: false, - wantPath: "/runtime-mnt/jindo/big-data/nofounddataset/jindofs-fuse", - wantType: common.JindoRuntime, - wantSubPath: "subtest", - }} - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - path, mountType, subpath, err := GetMountInfoFromVolumeClaim(client, tt.args.name, tt.args.namespace) - got := err != nil - - if got != tt.wantError { - t.Errorf("testcase %v GetMountInfoFromVolumeClaim() for %v in %v = %v, err = %v", tt.name, - tt.args.name, - tt.args.namespace, - got, - err) - } - - if path != tt.wantPath { - t.Errorf("testcase %v GetMountInfoFromVolumeClaim() for %v in %v got path %v, want path = %v", tt.name, - tt.args.name, - tt.args.namespace, - path, - tt.wantPath) - } - - if mountType != tt.wantType { - t.Errorf("testcase %v GetMountInfoFromVolumeClaim() for %v in %v got mountType %v, want mountType = %v", tt.name, - tt.args.name, - tt.args.namespace, - mountType, - tt.wantType) - } - - if subpath != tt.wantSubPath { - t.Errorf("testcase %v GetMountInfoFromVolumeClaim() for %v in %v got subpath %v, want subpath = %v", tt.name, - tt.args.name, - tt.args.namespace, - subpath, - tt.wantSubPath) - } - - }) - } - -} diff --git a/pkg/webhook/handler/mutating/mutating_handler.go b/pkg/webhook/handler/mutating/mutating_handler.go index 117acb8992d..d667b4d1385 100644 --- a/pkg/webhook/handler/mutating/mutating_handler.go +++ b/pkg/webhook/handler/mutating/mutating_handler.go @@ -123,7 +123,8 @@ func (a *FluidMutatingHandler) MutatePod(pod *corev1.Pod) (err error) { var setupLog = ctrl.Log.WithName("AddScheduleInfoToPod") setupLog.V(1).Info("start to add schedule info", "Pod", pod.Name, "Namespace", pod.Namespace) pvcNames := kubeclient.GetPVCNamesFromPod(pod) - runtimeInfos, err := webhookutils.CollectRuntimeInfosFromPVCs(a.Client, pvcNames, pod.Namespace, setupLog) + runtimeInfos, err := webhookutils.CollectRuntimeInfosFromPVCs(a.Client, pvcNames, pod.Namespace, setupLog, + utils.SkipPrecheckEnable(pod.Annotations)) if err != nil { setupLog.Error(err, "failed to collect runtime infos from PVCs", "pvcNames", pvcNames) return errors.Wrapf(err, "failed to collect runtime infos from PVCs %v", pvcNames) diff --git a/pkg/webhook/plugins/fusesidecar/fuse_sidecar.go b/pkg/webhook/plugins/fusesidecar/fuse_sidecar.go index 13babd6b622..3a4f6ae6800 100644 --- a/pkg/webhook/plugins/fusesidecar/fuse_sidecar.go +++ b/pkg/webhook/plugins/fusesidecar/fuse_sidecar.go @@ -76,7 +76,8 @@ func (p *FuseSidecar) Mutate(pod *corev1.Pod, runtimeInfos map[string]base.Runti } out.DeepCopyInto(pod) pvcNames := kubeclient.GetPVCNamesFromPod(pod) - runtimeInfos, err = webhookutils.CollectRuntimeInfosFromPVCs(p.client, pvcNames, pod.Namespace, p.log) + runtimeInfos, err = webhookutils.CollectRuntimeInfosFromPVCs(p.client, pvcNames, pod.Namespace, p.log, + utils.SkipPrecheckEnable(pod.Annotations)) if err != nil { return shouldStop, errors.Wrapf(err, "failed to collect runtime infos from PVCs %v", pvcNames) } diff --git a/pkg/webhook/utils/runtime_info.go b/pkg/webhook/utils/runtime_info.go index 47bb7f1518a..73e8ce89bc5 100644 --- a/pkg/webhook/utils/runtime_info.go +++ b/pkg/webhook/utils/runtime_info.go @@ -17,7 +17,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func CollectRuntimeInfosFromPVCs(client client.Client, pvcNames []string, namespace string, setupLog logr.Logger) (runtimeInfos map[string]base.RuntimeInfoInterface, err error) { +func CollectRuntimeInfosFromPVCs(client client.Client, pvcNames []string, namespace string, setupLog logr.Logger, skipPrecheck bool) (runtimeInfos map[string]base.RuntimeInfoInterface, err error) { if utils.IsTimeTrackerDebugEnabled() { defer utils.TimeTrack(time.Now(), "CreateUpdatePodForSchedulingHandler.checkIfDatasetPVCs", "pvc.names", pvcNames, "pvc.namespace", namespace) @@ -50,20 +50,7 @@ func CollectRuntimeInfosFromPVCs(client client.Client, pvcNames []string, namesp } isDatasetPVC = kubeclient.CheckIfPVCIsDataset(pvc) if isDatasetPVC { - // isReferringPVC, referringName, referringNamespace := kubeclient.GetReferringDatasetPVCInfo(pvc) - // if isReferringPVC { - // pvc, err = kubeclient.GetPersistentVolumeClaim(a.Client, referringName, referringNamespace) - // if err != nil { - // setupLog.Error(err, - // "unable to get referring pvc, get failure", - // "name", referringName, - // "namespace", referringNamespace) - // return - // } - // } - - runtimeInfo, err = buildRuntimeInfoInternal(client, pvc, setupLog) - // runtimeInfo, err = base.GetRuntimeInfo(a.Client, pvcName, namespace) + runtimeInfo, err = buildRuntimeInfoInternalWithPrecheck(client, pvc, setupLog, skipPrecheck) if err != nil { err = errors.Wrapf(err, "failed to build runtime info for PVC \"%v/%v\"", namespace, pvcName) return @@ -86,9 +73,9 @@ func CollectRuntimeInfosFromPVCs(client client.Client, pvcNames []string, namesp return } -func buildRuntimeInfoInternal(client client.Client, +func buildRuntimeInfoInternalWithPrecheck(client client.Client, pvc *corev1.PersistentVolumeClaim, - log logr.Logger) (runtimeInfo base.RuntimeInfoInterface, err error) { + log logr.Logger, skipPrecheck bool) (runtimeInfo base.RuntimeInfoInterface, err error) { if utils.IsTimeTrackerDebugEnabled() { defer utils.TimeTrack(time.Now(), "mutating.buildRuntimeInfoInternalByPVC", "pvc.name", pvc.GetName(), "pvc.namespace", pvc.GetNamespace()) @@ -102,7 +89,23 @@ func buildRuntimeInfoInternal(client client.Client, pvcName = datasetName } - dataset, err := utils.GetDataset(client, pvcName, namespace) + if !skipPrecheck { + if err = checkDatasetBound(client, pvcName, namespace); err != nil { + return + } + } + + runtimeInfo, err = base.GetRuntimeInfo(client, pvcName, namespace) + if err != nil { + log.Error(err, "unable to get runtimeInfo, get failure", "runtime", pvc.GetName(), "namespace", namespace) + return + } + runtimeInfo.SetDeprecatedNodeLabel(false) + return +} + +func checkDatasetBound(client client.Client, name, namespace string) (err error) { + dataset, err := utils.GetDataset(client, name, namespace) if err != nil { return } @@ -116,12 +119,5 @@ func buildRuntimeInfoInternal(client client.Client, err = fmt.Errorf("dataset \"%s/%s\" not bound", dataset.Namespace, dataset.Name) return } - - runtimeInfo, err = base.GetRuntimeInfo(client, pvcName, namespace) - if err != nil { - log.Error(err, "unable to get runtimeInfo, get failure", "runtime", pvc.GetName(), "namespace", namespace) - return - } - runtimeInfo.SetDeprecatedNodeLabel(false) - return + return nil }