jiebi/CodeConvo huggingface dataset:
v1.ResourceName("my.org"): resource.MustParse("9m"), }, }, <ins> skipLimitValueCheck: true, </ins> }, } for _, tc := range errorCase { t.Run(tc.name, func(t *testing.T) { <del> if errs := ValidateResourceRequirements(&tc.requirements, field.NewPath("resources")); len(errs) == 0 { </del> <ins> errs := ValidateResourceRequirements(&tc.requirements, field.NewPath("resources")) if len(errs) == 0 { </ins> t.Errorf("expected error") } <ins> validateNamesAndValuesInDescription(t, tc.requirements.Limits, errs, tc.skipLimitValueCheck, "limit") validateNamesAndValuesInDescription(t, tc.requirements.Requests, errs, tc.skipRequestValueCheck, "request") </ins> }) } } <ins> func validateNamesAndValuesInDescription(t *testing.T, r v1.ResourceList, errs field.ErrorList, skipValueTest bool, rl string) { for name, value := range r { containsName := false containsValue := false for _, e := range errs { if strings.Contains(e.Error(), name.String()) { containsName = true } if strings.Contains(e.Error(), value.String()) { containsValue = true } } if !containsName { t.Errorf("error must contain %s name", rl) } if !containsValue && !skipValueTest { t.Errorf("error must contain %s value", rl) } } } </ins> func TestValidateContainerResourceName(t *testing.T) { successCase := []struct { name         string
if exists { // For non overcommitable resources, not only requests can't exceed limits, they also can't be lower, i.e. must be equal. if quantity.Cmp(limitQuantity) != 0 && !helper.IsOvercommitAllowed(resourceName) { <del> allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be equal to %s limit", resourceName))) </del> <ins> allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be equal to %s limit of %s", resourceName, limitQuantity.String()))) </ins> } else if quantity.Cmp(limitQuantity) > 0 { <del> allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be less than or equal to %s limit", resourceName))) </del> <ins> allErrs = append(allErrs, field.Invalid(reqPath, quantity.String(), fmt.Sprintf("must be less than or equal to %s limit of %s", resourceName, limitQuantity.String()))) </ins> } } else if !helper.IsOvercommitAllowed(resourceName) { allErrs = append(allErrs, field.Required(limPath, "Limit must be set for non overcommitable resources"))
"k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/server/healthz" <ins> utilfeature "k8s.io/apiserver/pkg/util/feature" </ins> cacheddiscovery "k8s.io/client-go/discovery/cached" "k8s.io/client-go/informers" v1core "k8s.io/client-go/kubernetes/typed/core/v1"
cliflag "k8s.io/component-base/cli/flag" "k8s.io/component-base/cli/globalflag" "k8s.io/component-base/configz" <ins> "k8s.io/component-base/metrics/features" </ins> controllersmetrics "k8s.io/component-base/metrics/prometheus/controllers" <ins> "k8s.io/component-base/metrics/prometheus/slis" </ins> "k8s.io/component-base/term" "k8s.io/component-base/version" "k8s.io/component-base/version/verflag"
// Start the controller manager HTTP server if c.SecureServing != nil { unsecuredMux := genericcontrollermanager.NewBaseHandler(&c.ComponentConfig.Generic.Debugging, healthzHandler) <ins> if utilfeature.DefaultFeatureGate.Enabled(features.ComponentSLIs) { slis.SLIMetricsWithReset{}.Install(unsecuredMux) } </ins> handler := genericcontrollermanager.BuildHandlerChain(unsecuredMux, &c.Authorization, &c.Authentication) // TODO: handle stoppedCh and listenerStoppedCh returned by c.SecureServing.Serve if _, _, err := c.SecureServing.Serve(handler, 0, stopCh); err != nil {
// with gingko.BeforeEach/AfterEach/DeferCleanup. // // When a test runs, functions will be invoked in this order: <ins> // - BeforeEaches defined by tests before f.NewDefaultFramework //   in the order in which they were defined (first-in-first-out) </ins> // - f.BeforeEach <del> // - all BeforeEaches in the order in which they were defined (first-in-first-out) </del> <ins> // - BeforeEaches defined by tests after f.NewDefaultFramework </ins> // - It callback // - all AfterEaches in the order in which they were defined // - all DeferCleanups with the order reversed (first-in-last-out) // - f.AfterEach <ins> // // Because a test might skip test execution in a BeforeEach that runs // before f.BeforeEach, AfterEach callbacks that depend on the // framework instance must check whether it was initialized. They can // do that by checking f.ClientSet for nil. DeferCleanup callbacks // don't need to do this because they get defined when the test // runs. </ins> NewFrameworkExtensions []func(f *Framework) )
framework.NewFrameworkExtensions = append(framework.NewFrameworkExtensions, func(f *framework.Framework) { ginkgo.AfterEach(func() { <ins> if f.ClientSet == nil { // Test didn't reach f.BeforeEach, most // likely because the test got // skipped. Nothing to check... return } </ins> e2enode.AllNodesReady(f.ClientSet, 3*time.Minute) }) },
WhenScaled:  apps.DeletePersistentVolumeClaimRetentionPolicyType, WhenDeleted: apps.DeletePersistentVolumeClaimRetentionPolicyType, }, <ins> // tests the case when no policy is set. nil, </ins> } { subtestName := pvcDeletePolicyString(policy) + "/StatefulSetAutoDeletePVCEnabled" if testName != "" {
// claimOwnerMatchesSetAndPod returns false if the ownerRefs of the claim are not set consistently with the // PVC deletion policy for the StatefulSet. func claimOwnerMatchesSetAndPod(claim *v1.PersistentVolumeClaim, set *apps.StatefulSet, pod *v1.Pod) bool { <del> policy := set.Spec.PersistentVolumeClaimRetentionPolicy </del> <ins> policy := getPersistentVolumeClaimRetentionPolicy(set) </ins> const retain = apps.RetainPersistentVolumeClaimRetentionPolicyType const delete = apps.DeletePersistentVolumeClaimRetentionPolicyType switch {
updateMeta(&podMeta, "Pod") setMeta := set.TypeMeta updateMeta(&setMeta, "StatefulSet") <del> policy := set.Spec.PersistentVolumeClaimRetentionPolicy </del> <ins> policy := getPersistentVolumeClaimRetentionPolicy(set) </ins> const retain = apps.RetainPersistentVolumeClaimRetentionPolicyType const delete = apps.DeletePersistentVolumeClaimRetentionPolicyType switch {
/* Release : v1.23 Testname: Pod Lifecycle, poststart https hook <del> Description: When a post-start handler is specified in the container lifecycle using a 'HttpGet' action, then the handler MUST be invoked before the container is terminated. A server pod is created that will serve https requests, create a second pod with a container lifecycle specifying a post-start that invokes the server pod to validate that the post-start is executed. </del> <ins> Description: When a post-start handler is specified in the container lifecycle using a 'HttpGet' action, then the handler MUST be invoked before the container is terminated. A server pod is created that will serve https requests, create a second pod on the same node with a container lifecycle specifying a post-start that invokes the server pod to validate that the post-start is executed. </ins> */ ginkgo.It("should execute poststart https hook properly [MinimumKubeletVersion:1.23] [NodeConformance]", func() { lifecycle := &v1.Lifecycle{
}, } podWithHook := getPodWithHook("pod-with-poststart-https-hook", imageutils.GetPauseImageName(), lifecycle) <ins> // make sure we spawn the test pod on the same node as the webserver. nodeSelection := e2epod.NodeSelection{} e2epod.SetAffinity(&nodeSelection, targetNode) e2epod.SetNodeSelection(&podWithHook.Spec, nodeSelection) </ins> testPodWithHook(podWithHook) }) /*
/* Release : v1.23 Testname: Pod Lifecycle, prestop https hook <del> Description: When a pre-stop handler is specified in the container lifecycle using a 'HttpGet' action, then the handler MUST be invoked before the container is terminated. A server pod is created that will serve https requests, create a second pod with a container lifecycle specifying a pre-stop that invokes the server pod to validate that the pre-stop is executed. </del> <ins> Description: When a pre-stop handler is specified in the container lifecycle using a 'HttpGet' action, then the handler MUST be invoked before the container is terminated. A server pod is created that will serve https requests, create a second pod on the same node with a container lifecycle specifying a pre-stop that invokes the server pod to validate that the pre-stop is executed. </ins> */ ginkgo.It("should execute prestop https hook properly [MinimumKubeletVersion:1.23] [NodeConformance]", func() { lifecycle := &v1.Lifecycle{
}, } podWithHook := getPodWithHook("pod-with-prestop-https-hook", imageutils.GetPauseImageName(), lifecycle) <ins> // make sure we spawn the test pod on the same node as the webserver. nodeSelection := e2epod.NodeSelection{} e2epod.SetAffinity(&nodeSelection, targetNode) e2epod.SetNodeSelection(&podWithHook.Spec, nodeSelection) </ins> testPodWithHook(podWithHook) }) })
func createWindowsJobObject(pc uint32) (windows.Handle, error) { job, err := windows.CreateJobObject(nil, nil) if err != nil { <del> return windows.InvalidHandle, errors.Wrap(err, "windows.CreateJobObject failed") </del> <ins> return windows.InvalidHandle, fmt.Errorf("windows.CreateJobObject failed: %w", err) </ins> } limitInfo := windows.JOBOBJECT_BASIC_LIMIT_INFORMATION{ LimitFlags:    windows.JOB_OBJECT_LIMIT_PRIORITY_CLASS,
windows.JobObjectBasicLimitInformation, uintptr(unsafe.Pointer(&limitInfo)), uint32(unsafe.Sizeof(limitInfo))); err != nil { <del> return windows.InvalidHandle, errors.Wrap(err, "windows.SetInformationJobObject failed") </del> <ins> return windows.InvalidHandle, fmt.Errorf("windows.SetInformationJobObject failed: %w", err) </ins> } return job, nil }
if getPodRevision(replicas[target]) != updateRevision.Name && !isTerminating(replicas[target]) { klog.V(2).InfoS("Pod of StatefulSet is terminating for update", "statefulSet", klog.KObj(set), "pod", klog.KObj(replicas[target])) <del> err := ssc.podControl.DeleteStatefulPod(set, replicas[target]) </del> <ins> if err := ssc.podControl.DeleteStatefulPod(set, replicas[target]); err != nil { if !errors.IsNotFound(err) { return &status, err } } </ins> status.CurrentReplicas-- return &status, err }
} } <ins> func NewRevisionDeletePodFailure(t *testing.T, set *apps.StatefulSet, invariants invariantFunc) { client := fake.NewSimpleClientset(set) om, _, ssc := setupController(client) if err := scaleUpStatefulSetControl(set, ssc, om, invariants); err != nil { t.Errorf("Failed to turn up StatefulSet : %s", err) } var err error set, err = om.setsLister.StatefulSets(set.Namespace).Get(set.Name) if err != nil { t.Fatalf("Error getting updated StatefulSet: %v", err) } if set.Status.Replicas != 3 { t.Error("Failed to scale StatefulSet to 3 replicas") } selector, err := metav1.LabelSelectorAsSelector(set.Spec.Selector) if err != nil { t.Error(err) } pods, err := om.podsLister.Pods(set.Namespace).List(selector) if err != nil { t.Error(err) } // trigger a new revision updateSet := set.DeepCopy() updateSet.Spec.Template.Spec.Containers[0].Image = "nginx-new" if err := om.setsIndexer.Update(updateSet); err != nil { t.Error("Failed to update StatefulSet") } set, err = om.setsLister.StatefulSets(set.Namespace).Get(set.Name) if err != nil { t.Fatalf("Error getting updated StatefulSet: %v", err) } // delete fails om.SetDeleteStatefulPodError(apierrors.NewInternalError(errors.New("API server failed")), 0) _, err = ssc.UpdateStatefulSet(context.TODO(), set, pods) if err == nil { t.Error("Expected err in update StatefulSet when deleting a pod") } set, err = om.setsLister.StatefulSets(set.Namespace).Get(set.Name) if err != nil { t.Fatalf("Error getting updated StatefulSet: %v", err) } if err := invariants(set, om); err != nil { t.Error(err) } if set.Status.CurrentReplicas != 3 { t.Fatalf("Failed pod deletion should not update CurrentReplicas: want 3, got %d", set.Status.CurrentReplicas) } if set.Status.CurrentRevision == set.Status.UpdateRevision { t.Error("Failed to create new revision") } // delete works om.SetDeleteStatefulPodError(nil, 0) status, err := ssc.UpdateStatefulSet(context.TODO(), set, pods) if err != nil { t.Fatalf("Unexpected err in update StatefulSet: %v", err) } if status.CurrentReplicas != 2 { t.Fatalf("Pod deletion should update CurrentReplicas: want 2, got %d", status.CurrentReplicas) } if err := invariants(set, om); err != nil { t.Error(err) } } </ins> func emptyInvariants(set *apps.StatefulSet, om *fakeObjectManager) error { return nil }
return } ref := &v1.ObjectReference{ <del> Kind:      "Pod", Name:      nsName.Name, Namespace: nsName.Namespace, </del> <ins> APIVersion: "v1", Kind:       "Pod", Name:       nsName.Name, Namespace:  nsName.Namespace, </ins> } tc.recorder.Eventf(ref, v1.EventTypeNormal, "TaintManagerEviction", "Marking for deletion Pod %s", nsName.String()) }
return } ref := &v1.ObjectReference{ <del> Kind:      "Pod", Name:      nsName.Name, Namespace: nsName.Namespace, </del> <ins> APIVersion: "v1", Kind:       "Pod", Name:       nsName.Name, Namespace:  nsName.Namespace, </ins> } tc.recorder.Eventf(ref, v1.EventTypeNormal, "TaintManagerEviction", "Cancelling deletion of Pod %s", nsName.String()) }
"testing" "time" <ins> "github.com/google/go-cmp/cmp" </ins> v1 "k8s.io/api/core/v1" <ins> metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" </ins> "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types"
featuregatetesting "k8s.io/component-base/featuregate/testing" "k8s.io/kubernetes/pkg/controller/testutil" "k8s.io/kubernetes/pkg/features" <del> metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" </del> ) var timeForControllerToProgressForSanityCheck = 20 * time.Millisecond
t.Errorf("[%v]Unexpected test result. Expected delete %v, got %v", description, expectDelete, podDeleted) } } <ins> // TestPodDeletionEvent Verify that the output events are as expected func TestPodDeletionEvent(t *testing.T) { f := func(path cmp.Path) bool { switch path.String() { // These fields change at runtime, so ignore it case "LastTimestamp", "FirstTimestamp", "ObjectMeta.Name": return true } return false } t.Run("emitPodDeletionEvent", func(t *testing.T) { controller := &NoExecuteTaintManager{} recorder := testutil.NewFakeRecorder() controller.recorder = recorder controller.emitPodDeletionEvent(types.NamespacedName{ Name:      "test", Namespace: "test", }) want := []*v1.Event{ { ObjectMeta: metav1.ObjectMeta{ Namespace: "test", }, InvolvedObject: v1.ObjectReference{ Kind:       "Pod", APIVersion: "v1", Namespace:  "test", Name:       "test", }, Reason:  "TaintManagerEviction", Type:    "Normal", Count:   1, Message: "Marking for deletion Pod test/test", Source:  v1.EventSource{Component: "nodeControllerTest"}, }, } if diff := cmp.Diff(want, recorder.Events, cmp.FilterPath(f, cmp.Ignore())); len(diff) > 0 { t.Errorf("emitPodDeletionEvent() returned data (-want,+got):n%s", diff) } }) t.Run("emitCancelPodDeletionEvent", func(t *testing.T) { controller := &NoExecuteTaintManager{} recorder := testutil.NewFakeRecorder() controller.recorder = recorder controller.emitCancelPodDeletionEvent(types.NamespacedName{ Name:      "test", Namespace: "test", }) want := []*v1.Event{ { ObjectMeta: metav1.ObjectMeta{ Namespace: "test", }, InvolvedObject: v1.ObjectReference{ Kind:       "Pod", APIVersion: "v1", Namespace:  "test", Name:       "test", }, Reason:  "TaintManagerEviction", Type:    "Normal", Count:   1, Message: "Cancelling deletion of Pod test/test", Source:  v1.EventSource{Component: "nodeControllerTest"}, }, } if diff := cmp.Diff(want, recorder.Events, cmp.FilterPath(f, cmp.Ignore())); len(diff) > 0 { t.Errorf("emitPodDeletionEvent() returned data (-want,+got):n%s", diff) } }) } </ins>
QOSReserved featuregate.Feature = "QOSReserved" // owner: @chrishenzie <ins> // kep: https://kep.k8s.io/2485 </ins> // alpha: v1.22 <ins> // beta: v1.27 </ins> // // Enables usage of the ReadWriteOncePod PersistentVolume access mode. ReadWriteOncePod featuregate.Feature = "ReadWriteOncePod"
QOSReserved: {Default: false, PreRelease: featuregate.Alpha}, <del> ReadWriteOncePod: {Default: false, PreRelease: featuregate.Alpha}, </del> <ins> ReadWriteOncePod: {Default: true, PreRelease: featuregate.Beta}, </ins> RecoverVolumeExpansionFailure: {Default: false, PreRelease: featuregate.Alpha},
"github.com/onsi/ginkgo/v2" v1 "k8s.io/api/core/v1" <ins> schedulingv1 "k8s.io/api/scheduling/v1" </ins> metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" errors "k8s.io/apimachinery/pkg/util/errors" <ins> "k8s.io/apimachinery/pkg/util/uuid" </ins> clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/pkg/kubelet/events" "k8s.io/kubernetes/test/e2e/framework"
type readWriteOncePodTest struct { config *storageframework.PerTestConfig <del> cs     clientset.Interface volume *storageframework.VolumeResource pods   []*v1.Pod </del> <ins> cs            clientset.Interface volume        *storageframework.VolumeResource pods          []*v1.Pod priorityClass *schedulingv1.PriorityClass </ins> migrationCheck *migrationOpCheck }
err := l.volume.CleanupResource(ctx) errs = append(errs, err) <ins> if l.priorityClass != nil { framework.Logf("Deleting PriorityClass %v", l.priorityClass.Name) err := l.cs.SchedulingV1().PriorityClasses().Delete(ctx, l.priorityClass.Name, metav1.DeleteOptions{}) errs = append(errs, err) } </ins> framework.ExpectNoError(errors.NewAggregate(errs), "while cleaning up resource") l.migrationCheck.validateMigrationVolumeOpCounts(ctx) }
ginkgo.DeferCleanup(cleanup) }) <del> ginkgo.It("should block a second pod from using an in-use ReadWriteOncePod volume", func(ctx context.Context) { </del> <ins> ginkgo.It("should preempt lower priority pods using ReadWriteOncePod volumes", func(ctx context.Context) { </ins> // Create the ReadWriteOncePod PVC. accessModes := []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod} l.volume = storageframework.CreateVolumeResourceWithAccessModes(ctx, driver, l.config, pattern, t.GetTestSuiteInfo().SupportedSizeRange, accessModes) <ins> l.priorityClass = &schedulingv1.PriorityClass{ ObjectMeta: metav1.ObjectMeta{Name: "e2e-test-read-write-once-pod-" + string(uuid.NewUUID())}, Value:      int32(1000), } _, err := l.cs.SchedulingV1().PriorityClasses().Create(ctx, l.priorityClass, metav1.CreateOptions{}) framework.ExpectNoError(err, "failed to create priority class") </ins> podConfig := e2epod.Config{ NS:           f.Namespace.Name, PVCs:         []*v1.PersistentVolumeClaim{l.volume.Pvc},
framework.ExpectNoError(err, "failed to wait for pod1 running status") l.pods = append(l.pods, pod1) <del> // Create the second pod, which will fail scheduling because the ReadWriteOncePod PVC is already in use. </del> <ins> // Create the second pod, which will preempt the first pod because it's using the // ReadWriteOncePod PVC and has higher priority. </ins> pod2, err := e2epod.MakeSecPod(&podConfig) framework.ExpectNoError(err, "failed to create spec for pod2") <ins> pod2.Spec.PriorityClassName = l.priorityClass.Name </ins> _, err = l.cs.CoreV1().Pods(pod2.Namespace).Create(ctx, pod2, metav1.CreateOptions{}) framework.ExpectNoError(err, "failed to create pod2") <del> err = e2epod.WaitForPodNameUnschedulableInNamespace(ctx, l.cs, pod2.Name, pod2.Namespace) framework.ExpectNoError(err, "failed to wait for pod2 unschedulable status") </del> l.pods = append(l.pods, pod2) <del> // Delete the first pod and observe the second pod can now start. err = e2epod.DeletePodWithWait(ctx, l.cs, pod1) framework.ExpectNoError(err, "failed to delete pod1") </del> <ins> // Wait for the first pod to be preempted and the second pod to start. err = e2epod.WaitForPodNotFoundInNamespace(ctx, l.cs, pod1.Name, pod1.Namespace, f.Timeouts.PodStart) framework.ExpectNoError(err, "failed to wait for pod1 to be preempted") </ins> err = e2epod.WaitTimeoutForPodRunningInNamespace(ctx, l.cs, pod2.Name, pod2.Namespace, f.Timeouts.PodStart) framework.ExpectNoError(err, "failed to wait for pod2 running status") <ins> // Recreate the first pod, which will fail to schedule because the second pod // is using the ReadWriteOncePod PVC and has higher priority. _, err = l.cs.CoreV1().Pods(pod1.Namespace).Create(ctx, pod1, metav1.CreateOptions{}) framework.ExpectNoError(err, "failed to create pod1") err = e2epod.WaitForPodNameUnschedulableInNamespace(ctx, l.cs, pod1.Name, pod1.Namespace) framework.ExpectNoError(err, "failed to wait for pod1 unschedulable status") // Delete the second pod with higher priority and observe the first pod can now start. err = e2epod.DeletePodWithWait(ctx, l.cs, pod2) framework.ExpectNoError(err, "failed to delete pod2") err = e2epod.WaitTimeoutForPodRunningInNamespace(ctx, l.cs, pod1.Name, pod1.Namespace, f.Timeouts.PodStart) framework.ExpectNoError(err, "failed to wait for pod1 running status") </ins> }) ginkgo.It("should block a second pod from using an in-use ReadWriteOncePod volume on the same node", func(ctx context.Context) {
serviceAccountName: csi-hostpathplugin-sa containers: - name: hostpath <del> image: registry.k8s.io/sig-storage/hostpathplugin:v1.9.0 </del> <ins> image: registry.k8s.io/sig-storage/hostpathplugin:v1.11.0 </ins> args: - "--drivername=hostpath.csi.k8s.io" - "--v=5"
command := exec.Command("umount", target) output, err := command.CombinedOutput() if err != nil { <del> if err.Error() == errNoChildProcesses { if command.ProcessState.Success() { // We don't consider errNoChildProcesses an error if the process itself succeeded (see - k/k issue #103753). return nil } // Rewrite err with the actual exit error of the process. err = &exec.ExitError{ProcessState: command.ProcessState} } if mounter.withSafeNotMountedBehavior && strings.Contains(string(output), errNotMounted) { klog.V(4).Infof("ignoring 'not mounted' error for %s", target) return nil } return fmt.Errorf("unmount failed: %vnUnmounting arguments: %snOutput: %s", err, target, string(output)) </del> <ins> return checkUmountError(target, command, output, err, mounter.withSafeNotMountedBehavior) </ins> } return nil }
// UnmountWithForce unmounts given target but will retry unmounting with force option // after given timeout. func (mounter *Mounter) UnmountWithForce(target string, umountTimeout time.Duration) error { <del> err := tryUnmount(mounter, target, umountTimeout) </del> <ins> err := tryUnmount(target, mounter.withSafeNotMountedBehavior, umountTimeout) </ins> if err != nil { if err == context.DeadlineExceeded { klog.V(2).Infof("Timed out waiting for unmount of %s, trying with -f", target) <del> err = forceUmount(target) </del> <ins> err = forceUmount(target, mounter.withSafeNotMountedBehavior) </ins> } return err }
} // tryUnmount calls plain "umount" and waits for unmountTimeout for it to finish. <del> func tryUnmount(mounter *Mounter, path string, unmountTimeout time.Duration) error { klog.V(4).Infof("Unmounting %s", path) </del> <ins> func tryUnmount(target string, withSafeNotMountedBehavior bool, unmountTimeout time.Duration) error { klog.V(4).Infof("Unmounting %s", target) </ins> ctx, cancel := context.WithTimeout(context.Background(), unmountTimeout) defer cancel() <del> cmd := exec.CommandContext(ctx, "umount", path) out, cmderr := cmd.CombinedOutput() </del> <ins> command := exec.CommandContext(ctx, "umount", target) output, err := command.CombinedOutput() </ins> // CombinedOutput() does not return DeadlineExceeded, make sure it's // propagated on timeout.