Repository: kubernetes-sigs/aws-ebs-csi-driver
Pull request #2011 (2024-04-17 12:56:48)

Add Alpha Support for Windows HostProcess Containers
**Is this a bug fix or adding new feature?**

Feature

**What is this PR about? / Why do we need it?**

This PR adds alpha support for running the driver node pod as a Windows HostProcess container. This is a new feature that allows the driver to directly access the host's Windows storage APIs to perform privileged storage operations without requiring the CSI Proxy binary.

Summary of Changes

- Add a new `CSIProxyMounterV2` that implements the `Mounter` interface using direct `csi-proxy/v2` API calls instead of the v1 gRPC client.
- Update `NewNodeMounter` to return a `SafeFormatAndMount` configured with either `CSIProxyMounter` or `CSIProxyMounterV2` based on the `windowsHostProcess` parameter
- Add a `node.windowsHostProcess` configuration option to enable HostProcess mode.
- Add a new `external-windows-hostprocess` makefile target to test the feature in the CI environment.


**What testing is done?**

Manual


k8s-ci-robot: @torredil: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-aws-ebs-csi-driver-e2e-single-az | 94e470b258e55b7b2ea5922a0ad2bfe962981094 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-ebs-csi-driver/2011/pull-aws-ebs-csi-driver-e2e-single-az/1780581183554326528) | true | `/test pull-aws-ebs-csi-driver-e2e-single-az`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-ebs-csi-driver&pr=2011). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Atorredil). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @torredil: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-aws-ebs-csi-driver-test-e2e-external-eks-windows | 8aa0dcbc53d702619b8f1eb9b355b3ba44962883 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_aws-ebs-csi-driver/2011/pull-aws-ebs-csi-driver-test-e2e-external-eks-windows/1780586038863859712) | true | `/test pull-aws-ebs-csi-driver-test-e2e-external-eks-windows`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=aws-ebs-csi-driver&pr=2011). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Atorredil). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/.github/workflows/publish-ecr.yaml b/.github/workflows/publish-ecr.yaml
new file mode 100644
index 00000000..0d922c6e
--- /dev/null
+++ b/.github/workflows/publish-ecr.yaml
@@ -0,0 +1,83 @@
+name: Publish to ECR
+on:
+  push:
+    tags: ['*']
+jobs:
+  ecr-private:
+    name: Push to ECR Private
+    runs-on: ubuntu-latest
+    steps:
+    - name: Checkout
+      uses: actions/checkout@v3
+
+    - name: Set up Docker Buildx
+      uses: docker/setup-buildx-action@v2
+
+    - name: Set up QEMU
+      uses: docker/setup-qemu-action@v2
+
+    - name: Configure AWS Credentials
+      uses: aws-actions/configure-aws-credentials@v1-node16
+      with:
+        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
+        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+        role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
+        role-session-name: GitHubCI
+        aws-region: us-east-1
+        role-duration-seconds: 1800
+        role-skip-session-tagging: true
+
+    - name: Login to Amazon ECR
+      uses: aws-actions/amazon-ecr-login@v1
+
+    - name: Set environment variables
+      env:
+        REGISTRY: ${{ secrets.ECR_PRIVATE_REPOSITORY }}
+      run: |
+          echo "REGISTRY=${REGISTRY}" >> $GITHUB_ENV
+          echo "TAG=${GITHUB_REF_NAME}" >> $GITHUB_ENV
+          echo "VERSION=${GITHUB_REF_NAME}" >> $GITHUB_ENV
+
+    - name: Build, tag, and push manifest to Amazon ECR
+      run: make -j `nproc` all-push-with-a1compat
+
+  ecr-public:
+    name: Push to ECR Public
+    runs-on: ubuntu-latest
+    environment: ecr-public
+    needs: ecr-private
+
+    steps:
+    - name: Set up crane
+      uses: imjasonh/setup-crane@v0.1
+
+    - name: Configure AWS Credentials
+      uses: aws-actions/configure-aws-credentials@v1-node16
+      with:
+        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
+        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+        role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
+        role-session-name: GitHubCI
+        aws-region: us-east-1
+        role-duration-seconds: 1800
+        role-skip-session-tagging: true
+
+    - name: Login to Amazon ECR
+      uses: aws-actions/amazon-ecr-login@v1
+
+    - name: Login to Amazon ECR Public
+      uses: aws-actions/amazon-ecr-login@v1
+      with:
+        registry-type: public
+
+    - name: Copy a1-compatible manifest to ECR Public
+      env:
+        ECR_PRIVATE_REPOSITORY: ${{ secrets.ECR_PRIVATE_REPOSITORY }}
+        ECR_PUBLIC_REPOSITORY: ${{ secrets.ECR_PUBLIC_REPOSITORY }}
+      run: crane copy ${ECR_PRIVATE_REPOSITORY}/aws-ebs-csi-driver:${GITHUB_REF_NAME}-linux-arm64-al2 ${ECR_PUBLIC_REPOSITORY}/aws-ebs-csi-driver:${GITHUB_REF_NAME}-a1compat
+
+    - name: Copy manifest list to ECR Public
+      env:
+        ECR_PRIVATE_REPOSITORY: ${{ secrets.ECR_PRIVATE_REPOSITORY }}
+        ECR_PUBLIC_REPOSITORY: ${{ secrets.ECR_PUBLIC_REPOSITORY }}
+      run: crane copy ${ECR_PRIVATE_REPOSITORY}/aws-ebs-csi-driver:${GITHUB_REF_NAME} ${ECR_PUBLIC_REPOSITORY}/aws-ebs-csi-driver:${GITHUB_REF_NAME}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b9972f44..3874dd65 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,23 +1,3 @@
-# v1.30.0
-### Notable Changes
-* Add retry manager to reduce RateLimitExceeded errors ([#2010](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2010), [@AndrewSirenko](https://github.com/AndrewSirenko))
-* Add options to run metrics endpoint over HTTPS ([#2014](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2014), [@ConnorJC3](https://github.com/ConnorJC3))
-
-### Bug Fixes
-* Remove DeleteDisk call in CreateDisk path ([#2009](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2009), [@ConnorJC3](https://github.com/ConnorJC3))
-* Consolidate request handling in RecordRequestsMiddleware ([#2013](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2013), [@torredil](https://github.com/torredil))
-* Run taint removal only if Kubernetes API is available ([#2015](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2015), [@torredil](https://github.com/torredil))
-
-### Improvements
-* Migrate to AWS SDKv2 ([#1963](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1963), [@torredil](https://github.com/torredil))
-* Batch EC2 DescribeVolumesModifications API calls ([#1965](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1965), [@AndrewSirenko](https://github.com/AndrewSirenko))
-* Improve configuration management; Improve the relationship between driver, controller, & cloud ([#1995](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1995), [@torredil](https://github.com/torredil))
-* Fix CVE G0-2024-2687 by bumping go and /x/net dependencies ([#1996](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1996), [@AndrewSirenko](https://github.com/AndrewSirenko))
-* Fix relationship between node service and mounter interface ([#1997](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1997), [@torredil](https://github.com/torredil))
-* Fix DeleteSnapshot error message ([#2000](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2000), [@AndrewSirenko](https://github.com/AndrewSirenko))
-* Add explicit AttachVolume call in WaitForAttachmentState ([#2005](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2005), [@torredil](https://github.com/torredil))
-* Handle deleted Node case in hook; Add support for CAS taint ([#2007](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2007), [@ConnorJC3](https://github.com/ConnorJC3))
-
 # v1.29.1
 ### Bug Fixes
 * Correctly forward os.version for Windows images in multi-arch manifests ([#1985](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1985), [@ConnorJC3](https://github.com/ConnorJC3))
diff --git a/Dockerfile b/Dockerfile
index 4ea5e1dd..f080a598 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -36,8 +36,10 @@ ENTRYPOINT ["/bin/aws-ebs-csi-driver"]
 
 FROM public.ecr.aws/eks-distro-build-tooling/eks-distro-windows-base:1809 AS windows-ltsc2019
 COPY --from=builder /go/src/github.com/kubernetes-sigs/aws-ebs-csi-driver/bin/aws-ebs-csi-driver.exe /aws-ebs-csi-driver.exe
+ENV PATH="C:\\Windows\\System32\\WindowsPowerShell\\v1.0;${PATH}"
 ENTRYPOINT ["/aws-ebs-csi-driver.exe"]
 
 FROM public.ecr.aws/eks-distro-build-tooling/eks-distro-windows-base:ltsc2022 AS windows-ltsc2022
 COPY --from=builder /go/src/github.com/kubernetes-sigs/aws-ebs-csi-driver/bin/aws-ebs-csi-driver.exe /aws-ebs-csi-driver.exe
+ENV PATH="C:\\Windows\\System32\\WindowsPowerShell\\v1.0;${PATH}"
 ENTRYPOINT ["/aws-ebs-csi-driver.exe"]
diff --git a/Makefile b/Makefile
index bddd678b..5502d27c 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@
 
 ## Variables/Functions
 
-VERSION?=v1.30.0
+VERSION?=v1.29.1
 
 PKG=github.com/kubernetes-sigs/aws-ebs-csi-driver
 GIT_COMMIT?=$(shell git rev-parse HEAD)
@@ -54,6 +54,7 @@ ALL_OS_ARCH_OSVERSION=$(foreach os, $(ALL_OS), ${ALL_OS_ARCH_OSVERSION_${os}})
 CLUSTER_NAME?=ebs-csi-e2e.k8s.local
 CLUSTER_TYPE?=kops
 WINDOWS?=false
+WINDOWS_HOSTPROCESS?=false
 
 # split words on hyphen, access by 1-index
 word-hyphen = $(word $2,$(subst -, ,$1))
@@ -149,6 +150,15 @@ e2e/external-windows: bin/helm bin/kubetest2
 	EBS_INSTALL_SNAPSHOT="false" \
 	./hack/e2e/run.sh
 
+.PHONY: e2e/external-windows-hostprocess
+e2e/external-windows-hostprocess: bin/helm bin/kubetest2
+	WINDOWS_HOSTPROCESS=true \
+	WINDOWS=true \
+	GINKGO_SKIP="\[Disruptive\]|\[Serial\]|\[LinuxOnly\]|\[Feature:VolumeSnapshotDataSource\]|\(xfs\)|\(ext4\)|\(block volmode\)" \
+	GINKGO_PARALLEL=15 \
+	EBS_INSTALL_SNAPSHOT="false" \
+	./hack/e2e/run.sh
+
 .PHONY: e2e/external-kustomize
 e2e/external-kustomize: bin/kubetest2
 	DEPLOY_METHOD="kustomize" \
diff --git a/README.md b/README.md
index c19b4315..92245105 100644
--- a/README.md
+++ b/README.md
@@ -20,8 +20,8 @@ The [Amazon Elastic Block Store](https://aws.amazon.com/ebs/) Container Storage
 
 | Driver Version | [registry.k8s.io](https://kubernetes.io/blog/2022/11/28/registry-k8s-io-faster-cheaper-ga/) Image | [ECR Public](https://gallery.ecr.aws/ebs-csi-driver/aws-ebs-csi-driver) Image |
 |----------------|---------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
-| v1.30.0        | registry.k8s.io/provider-aws/aws-ebs-csi-driver:v1.30.0                                           | public.ecr.aws/ebs-csi-driver/aws-ebs-csi-driver:v1.30.0                      |
 | v1.29.1        | registry.k8s.io/provider-aws/aws-ebs-csi-driver:v1.29.1                                           | public.ecr.aws/ebs-csi-driver/aws-ebs-csi-driver:v1.29.1                      |
+| v1.28.0        | registry.k8s.io/provider-aws/aws-ebs-csi-driver:v1.28.0                                           | public.ecr.aws/ebs-csi-driver/aws-ebs-csi-driver:v1.28.0                      |
 
 ## Releases
 
diff --git a/charts/aws-ebs-csi-driver/CHANGELOG.md b/charts/aws-ebs-csi-driver/CHANGELOG.md
index 3daf61e5..56aaf3d4 100644
--- a/charts/aws-ebs-csi-driver/CHANGELOG.md
+++ b/charts/aws-ebs-csi-driver/CHANGELOG.md
@@ -1,12 +1,7 @@
 # Helm chart
-## v2.30.0
-* Bump driver version to `v1.30.0`
-* Update voluemessnapshotcontents/status RBAC ([#1991](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/1991), [@AndrewSirenko](https://github.com/AndrewSirenko))
-* Upgrade dependencies ([#2016](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/pull/2016), [@torredil](https://github.com/torredil))
-
 ## v2.29.1
 * Bump driver version to `v1.29.1`
-* Remove `--reuse-values` deprecation warning
+* Remove `--reuse-values` deprecation warning 
 
 ## v2.29.0
 ### Urgent Upgrade Notes
diff --git a/charts/aws-ebs-csi-driver/Chart.yaml b/charts/aws-ebs-csi-driver/Chart.yaml
index b0adc5dd..f64d0622 100644
--- a/charts/aws-ebs-csi-driver/Chart.yaml
+++ b/charts/aws-ebs-csi-driver/Chart.yaml
@@ -1,8 +1,8 @@
 apiVersion: v2
-appVersion: 1.30.0
+appVersion: 1.29.1
 name: aws-ebs-csi-driver
 description: A Helm chart for AWS EBS CSI Driver
-version: 2.30.0
+version: 2.29.1
 kubeVersion: ">=1.17.0-0"
 home: https://github.com/kubernetes-sigs/aws-ebs-csi-driver
 sources:
diff --git a/charts/aws-ebs-csi-driver/templates/_node-windows.tpl b/charts/aws-ebs-csi-driver/templates/_node-windows.tpl
index 56e8dcfa..ab17f71e 100644
--- a/charts/aws-ebs-csi-driver/templates/_node-windows.tpl
+++ b/charts/aws-ebs-csi-driver/templates/_node-windows.tpl
@@ -49,10 +49,21 @@ spec:
         {{- toYaml . | nindent 8 }}
         {{- end }}
         {{- end }}
+      {{- if .Values.node.windowsHostProcess }}
+      securityContext:
+        windowsOptions:
+          hostProcess: true
+          runAsUserName: "NT AUTHORITY\\SYSTEM"
+      hostNetwork: true
+      {{- end }}
       containers:
         - name: ebs-plugin
           image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.image.repository (default (printf "v%s" .Chart.AppVersion) (toString .Values.image.tag)) }}
           imagePullPolicy: {{ .Values.image.pullPolicy }}
+          {{- if .Values.node.windowsHostProcess }}
+          command:
+            - "aws-ebs-csi-driver.exe"
+          {{- end }}
           args:
             - node
             - --endpoint=$(CSI_ENDPOINT)
@@ -66,9 +77,16 @@ spec:
             {{- if .Values.node.otelTracing }}
             - --enable-otel-tracing=true
             {{- end}}
+            {{- if .Values.node.windowsHostProcess }}
+            - --windows-host-process=true
+            {{- end }}
           env:
             - name: CSI_ENDPOINT
+            {{- if .Values.node.windowsHostProcess }}
+              value: unix://C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock
+            {{- else }}
               value: unix:/csi/csi.sock
+            {{- end }}
             - name: CSI_NODE_NAME
               valueFrom:
                 fieldRef:
@@ -91,12 +109,14 @@ spec:
               mountPropagation: "None"
             - name: plugin-dir
               mountPath: C:\csi
+          {{- if not .Values.node.windowsHostProcess }}
             - name: csi-proxy-disk-pipe
               mountPath: \\.\pipe\csi-proxy-disk-v1
             - name: csi-proxy-volume-pipe
               mountPath: \\.\pipe\csi-proxy-volume-v1
             - name: csi-proxy-filesystem-pipe
               mountPath: \\.\pipe\csi-proxy-filesystem-v1
+          {{- end }}
           ports:
             - name: healthz
               containerPort: 9808
@@ -113,9 +133,11 @@ spec:
           resources:
             {{- toYaml . | nindent 12 }}
           {{- end }}
+          {{- if not .Values.node.windowsHostProcess }}
           securityContext:
             windowsOptions:
               runAsUserName: "ContainerAdministrator"
+          {{- end }}
           lifecycle:
             preStop:
               exec:
@@ -123,15 +145,34 @@ spec:
         - name: node-driver-registrar
           image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.nodeDriverRegistrar.image.repository .Values.sidecars.nodeDriverRegistrar.image.tag }}
           imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.nodeDriverRegistrar.image.pullPolicy }}
+          {{- if .Values.node.windowsHostProcess }}
+          command:
+            - "csi-node-driver-registrar.exe"
+          {{- end }}
           args:
             - --csi-address=$(ADDRESS)
             - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH)
+          {{- if .Values.node.windowsHostProcess }}
+            - --plugin-registration-path=$(PLUGIN_REG_DIR)
+          {{- end }}
             - --v={{ .Values.sidecars.nodeDriverRegistrar.logLevel }}
           env:
             - name: ADDRESS
+            {{- if .Values.node.windowsHostProcess }}
+              value: unix://C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock
+            {{- else }}
               value: unix:/csi/csi.sock
+            {{- end }}
             - name: DRIVER_REG_SOCK_PATH
+            {{- if .Values.node.windowsHostProcess }}
+              value: C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock
+            {{- else }}
               value: C:\var\lib\kubelet\plugins\ebs.csi.aws.com\csi.sock
+            {{- end }}
+          {{- if .Values.node.windowsHostProcess }}
+            - name: PLUGIN_REG_DIR
+              value: C:\\var\\lib\\kubelet\\plugins_registry\\
+          {{- end }}
             {{- if .Values.proxy.http_proxy }}
             {{- include "aws-ebs-csi-driver.http-proxy" . | nindent 12 }}
             {{- end }}
@@ -161,8 +202,16 @@ spec:
         - name: liveness-probe
           image: {{ printf "%s%s:%s" (default "" .Values.image.containerRegistry) .Values.sidecars.livenessProbe.image.repository .Values.sidecars.livenessProbe.image.tag }}
           imagePullPolicy: {{ default .Values.image.pullPolicy .Values.sidecars.livenessProbe.image.pullPolicy }}
+          {{- if .Values.node.windowsHostProcess }}
+          command:
+            - "livenessprobe.exe"
+          {{- end }}
           args:
+            {{- if .Values.node.windowsHostProcess }}
+            - --csi-address=unix://C:\\var\\lib\\kubelet\\plugins\\ebs.csi.aws.com\\csi.sock
+            {{- else }}
             - --csi-address=unix:/csi/csi.sock
+            {{- end }}
           volumeMounts:
             - name: plugin-dir
               mountPath: C:\csi
@@ -189,6 +238,7 @@ spec:
           hostPath:
             path: C:\var\lib\kubelet\plugins_registry
             type: Directory
+      {{- if not .Values.node.windowsHostProcess }}
         - name: csi-proxy-disk-pipe
           hostPath:
             path: \\.\pipe\csi-proxy-disk-v1
@@ -201,6 +251,7 @@ spec:
           hostPath:
             path: \\.\pipe\csi-proxy-filesystem-v1
             type: ""
+      {{- end }}
         - name: probe-dir
           {{- if .Values.node.probeDirVolume }}
           {{- toYaml .Values.node.probeDirVolume | nindent 10 }}
diff --git a/charts/aws-ebs-csi-driver/values.yaml b/charts/aws-ebs-csi-driver/values.yaml
index ca9cea07..0c4e51e3 100644
--- a/charts/aws-ebs-csi-driver/values.yaml
+++ b/charts/aws-ebs-csi-driver/values.yaml
@@ -19,7 +19,7 @@ sidecars:
     image:
       pullPolicy: IfNotPresent
       repository: public.ecr.aws/eks-distro/kubernetes-csi/external-provisioner
-      tag: "v4.0.1-eks-1-30-2"
+      tag: "v4.0.0-eks-1-29-7"
     logLevel: 2
     # Additional parameters provided by external-provisioner.
     additionalArgs: []
@@ -44,7 +44,7 @@ sidecars:
     image:
       pullPolicy: IfNotPresent
       repository: public.ecr.aws/eks-distro/kubernetes-csi/external-attacher
-      tag: "v4.5.1-eks-1-30-2"
+      tag: "v4.5.0-eks-1-29-7"
     # Tune leader lease election for csi-attacher.
     # Leader election is on by default.
     leaderElection:
@@ -71,7 +71,7 @@ sidecars:
     image:
       pullPolicy: IfNotPresent
       repository: public.ecr.aws/eks-distro/kubernetes-csi/external-snapshotter/csi-snapshotter
-      tag: "v7.0.2-eks-1-30-2"
+      tag: "v7.0.1-eks-1-29-7"
     logLevel: 2
     # Additional parameters provided by csi-snapshotter.
     additionalArgs: []
@@ -85,7 +85,7 @@ sidecars:
     image:
       pullPolicy: IfNotPresent
       repository: public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe
-      tag: "v2.12.0-eks-1-30-2"
+      tag: "v2.12.0-eks-1-29-7"
     # Additional parameters provided by livenessprobe.
     additionalArgs: []
     resources: {}
@@ -97,7 +97,7 @@ sidecars:
     image:
       pullPolicy: IfNotPresent
       repository: public.ecr.aws/eks-distro/kubernetes-csi/external-resizer
-      tag: "v1.10.1-eks-1-30-2"
+      tag: "v1.10.0-eks-1-29-7"
     # Tune leader lease election for csi-resizer.
     # Leader election is on by default.
     leaderElection:
@@ -122,7 +122,7 @@ sidecars:
     image:
       pullPolicy: IfNotPresent
       repository: public.ecr.aws/eks-distro/kubernetes-csi/node-driver-registrar
-      tag: "v2.10.1-eks-1-30-2"
+      tag: "v2.10.0-eks-1-29-7"
     logLevel: 2
     # Additional parameters provided by node-driver-registrar.
     additionalArgs: []
@@ -144,7 +144,7 @@ sidecars:
     image:
       pullPolicy: IfNotPresent
       repository: public.ecr.aws/ebs-csi-driver/volume-modifier-for-k8s
-      tag: "v0.3.0"
+      tag: "v0.2.1"
     leaderElection:
       enabled: true
       # Optional values to tune lease behavior.
diff --git a/cmd/main.go b/cmd/main.go
index 417ec491..24b780ac 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -89,12 +89,7 @@ func main() {
 	options.AddFlags(fs)
 
 	if err = fs.Parse(args); err != nil {
-		klog.ErrorS(err, "Failed to parse options")
-		klog.FlushAndExit(klog.ExitFlushTimeout, 0)
-	}
-	if err = options.Validate(); err != nil {
-		klog.ErrorS(err, "Invalid options")
-		klog.FlushAndExit(klog.ExitFlushTimeout, 0)
+		panic(err)
 	}
 
 	err = logsapi.ValidateAndApply(c, featureGate)
@@ -135,7 +130,7 @@ func main() {
 
 	if options.HttpEndpoint != "" {
 		r := metrics.InitializeRecorder()
-		r.InitializeMetricsHandler(options.HttpEndpoint, "/metrics", options.MetricsCertFile, options.MetricsKeyFile)
+		r.InitializeMetricsHandler(options.HttpEndpoint, "/metrics")
 	}
 
 	cfg := metadata.MetadataServiceConfig{
@@ -173,14 +168,15 @@ func main() {
 		klog.FlushAndExit(klog.ExitFlushTimeout, 1)
 	}
 
-	m, err := mounter.NewNodeMounter()
+	m, err := mounter.NewNodeMounter(options.WindowsHostProcess)
 	if err != nil {
-		panic(err)
+		klog.ErrorS(err, "failed to create node mounter")
+		klog.FlushAndExit(klog.ExitFlushTimeout, 1)
 	}
 
 	k8sClient, err := cfg.K8sAPIClient()
 	if err != nil {
-		klog.V(2).InfoS("Failed to setup k8s client")
+		klog.V(2).InfoS("Failed to setup k8s client", "err", err)
 	}
 
 	drv, err := driver.NewDriver(cloud, &options, m, md, k8sClient)
diff --git a/deploy/kubernetes/base/controller.yaml b/deploy/kubernetes/base/controller.yaml
index 787dc93b..a462b853 100644
--- a/deploy/kubernetes/base/controller.yaml
+++ b/deploy/kubernetes/base/controller.yaml
@@ -62,7 +62,7 @@ spec:
         runAsUser: 1000
       containers:
         - name: ebs-plugin
-          image: public.ecr.aws/ebs-csi-driver/aws-ebs-csi-driver:v1.30.0
+          image: public.ecr.aws/ebs-csi-driver/aws-ebs-csi-driver:v1.29.1
           imagePullPolicy: IfNotPresent
           args:
             # - {all,controller,node} # specify the driver mode
@@ -129,7 +129,7 @@ spec:
             allowPrivilegeEscalation: false
             readOnlyRootFilesystem: true
         - name: csi-provisioner
-          image: public.ecr.aws/eks-distro/kubernetes-csi/external-provisioner:v4.0.1-eks-1-30-2
+          image: public.ecr.aws/eks-distro/kubernetes-csi/external-provisioner:v4.0.0-eks-1-29-7
           imagePullPolicy: IfNotPresent
           args:
             - --timeout=60s
@@ -158,7 +158,7 @@ spec:
             allowPrivilegeEscalation: false
             readOnlyRootFilesystem: true
         - name: csi-attacher
-          image: public.ecr.aws/eks-distro/kubernetes-csi/external-attacher:v4.5.1-eks-1-30-2
+          image: public.ecr.aws/eks-distro/kubernetes-csi/external-attacher:v4.5.0-eks-1-29-7
           imagePullPolicy: IfNotPresent
           args:
             - --timeout=60s
@@ -184,7 +184,7 @@ spec:
             allowPrivilegeEscalation: false
             readOnlyRootFilesystem: true
         - name: csi-snapshotter
-          image: public.ecr.aws/eks-distro/kubernetes-csi/external-snapshotter/csi-snapshotter:v7.0.2-eks-1-30-2
+          image: public.ecr.aws/eks-distro/kubernetes-csi/external-snapshotter/csi-snapshotter:v7.0.1-eks-1-29-7
           imagePullPolicy: IfNotPresent
           args:
             - --csi-address=$(ADDRESS)
@@ -209,7 +209,7 @@ spec:
             allowPrivilegeEscalation: false
             readOnlyRootFilesystem: true
         - name: csi-resizer
-          image: public.ecr.aws/eks-distro/kubernetes-csi/external-resizer:v1.10.1-eks-1-30-2
+          image: public.ecr.aws/eks-distro/kubernetes-csi/external-resizer:v1.10.0-eks-1-29-7
           imagePullPolicy: IfNotPresent
           args:
             - --timeout=60s
@@ -236,7 +236,7 @@ spec:
             allowPrivilegeEscalation: false
             readOnlyRootFilesystem: true
         - name: liveness-probe
-          image: public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe:v2.12.0-eks-1-30-2
+          image: public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe:v2.12.0-eks-1-29-7
           imagePullPolicy: IfNotPresent
           args:
             - --csi-address=/csi/csi.sock
diff --git a/deploy/kubernetes/base/node.yaml b/deploy/kubernetes/base/node.yaml
index 13c50070..c9f28992 100644
--- a/deploy/kubernetes/base/node.yaml
+++ b/deploy/kubernetes/base/node.yaml
@@ -53,7 +53,7 @@ spec:
         runAsUser: 0
       containers:
         - name: ebs-plugin
-          image: public.ecr.aws/ebs-csi-driver/aws-ebs-csi-driver:v1.30.0
+          image: public.ecr.aws/ebs-csi-driver/aws-ebs-csi-driver:v1.29.1
           imagePullPolicy: IfNotPresent
           args:
             - node
@@ -101,7 +101,7 @@ spec:
               exec:
                 command: ["/bin/aws-ebs-csi-driver", "pre-stop-hook"]
         - name: node-driver-registrar
-          image: public.ecr.aws/eks-distro/kubernetes-csi/node-driver-registrar:v2.10.1-eks-1-30-2
+          image: public.ecr.aws/eks-distro/kubernetes-csi/node-driver-registrar:v2.10.0-eks-1-29-7
           imagePullPolicy: IfNotPresent
           args:
             - --csi-address=$(ADDRESS)
@@ -138,7 +138,7 @@ spec:
             allowPrivilegeEscalation: false
             readOnlyRootFilesystem: true
         - name: liveness-probe
-          image: public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe:v2.12.0-eks-1-30-2
+          image: public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe:v2.12.0-eks-1-29-7
           imagePullPolicy: IfNotPresent
           args:
             - --csi-address=/csi/csi.sock
diff --git a/deploy/kubernetes/overlays/stable/gcr/kustomization.yaml b/deploy/kubernetes/overlays/stable/gcr/kustomization.yaml
index 41fcc2fe..8f9aab93 100644
--- a/deploy/kubernetes/overlays/stable/gcr/kustomization.yaml
+++ b/deploy/kubernetes/overlays/stable/gcr/kustomization.yaml
@@ -7,19 +7,19 @@ images:
     newName: registry.k8s.io/provider-aws/aws-ebs-csi-driver
   - name: public.ecr.aws/eks-distro/kubernetes-csi/external-provisioner
     newName: registry.k8s.io/sig-storage/csi-provisioner
-    newTag: v4.0.1
+    newTag: v4.0.0
   - name: public.ecr.aws/eks-distro/kubernetes-csi/external-attacher
     newName: registry.k8s.io/sig-storage/csi-attacher
-    newTag: v4.5.1
+    newTag: v4.5.0
   - name: public.ecr.aws/eks-distro/kubernetes-csi/livenessprobe
     newName: registry.k8s.io/sig-storage/livenessprobe
     newTag: v2.12.0
   - name: public.ecr.aws/eks-distro/kubernetes-csi/external-snapshotter/csi-snapshotter
     newName: registry.k8s.io/sig-storage/csi-snapshotter
-    newTag: v7.0.2
+    newTag: v7.0.1
   - name: public.ecr.aws/eks-distro/kubernetes-csi/external-resizer
     newName: registry.k8s.io/sig-storage/csi-resizer
-    newTag: v1.10.1
+    newTag: v1.10.0
   - name: public.ecr.aws/eks-distro/kubernetes-csi/node-driver-registrar
     newName: registry.k8s.io/sig-storage/csi-node-driver-registrar
-    newTag: v2.10.1
+    newTag: v2.10.0
diff --git a/docs/install.md b/docs/install.md
index 9f39a061..35979dd5 100644
--- a/docs/install.md
+++ b/docs/install.md
@@ -52,7 +52,7 @@ You may deploy the EBS CSI driver via Kustomize, Helm, or as an [Amazon EKS mana
 
 #### Kustomize
 ```sh
-kubectl apply -k "github.com/kubernetes-sigs/aws-ebs-csi-driver/deploy/kubernetes/overlays/stable/?ref=release-1.30"
+kubectl apply -k "github.com/kubernetes-sigs/aws-ebs-csi-driver/deploy/kubernetes/overlays/stable/?ref=release-1.29"
 ```
 
 *Note: Using the master branch to deploy the driver is not supported as the master branch may contain upcoming features incompatible with the currently released stable version of the driver.*
diff --git a/docs/options.md b/docs/options.md
index 05951f2a..4a7d5f20 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -6,8 +6,6 @@ There are a couple of driver options that can be passed as arguments when starti
 |-----------------------------|---------------------------------------------------|-----------------------------------------------------|---------------------|
 | endpoint                    | tcp://127.0.0.1:10000/                            | unix:///var/lib/csi/sockets/pluginproxy/csi.sock    | The socket on which the driver will listen for CSI RPCs|
 | http-endpoint               | :8080                                             |                                                     | The TCP network address where the HTTP server for metrics will listen (example: `:8080`). The default is empty string, which means the server is disabled.|
-| metrics-cert-file           | /metrics.crt                                      |                                                     | The path to a certificate to use for serving the metrics server over HTTPS. If the certificate is signed by a certificate authority, this file should be the concatenation of the server's certificate, any intermediates, and the CA's certificate. If this is non-empty, `--http-endpoint` and `--metrics-key-file` MUST also be non-empty.|
-| metrics-key-file            | /metrics.key                                      |                                                     | The path to a key to use for serving the metrics server over HTTPS. If this is non-empty, `--http-endpoint` and `--metrics-cert-file` MUST also be non-empty.|
 | volume-attach-limit         | 1,2,3 ...                                         | -1                                                  | Value for the maximum number of volumes attachable per node. If specified, the limit applies to all nodes. If not specified, the value is approximated from the instance type|
 | extra-tags                  | key1=value1,key2=value2                           |                                                     | Tags attached to each dynamically provisioned resource|
 | k8s-tag-cluster-id          | aws-cluster-id-1                                  |                                                     | ID of the Kubernetes cluster used for tagging provisioned EBS volumes|
diff --git a/go.mod b/go.mod
index 954cedd5..7e4dc2e0 100644
--- a/go.mod
+++ b/go.mod
@@ -1,59 +1,60 @@
 module github.com/kubernetes-sigs/aws-ebs-csi-driver
 
 require (
-	github.com/aws/aws-sdk-go-v2 v1.26.1
-	github.com/aws/aws-sdk-go-v2/config v1.27.11
-	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1
-	github.com/aws/aws-sdk-go-v2/service/ec2 v1.157.0
-	github.com/aws/smithy-go v1.20.2
+	github.com/aws/aws-sdk-go-v2 v1.25.3
+	github.com/aws/aws-sdk-go-v2/config v1.27.7
+	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3
+	github.com/aws/aws-sdk-go-v2/service/ec2 v1.150.0
+	github.com/aws/smithy-go v1.20.1
 	github.com/awslabs/volume-modifier-for-k8s v0.2.1
 	github.com/container-storage-interface/spec v1.9.0
 	github.com/golang/mock v1.6.0
 	github.com/google/go-cmp v0.6.0
 	github.com/google/uuid v1.6.0
 	github.com/kubernetes-csi/csi-proxy/client v1.1.3
+	github.com/kubernetes-csi/csi-proxy/v2 v2.0.0-alpha.1
 	github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0
-	github.com/onsi/ginkgo/v2 v2.17.1
-	github.com/onsi/gomega v1.33.0
+	github.com/onsi/ginkgo/v2 v2.17.0
+	github.com/onsi/gomega v1.32.0
 	github.com/spf13/pflag v1.0.5
 	github.com/stretchr/testify v1.9.0
-	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.50.0
-	go.opentelemetry.io/otel v1.25.0
-	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.25.0
-	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.25.0
-	go.opentelemetry.io/otel/sdk v1.25.0
-	golang.org/x/sys v0.19.0
-	google.golang.org/grpc v1.63.2
+	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0
+	go.opentelemetry.io/otel v1.24.0
+	go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0
+	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0
+	go.opentelemetry.io/otel/sdk v1.24.0
+	golang.org/x/sys v0.18.0
+	google.golang.org/grpc v1.62.1
 	google.golang.org/protobuf v1.33.0
-	k8s.io/api v0.30.0
-	k8s.io/apimachinery v0.30.0
+	k8s.io/api v0.29.2
+	k8s.io/apimachinery v0.29.2
 	k8s.io/client-go v1.5.2
-	k8s.io/component-base v0.30.0
+	k8s.io/component-base v0.29.2
 	k8s.io/klog/v2 v2.120.1
-	k8s.io/kubernetes v1.30.0
-	k8s.io/mount-utils v0.30.0
-	k8s.io/pod-security-admission v0.30.0
+	k8s.io/kubernetes v1.29.2
+	k8s.io/mount-utils v0.29.2
+	k8s.io/pod-security-admission v0.29.2
 	k8s.io/utils v0.0.0-20240310230437-4693a0247e57
 )
 
 require (
 	github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
-	github.com/aws/aws-sdk-go-v2/credentials v1.17.11 // indirect
-	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
-	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
+	github.com/aws/aws-sdk-go-v2/credentials v1.17.7 // indirect
+	github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3 // indirect
+	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3 // indirect
 	github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
-	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
-	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect
-	github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 // indirect
-	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 // indirect
-	github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 // indirect
+	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
+	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5 // indirect
+	github.com/aws/aws-sdk-go-v2/service/sso v1.20.2 // indirect
+	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.2 // indirect
+	github.com/aws/aws-sdk-go-v2/service/sts v1.28.4 // indirect
 	github.com/distribution/reference v0.5.0 // indirect
 	github.com/gorilla/websocket v1.5.1 // indirect
 	github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
 	github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
 	github.com/robfig/cron/v3 v3.0.1 // indirect
 	github.com/samber/lo v1.39.0 // indirect
-	k8s.io/component-helpers v0.30.0 // indirect
+	k8s.io/component-helpers v0.29.2 // indirect
 	knative.dev/pkg v0.0.0-20230712131115-7051d301e7f4 // indirect
 )
 
@@ -63,7 +64,7 @@ require (
 	github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/blang/semver/v4 v4.0.0 // indirect
-	github.com/cenkalti/backoff/v4 v4.3.0 // indirect
+	github.com/cenkalti/backoff/v4 v4.2.1 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/coreos/go-semver v0.3.1 // indirect
 	github.com/coreos/go-systemd/v22 v22.5.0 // indirect
@@ -113,37 +114,37 @@ require (
 	go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect
 	go.etcd.io/etcd/client/v3 v3.5.12 // indirect
 	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 // indirect
-	go.opentelemetry.io/otel/metric v1.25.0 // indirect
-	go.opentelemetry.io/otel/trace v1.25.0 // indirect
+	go.opentelemetry.io/otel/metric v1.24.0 // indirect
+	go.opentelemetry.io/otel/trace v1.24.0 // indirect
 	go.opentelemetry.io/proto/otlp v1.1.0 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
-	golang.org/x/crypto v0.22.0 // indirect
+	golang.org/x/crypto v0.21.0 // indirect
 	golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 // indirect
 	golang.org/x/mod v0.16.0 // indirect
-	golang.org/x/net v0.24.0 // indirect
+	golang.org/x/net v0.23.0 // indirect
 	golang.org/x/oauth2 v0.18.0 // indirect
 	golang.org/x/sync v0.6.0 // indirect
-	golang.org/x/term v0.19.0 // indirect
+	golang.org/x/term v0.18.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	golang.org/x/time v0.5.0 // indirect
 	golang.org/x/tools v0.19.0 // indirect
 	google.golang.org/appengine v1.6.8 // indirect
 	google.golang.org/genproto v0.0.0-20240318140521-94a12d6c2237 // indirect
 	google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
-	k8s.io/apiextensions-apiserver v0.30.0 // indirect
-	k8s.io/apiserver v0.30.0 // indirect
-	k8s.io/cloud-provider v0.30.0 // indirect
-	k8s.io/controller-manager v0.30.0 // indirect
-	k8s.io/kms v0.30.0 // indirect
-	k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
-	k8s.io/kubectl v0.30.0 // indirect
-	k8s.io/kubelet v0.30.0 // indirect
+	k8s.io/apiextensions-apiserver v0.29.2 // indirect
+	k8s.io/apiserver v0.29.2 // indirect
+	k8s.io/cloud-provider v0.29.2 // indirect
+	k8s.io/controller-manager v0.29.2 // indirect
+	k8s.io/kms v0.29.2 // indirect
+	k8s.io/kube-openapi v0.0.0-20240209001042-7a0d5b415232 // indirect
+	k8s.io/kubectl v0.29.2 // indirect
+	k8s.io/kubelet v0.29.2 // indirect
 	sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 // indirect
 	sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
 	sigs.k8s.io/karpenter v0.35.2
@@ -153,36 +154,36 @@ require (
 
 replace (
 	github.com/google/cel-go => github.com/google/cel-go v0.17.7 // Mitigate https://github.com/kubernetes/apiserver/issues/97
-	k8s.io/api => k8s.io/api v0.30.0
-	k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.30.0
-	k8s.io/apimachinery => k8s.io/apimachinery v0.30.0
-	k8s.io/apiserver => k8s.io/apiserver v0.30.0
-	k8s.io/cli-runtime => k8s.io/cli-runtime v0.30.0
-	k8s.io/client-go => k8s.io/client-go v0.30.0
-	k8s.io/cloud-provider => k8s.io/cloud-provider v0.30.0
-	k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.30.0
-	k8s.io/code-generator => k8s.io/code-generator v0.30.0
-	k8s.io/component-base => k8s.io/component-base v0.30.0
-	k8s.io/component-helpers => k8s.io/component-helpers v0.30.0
-	k8s.io/controller-manager => k8s.io/controller-manager v0.30.0
-	k8s.io/cri-api => k8s.io/cri-api v0.30.0
-	k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.30.0
-	k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.30.0
-	k8s.io/endpointslice => k8s.io/endpointslice v0.30.0
-	k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.30.0
-	k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.30.0
-	k8s.io/kube-proxy => k8s.io/kube-proxy v0.30.0
-	k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.30.0
-	k8s.io/kubectl => k8s.io/kubectl v0.30.0
-	k8s.io/kubelet => k8s.io/kubelet v0.30.0
-	k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.0
-	k8s.io/metrics => k8s.io/metrics v0.30.0
-	k8s.io/mount-utils => k8s.io/mount-utils v0.30.0
-	k8s.io/node-api => k8s.io/node-api v0.30.0
-	k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.30.0
-	k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.30.0
-	k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.30.0
-	k8s.io/sample-controller => k8s.io/sample-controller v0.30.0
+	k8s.io/api => k8s.io/api v0.29.2
+	k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.29.2
+	k8s.io/apimachinery => k8s.io/apimachinery v0.29.2
+	k8s.io/apiserver => k8s.io/apiserver v0.29.2
+	k8s.io/cli-runtime => k8s.io/cli-runtime v0.29.2
+	k8s.io/client-go => k8s.io/client-go v0.29.2
+	k8s.io/cloud-provider => k8s.io/cloud-provider v0.29.2
+	k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.29.2
+	k8s.io/code-generator => k8s.io/code-generator v0.29.2
+	k8s.io/component-base => k8s.io/component-base v0.29.2
+	k8s.io/component-helpers => k8s.io/component-helpers v0.29.2
+	k8s.io/controller-manager => k8s.io/controller-manager v0.29.2
+	k8s.io/cri-api => k8s.io/cri-api v0.29.2
+	k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.29.2
+	k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.29.2
+	k8s.io/endpointslice => k8s.io/endpointslice v0.29.2
+	k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.29.2
+	k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.29.2
+	k8s.io/kube-proxy => k8s.io/kube-proxy v0.29.2
+	k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.29.2
+	k8s.io/kubectl => k8s.io/kubectl v0.29.2
+	k8s.io/kubelet => k8s.io/kubelet v0.29.2
+	k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.29.2
+	k8s.io/metrics => k8s.io/metrics v0.29.2
+	k8s.io/mount-utils => k8s.io/mount-utils v0.29.2
+	k8s.io/node-api => k8s.io/node-api v0.29.2
+	k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.29.2
+	k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.29.2
+	k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.29.2
+	k8s.io/sample-controller => k8s.io/sample-controller v0.29.2
 	vbom.ml/util => github.com/fvbommel/util v0.0.2 // Mitigate https://github.com/fvbommel/util/issues/6
 )
 
diff --git a/go.sum b/go.sum
index 3a1fb734..4cf32963 100644
--- a/go.sum
+++ b/go.sum
@@ -627,34 +627,34 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d
 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
 github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
 github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
-github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=
-github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
-github.com/aws/aws-sdk-go-v2/config v1.27.11 h1:f47rANd2LQEYHda2ddSCKYId18/8BhSRM4BULGmfgNA=
-github.com/aws/aws-sdk-go-v2/config v1.27.11/go.mod h1:SMsV78RIOYdve1vf36z8LmnszlRWkwMQtomCAI0/mIE=
-github.com/aws/aws-sdk-go-v2/credentials v1.17.11 h1:YuIB1dJNf1Re822rriUOTxopaHHvIq0l/pX3fwO+Tzs=
-github.com/aws/aws-sdk-go-v2/credentials v1.17.11/go.mod h1:AQtFPsDH9bI2O+71anW6EKL+NcD7LG3dpKGMV4SShgo=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc=
+github.com/aws/aws-sdk-go-v2 v1.25.3 h1:xYiLpZTQs1mzvz5PaI6uR0Wh57ippuEthxS4iK5v0n0=
+github.com/aws/aws-sdk-go-v2 v1.25.3/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I=
+github.com/aws/aws-sdk-go-v2/config v1.27.7 h1:JSfb5nOQF01iOgxFI5OIKWwDiEXWTyTgg1Mm1mHi0A4=
+github.com/aws/aws-sdk-go-v2/config v1.27.7/go.mod h1:PH0/cNpoMO+B04qET699o5W92Ca79fVtbUnvMIZro4I=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.7 h1:WJd+ubWKoBeRh7A5iNMnxEOs982SyVKOJD+K8HIezu4=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.7/go.mod h1:UQi7LMR0Vhvs+44w5ec8Q+VS+cd10cjwgHwiVkE0YGU=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3 h1:p+y7FvkK2dxS+FEwRIDHDe//ZX+jDhP8HHE50ppj4iI=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.3/go.mod h1:/fYB+FZbDlwlAiynK9KDXlzZl3ANI9JkD0Uhz5FjNT4=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3 h1:ifbIbHZyGl1alsAhPIYsHOg5MuApgqOvVeI8wIugXfs=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3/go.mod h1:oQZXg3c6SNeY6OZrDY+xHcF4VGIEoNotX2B4PrDeoJI=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3 h1:Qvodo9gHG9F3E8SfYOspPeBt0bjSbsevK8WhRAUHcoY=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3/go.mod h1:vCKrdLXtybdf/uQd/YfVR2r5pcbNuEYKzMQpcxmeSJw=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
-github.com/aws/aws-sdk-go-v2/service/ec2 v1.157.0 h1:BCNvChkZM4xqssztw+rFllaDnoS4Hm6bZ20XBj8RsI0=
-github.com/aws/aws-sdk-go-v2/service/ec2 v1.157.0/go.mod h1:xejKuuRDjz6z5OqyeLsz01MlOqqW7CqpAB4PabNvpu8=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk=
-github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 h1:vN8hEbpRnL7+Hopy9dzmRle1xmDc7o8tmY0klsr175w=
-github.com/aws/aws-sdk-go-v2/service/sso v1.20.5/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 h1:Jux+gDDyi1Lruk+KHF91tK2KCuY61kzoCpvtvJJBtOE=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak=
-github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 h1:cwIxeBttqPN3qkaAjcEcsh8NYr8n2HZPkcKgPAi1phU=
-github.com/aws/aws-sdk-go-v2/service/sts v1.28.6/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw=
-github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
-github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
+github.com/aws/aws-sdk-go-v2/service/ec2 v1.150.0 h1:9JPrA5MyHUqr5hcU1o/xyryVctoyRrj5eHsxRSSDGfg=
+github.com/aws/aws-sdk-go-v2/service/ec2 v1.150.0/go.mod h1:KNJMjsbzK97hci9ev2Vl/27GgUt3ZciRP4RGujAPF2I=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5 h1:K/NXvIftOlX+oGgWGIa3jDyYLDNsdVhsjHmsBH2GLAQ=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5/go.mod h1:cl9HGLV66EnCmMNzq4sYOti+/xo8w34CsgzVtm2GgsY=
+github.com/aws/aws-sdk-go-v2/service/sso v1.20.2 h1:XOPfar83RIRPEzfihnp+U6udOveKZJvPQ76SKWrLRHc=
+github.com/aws/aws-sdk-go-v2/service/sso v1.20.2/go.mod h1:Vv9Xyk1KMHXrR3vNQe8W5LMFdTjSeWk0gBZBzvf3Qa0=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.2 h1:pi0Skl6mNl2w8qWZXcdOyg197Zsf4G97U7Sso9JXGZE=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.2/go.mod h1:JYzLoEVeLXk+L4tn1+rrkfhkxl6mLDEVaDSvGq9og90=
+github.com/aws/aws-sdk-go-v2/service/sts v1.28.4 h1:Ppup1nVNAOWbBOrcoOxaxPeEnSFB2RnnQdguhXpmeQk=
+github.com/aws/aws-sdk-go-v2/service/sts v1.28.4/go.mod h1:+K1rNPVyGxkRuv9NNiaZ4YhBFuyw2MMA9SlIJ1Zlpz8=
+github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
+github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
 github.com/awslabs/volume-modifier-for-k8s v0.2.1 h1:TOGWgBjkr1S+mTwZJr4rheV5h43HVJIabGcBC5QMaAQ=
 github.com/awslabs/volume-modifier-for-k8s v0.2.1/go.mod h1:C8A6tJ+axmdtEqrwXwxSZrVux3Ws4bWEmgvQMI9eIXg=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -665,8 +665,8 @@ github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHf
 github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc=
 github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
 github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
-github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
-github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
+github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
@@ -739,7 +739,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
 github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
-github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
 github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks=
@@ -751,7 +750,9 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
 github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=
+github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
+github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -956,6 +957,7 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@@ -966,6 +968,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/kubernetes-csi/csi-proxy/client v1.1.3 h1:FdGU7NtxGhQX2wTfnuscmThG920hq0OaVVpuJW9t2k0=
 github.com/kubernetes-csi/csi-proxy/client v1.1.3/go.mod h1:SfK4HVKQdMH5KrffivddAWgX5hl3P5KmnuOTBbDNboU=
+github.com/kubernetes-csi/csi-proxy/v2 v2.0.0-alpha.1 h1:tVPvlL5N5X598hrO3g9rhyoi6h0LP4RpSJlGHItsbEE=
+github.com/kubernetes-csi/csi-proxy/v2 v2.0.0-alpha.1/go.mod h1:pacx+PW7lLlu6kAvpr8Lgq/5fdiAsKxOtXXFHMaLMb8=
 github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 h1:nHHjmvjitIiyPlUHk/ofpgvBcNcawJLtf4PYHORLjAA=
 github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0/go.mod h1:YBCo4DoEeDndqvAn6eeu0vWM7QdXmHEeI9cFWplmBys=
 github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
@@ -1014,10 +1018,8 @@ github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3Ro
 github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0=
 github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
 github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
-github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
-github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
-github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
-github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
+github.com/onsi/ginkgo/v2 v2.17.0 h1:kdnunFXpBjbzN56hcJHrXZ8M+LOkenKA7NnBzTNigTI=
+github.com/onsi/ginkgo/v2 v2.17.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
@@ -1036,10 +1038,8 @@ github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRah
 github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ=
 github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
 github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
-github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
-github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk=
-github.com/onsi/gomega v1.33.0 h1:snPCflnZrpMsy94p4lXVEkHo12lmPnc3vY5XBbreexE=
-github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY=
+github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk=
+github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg=
 github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
 github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
@@ -1091,6 +1091,7 @@ github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs
 github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
 github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
 github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
 github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
 github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
@@ -1118,7 +1119,6 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
-github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -1154,22 +1154,22 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
 go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
 go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.50.0 h1:zvpPXY7RfYAGSdYQLjp6zxdJNSYD/+FFoCTQN9IPxBs=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.50.0/go.mod h1:BMn8NB1vsxTljvuorms2hyOs8IBuuBEq0pl7ltOfy30=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0=
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 h1:doUP+ExOpH3spVTLS0FcWGLnQrPct/hD/bCPbDRUEAU=
 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA=
-go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k=
-go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.25.0 h1:dT33yIHtmsqpixFsSQPwNeY5drM9wTcoL8h0FWF4oGM=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.25.0/go.mod h1:h95q0LBGh7hlAC08X2DhSeyIG02YQ0UyioTCVAqRPmc=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.25.0 h1:vOL89uRfOCCNIjkisd0r7SEdJF3ZJFyCNY34fdZs8eU=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.25.0/go.mod h1:8GlBGcDk8KKi7n+2S4BT/CPZQYH3erLu0/k64r1MYgo=
-go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA=
-go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s=
-go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo=
-go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw=
-go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM=
-go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I=
+go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
+go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM=
+go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
+go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
+go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
+go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
+go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
+go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
 go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
@@ -1199,10 +1199,8 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y
 golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
 golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
 golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
+golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
 golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
-golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
-golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
 golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1266,9 +1264,7 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
 golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1338,13 +1334,10 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
 golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
 golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
-golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
 golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
 golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
-golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
 golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
-golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
-golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1396,7 +1389,6 @@ golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
 golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
@@ -1493,13 +1485,9 @@ golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
 golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
-golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1515,10 +1503,8 @@ golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
 golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
 golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
 golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
-golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
+golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
 golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
-golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
-golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1586,6 +1572,7 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
 golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
 golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
 golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@@ -1620,9 +1607,7 @@ golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
 golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
 golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
 golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
-golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
 golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
-golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
 golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
 golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1861,8 +1846,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.
 google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -1904,8 +1889,8 @@ google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5v
 google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
 google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
 google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
-google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
-google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
+google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
+google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@@ -1929,6 +1914,7 @@ google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGm
 google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
@@ -1957,46 +1943,51 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
-k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA=
-k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE=
-k8s.io/apiextensions-apiserver v0.30.0 h1:jcZFKMqnICJfRxTgnC4E+Hpcq8UEhT8B2lhBcQ+6uAs=
-k8s.io/apiextensions-apiserver v0.30.0/go.mod h1:N9ogQFGcrbWqAY9p2mUAL5mGxsLqwgtUce127VtRX5Y=
-k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA=
-k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
-k8s.io/apiserver v0.30.0 h1:QCec+U72tMQ+9tR6A0sMBB5Vh6ImCEkoKkTDRABWq6M=
-k8s.io/apiserver v0.30.0/go.mod h1:smOIBq8t0MbKZi7O7SyIpjPsiKJ8qa+llcFCluKyqiY=
-k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ=
-k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY=
-k8s.io/cloud-provider v0.30.0 h1:hz1MXkFjsyO167sRZVchXEi2YYMQ6kolBi79nuICjzw=
-k8s.io/cloud-provider v0.30.0/go.mod h1:iyVcGvDfmZ7m5cliI9TTHj0VTjYDNpc/K71Gp6hukjU=
-k8s.io/code-generator v0.30.0/go.mod h1:mBMZhfRR4IunJUh2+7LVmdcWwpouCH5+LNPkZ3t/v7Q=
-k8s.io/component-base v0.30.0 h1:cj6bp38g0ainlfYtaOQuRELh5KSYjhKxM+io7AUIk4o=
-k8s.io/component-base v0.30.0/go.mod h1:V9x/0ePFNaKeKYA3bOvIbrNoluTSG+fSJKjLdjOoeXQ=
-k8s.io/component-helpers v0.30.0 h1:xbJtNCfSM4SB/Tz5JqCKDZv4eT5LVi/AWQ1VOxhmStU=
-k8s.io/component-helpers v0.30.0/go.mod h1:68HlSwXIumMKmCx8cZe1PoafQEYh581/sEpxMrkhmX4=
-k8s.io/controller-manager v0.30.0 h1:jqqT8cK0Awdy0IfT0yuqYIRmwskbdzH5AEZqkuhEVMs=
-k8s.io/controller-manager v0.30.0/go.mod h1:suM1r/pxUuk2ij5Bbm7W9kBLrFujXuzIboNuWK5AfRA=
-k8s.io/csi-translation-lib v0.30.0 h1:pEe6jshNVE4od2AdgYlsAtiKP/MH+NcsBbUPA/dWA6U=
-k8s.io/csi-translation-lib v0.30.0/go.mod h1:5TT/awOiKEX+8CcbReVYJyddT7xqlFrp3ChE9e45MyU=
-k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8=
+k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A=
+k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0=
+k8s.io/apiextensions-apiserver v0.29.2 h1:UK3xB5lOWSnhaCk0RFZ0LUacPZz9RY4wi/yt2Iu+btg=
+k8s.io/apiextensions-apiserver v0.29.2/go.mod h1:aLfYjpA5p3OwtqNXQFkhJ56TB+spV8Gc4wfMhUA3/b8=
+k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8=
+k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU=
+k8s.io/apiserver v0.29.2 h1:+Z9S0dSNr+CjnVXQePG8TcBWHr3Q7BmAr7NraHvsMiQ=
+k8s.io/apiserver v0.29.2/go.mod h1:B0LieKVoyU7ykQvPFm7XSdIHaCHSzCzQWPFa5bqbeMQ=
+k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg=
+k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA=
+k8s.io/cloud-provider v0.29.2 h1:ghKNXoQmeP8Fj/YTJNR6xQOzNrKXt6YZyy6mOEEa3yg=
+k8s.io/cloud-provider v0.29.2/go.mod h1:KAp+07AUGmxcLnoLY5FndU4hj6158KMbiviNgctNRUk=
+k8s.io/code-generator v0.29.2/go.mod h1:FwFi3C9jCrmbPjekhaCYcYG1n07CYiW1+PAPCockaos=
+k8s.io/component-base v0.29.2 h1:lpiLyuvPA9yV1aQwGLENYyK7n/8t6l3nn3zAtFTJYe8=
+k8s.io/component-base v0.29.2/go.mod h1:BfB3SLrefbZXiBfbM+2H1dlat21Uewg/5qtKOl8degM=
+k8s.io/component-helpers v0.29.2 h1:1kTIanIdqUVG2nW3e2ENVEaYbZKphqPgEdCmJvk71aw=
+k8s.io/component-helpers v0.29.2/go.mod h1:gFc/p60rYtpD8UCcNfPCmbokHT2uy0yDpmr/KKUMNAw=
+k8s.io/controller-manager v0.29.2 h1:S99UKzjvyFWG4WZWaWQ+iu64X9axwzbi4152tFd73+4=
+k8s.io/controller-manager v0.29.2/go.mod h1:xghbiyv5l/SVA5yVvRuGDmNVJEGl7MQqPAD0hvjZLhM=
+k8s.io/csi-translation-lib v0.29.2 h1:TJVZTzR7gj6+HSb+jJxLUxnAuwrEy71IxhJ4nmTzyjE=
+k8s.io/csi-translation-lib v0.29.2/go.mod h1:vbSYY4c6mVPwTHAvb5V3CHlq/dmQFIZC1SJOsaFiY3I=
+k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
+k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
 k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
+k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
 k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
+k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
 k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
 k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
-k8s.io/kms v0.30.0 h1:ZlnD/ei5lpvUlPw6eLfVvH7d8i9qZ6HwUQgydNVks8g=
-k8s.io/kms v0.30.0/go.mod h1:GrMurD0qk3G4yNgGcsCEmepqf9KyyIrTXYR2lyUOJC4=
-k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
-k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
-k8s.io/kubectl v0.30.0 h1:xbPvzagbJ6RNYVMVuiHArC1grrV5vSmmIcSZuCdzRyk=
-k8s.io/kubectl v0.30.0/go.mod h1:zgolRw2MQXLPwmic2l/+iHs239L49fhSeICuMhQQXTI=
-k8s.io/kubelet v0.30.0 h1:/pqHVR2Rn8ExCpn211wL3pMtqRFpcBcJPl4+1INbIMk=
-k8s.io/kubelet v0.30.0/go.mod h1:WukdKqbQxnj+csn3K8XOKeX7Sh60J/da25IILjvvB5s=
-k8s.io/kubernetes v1.30.0 h1:u3Yw8rNlo2NDSGaDpoxoHXLPQnEu1tfqHATKOJe94HY=
-k8s.io/kubernetes v1.30.0/go.mod h1:yPbIk3MhmhGigX62FLJm+CphNtjxqCvAIFQXup6RKS0=
-k8s.io/mount-utils v0.30.0 h1:EceYTNYVabfpdtIAHC4KgMzoZkm1B8ovZ1J666mYZQI=
-k8s.io/mount-utils v0.30.0/go.mod h1:9sCVmwGLcV1MPvbZ+rToMDnl1QcGozy+jBPd0MsQLIo=
-k8s.io/pod-security-admission v0.30.0 h1:C8J/zbrA3hVR7jatN+mN/ymUWxwU6KceS5HsEEt6rTY=
-k8s.io/pod-security-admission v0.30.0/go.mod h1:eyzZB+gtMwnNduqr9tVO2vjf2DdepZsUA11SzyfXhfM=
+k8s.io/kms v0.29.2 h1:MDsbp98gSlEQs7K7dqLKNNTwKFQRYYvO4UOlBOjNy6Y=
+k8s.io/kms v0.29.2/go.mod h1:s/9RC4sYRZ/6Tn6yhNjbfJuZdb8LzlXhdlBnKizeFDo=
+k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
+k8s.io/kube-openapi v0.0.0-20240209001042-7a0d5b415232 h1:MMq4iF9pHuAz/9dLnHwBQKEoeigXClzs3MFh/seyqtA=
+k8s.io/kube-openapi v0.0.0-20240209001042-7a0d5b415232/go.mod h1:Pa1PvrP7ACSkuX6I7KYomY6cmMA0Tx86waBhDUgoKPw=
+k8s.io/kubectl v0.29.2 h1:uaDYaBhumvkwz0S2XHt36fK0v5IdNgL7HyUniwb2IUo=
+k8s.io/kubectl v0.29.2/go.mod h1:BhizuYBGcKaHWyq+G7txGw2fXg576QbPrrnQdQDZgqI=
+k8s.io/kubelet v0.29.2 h1:bQ2StqkUqPCFNLtGLsb3v3O2LKQHXNMju537zOGboRg=
+k8s.io/kubelet v0.29.2/go.mod h1:i5orNPqW/fAMrqptbCXFW/vLBBP12TZZc41IrrvF7SY=
+k8s.io/kubernetes v1.29.2 h1:8hh1cntqdulanjQt7wSSSsJfBgOyx6fUdFWslvGL5m0=
+k8s.io/kubernetes v1.29.2/go.mod h1:xZPKU0yO0CBbLTnbd+XGyRmmtmaVuJykDb8gNCkeeUE=
+k8s.io/mount-utils v0.29.2 h1:FrUfgvOo63nqJRPXKoqN/DW1lMnR/y0pzpFErKh6p2o=
+k8s.io/mount-utils v0.29.2/go.mod h1:9IWJTMe8tG0MYMLEp60xK9GYVeCdA3g4LowmnVi+t9Y=
+k8s.io/pod-security-admission v0.29.2 h1:0/hhZzk1rPmUG2D02OHPWoZgo/3D5Wi/TXfwByD3xLs=
+k8s.io/pod-security-admission v0.29.2/go.mod h1:HBi3TJjRgPJmzdkbqtTxZshMf74ppA7Hth4dxGmUZj0=
+k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
 k8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0gQBEuevE/AaBsHY=
 k8s.io/utils v0.0.0-20240310230437-4693a0247e57/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
diff --git a/hack/tools/install.sh b/hack/tools/install.sh
index 47c88cde..7cf5e5a2 100755
--- a/hack/tools/install.sh
+++ b/hack/tools/install.sh
@@ -17,17 +17,17 @@
 set -euo pipefail
 
 # https://pypi.org/project/awscli/
-AWSCLI_VERSION="1.32.88"
+AWSCLI_VERSION="1.32.66"
 # https://github.com/helm/chart-testing
 CT_VERSION="v3.10.1"
 # https://github.com/eksctl-io/eksctl
-EKSCTL_VERSION="v0.175.0"
+EKSCTL_VERSION="v0.174.0"
 # https://github.com/onsi/ginkgo
-GINKGO_VERSION="v2.17.1"
+GINKGO_VERSION="v2.17.0"
 # https://github.com/golangci/golangci-lint
-GOLANGCI_LINT_VERSION="v1.57.2"
+GOLANGCI_LINT_VERSION="v1.56.2"
 # https://github.com/helm/helm
-HELM_VERSION="v3.14.4"
+HELM_VERSION="v3.14.3"
 # https://github.com/kubernetes/kops
 KOPS_VERSION="v1.29.0-beta.1"
 # https://github.com/golang/mock
@@ -35,7 +35,7 @@ MOCKGEN_VERSION="v1.6.0"
 # https://github.com/mvdan/sh
 SHFMT_VERSION="v3.8.0"
 # https://pypi.org/project/yamale/
-YAMALE_VERSION="5.1.0"
+YAMALE_VERSION="4.0.4"
 # https://pypi.org/project/yamllint/
 YAMLLINT_VERSION="1.35.1"
 
diff --git a/hack/update-mockgen.sh b/hack/update-mockgen.sh
index 10cd3ed6..ec78cfd3 100755
--- a/hack/update-mockgen.sh
+++ b/hack/update-mockgen.sh
@@ -22,7 +22,6 @@ BIN="$(dirname "$(realpath "${BASH_SOURCE[0]}")")/../bin"
 "${BIN}/mockgen" -package cloud -destination=./pkg/cloud/mock_cloud.go -source pkg/cloud/interface.go
 "${BIN}/mockgen" -package metadata -destination=./pkg/cloud/metadata/mock_metadata.go -source pkg/cloud/metadata/interface.go
 "${BIN}/mockgen" -package mounter -destination=./pkg/mounter/mock_mount.go -source pkg/mounter/mount.go
-"${BIN}/mockgen" -package mounter -destination=./pkg/mounter/mock_mount_windows.go -source pkg/mounter/safe_mounter_windows.go
 "${BIN}/mockgen" -package cloud -destination=./pkg/cloud/mock_ec2.go -source pkg/cloud/ec2_interface.go EC2API
 
 # Reflection-based mocking for external dependencies
diff --git a/pkg/cloud/cloud.go b/pkg/cloud/cloud.go
index fa8aea89..ac6984bc 100644
--- a/pkg/cloud/cloud.go
+++ b/pkg/cloud/cloud.go
@@ -87,22 +87,17 @@ var (
 		VolumeTypeStandard,
 	}
 
-	volumeCreationPollInitialDelay    = 1250 * time.Millisecond
-	volumeCreationPollBackoffDuration = 500 * time.Millisecond
-	volumeCreationPollBackoffFactor   = 1.5
-	volumeCreationPollBackoffSteps    = 25
-	volumeCreationPollBackoffCap      = 3 * time.Second
-
 	volumeModificationDuration   = 1 * time.Second
 	volumeModificationWaitFactor = 1.7
 	volumeModificationWaitSteps  = 10
 
-	volumeAttachmentStatePollSteps  = 13
-	volumeAttachmentStatePollDelay  = 1 * time.Second
-	volumeAttachmentStatePollFactor = 1.8
+	volumeAttachmentStatePollSteps = 13
 )
 
 const (
+	volumeAttachmentStatePollDelay  = 1 * time.Second
+	volumeAttachmentStatePollFactor = 1.8
+
 	volumeDetachedState = "detached"
 	volumeAttachedState = "attached"
 )
@@ -286,7 +281,6 @@ type cloud struct {
 	ec2    EC2API
 	dm     dm.DeviceManager
 	bm     *batcherManager
-	rm     *retryManager
 }
 
 var _ Cloud = &cloud{}
@@ -332,9 +326,8 @@ func newEC2Cloud(region string, awsSdkDebugLog bool, userAgentExtra string, batc
 	svc := ec2.NewFromConfig(cfg, func(o *ec2.Options) {
 		o.APIOptions = append(o.APIOptions,
 			RecordRequestsMiddleware(),
+			RecordThrottledRequestsMiddleware(),
 		)
-
-		o.RetryMaxAttempts = retryMaxAttempt //  Retry EC2 API calls at sdk level until request contexts are cancelled
 	})
 
 	var bm *batcherManager
@@ -343,14 +336,11 @@ func newEC2Cloud(region string, awsSdkDebugLog bool, userAgentExtra string, batc
 		bm = newBatcherManager(svc)
 	}
 
-	rm := newRetryManager()
-
 	return &cloud{
 		region: region,
 		dm:     dm.NewDeviceManager(),
 		ec2:    svc,
 		bm:     bm,
-		rm:     rm,
 	}
 }
 
@@ -601,9 +591,7 @@ func (c *cloud) CreateDisk(ctx context.Context, volumeName string, diskOptions *
 		requestInput.SnapshotId = aws.String(snapshotID)
 	}
 
-	response, err := c.ec2.CreateVolume(ctx, requestInput, func(o *ec2.Options) {
-		o.Retryer = c.rm.createVolumeRetryer
-	})
+	response, err := c.ec2.CreateVolume(ctx, requestInput)
 	if err != nil {
 		if isAWSErrorSnapshotNotFound(err) {
 			return nil, ErrNotFound
@@ -735,9 +723,7 @@ func (c *cloud) ResizeOrModifyDisk(ctx context.Context, volumeID string, newSize
 	if options.Throughput != 0 {
 		req.Throughput = aws.Int32(options.Throughput)
 	}
-	response, err := c.ec2.ModifyVolume(ctx, req, func(o *ec2.Options) {
-		o.Retryer = c.rm.modifyVolumeRetryer
-	})
+	response, err := c.ec2.ModifyVolume(ctx, req)
 	if err != nil {
 		if isAWSErrorInvalidParameter(err) {
 			// Wrap error to preserve original message from AWS as to why this was an invalid argument
@@ -759,9 +745,7 @@ func (c *cloud) ResizeOrModifyDisk(ctx context.Context, volumeID string, newSize
 
 func (c *cloud) DeleteDisk(ctx context.Context, volumeID string) (bool, error) {
 	request := &ec2.DeleteVolumeInput{VolumeId: &volumeID}
-	if _, err := c.ec2.DeleteVolume(ctx, request, func(o *ec2.Options) {
-		o.Retryer = c.rm.deleteVolumeRetryer
-	}); err != nil {
+	if _, err := c.ec2.DeleteVolume(ctx, request); err != nil {
 		if isAWSErrorVolumeNotFound(err) {
 			return false, ErrNotFound
 		}
@@ -866,9 +850,7 @@ func (c *cloud) AttachDisk(ctx context.Context, volumeID, nodeID string) (string
 			VolumeId:   aws.String(volumeID),
 		}
 
-		resp, attachErr := c.ec2.AttachVolume(ctx, request, func(o *ec2.Options) {
-			o.Retryer = c.rm.attachVolumeRetryer
-		})
+		resp, attachErr := c.ec2.AttachVolume(ctx, request)
 		if attachErr != nil {
 			if isAWSErrorBlockDeviceInUse(attachErr) {
 				cacheMutex.Lock()
@@ -941,9 +923,7 @@ func (c *cloud) DetachDisk(ctx context.Context, volumeID, nodeID string) error {
 		VolumeId:   aws.String(volumeID),
 	}
 
-	_, err = c.ec2.DetachVolume(ctx, request, func(o *ec2.Options) {
-		o.Retryer = c.rm.detachVolumeRetryer
-	})
+	_, err = c.ec2.DetachVolume(ctx, request)
 	if err != nil {
 		if isAWSErrorIncorrectState(err) ||
 			isAWSErrorInvalidAttachmentNotFound(err) ||
@@ -1245,9 +1225,7 @@ func (c *cloud) CreateSnapshot(ctx context.Context, volumeID string, snapshotOpt
 		Description:       aws.String(descriptions),
 	}
 
-	res, err := c.ec2.CreateSnapshot(ctx, request, func(o *ec2.Options) {
-		o.Retryer = c.rm.createSnapshotRetryer
-	})
+	res, err := c.ec2.CreateSnapshot(ctx, request)
 	if err != nil {
 		return nil, fmt.Errorf("error creating snapshot of volume %s: %w", volumeID, err)
 	}
@@ -1268,9 +1246,7 @@ func (c *cloud) DeleteSnapshot(ctx context.Context, snapshotID string) (success
 	request := &ec2.DeleteSnapshotInput{}
 	request.SnapshotId = aws.String(snapshotID)
 	request.DryRun = aws.Bool(false)
-	if _, err := c.ec2.DeleteSnapshot(ctx, request, func(o *ec2.Options) {
-		o.Retryer = c.rm.deleteSnapshotRetryer
-	}); err != nil {
+	if _, err := c.ec2.DeleteSnapshot(ctx, request); err != nil {
 		if isAWSErrorSnapshotNotFound(err) {
 			return false, ErrNotFound
 		}
@@ -1377,9 +1353,7 @@ func (c *cloud) EnableFastSnapshotRestores(ctx context.Context, availabilityZone
 		SourceSnapshotIds: []string{snapshotID},
 	}
 	klog.V(4).InfoS("Creating Fast Snapshot Restores", "snapshotID", snapshotID, "availabilityZones", availabilityZones)
-	response, err := c.ec2.EnableFastSnapshotRestores(ctx, request, func(o *ec2.Options) {
-		o.Retryer = c.rm.enableFastSnapshotRestoresRetryer
-	})
+	response, err := c.ec2.EnableFastSnapshotRestores(ctx, request)
 	if err != nil {
 		return nil, err
 	}
@@ -1532,27 +1506,20 @@ func (c *cloud) listSnapshots(ctx context.Context, request *ec2.DescribeSnapshot
 }
 
 // waitForVolume waits for volume to be in the "available" state.
+// On a random AWS account (shared among several developers) it took 4s on average.
 func (c *cloud) waitForVolume(ctx context.Context, volumeID string) error {
-	// Based on our testing in us-west-2 and ap-south-1, the median/p99 time until volume creation is ~1.5/~4 seconds.
-	// We have found that the following parameters are optimal for minimizing provisioning time and DescribeVolumes calls
-	// we queue DescribeVolume calls after [1.25, 0.5, 0.75, 1.125, 1.7, 2.5, 3] seconds.
-	// In total, we wait for ~60 seconds.
 	var (
-		backoff = wait.Backoff{
-			Duration: volumeCreationPollBackoffDuration,
-			Factor:   volumeCreationPollBackoffFactor,
-			Steps:    volumeCreationPollBackoffSteps,
-			Cap:      volumeCreationPollBackoffCap,
-		}
+		checkInterval = 3 * time.Second
+		// This timeout can be "ovewritten" if the value returned by ctx.Deadline()
+		// comes sooner. That value comes from the external provisioner controller.
+		checkTimeout = 1 * time.Minute
 	)
 
-	time.Sleep(volumeCreationPollInitialDelay)
-
 	request := &ec2.DescribeVolumesInput{
 		VolumeIds: []string{volumeID},
 	}
 
-	err := wait.ExponentialBackoffWithContext(ctx, backoff, func(ctx context.Context) (done bool, err error) {
+	err := wait.PollUntilContextTimeout(ctx, checkInterval, checkTimeout, false, func(ctx context.Context) (done bool, err error) {
 		vol, err := c.getVolume(ctx, request)
 		if err != nil {
 			return true, err
@@ -1742,9 +1709,7 @@ func (c *cloud) getLatestVolumeModification(ctx context.Context, volumeID string
 	}
 
 	if c.bm == nil || !isBatchable {
-		mod, err := c.ec2.DescribeVolumesModifications(ctx, request, func(o *ec2.Options) {
-			o.Retryer = c.rm.unbatchableDescribeVolumesModificationsRetryer
-		})
+		mod, err := c.ec2.DescribeVolumesModifications(ctx, request)
 		if err != nil {
 			if isAWSErrorModificationNotFound(err) {
 				return nil, VolumeNotBeingModified
diff --git a/pkg/cloud/handlers.go b/pkg/cloud/handlers.go
index dd45ddfc..dc5b0648 100644
--- a/pkg/cloud/handlers.go
+++ b/pkg/cloud/handlers.go
@@ -38,25 +38,34 @@ func RecordRequestsMiddleware() func(*middleware.Stack) error {
 			output, metadata, err = next.HandleFinalize(ctx, input)
 			labels := createLabels(ctx)
 			if err != nil {
-				var apiErr smithy.APIError
-				if errors.As(err, &apiErr) {
-					if apiErr.ErrorCode() == requestLimitExceededErrorCode {
-						operationName := awsmiddleware.GetOperationName(ctx)
-						labels = map[string]string{
-							"operation_name": operationName,
-						}
-						metrics.Recorder().IncreaseCount("cloudprovider_aws_api_throttled_requests_total", labels)
-						klog.InfoS("Got RequestLimitExceeded error on AWS request", "request", operationName)
-					} else {
-						metrics.Recorder().IncreaseCount("cloudprovider_aws_api_request_errors", labels)
-					}
-				}
+				metrics.Recorder().IncreaseCount("cloudprovider_aws_api_request_errors", labels)
 			} else {
 				duration := time.Since(start).Seconds()
 				metrics.Recorder().ObserveHistogram("cloudprovider_aws_api_request_duration_seconds", duration, labels, nil)
 			}
 			return output, metadata, err
-		}), middleware.After)
+		}), middleware.Before)
+	}
+}
+
+// RecordThrottledRequestsHandler is added to the AfterRetry chain; called after any error
+func RecordThrottledRequestsMiddleware() func(*middleware.Stack) error {
+	return func(stack *middleware.Stack) error {
+		return stack.Finalize.Add(middleware.FinalizeMiddlewareFunc("RecordThrottledRequestsMiddleware", func(ctx context.Context, input middleware.FinalizeInput, next middleware.FinalizeHandler) (output middleware.FinalizeOutput, metadata middleware.Metadata, err error) {
+			output, metadata, err = next.HandleFinalize(ctx, input)
+			if err != nil {
+				var apiErr smithy.APIError
+				if errors.As(err, &apiErr) && apiErr.ErrorCode() == requestLimitExceededErrorCode {
+					operationName := awsmiddleware.GetOperationName(ctx)
+					labels := map[string]string{
+						"operation_name": operationName,
+					}
+					metrics.Recorder().IncreaseCount("cloudprovider_aws_api_throttled_requests_total", labels)
+					klog.InfoS("Got RequestLimitExceeded error on AWS request", "request", operationName)
+				}
+			}
+			return output, metadata, err
+		}), middleware.Before)
 	}
 }
 
diff --git a/pkg/cloud/metadata/k8s.go b/pkg/cloud/metadata/k8s.go
index c288f634..4ff8dd63 100644
--- a/pkg/cloud/metadata/k8s.go
+++ b/pkg/cloud/metadata/k8s.go
@@ -2,14 +2,19 @@ package metadata
 
 import (
 	"context"
+	"errors"
 	"fmt"
+	"net"
 	"os"
+	"path/filepath"
 	"regexp"
 
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/client-go/rest"
+	"k8s.io/client-go/util/cert"
+	"k8s.io/klog/v2"
 )
 
 type KubernetesAPIClient func() (kubernetes.Interface, error)
@@ -18,7 +23,39 @@ var DefaultKubernetesAPIClient = func() (kubernetes.Interface, error) {
 	// creates the in-cluster config
 	config, err := rest.InClusterConfig()
 	if err != nil {
-		return nil, err
+		if errors.Is(err, os.ErrNotExist) {
+			klog.InfoS("InClusterConfig failed to read token file, retrieving file from sandbox mount point")
+			// CONTAINER_SANDBOX_MOUNT_POINT env is set upon container creation in containerd v1.6+
+			// it provides the absolute host path to the container volume.
+			sandboxMountPoint := os.Getenv("CONTAINER_SANDBOX_MOUNT_POINT")
+			if sandboxMountPoint == "" {
+				return nil, fmt.Errorf("CONTAINER_SANDBOX_MOUNT_POINT environment variable is not set")
+			}
+
+			tokenFile := filepath.Join(sandboxMountPoint, "var", "run", "secrets", "kubernetes.io", "serviceaccount", "token")
+			rootCAFile := filepath.Join(sandboxMountPoint, "var", "run", "secrets", "kubernetes.io", "serviceaccount", "ca.crt")
+
+			token, tokenErr := os.ReadFile(tokenFile)
+			if err != nil {
+				return nil, tokenErr
+			}
+
+			tlsClientConfig := rest.TLSClientConfig{}
+			if _, certErr := cert.NewPool(rootCAFile); err != nil {
+				return nil, fmt.Errorf("expected to load root CA config from %s, but got err: %w", rootCAFile, certErr)
+			} else {
+				tlsClientConfig.CAFile = rootCAFile
+			}
+
+			config = &rest.Config{
+				Host:            "https://" + net.JoinHostPort(os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT")),
+				TLSClientConfig: tlsClientConfig,
+				BearerToken:     string(token),
+				BearerTokenFile: tokenFile,
+			}
+		} else {
+			return nil, err
+		}
 	}
 	// creates the clientset
 	clientset, err := kubernetes.NewForConfig(config)
diff --git a/pkg/cloud/retry_manager.go b/pkg/cloud/retry_manager.go
deleted file mode 100644
index 5258d38d..00000000
--- a/pkg/cloud/retry_manager.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package cloud
-
-import (
-	"github.com/aws/aws-sdk-go-v2/aws"
-	"github.com/aws/aws-sdk-go-v2/aws/retry"
-)
-
-const (
-	// retryMaxAttempt sets max number of EC2 API call attempts.
-	// Set high enough to ensure default sidecar timeout will cancel context long before we stop retrying.
-	retryMaxAttempt = 50
-)
-
-// retryManager dictates the retry strategies of EC2 API calls.
-// Each mutating EC2 API has its own retryer because the AWS SDK throttles on a retryer object level, not by API name.
-// While default AWS accounts share request tokens between mutating APIs, users can raise limits for individual APIs.
-// Separate retryers ensures that throttling one API doesn't unintentionally throttle others with separate token buckets.
-type retryManager struct {
-	createVolumeRetryer                            aws.Retryer
-	deleteVolumeRetryer                            aws.Retryer
-	attachVolumeRetryer                            aws.Retryer
-	detachVolumeRetryer                            aws.Retryer
-	modifyVolumeRetryer                            aws.Retryer
-	createSnapshotRetryer                          aws.Retryer
-	deleteSnapshotRetryer                          aws.Retryer
-	enableFastSnapshotRestoresRetryer              aws.Retryer
-	unbatchableDescribeVolumesModificationsRetryer aws.Retryer
-}
-
-func newRetryManager() *retryManager {
-	return &retryManager{
-		createVolumeRetryer:                            newAdaptiveRetryer(),
-		attachVolumeRetryer:                            newAdaptiveRetryer(),
-		deleteVolumeRetryer:                            newAdaptiveRetryer(),
-		detachVolumeRetryer:                            newAdaptiveRetryer(),
-		modifyVolumeRetryer:                            newAdaptiveRetryer(),
-		createSnapshotRetryer:                          newAdaptiveRetryer(),
-		deleteSnapshotRetryer:                          newAdaptiveRetryer(),
-		enableFastSnapshotRestoresRetryer:              newAdaptiveRetryer(),
-		unbatchableDescribeVolumesModificationsRetryer: newAdaptiveRetryer(),
-	}
-}
-
-// newAdaptiveRetryer restricts attempts of API calls that recently hit throttle errors.
-func newAdaptiveRetryer() *retry.AdaptiveMode {
-	return retry.NewAdaptiveMode(func(ao *retry.AdaptiveModeOptions) {
-		ao.StandardOptions = append(ao.StandardOptions, func(so *retry.StandardOptions) {
-			so.MaxAttempts = retryMaxAttempt
-		})
-	})
-}
diff --git a/pkg/cloud/volume_limits.go b/pkg/cloud/volume_limits.go
index b64f69a9..ced91717 100644
--- a/pkg/cloud/volume_limits.go
+++ b/pkg/cloud/volume_limits.go
@@ -225,16 +225,6 @@ var nvmeInstanceStoreVolumes = map[string]int{
 	"g5.4xlarge":      1,
 	"g5.8xlarge":      1,
 	"g5.xlarge":       1,
-	"g6.12xlarge":     4,
-	"g6.16xlarge":     2,
-	"g6.24xlarge":     4,
-	"g6.2xlarge":      1,
-	"g6.48xlarge":     8,
-	"g6.4xlarge":      1,
-	"g6.8xlarge":      2,
-	"g6.xlarge":       1,
-	"gr6.4xlarge":     1,
-	"gr6.8xlarge":     2,
 	"h1.16xlarge":     8,
 	"h1.2xlarge":      1,
 	"h1.4xlarge":      2,
diff --git a/pkg/driver/driver.go b/pkg/driver/driver.go
index 63471429..2e73a2c9 100644
--- a/pkg/driver/driver.go
+++ b/pkg/driver/driver.go
@@ -91,7 +91,7 @@ func NewDriver(c cloud.Cloud, o *Options, m mounter.Mounter, md metadata.Metadat
 }
 
 func (d *Driver) Run() error {
-	scheme, addr, err := util.ParseEndpoint(d.options.Endpoint)
+	scheme, addr, err := util.ParseEndpoint(d.options.Endpoint, d.options.WindowsHostProcess)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/driver/mock_k8s_client.go b/pkg/driver/mock_k8s_client.go
index 25f93a86..1ce0290a 100644
--- a/pkg/driver/mock_k8s_client.go
+++ b/pkg/driver/mock_k8s_client.go
@@ -60,7 +60,6 @@ import (
 	v116 "k8s.io/client-go/kubernetes/typed/storage/v1"
 	v1alpha17 "k8s.io/client-go/kubernetes/typed/storage/v1alpha1"
 	v1beta115 "k8s.io/client-go/kubernetes/typed/storage/v1beta1"
-	v1alpha18 "k8s.io/client-go/kubernetes/typed/storagemigration/v1alpha1"
 )
 
 // MockKubernetesClient is a mock of Interface interface.
@@ -813,17 +812,3 @@ func (mr *MockKubernetesClientMockRecorder) StorageV1beta1() *gomock.Call {
 	mr.mock.ctrl.T.Helper()
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StorageV1beta1", reflect.TypeOf((*MockKubernetesClient)(nil).StorageV1beta1))
 }
-
-// StoragemigrationV1alpha1 mocks base method.
-func (m *MockKubernetesClient) StoragemigrationV1alpha1() v1alpha18.StoragemigrationV1alpha1Interface {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "StoragemigrationV1alpha1")
-	ret0, _ := ret[0].(v1alpha18.StoragemigrationV1alpha1Interface)
-	return ret0
-}
-
-// StoragemigrationV1alpha1 indicates an expected call of StoragemigrationV1alpha1.
-func (mr *MockKubernetesClientMockRecorder) StoragemigrationV1alpha1() *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoragemigrationV1alpha1", reflect.TypeOf((*MockKubernetesClient)(nil).StoragemigrationV1alpha1))
-}
diff --git a/pkg/driver/node.go b/pkg/driver/node.go
index 19d1d052..d9a3680f 100644
--- a/pkg/driver/node.go
+++ b/pkg/driver/node.go
@@ -96,13 +96,11 @@ func NewNodeService(o *Options, md metadata.MetadataService, m mounter.Mounter,
 	region := os.Getenv("AWS_REGION")
 	klog.InfoS("regionFromSession Node service", "region", region)
 
-	if k != nil {
-		// Remove taint from node to indicate driver startup success
-		// This is done at the last possible moment to prevent race conditions or false positive removals
-		time.AfterFunc(taintRemovalInitialDelay, func() {
-			removeTaintInBackground(k, taintRemovalBackoff, removeNotReadyTaint)
-		})
-	}
+	// Remove taint from node to indicate driver startup success
+	// This is done at the last possible moment to prevent race conditions or false positive removals
+	time.AfterFunc(taintRemovalInitialDelay, func() {
+		removeTaintInBackground(k, taintRemovalBackoff, removeNotReadyTaint)
+	})
 
 	return &NodeService{
 		metadata: md,
diff --git a/pkg/driver/options.go b/pkg/driver/options.go
index 2a4a8165..b0e38e12 100644
--- a/pkg/driver/options.go
+++ b/pkg/driver/options.go
@@ -34,10 +34,6 @@ type Options struct {
 	Endpoint string
 	// HttpEndpoint is the TCP network address where the HTTP server for metrics will listen
 	HttpEndpoint string
-	// MetricsCertFile is the location of the certificate for serving the metrics server over HTTPS
-	MetricsCertFile string
-	// MetricsKeyFile is the location of the key for serving the metrics server over HTTPS
-	MetricsKeyFile string
 	// EnableOtelTracing is a flag to enable opentelemetry tracing for the driver
 	EnableOtelTracing bool
 
@@ -81,14 +77,14 @@ type Options struct {
 	// When -1, the amount of reserved attachments is loaded from instance metadata that captured state at node boot
 	// and may include not only system disks but also CSI volumes (and therefore it may be wrong).
 	ReservedVolumeAttachments int
+	// ALPHA: WindowsHostProcess indicates whether the driver is running in a Windows privileged container
+	WindowsHostProcess bool
 }
 
 func (o *Options) AddFlags(f *flag.FlagSet) {
 	// Server options
 	f.StringVar(&o.Endpoint, "endpoint", DefaultCSIEndpoint, "Endpoint for the CSI driver server")
 	f.StringVar(&o.HttpEndpoint, "http-endpoint", "", "The TCP network address where the HTTP server for metrics will listen (example: `:8080`). The default is empty string, which means the server is disabled.")
-	f.StringVar(&o.MetricsCertFile, "metrics-cert-file", "", "The path to a certificate to use for serving the metrics server over HTTPS. If the certificate is signed by a certificate authority, this file should be the concatenation of the server's certificate, any intermediates, and the CA's certificate. If this is non-empty, --http-endpoint and --metrics-key-file MUST also be non-empty.")
-	f.StringVar(&o.MetricsKeyFile, "metrics-key-file", "", "The path to a key to use for serving the metrics server over HTTPS. If this is non-empty, --http-endpoint and --metrics-cert-file MUST also be non-empty.")
 	f.BoolVar(&o.EnableOtelTracing, "enable-otel-tracing", false, "To enable opentelemetry tracing for the driver. The tracing is disabled by default. Configure the exporter endpoint with OTEL_EXPORTER_OTLP_ENDPOINT and other env variables, see https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#general-sdk-configuration.")
 
 	// Controller options
@@ -106,25 +102,13 @@ func (o *Options) AddFlags(f *flag.FlagSet) {
 	if o.Mode == AllMode || o.Mode == NodeMode {
 		f.Int64Var(&o.VolumeAttachLimit, "volume-attach-limit", -1, "Value for the maximum number of volumes attachable per node. If specified, the limit applies to all nodes and overrides --reserved-volume-attachments. If not specified, the value is approximated from the instance type.")
 		f.IntVar(&o.ReservedVolumeAttachments, "reserved-volume-attachments", -1, "Number of volume attachments reserved for system use. Not used when --volume-attach-limit is specified. The total amount of volume attachments for a node is computed as: <nr. of attachments for corresponding instance type> - <number of NICs, if relevant to the instance type> - <reserved-volume-attachments value>. When -1, the amount of reserved attachments is loaded from instance metadata that captured state at node boot and may include not only system disks but also CSI volumes.")
+		f.BoolVar(&o.WindowsHostProcess, "windows-host-process", false, "ALPHA: Indicates whether the driver is running in a Windows privileged container")
 	}
 }
 
 func (o *Options) Validate() error {
-	if o.Mode == AllMode || o.Mode == NodeMode {
-		if o.VolumeAttachLimit != -1 && o.ReservedVolumeAttachments != -1 {
-			return fmt.Errorf("only one of --volume-attach-limit and --reserved-volume-attachments may be specified")
-		}
-	}
-
-	if o.MetricsCertFile != "" || o.MetricsKeyFile != "" {
-		if o.HttpEndpoint == "" {
-			return fmt.Errorf("--http-endpoint MUST be specififed when using the metrics server with HTTPS")
-		} else if o.MetricsCertFile == "" {
-			return fmt.Errorf("--metrics-cert-file MUST be specififed when using the metrics server with HTTPS")
-		} else if o.MetricsKeyFile == "" {
-			return fmt.Errorf("--metrics-key-file MUST be specififed when using the metrics server with HTTPS")
-		}
+	if o.VolumeAttachLimit != -1 && o.ReservedVolumeAttachments != -1 {
+		return fmt.Errorf("only one of --volume-attach-limit and --reserved-volume-attachments may be specified")
 	}
-
 	return nil
 }
diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go
index cfa5a1d3..4ad4aab7 100644
--- a/pkg/metrics/metrics.go
+++ b/pkg/metrics/metrics.go
@@ -72,7 +72,7 @@ func (m *metricRecorder) ObserveHistogram(name string, value float64, labels map
 }
 
 // InitializeMetricsHandler starts a new HTTP server to expose the metrics.
-func (m *metricRecorder) InitializeMetricsHandler(address, path, certFile, keyFile string) {
+func (m *metricRecorder) InitializeMetricsHandler(address, path string) {
 	if m == nil {
 		klog.InfoS("InitializeMetricsHandler: metric recorder is not initialized")
 		return
@@ -92,16 +92,9 @@ func (m *metricRecorder) InitializeMetricsHandler(address, path, certFile, keyFi
 	}
 
 	go func() {
-		var err error
 		klog.InfoS("Metric server listening", "address", address, "path", path)
 
-		if certFile != "" {
-			err = server.ListenAndServeTLS(certFile, keyFile)
-		} else {
-			err = server.ListenAndServe()
-		}
-
-		if err != nil && err != http.ErrServerClosed {
+		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
 			klog.ErrorS(err, "Failed to start metric server", "address", address, "path", path)
 			klog.FlushAndExit(klog.ExitFlushTimeout, 1)
 		}
diff --git a/pkg/mounter/mock_mount_windows.go b/pkg/mounter/mock_mount_windows.go
deleted file mode 100644
index 0c5ffe98..00000000
--- a/pkg/mounter/mock_mount_windows.go
+++ /dev/null
@@ -1,351 +0,0 @@
-// Code generated by MockGen. DO NOT EDIT.
-// Source: pkg/mounter/safe_mounter_windows.go
-
-// Package mounter is a generated GoMock package.
-package mounter
-
-import (
-	reflect "reflect"
-
-	gomock "github.com/golang/mock/gomock"
-	mount "k8s.io/mount-utils"
-)
-
-// MockProxyMounter is a mock of ProxyMounter interface.
-type MockProxyMounter struct {
-	ctrl     *gomock.Controller
-	recorder *MockProxyMounterMockRecorder
-}
-
-// MockProxyMounterMockRecorder is the mock recorder for MockProxyMounter.
-type MockProxyMounterMockRecorder struct {
-	mock *MockProxyMounter
-}
-
-// NewMockProxyMounter creates a new mock instance.
-func NewMockProxyMounter(ctrl *gomock.Controller) *MockProxyMounter {
-	mock := &MockProxyMounter{ctrl: ctrl}
-	mock.recorder = &MockProxyMounterMockRecorder{mock}
-	return mock
-}
-
-// EXPECT returns an object that allows the caller to indicate expected use.
-func (m *MockProxyMounter) EXPECT() *MockProxyMounterMockRecorder {
-	return m.recorder
-}
-
-// CanSafelySkipMountPointCheck mocks base method.
-func (m *MockProxyMounter) CanSafelySkipMountPointCheck() bool {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "CanSafelySkipMountPointCheck")
-	ret0, _ := ret[0].(bool)
-	return ret0
-}
-
-// CanSafelySkipMountPointCheck indicates an expected call of CanSafelySkipMountPointCheck.
-func (mr *MockProxyMounterMockRecorder) CanSafelySkipMountPointCheck() *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CanSafelySkipMountPointCheck", reflect.TypeOf((*MockProxyMounter)(nil).CanSafelySkipMountPointCheck))
-}
-
-// ExistsPath mocks base method.
-func (m *MockProxyMounter) ExistsPath(path string) (bool, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "ExistsPath", path)
-	ret0, _ := ret[0].(bool)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// ExistsPath indicates an expected call of ExistsPath.
-func (mr *MockProxyMounterMockRecorder) ExistsPath(path interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExistsPath", reflect.TypeOf((*MockProxyMounter)(nil).ExistsPath), path)
-}
-
-// FindDiskByLun mocks base method.
-func (m *MockProxyMounter) FindDiskByLun(lun string) (string, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "FindDiskByLun", lun)
-	ret0, _ := ret[0].(string)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// FindDiskByLun indicates an expected call of FindDiskByLun.
-func (mr *MockProxyMounterMockRecorder) FindDiskByLun(lun interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindDiskByLun", reflect.TypeOf((*MockProxyMounter)(nil).FindDiskByLun), lun)
-}
-
-// FormatAndMountSensitiveWithFormatOptions mocks base method.
-func (m *MockProxyMounter) FormatAndMountSensitiveWithFormatOptions(source, target, fstype string, options, sensitiveOptions, formatOptions []string) error {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "FormatAndMountSensitiveWithFormatOptions", source, target, fstype, options, sensitiveOptions, formatOptions)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// FormatAndMountSensitiveWithFormatOptions indicates an expected call of FormatAndMountSensitiveWithFormatOptions.
-func (mr *MockProxyMounterMockRecorder) FormatAndMountSensitiveWithFormatOptions(source, target, fstype, options, sensitiveOptions, formatOptions interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FormatAndMountSensitiveWithFormatOptions", reflect.TypeOf((*MockProxyMounter)(nil).FormatAndMountSensitiveWithFormatOptions), source, target, fstype, options, sensitiveOptions, formatOptions)
-}
-
-// GetDeviceNameFromMount mocks base method.
-func (m *MockProxyMounter) GetDeviceNameFromMount(mountPath, pluginMountDir string) (string, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "GetDeviceNameFromMount", mountPath, pluginMountDir)
-	ret0, _ := ret[0].(string)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// GetDeviceNameFromMount indicates an expected call of GetDeviceNameFromMount.
-func (mr *MockProxyMounterMockRecorder) GetDeviceNameFromMount(mountPath, pluginMountDir interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeviceNameFromMount", reflect.TypeOf((*MockProxyMounter)(nil).GetDeviceNameFromMount), mountPath, pluginMountDir)
-}
-
-// GetDeviceSize mocks base method.
-func (m *MockProxyMounter) GetDeviceSize(devicePath string) (int64, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "GetDeviceSize", devicePath)
-	ret0, _ := ret[0].(int64)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// GetDeviceSize indicates an expected call of GetDeviceSize.
-func (mr *MockProxyMounterMockRecorder) GetDeviceSize(devicePath interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeviceSize", reflect.TypeOf((*MockProxyMounter)(nil).GetDeviceSize), devicePath)
-}
-
-// GetMountRefs mocks base method.
-func (m *MockProxyMounter) GetMountRefs(pathname string) ([]string, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "GetMountRefs", pathname)
-	ret0, _ := ret[0].([]string)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// GetMountRefs indicates an expected call of GetMountRefs.
-func (mr *MockProxyMounterMockRecorder) GetMountRefs(pathname interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMountRefs", reflect.TypeOf((*MockProxyMounter)(nil).GetMountRefs), pathname)
-}
-
-// GetVolumeSizeInBytes mocks base method.
-func (m *MockProxyMounter) GetVolumeSizeInBytes(deviceMountPath string) (int64, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "GetVolumeSizeInBytes", deviceMountPath)
-	ret0, _ := ret[0].(int64)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// GetVolumeSizeInBytes indicates an expected call of GetVolumeSizeInBytes.
-func (mr *MockProxyMounterMockRecorder) GetVolumeSizeInBytes(deviceMountPath interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVolumeSizeInBytes", reflect.TypeOf((*MockProxyMounter)(nil).GetVolumeSizeInBytes), deviceMountPath)
-}
-
-// IsLikelyNotMountPoint mocks base method.
-func (m *MockProxyMounter) IsLikelyNotMountPoint(file string) (bool, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "IsLikelyNotMountPoint", file)
-	ret0, _ := ret[0].(bool)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// IsLikelyNotMountPoint indicates an expected call of IsLikelyNotMountPoint.
-func (mr *MockProxyMounterMockRecorder) IsLikelyNotMountPoint(file interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsLikelyNotMountPoint", reflect.TypeOf((*MockProxyMounter)(nil).IsLikelyNotMountPoint), file)
-}
-
-// IsMountPoint mocks base method.
-func (m *MockProxyMounter) IsMountPoint(file string) (bool, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "IsMountPoint", file)
-	ret0, _ := ret[0].(bool)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// IsMountPoint indicates an expected call of IsMountPoint.
-func (mr *MockProxyMounterMockRecorder) IsMountPoint(file interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsMountPoint", reflect.TypeOf((*MockProxyMounter)(nil).IsMountPoint), file)
-}
-
-// IsMountPointMatch mocks base method.
-func (m *MockProxyMounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "IsMountPointMatch", mp, dir)
-	ret0, _ := ret[0].(bool)
-	return ret0
-}
-
-// IsMountPointMatch indicates an expected call of IsMountPointMatch.
-func (mr *MockProxyMounterMockRecorder) IsMountPointMatch(mp, dir interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsMountPointMatch", reflect.TypeOf((*MockProxyMounter)(nil).IsMountPointMatch), mp, dir)
-}
-
-// List mocks base method.
-func (m *MockProxyMounter) List() ([]mount.MountPoint, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "List")
-	ret0, _ := ret[0].([]mount.MountPoint)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// List indicates an expected call of List.
-func (mr *MockProxyMounterMockRecorder) List() *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockProxyMounter)(nil).List))
-}
-
-// MakeFile mocks base method.
-func (m *MockProxyMounter) MakeFile(pathname string) error {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "MakeFile", pathname)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// MakeFile indicates an expected call of MakeFile.
-func (mr *MockProxyMounterMockRecorder) MakeFile(pathname interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MakeFile", reflect.TypeOf((*MockProxyMounter)(nil).MakeFile), pathname)
-}
-
-// Mount mocks base method.
-func (m *MockProxyMounter) Mount(source, target, fstype string, options []string) error {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Mount", source, target, fstype, options)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// Mount indicates an expected call of Mount.
-func (mr *MockProxyMounterMockRecorder) Mount(source, target, fstype, options interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Mount", reflect.TypeOf((*MockProxyMounter)(nil).Mount), source, target, fstype, options)
-}
-
-// MountSensitive mocks base method.
-func (m *MockProxyMounter) MountSensitive(source, target, fstype string, options, sensitiveOptions []string) error {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "MountSensitive", source, target, fstype, options, sensitiveOptions)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// MountSensitive indicates an expected call of MountSensitive.
-func (mr *MockProxyMounterMockRecorder) MountSensitive(source, target, fstype, options, sensitiveOptions interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MountSensitive", reflect.TypeOf((*MockProxyMounter)(nil).MountSensitive), source, target, fstype, options, sensitiveOptions)
-}
-
-// MountSensitiveWithoutSystemd mocks base method.
-func (m *MockProxyMounter) MountSensitiveWithoutSystemd(source, target, fstype string, options, sensitiveOptions []string) error {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "MountSensitiveWithoutSystemd", source, target, fstype, options, sensitiveOptions)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// MountSensitiveWithoutSystemd indicates an expected call of MountSensitiveWithoutSystemd.
-func (mr *MockProxyMounterMockRecorder) MountSensitiveWithoutSystemd(source, target, fstype, options, sensitiveOptions interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MountSensitiveWithoutSystemd", reflect.TypeOf((*MockProxyMounter)(nil).MountSensitiveWithoutSystemd), source, target, fstype, options, sensitiveOptions)
-}
-
-// MountSensitiveWithoutSystemdWithMountFlags mocks base method.
-func (m *MockProxyMounter) MountSensitiveWithoutSystemdWithMountFlags(source, target, fstype string, options, sensitiveOptions, mountFlags []string) error {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "MountSensitiveWithoutSystemdWithMountFlags", source, target, fstype, options, sensitiveOptions, mountFlags)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// MountSensitiveWithoutSystemdWithMountFlags indicates an expected call of MountSensitiveWithoutSystemdWithMountFlags.
-func (mr *MockProxyMounterMockRecorder) MountSensitiveWithoutSystemdWithMountFlags(source, target, fstype, options, sensitiveOptions, mountFlags interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MountSensitiveWithoutSystemdWithMountFlags", reflect.TypeOf((*MockProxyMounter)(nil).MountSensitiveWithoutSystemdWithMountFlags), source, target, fstype, options, sensitiveOptions, mountFlags)
-}
-
-// Rescan mocks base method.
-func (m *MockProxyMounter) Rescan() error {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Rescan")
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// Rescan indicates an expected call of Rescan.
-func (mr *MockProxyMounterMockRecorder) Rescan() *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rescan", reflect.TypeOf((*MockProxyMounter)(nil).Rescan))
-}
-
-// ResizeVolume mocks base method.
-func (m *MockProxyMounter) ResizeVolume(deviceMountPath string) (bool, error) {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "ResizeVolume", deviceMountPath)
-	ret0, _ := ret[0].(bool)
-	ret1, _ := ret[1].(error)
-	return ret0, ret1
-}
-
-// ResizeVolume indicates an expected call of ResizeVolume.
-func (mr *MockProxyMounterMockRecorder) ResizeVolume(deviceMountPath interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResizeVolume", reflect.TypeOf((*MockProxyMounter)(nil).ResizeVolume), deviceMountPath)
-}
-
-// Rmdir mocks base method.
-func (m *MockProxyMounter) Rmdir(path string) error {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Rmdir", path)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// Rmdir indicates an expected call of Rmdir.
-func (mr *MockProxyMounterMockRecorder) Rmdir(path interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Rmdir", reflect.TypeOf((*MockProxyMounter)(nil).Rmdir), path)
-}
-
-// Unmount mocks base method.
-func (m *MockProxyMounter) Unmount(target string) error {
-	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Unmount", target)
-	ret0, _ := ret[0].(error)
-	return ret0
-}
-
-// Unmount indicates an expected call of Unmount.
-func (mr *MockProxyMounterMockRecorder) Unmount(target interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unmount", reflect.TypeOf((*MockProxyMounter)(nil).Unmount), target)
-}
-
-// WriteVolumeCache mocks base method.
-func (m *MockProxyMounter) WriteVolumeCache(target string) {
-	m.ctrl.T.Helper()
-	m.ctrl.Call(m, "WriteVolumeCache", target)
-}
-
-// WriteVolumeCache indicates an expected call of WriteVolumeCache.
-func (mr *MockProxyMounterMockRecorder) WriteVolumeCache(target interface{}) *gomock.Call {
-	mr.mock.ctrl.T.Helper()
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteVolumeCache", reflect.TypeOf((*MockProxyMounter)(nil).WriteVolumeCache), target)
-}
diff --git a/pkg/mounter/mount.go b/pkg/mounter/mount.go
index e4a69fd7..c75bfb4c 100644
--- a/pkg/mounter/mount.go
+++ b/pkg/mounter/mount.go
@@ -54,9 +54,16 @@ type NodeMounter struct {
 }
 
 // NewNodeMounter returns a new intsance of NodeMounter.
-func NewNodeMounter() (Mounter, error) {
-	// mounter.NewSafeMounter returns a SafeFormatAndMount
-	safeMounter, err := NewSafeMounter()
+func NewNodeMounter(hostprocess bool) (Mounter, error) {
+	var safeMounter *mountutils.SafeFormatAndMount
+	var err error
+
+	if hostprocess {
+		safeMounter, err = NewSafeMounterV2()
+	} else {
+		safeMounter, err = NewSafeMounter()
+	}
+
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/mounter/mount_linux.go b/pkg/mounter/mount_linux.go
index e2b6c6b0..7df2219b 100644
--- a/pkg/mounter/mount_linux.go
+++ b/pkg/mounter/mount_linux.go
@@ -32,6 +32,7 @@ import (
 	"golang.org/x/sys/unix"
 	"k8s.io/klog/v2"
 	mountutils "k8s.io/mount-utils"
+	utilexec "k8s.io/utils/exec"
 )
 
 const (
@@ -39,6 +40,17 @@ const (
 	diskPartitionSuffix     = ""
 )
 
+func NewSafeMounter() (*mountutils.SafeFormatAndMount, error) {
+	return &mountutils.SafeFormatAndMount{
+		Interface: mountutils.New(""),
+		Exec:      utilexec.New(),
+	}, nil
+}
+
+func NewSafeMounterV2() (*mountutils.SafeFormatAndMount, error) {
+	return nil, fmt.Errorf("NewSafeMounterV2 is not supported on this platform")
+}
+
 // FindDevicePath finds path of device and verifies its existence
 // if the device is not nvme, return the path directly
 // if the device is nvme, finds and returns the nvme device path eg. /dev/nvme1n1
diff --git a/pkg/mounter/mount_windows.go b/pkg/mounter/mount_windows.go
index 15ceb1f6..afb4f411 100644
--- a/pkg/mounter/mount_windows.go
+++ b/pkg/mounter/mount_windows.go
@@ -20,51 +20,29 @@ limitations under the License.
 package mounter
 
 import (
-	"context"
 	"fmt"
+
 	"regexp"
-	"strconv"
-	"strings"
 
-	diskapi "github.com/kubernetes-csi/csi-proxy/client/api/disk/v1"
-	diskclient "github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1"
+	"github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/util"
+
 	"k8s.io/klog/v2"
 	mountutils "k8s.io/mount-utils"
 )
 
-const (
-	DefaultBlockSize = 4096
+var (
+	ErrUnsupportedMounter = fmt.Errorf("unsupported mounter type")
 )
 
 func (m NodeMounter) FindDevicePath(devicePath, volumeID, _, _ string) (string, error) {
-	diskClient, err := diskclient.NewClient()
-	if err != nil {
-		return "", fmt.Errorf("error creating csi-proxy disk client: %q", err)
-	}
-	defer diskClient.Close()
-
-	response, err := diskClient.ListDiskIDs(context.TODO(), &diskapi.ListDiskIDsRequest{})
-	if err != nil {
-		return "", fmt.Errorf("error listing disk ids: %q", err)
+	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
+	case *CSIProxyMounterV2:
+		return proxyMounter.FindDevicePath(devicePath, volumeID, "", "")
+	case *CSIProxyMounter:
+		return proxyMounter.FindDevicePath(devicePath, volumeID, "", "")
+	default:
+		return "", ErrUnsupportedMounter
 	}
-
-	diskIDs := response.GetDiskIDs()
-
-	foundDiskNumber := ""
-	for diskNumber, diskID := range diskIDs {
-		serialNumber := diskID.GetSerialNumber()
-		cleanVolumeID := strings.ReplaceAll(volumeID, "-", "")
-		if strings.Contains(serialNumber, cleanVolumeID) {
-			foundDiskNumber = strconv.Itoa(int(diskNumber))
-			break
-		}
-	}
-
-	if foundDiskNumber == "" {
-		return "", fmt.Errorf("disk number for device path %q volume id %q not found", devicePath, volumeID)
-	}
-
-	return foundDiskNumber, nil
 }
 
 func (m NodeMounter) PreparePublishTarget(target string) error {
@@ -78,16 +56,24 @@ func (m NodeMounter) PreparePublishTarget(target string) error {
 		return fmt.Errorf("error checking path %q exists: %v", target, err)
 	}
 
-	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
-	if !ok {
-		return fmt.Errorf("failed to cast mounter to csi proxy mounter")
+	if !exists {
+		return nil // If the target does not exist, no action is necessary
 	}
 
-	if exists {
+	// Handle different mounter implementations
+	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
+	case *CSIProxyMounterV2:
+		if err := proxyMounter.Rmdir(target); err != nil {
+			return fmt.Errorf("error Rmdir target %q: %v", target, err)
+		}
+	case *CSIProxyMounter:
 		if err := proxyMounter.Rmdir(target); err != nil {
 			return fmt.Errorf("error Rmdir target %q: %v", target, err)
 		}
+	default:
+		return ErrUnsupportedMounter
 	}
+
 	return nil
 }
 
@@ -98,25 +84,33 @@ func (m NodeMounter) IsBlockDevice(fullPath string) (bool, error) {
 
 // getBlockSizeBytes gets the size of the disk in bytes
 func (m NodeMounter) GetBlockSizeBytes(devicePath string) (int64, error) {
-	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
-	if !ok {
-		return -1, fmt.Errorf("failed to cast mounter to csi proxy mounter")
-	}
-
-	sizeInBytes, err := proxyMounter.GetDeviceSize(devicePath)
-	if err != nil {
-		return -1, err
+	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
+	case *CSIProxyMounterV2:
+		sizeInBytes, err := proxyMounter.GetDeviceSize(devicePath)
+		if err != nil {
+			return -1, err
+		}
+		return sizeInBytes, nil
+	case *CSIProxyMounter:
+		sizeInBytes, err := proxyMounter.GetDeviceSize(devicePath)
+		if err != nil {
+			return -1, err
+		}
+		return sizeInBytes, nil
+	default:
+		return -1, ErrUnsupportedMounter
 	}
-
-	return sizeInBytes, nil
 }
 
 func (m NodeMounter) FormatAndMountSensitiveWithFormatOptions(source string, target string, fstype string, options []string, sensitiveOptions []string, formatOptions []string) error {
-	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
-	if !ok {
-		return fmt.Errorf("failed to cast mounter to csi proxy mounter")
+	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
+	case *CSIProxyMounterV2:
+		return proxyMounter.FormatAndMountSensitiveWithFormatOptions(source, target, fstype, options, sensitiveOptions, formatOptions)
+	case *CSIProxyMounter:
+		return proxyMounter.FormatAndMountSensitiveWithFormatOptions(source, target, fstype, options, sensitiveOptions, formatOptions)
+	default:
+		return ErrUnsupportedMounter
 	}
-	return proxyMounter.FormatAndMountSensitiveWithFormatOptions(source, target, fstype, options, sensitiveOptions, formatOptions)
 }
 
 // GetDeviceNameFromMount returns the volume ID for a mount path.
@@ -128,30 +122,42 @@ func (m NodeMounter) FormatAndMountSensitiveWithFormatOptions(source string, tar
 // Command to determine ref count would be something like:
 // Get-Volume -UniqueId "\\?\Volume{7c3da0c1-0000-0000-0000-010000000000}\" | Get-Partition | Select AccessPaths
 func (m NodeMounter) GetDeviceNameFromMount(mountPath string) (string, int, error) {
-	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
-	if !ok {
-		return "", 0, fmt.Errorf("failed to cast mounter to csi proxy mounter")
-	}
-	deviceName, err := proxyMounter.GetDeviceNameFromMount(mountPath, "")
-	if err != nil {
-		// HACK change csi-proxy behavior instead of relying on fragile internal
-		// implementation details!
-		// if err contains '"(Get-Item...).Target, output: , error: <nil>' then the
-		// internal Get-Item cmdlet didn't fail but no item/device was found at the
-		// path so we should return empty string and nil error just like the Linux
-		// implementation would.
-		pattern := `(Get-Item -Path \S+).Target, output: , error: <nil>|because it does not exist`
-		matched, matchErr := regexp.MatchString(pattern, err.Error())
-		if matched {
-			return "", 0, nil
+	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
+	// HACK change csi-proxy behavior instead of relying on fragile internal
+	// implementation details!
+	// if err contains '"(Get-Item...).Target, output: , error: <nil>' then the
+	// internal Get-Item cmdlet didn't fail but no item/device was found at the
+	// path so we should return empty string and nil error just like the Linux
+	// implementation would.
+	case *CSIProxyMounterV2:
+		deviceName, err := proxyMounter.GetDeviceNameFromMount(mountPath, "")
+		if err != nil {
+			return handleGetDeviceNameFromMountError(err)
 		}
-		err = fmt.Errorf("error getting device name from mount: %v", err)
-		if matchErr != nil {
-			err = fmt.Errorf("%v, and error matching pattern %q: %v", err, pattern, matchErr)
+		return deviceName, 1, nil
+	case *CSIProxyMounter:
+		deviceName, err := proxyMounter.GetDeviceNameFromMount(mountPath, "")
+		if err != nil {
+			return handleGetDeviceNameFromMountError(err)
 		}
-		return "", 0, err
+		return deviceName, 1, nil
+	default:
+		return "", 0, ErrUnsupportedMounter
 	}
-	return deviceName, 1, nil
+}
+
+// handleGetDeviceNameFromMountError processes common error patterns for GetDeviceNameFromMount
+func handleGetDeviceNameFromMountError(err error) (string, int, error) {
+	// Handling common error pattern as seen in previous implementations
+	pattern := `(Get-Item -Path \S+).Target, output: , error: <nil>|because it does not exist`
+	matched, matchErr := regexp.MatchString(pattern, err.Error())
+	if matched {
+		return "", 0, nil // No device found, but not an error condition
+	}
+	if matchErr != nil {
+		return "", 0, fmt.Errorf("error processing error message: %v, matching pattern %q: %v", err, pattern, matchErr)
+	}
+	return "", 0, fmt.Errorf("error getting device name from mount: %v", err)
 }
 
 // IsCorruptedMnt return true if err is about corrupted mount point
@@ -160,55 +166,79 @@ func (m NodeMounter) IsCorruptedMnt(err error) bool {
 }
 
 func (m *NodeMounter) MakeFile(path string) error {
-	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
-	if !ok {
-		return fmt.Errorf("failed to cast mounter to csi proxy mounter")
+	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
+	case *CSIProxyMounterV2:
+		return proxyMounter.MakeFile(path)
+	case *CSIProxyMounter:
+		return proxyMounter.MakeFile(path)
+	default:
+		return ErrUnsupportedMounter
 	}
-	return proxyMounter.MakeFile(path)
 }
 
 func (m *NodeMounter) MakeDir(path string) error {
-	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
-	if !ok {
-		return fmt.Errorf("failed to cast mounter to csi proxy mounter")
+	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
+	case *CSIProxyMounterV2:
+		return proxyMounter.MakeDir(path)
+	case *CSIProxyMounter:
+		return proxyMounter.MakeDir(path)
+	default:
+		return ErrUnsupportedMounter
 	}
-	return proxyMounter.MakeDir(path)
 }
 
 func (m *NodeMounter) PathExists(path string) (bool, error) {
-	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
-	if !ok {
-		return false, fmt.Errorf("failed to cast mounter to csi proxy mounter")
+	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
+	case *CSIProxyMounterV2:
+		return proxyMounter.ExistsPath(path)
+	case *CSIProxyMounter:
+		return proxyMounter.ExistsPath(path)
+	default:
+		return false, ErrUnsupportedMounter
 	}
-	return proxyMounter.ExistsPath(path)
 }
 
 func (m *NodeMounter) Resize(devicePath, deviceMountPath string) (bool, error) {
-	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
-	if !ok {
-		return false, fmt.Errorf("failed to cast mounter to csi proxy mounter")
+	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
+	case *CSIProxyMounterV2:
+		return proxyMounter.ResizeVolume(deviceMountPath)
+	case *CSIProxyMounter:
+		return proxyMounter.ResizeVolume(deviceMountPath)
+	default:
+		return false, ErrUnsupportedMounter
 	}
-	return proxyMounter.ResizeVolume(deviceMountPath)
 }
 
 // NeedResize called at NodeStage to ensure file system is the correct size
 func (m *NodeMounter) NeedResize(devicePath, deviceMountPath string) (bool, error) {
-	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
-	if !ok {
-		return false, fmt.Errorf("failed to cast mounter to csi proxy mounter")
-	}
-
-	deviceSize, err := proxyMounter.GetDeviceSize(devicePath)
-	if err != nil {
-		return false, err
+	var err error
+	var deviceSize, fsSize int64
+
+	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
+	case *CSIProxyMounterV2:
+		deviceSize, err = proxyMounter.GetDeviceSize(devicePath)
+		if err != nil {
+			return false, fmt.Errorf("failed to get device size: %w", err)
+		}
+		fsSize, err = proxyMounter.GetVolumeSizeInBytes(deviceMountPath)
+		if err != nil {
+			return false, fmt.Errorf("failed to get filesystem size: %w", err)
+		}
+	case *CSIProxyMounter:
+		deviceSize, err = proxyMounter.GetDeviceSize(devicePath)
+		if err != nil {
+			return false, fmt.Errorf("failed to get device size: %w", err)
+		}
+		fsSize, err = proxyMounter.GetVolumeSizeInBytes(deviceMountPath)
+		if err != nil {
+			return false, fmt.Errorf("failed to get filesystem size: %w", err)
+		}
+	default:
+		return false, ErrUnsupportedMounter
 	}
 
-	fsSize, err := proxyMounter.GetVolumeSizeInBytes(deviceMountPath)
-	if err != nil {
-		return false, err
-	}
 	// Tolerate one block difference (4096 bytes)
-	if deviceSize <= DefaultBlockSize+fsSize {
+	if deviceSize <= util.DefaultBlockSize+fsSize {
 		return true, nil
 	}
 	return false, nil
@@ -216,29 +246,39 @@ func (m *NodeMounter) NeedResize(devicePath, deviceMountPath string) (bool, erro
 
 // Unmount volume from target path
 func (m *NodeMounter) Unpublish(target string) error {
-	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
-	if !ok {
-		return fmt.Errorf("failed to cast mounter to csi proxy mounter")
+	var err error
+	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
+	case *CSIProxyMounterV2:
+		err = proxyMounter.Rmdir(target)
+	case *CSIProxyMounter:
+		err = proxyMounter.Rmdir(target)
+	default:
+		return ErrUnsupportedMounter
 	}
-	// Remove symlink
-	err := proxyMounter.Rmdir(target)
+
 	if err != nil {
-		return err
+		return fmt.Errorf("failed to remove directory: %w", err)
 	}
+
 	return nil
 }
 
 // Unmount volume from staging path
 // usually this staging path is a global directory on the node
 func (m *NodeMounter) Unstage(target string) error {
-	proxyMounter, ok := m.SafeFormatAndMount.Interface.(*CSIProxyMounter)
-	if !ok {
-		return fmt.Errorf("failed to cast mounter to csi proxy mounter")
+	var err error
+	switch proxyMounter := m.SafeFormatAndMount.Interface.(type) {
+	case *CSIProxyMounterV2:
+		err = proxyMounter.Unmount(target)
+	case *CSIProxyMounter:
+		err = proxyMounter.Unmount(target)
+	default:
+		return ErrUnsupportedMounter
 	}
-	// Unmounts and offlines the disk via the CSI Proxy API
-	err := proxyMounter.Unmount(target)
+
 	if err != nil {
-		return err
+		return fmt.Errorf("unmount failed: %w", err)
 	}
+
 	return nil
 }
diff --git a/pkg/mounter/safe_mounter_windows.go b/pkg/mounter/mount_windows_proxyV1.go
similarity index 85%
rename from pkg/mounter/safe_mounter_windows.go
rename to pkg/mounter/mount_windows_proxyV1.go
index 81ef3aa6..71cdf93c 100644
--- a/pkg/mounter/safe_mounter_windows.go
+++ b/pkg/mounter/mount_windows_proxyV1.go
@@ -2,7 +2,7 @@
 // +build windows
 
 /*
-Copyright 2020 The Kubernetes Authors.
+Copyright 2024 The Kubernetes Authors.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -28,52 +28,46 @@ import (
 	"strings"
 
 	disk "github.com/kubernetes-csi/csi-proxy/client/api/disk/v1"
-	diskclient "github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1"
-
 	fs "github.com/kubernetes-csi/csi-proxy/client/api/filesystem/v1"
-	fsclient "github.com/kubernetes-csi/csi-proxy/client/groups/filesystem/v1"
-
 	volume "github.com/kubernetes-csi/csi-proxy/client/api/volume/v1"
+	diskclient "github.com/kubernetes-csi/csi-proxy/client/groups/disk/v1"
+	fsclient "github.com/kubernetes-csi/csi-proxy/client/groups/filesystem/v1"
 	volumeclient "github.com/kubernetes-csi/csi-proxy/client/groups/volume/v1"
+	"github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/util"
 
 	"k8s.io/klog/v2"
-	mount_utils "k8s.io/mount-utils"
+	mountutils "k8s.io/mount-utils"
 	utilexec "k8s.io/utils/exec"
 )
 
-var _ ProxyMounter = &CSIProxyMounter{}
-
-type ProxyMounter interface {
-	mount_utils.Interface
-
-	Rmdir(path string) error
-	WriteVolumeCache(target string)
-	IsMountPointMatch(mp mount_utils.MountPoint, dir string) bool
-	GetDeviceNameFromMount(mountPath, pluginMountDir string) (string, error)
-	MakeFile(pathname string) error
-	ExistsPath(path string) (bool, error)
-	Rescan() error
-	FindDiskByLun(lun string) (diskNum string, err error)
-	FormatAndMountSensitiveWithFormatOptions(source string, target string, fstype string, options []string, sensitiveOptions []string, formatOptions []string) error
-	ResizeVolume(deviceMountPath string) (bool, error)
-	GetVolumeSizeInBytes(deviceMountPath string) (int64, error)
-	GetDeviceSize(devicePath string) (int64, error)
-	IsMountPoint(pathname string) (bool, error)
-}
-
 type CSIProxyMounter struct {
-	mount_utils.Interface
 	FsClient     *fsclient.Client
 	DiskClient   *diskclient.Client
 	VolumeClient *volumeclient.Client
 }
 
-func normalizeWindowsPath(path string) string {
-	normalizedPath := strings.Replace(path, "/", "\\", -1)
-	if strings.HasPrefix(normalizedPath, "\\") {
-		normalizedPath = "c:" + normalizedPath
+// NewSafeMounter returns a new instance of SafeFormatAndMount.
+func NewSafeMounter() (*mountutils.SafeFormatAndMount, error) {
+	fsClient, err := fsclient.NewClient()
+	if err != nil {
+		return nil, err
+	}
+	diskClient, err := diskclient.NewClient()
+	if err != nil {
+		return nil, err
+	}
+	volumeClient, err := volumeclient.NewClient()
+	if err != nil {
+		return nil, err
 	}
-	return normalizedPath
+	return &mountutils.SafeFormatAndMount{
+		Interface: &CSIProxyMounter{
+			FsClient:     fsClient,
+			DiskClient:   diskClient,
+			VolumeClient: volumeClient,
+		},
+		Exec: utilexec.New(),
+	}, nil
 }
 
 // Mount just creates a soft link at target pointing to source.
@@ -81,8 +75,8 @@ func (mounter *CSIProxyMounter) Mount(source string, target string, fstype strin
 	// Mount is called after the format is done.
 	// TODO: Confirm that fstype is empty.
 	linkRequest := &fs.CreateSymlinkRequest{
-		SourcePath: normalizeWindowsPath(source),
-		TargetPath: normalizeWindowsPath(target),
+		SourcePath: util.NormalizeWindowsPath(source),
+		TargetPath: util.NormalizeWindowsPath(target),
 	}
 	_, err := mounter.FsClient.CreateSymlink(context.Background(), linkRequest)
 	if err != nil {
@@ -94,7 +88,7 @@ func (mounter *CSIProxyMounter) Mount(source string, target string, fstype strin
 func (mounter *CSIProxyMounter) Unmount(target string) error {
 	// Find the volume id
 	getVolumeIdRequest := &volume.GetVolumeIDFromTargetPathRequest{
-		TargetPath: normalizeWindowsPath(target),
+		TargetPath: util.NormalizeWindowsPath(target),
 	}
 	volumeIdResponse, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), getVolumeIdRequest)
 	if err != nil {
@@ -104,7 +98,7 @@ func (mounter *CSIProxyMounter) Unmount(target string) error {
 	// Call UnmountVolume CSI proxy function which flushes data cache to disk and removes the global staging path
 	unmountVolumeRequest := &volume.UnmountVolumeRequest{
 		VolumeId:   volumeIdResponse.VolumeId,
-		TargetPath: normalizeWindowsPath(target),
+		TargetPath: util.NormalizeWindowsPath(target),
 	}
 	_, err = mounter.VolumeClient.UnmountVolume(context.Background(), unmountVolumeRequest)
 	if err != nil {
@@ -142,7 +136,7 @@ func (mounter *CSIProxyMounter) Unmount(target string) error {
 // Rmdir - delete the given directory
 func (mounter *CSIProxyMounter) Rmdir(path string) error {
 	rmdirRequest := &fs.RmdirRequest{
-		Path:  normalizeWindowsPath(path),
+		Path:  util.NormalizeWindowsPath(path),
 		Force: true,
 	}
 	_, err := mounter.FsClient.Rmdir(context.Background(), rmdirRequest)
@@ -153,7 +147,7 @@ func (mounter *CSIProxyMounter) Rmdir(path string) error {
 }
 
 func (mounter *CSIProxyMounter) WriteVolumeCache(target string) {
-	request := &volume.GetVolumeIDFromTargetPathRequest{TargetPath: normalizeWindowsPath(target)}
+	request := &volume.GetVolumeIDFromTargetPathRequest{TargetPath: util.NormalizeWindowsPath(target)}
 	response, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), request)
 	if err != nil || response == nil {
 		klog.InfoS("GetVolumeIDFromTargetPath failed", "target", target, "err", err, "response", response)
@@ -167,11 +161,11 @@ func (mounter *CSIProxyMounter) WriteVolumeCache(target string) {
 	}
 }
 
-func (mounter *CSIProxyMounter) List() ([]mount_utils.MountPoint, error) {
-	return []mount_utils.MountPoint{}, fmt.Errorf("List not implemented for CSIProxyMounter")
+func (mounter *CSIProxyMounter) List() ([]mountutils.MountPoint, error) {
+	return []mountutils.MountPoint{}, fmt.Errorf("List not implemented for CSIProxyMounter")
 }
 
-func (mounter *CSIProxyMounter) IsMountPointMatch(mp mount_utils.MountPoint, dir string) bool {
+func (mounter *CSIProxyMounter) IsMountPointMatch(mp mountutils.MountPoint, dir string) bool {
 	return mp.Path == dir
 }
 
@@ -200,7 +194,7 @@ func (mounter *CSIProxyMounter) IsLikelyNotMountPoint(path string) (bool, error)
 
 	response, err := mounter.FsClient.IsSymlink(context.Background(),
 		&fs.IsSymlinkRequest{
-			Path: normalizeWindowsPath(path),
+			Path: util.NormalizeWindowsPath(path),
 		})
 	if err != nil {
 		return false, err
@@ -218,7 +212,7 @@ func (mounter *CSIProxyMounter) DeviceOpened(pathname string) (bool, error) {
 
 // GetDeviceNameFromMount returns the disk number for a mount path.
 func (mounter *CSIProxyMounter) GetDeviceNameFromMount(mountPath, _ string) (string, error) {
-	req := &volume.GetVolumeIDFromTargetPathRequest{TargetPath: normalizeWindowsPath(mountPath)}
+	req := &volume.GetVolumeIDFromTargetPathRequest{TargetPath: util.NormalizeWindowsPath(mountPath)}
 	resp, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), req)
 	if err != nil {
 		return "", err
@@ -248,7 +242,7 @@ func (mounter *CSIProxyMounter) MakeFile(pathname string) error {
 // with Plugin context..
 func (mounter *CSIProxyMounter) MakeDir(pathname string) error {
 	mkdirReq := &fs.MkdirRequest{
-		Path: normalizeWindowsPath(pathname),
+		Path: util.NormalizeWindowsPath(pathname),
 	}
 	_, err := mounter.FsClient.Mkdir(context.Background(), mkdirReq)
 	if err != nil {
@@ -263,7 +257,7 @@ func (mounter *CSIProxyMounter) MakeDir(pathname string) error {
 func (mounter *CSIProxyMounter) ExistsPath(path string) (bool, error) {
 	isExistsResponse, err := mounter.FsClient.PathExists(context.Background(),
 		&fs.PathExistsRequest{
-			Path: normalizeWindowsPath(path),
+			Path: util.NormalizeWindowsPath(path),
 		})
 	if err != nil {
 		return false, err
@@ -402,7 +396,7 @@ func (mounter *CSIProxyMounter) FormatAndMountSensitiveWithFormatOptions(source
 	// Mount the volume by calling the CSI proxy call.
 	mountVolumeRequest := &volume.MountVolumeRequest{
 		VolumeId:   volumeID,
-		TargetPath: normalizeWindowsPath(target),
+		TargetPath: util.NormalizeWindowsPath(target),
 	}
 	_, err = mounter.VolumeClient.MountVolume(context.Background(), mountVolumeRequest)
 	if err != nil {
@@ -415,7 +409,7 @@ func (mounter *CSIProxyMounter) FormatAndMountSensitiveWithFormatOptions(source
 func (mounter *CSIProxyMounter) ResizeVolume(deviceMountPath string) (bool, error) {
 	// Find the volume id
 	getVolumeIdRequest := &volume.GetVolumeIDFromTargetPathRequest{
-		TargetPath: normalizeWindowsPath(deviceMountPath),
+		TargetPath: util.NormalizeWindowsPath(deviceMountPath),
 	}
 	volumeIdResponse, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), getVolumeIdRequest)
 	if err != nil {
@@ -439,7 +433,7 @@ func (mounter *CSIProxyMounter) ResizeVolume(deviceMountPath string) (bool, erro
 func (mounter *CSIProxyMounter) GetVolumeSizeInBytes(deviceMountPath string) (int64, error) {
 	// Find the volume id
 	getVolumeIdRequest := &volume.GetVolumeIDFromTargetPathRequest{
-		TargetPath: normalizeWindowsPath(deviceMountPath),
+		TargetPath: util.NormalizeWindowsPath(deviceMountPath),
 	}
 	volumeIdResponse, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), getVolumeIdRequest)
 	if err != nil {
@@ -478,35 +472,37 @@ func (mounter *CSIProxyMounter) GetDeviceSize(devicePath string) (int64, error)
 	return resp.TotalBytes, nil
 }
 
-// NewCSIProxyMounter - creates a new CSI Proxy mounter struct which encompassed all the
-// clients to the CSI proxy - filesystem, disk and volume clients.
-func NewCSIProxyMounter() (*CSIProxyMounter, error) {
-	fsClient, err := fsclient.NewClient()
-	if err != nil {
-		return nil, err
-	}
+func (mounter *CSIProxyMounter) CanSafelySkipMountPointCheck() bool {
+	return false
+}
+
+func (mounter *CSIProxyMounter) FindDevicePath(devicePath, volumeID, _, _ string) (string, error) {
 	diskClient, err := diskclient.NewClient()
 	if err != nil {
-		return nil, err
+		return "", fmt.Errorf("error creating csi-proxy disk client: %q", err)
 	}
-	volumeClient, err := volumeclient.NewClient()
+	defer diskClient.Close()
+
+	response, err := diskClient.ListDiskIDs(context.TODO(), &disk.ListDiskIDsRequest{})
 	if err != nil {
-		return nil, err
+		return "", fmt.Errorf("error listing disk ids: %q", err)
 	}
-	return &CSIProxyMounter{
-		FsClient:     fsClient,
-		DiskClient:   diskClient,
-		VolumeClient: volumeClient,
-	}, nil
-}
 
-func NewSafeMounter() (*mount_utils.SafeFormatAndMount, error) {
-	csiProxyMounter, err := NewCSIProxyMounter()
-	if err != nil {
-		return nil, err
+	diskIDs := response.GetDiskIDs()
+
+	foundDiskNumber := ""
+	for diskNumber, diskID := range diskIDs {
+		serialNumber := diskID.GetSerialNumber()
+		cleanVolumeID := strings.ReplaceAll(volumeID, "-", "")
+		if strings.Contains(serialNumber, cleanVolumeID) {
+			foundDiskNumber = strconv.Itoa(int(diskNumber))
+			break
+		}
 	}
-	return &mount_utils.SafeFormatAndMount{
-		Interface: csiProxyMounter,
-		Exec:      utilexec.New(),
-	}, nil
+
+	if foundDiskNumber == "" {
+		return "", fmt.Errorf("disk number for device path %q volume id %q not found", devicePath, volumeID)
+	}
+
+	return foundDiskNumber, nil
 }
diff --git a/pkg/mounter/mount_windows_proxyV2.go b/pkg/mounter/mount_windows_proxyV2.go
new file mode 100644
index 00000000..468ee219
--- /dev/null
+++ b/pkg/mounter/mount_windows_proxyV2.go
@@ -0,0 +1,501 @@
+//go:build windows
+// +build windows
+
+/*
+Copyright 2024 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package mounter
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+
+	diskv2 "github.com/kubernetes-csi/csi-proxy/v2/pkg/disk"
+	diskapiv2 "github.com/kubernetes-csi/csi-proxy/v2/pkg/disk/hostapi"
+	fsv2 "github.com/kubernetes-csi/csi-proxy/v2/pkg/filesystem"
+	fsapiv2 "github.com/kubernetes-csi/csi-proxy/v2/pkg/filesystem/hostapi"
+	volumev2 "github.com/kubernetes-csi/csi-proxy/v2/pkg/volume"
+	volumeapiv2 "github.com/kubernetes-csi/csi-proxy/v2/pkg/volume/hostapi"
+	"github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/util"
+	"k8s.io/klog/v2"
+	mountutils "k8s.io/mount-utils"
+	utilexec "k8s.io/utils/exec"
+)
+
+type CSIProxyMounterV2 struct {
+	FsClient     fsv2.Interface
+	DiskClient   diskv2.Interface
+	VolumeClient volumev2.Interface
+}
+
+// NewSafeMounterV2 returns a new instance of SafeFormatAndMount.
+func NewSafeMounterV2() (*mountutils.SafeFormatAndMount, error) {
+	fs, err := fsv2.New(fsapiv2.New())
+	if err != nil {
+		return nil, err
+	}
+	disk, err := diskv2.New(diskapiv2.New())
+	if err != nil {
+		return nil, err
+	}
+	volume, err := volumev2.New(volumeapiv2.New())
+	if err != nil {
+		return nil, err
+	}
+	return &mountutils.SafeFormatAndMount{
+		Interface: &CSIProxyMounterV2{
+			FsClient:     fs,
+			DiskClient:   disk,
+			VolumeClient: volume,
+		},
+		Exec: utilexec.New(),
+	}, nil
+}
+
+// Mount just creates a soft link at target pointing to source.
+func (mounter *CSIProxyMounterV2) Mount(source string, target string, fstype string, options []string) error {
+	// Mount is called after the format is done.
+	// TODO: Confirm that fstype is empty.
+	linkRequest := &fsv2.CreateSymlinkRequest{
+		SourcePath: util.NormalizeWindowsPath(source),
+		TargetPath: util.NormalizeWindowsPath(target),
+	}
+	_, err := mounter.FsClient.CreateSymlink(context.Background(), linkRequest)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (mounter *CSIProxyMounterV2) Unmount(target string) error {
+	// Find the volume id
+	getVolumeIdRequest := &volumev2.GetVolumeIDFromTargetPathRequest{
+		TargetPath: util.NormalizeWindowsPath(target),
+	}
+	volumeIdResponse, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), getVolumeIdRequest)
+	if err != nil {
+		return err
+	}
+
+	// Call UnmountVolume CSI proxy function which flushes data cache to disk and removes the global staging path
+	unmountVolumeRequest := &volumev2.UnmountVolumeRequest{
+		VolumeID:   volumeIdResponse.VolumeID,
+		TargetPath: util.NormalizeWindowsPath(target),
+	}
+	_, err = mounter.VolumeClient.UnmountVolume(context.Background(), unmountVolumeRequest)
+	if err != nil {
+		return err
+	}
+
+	// Cleanup stage path
+	err = mounter.Rmdir(target)
+	if err != nil {
+		return err
+	}
+
+	// Get disk number
+	getDiskNumberRequest := &volumev2.GetDiskNumberFromVolumeIDRequest{
+		VolumeID: volumeIdResponse.VolumeID,
+	}
+	getDiskNumberResponse, err := mounter.VolumeClient.GetDiskNumberFromVolumeID(context.Background(), getDiskNumberRequest)
+	if err != nil {
+		return err
+	}
+
+	// Offline the disk
+	setDiskStateRequest := &diskv2.SetDiskStateRequest{
+		DiskNumber: getDiskNumberResponse.DiskNumber,
+		IsOnline:   false,
+	}
+	_, err = mounter.DiskClient.SetDiskState(context.Background(), setDiskStateRequest)
+	if err != nil {
+		return err
+	}
+	klog.V(4).InfoS("Successfully unmounted volume", "diskNumber", getDiskNumberResponse.DiskNumber, "volumeId", volumeIdResponse.VolumeID, "target", target)
+	return nil
+}
+
+// Rmdir - delete the given directory
+func (mounter *CSIProxyMounterV2) Rmdir(path string) error {
+	rmdirRequest := &fsv2.RmdirRequest{
+		Path:  util.NormalizeWindowsPath(path),
+		Force: true,
+	}
+	_, err := mounter.FsClient.Rmdir(context.Background(), rmdirRequest)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (mounter *CSIProxyMounterV2) WriteVolumeCache(target string) {
+	request := &volumev2.GetVolumeIDFromTargetPathRequest{TargetPath: util.NormalizeWindowsPath(target)}
+	response, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), request)
+	if err != nil || response == nil {
+		klog.InfoS("GetVolumeIDFromTargetPath failed", "target", target, "err", err, "response", response)
+	} else {
+		request := &volumev2.WriteVolumeCacheRequest{
+			VolumeID: response.VolumeID,
+		}
+		if res, err := mounter.VolumeClient.WriteVolumeCache(context.Background(), request); err != nil {
+			klog.InfoS("WriteVolumeCache failed", "volumeID", response.VolumeID, "err", err, "res", res)
+		}
+	}
+}
+
+func (mounter *CSIProxyMounterV2) List() ([]mountutils.MountPoint, error) {
+	return []mountutils.MountPoint{}, fmt.Errorf("List not implemented for CSIProxyMounter")
+}
+
+func (mounter *CSIProxyMounterV2) IsMountPointMatch(mp mountutils.MountPoint, dir string) bool {
+	return mp.Path == dir
+}
+
+// IsMountPoint: determines if a directory is a mountpoint.
+func (mounter *CSIProxyMounterV2) IsMountPoint(file string) (bool, error) {
+	isNotMnt, err := mounter.IsLikelyNotMountPoint(file)
+	if err != nil {
+		return false, err
+	}
+	return !isNotMnt, nil
+}
+
+// IsLikelyMountPoint - If the directory does not exists, the function will return os.ErrNotExist error.
+//
+//	If the path exists, call to CSI proxy will check if its a link, if its a link then existence of target
+//	path is checked.
+func (mounter *CSIProxyMounterV2) IsLikelyNotMountPoint(path string) (bool, error) {
+	isExists, err := mounter.ExistsPath(path)
+	if err != nil {
+		return false, err
+	}
+
+	if !isExists {
+		return true, os.ErrNotExist
+	}
+
+	response, err := mounter.FsClient.IsSymlink(context.Background(),
+		&fsv2.IsSymlinkRequest{
+			Path: util.NormalizeWindowsPath(path),
+		})
+	if err != nil {
+		return false, err
+	}
+	return !response.IsSymlink, nil
+}
+
+func (mounter *CSIProxyMounterV2) PathIsDevice(pathname string) (bool, error) {
+	return false, fmt.Errorf("PathIsDevice not implemented for CSIProxyMounter")
+}
+
+func (mounter *CSIProxyMounterV2) DeviceOpened(pathname string) (bool, error) {
+	return false, fmt.Errorf("DeviceOpened not implemented for CSIProxyMounter")
+}
+
+// GetDeviceNameFromMount returns the disk number for a mount path.
+func (mounter *CSIProxyMounterV2) GetDeviceNameFromMount(mountPath, _ string) (string, error) {
+	req := &volumev2.GetVolumeIDFromTargetPathRequest{TargetPath: util.NormalizeWindowsPath(mountPath)}
+	resp, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), req)
+	if err != nil {
+		return "", err
+	}
+	// Get disk number
+	getDiskNumberRequest := &volumev2.GetDiskNumberFromVolumeIDRequest{
+		VolumeID: resp.VolumeID,
+	}
+	getDiskNumberResponse, err := mounter.VolumeClient.GetDiskNumberFromVolumeID(context.Background(), getDiskNumberRequest)
+	if err != nil {
+		return "", err
+	}
+	klog.V(4).InfoS("GetDeviceNameFromMount called", "diskNumber", getDiskNumberResponse.DiskNumber, "volumeID", resp.VolumeID, "mountPath", mountPath)
+	return fmt.Sprint(getDiskNumberResponse.DiskNumber), nil
+}
+
+func (mounter *CSIProxyMounterV2) MakeRShared(path string) error {
+	return fmt.Errorf("MakeRShared not implemented for CSIProxyMounter")
+}
+
+func (mounter *CSIProxyMounterV2) MakeFile(pathname string) error {
+	return fmt.Errorf("MakeFile not implemented for CSIProxyMounter")
+}
+
+// MakeDir - Creates a directory. The CSI proxy takes in context information.
+// Currently the make dir is only used from the staging code path, hence we call it
+// with Plugin context..
+func (mounter *CSIProxyMounterV2) MakeDir(pathname string) error {
+	mkdirReq := &fsv2.MkdirRequest{
+		Path: util.NormalizeWindowsPath(pathname),
+	}
+	_, err := mounter.FsClient.Mkdir(context.Background(), mkdirReq)
+	if err != nil {
+		klog.V(4).InfoS("Error", err)
+		return err
+	}
+
+	return nil
+}
+
+// ExistsPath - Checks if a path exists. Unlike util ExistsPath, this call does not perform follow link.
+func (mounter *CSIProxyMounterV2) ExistsPath(path string) (bool, error) {
+	isExistsResponse, err := mounter.FsClient.PathExists(context.Background(),
+		&fsv2.PathExistsRequest{
+			Path: util.NormalizeWindowsPath(path),
+		})
+	if err != nil {
+		return false, err
+	}
+	return isExistsResponse.Exists, err
+}
+
+func (mounter *CSIProxyMounterV2) EvalHostSymlinks(pathname string) (string, error) {
+	return "", fmt.Errorf("EvalHostSymlinks is not implemented for CSIProxyMounter")
+}
+
+func (mounter *CSIProxyMounterV2) GetMountRefs(pathname string) ([]string, error) {
+	return []string{}, fmt.Errorf("GetMountRefs is not implemented for CSIProxyMounter")
+}
+
+func (mounter *CSIProxyMounterV2) GetFSGroup(pathname string) (int64, error) {
+	return -1, fmt.Errorf("GetFSGroup is not implemented for CSIProxyMounter")
+}
+
+func (mounter *CSIProxyMounterV2) GetSELinuxSupport(pathname string) (bool, error) {
+	return false, fmt.Errorf("GetSELinuxSupport is not implemented for CSIProxyMounter")
+}
+
+func (mounter *CSIProxyMounterV2) GetMode(pathname string) (os.FileMode, error) {
+	return 0, fmt.Errorf("GetMode is not implemented for CSIProxyMounter")
+}
+
+func (mounter *CSIProxyMounterV2) MountSensitive(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
+	return fmt.Errorf("MountSensitive is not implemented for CSIProxyMounter")
+}
+
+func (mounter *CSIProxyMounterV2) MountSensitiveWithoutSystemd(source string, target string, fstype string, options []string, sensitiveOptions []string) error {
+	return fmt.Errorf("MountSensitiveWithoutSystemd is not implemented for CSIProxyMounter")
+}
+
+func (mounter *CSIProxyMounterV2) MountSensitiveWithoutSystemdWithMountFlags(source string, target string, fstype string, options []string, sensitiveOptions []string, mountFlags []string) error {
+	return fmt.Errorf("MountSensitiveWithoutSystemdWithMountFlags is not implemented for CSIProxyMounter")
+}
+
+// Rescan would trigger an update storage cache via the CSI proxy.
+func (mounter *CSIProxyMounterV2) Rescan() error {
+	// Call Rescan from disk APIs of CSI Proxy.
+	if _, err := mounter.DiskClient.Rescan(context.Background(), &diskv2.RescanRequest{}); err != nil {
+		return err
+	}
+	return nil
+}
+
+// FindDiskByLun - given a lun number, find out the corresponding disk
+func (mounter *CSIProxyMounterV2) FindDiskByLun(lun string) (diskNum string, err error) {
+	findDiskByLunResponse, err := mounter.DiskClient.ListDiskLocations(context.Background(), &diskv2.ListDiskLocationsRequest{})
+	if err != nil {
+		return "", err
+	}
+
+	// List all disk locations and match the lun id being requested for.
+	// If match is found then return back the disk number.
+	for diskID, location := range findDiskByLunResponse.DiskLocations {
+		if strings.EqualFold(location.LUNID, lun) {
+			return strconv.Itoa(int(diskID)), nil
+		}
+	}
+	return "", fmt.Errorf("could not find disk id for lun: %s", lun)
+}
+
+// FormatAndMount - accepts the source disk number, target path to mount, the fstype to format with and options to be used.
+func (mounter *CSIProxyMounterV2) FormatAndMountSensitiveWithFormatOptions(source string, target string, fstype string, options []string, sensitiveOptions []string, formatOptions []string) error {
+	// sensitiveOptions is not supported on Windows because we have no reasonable way to control what the csi-proxy does
+	if len(sensitiveOptions) > 0 {
+		return errors.New("sensitiveOptions not supported on Windows!")
+	}
+	// formatOptions is not supported on Windows because the csi-proxy does not allow supplying format arguments
+	// This limitation will be addressed in the future with privileged Windows containers
+	if len(formatOptions) > 0 {
+		return errors.New("formatOptions not supported on Windows!")
+	}
+
+	diskNumber, err := strconv.Atoi(source)
+	if err != nil {
+		return err
+	}
+
+	// Call PartitionDisk CSI proxy call to partition the disk and return the volume id
+	partionDiskRequest := &diskv2.PartitionDiskRequest{
+		DiskNumber: uint32(diskNumber),
+	}
+	_, err = mounter.DiskClient.PartitionDisk(context.Background(), partionDiskRequest)
+	if err != nil {
+		return err
+	}
+
+	// Ensure the disk is online before mounting.
+	setDiskStateRequest := &diskv2.SetDiskStateRequest{
+		DiskNumber: uint32(diskNumber),
+		IsOnline:   true,
+	}
+	_, err = mounter.DiskClient.SetDiskState(context.Background(), setDiskStateRequest)
+	if err != nil {
+		return err
+	}
+
+	// List the volumes on the given disk.
+	volumeIDsRequest := &volumev2.ListVolumesOnDiskRequest{
+		DiskNumber: uint32(diskNumber),
+	}
+	volumeIdResponse, err := mounter.VolumeClient.ListVolumesOnDisk(context.Background(), volumeIDsRequest)
+	if err != nil {
+		return err
+	}
+
+	// TODO: consider partitions and choose the right partition.
+	// For now just choose the first volume.
+	volumeID := volumeIdResponse.VolumeIDs[0]
+
+	// Check if the volume is formatted.
+	isVolumeFormattedRequest := &volumev2.IsVolumeFormattedRequest{
+		VolumeID: volumeID,
+	}
+	isVolumeFormattedResponse, err := mounter.VolumeClient.IsVolumeFormatted(context.Background(), isVolumeFormattedRequest)
+	if err != nil {
+		return err
+	}
+
+	// If the volume is not formatted, then format it, else proceed to mount.
+	if !isVolumeFormattedResponse.Formatted {
+		formatVolumeRequest := &volumev2.FormatVolumeRequest{
+			VolumeID: volumeID,
+			// TODO: Accept the filesystem and other options
+		}
+		_, err = mounter.VolumeClient.FormatVolume(context.Background(), formatVolumeRequest)
+		if err != nil {
+			return err
+		}
+	}
+
+	// Mount the volume by calling the CSI proxy call.
+	mountVolumeRequest := &volumev2.MountVolumeRequest{
+		VolumeID:   volumeID,
+		TargetPath: util.NormalizeWindowsPath(target),
+	}
+	_, err = mounter.VolumeClient.MountVolume(context.Background(), mountVolumeRequest)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// ResizeVolume resizes the volume at given mount path
+func (mounter *CSIProxyMounterV2) ResizeVolume(deviceMountPath string) (bool, error) {
+	// Find the volume id
+	getVolumeIdRequest := &volumev2.GetVolumeIDFromTargetPathRequest{
+		TargetPath: util.NormalizeWindowsPath(deviceMountPath),
+	}
+	volumeIdResponse, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), getVolumeIdRequest)
+	if err != nil {
+		return false, err
+	}
+	volumeId := volumeIdResponse.VolumeID
+
+	// Resize volume
+	resizeVolumeRequest := &volumev2.ResizeVolumeRequest{
+		VolumeID: volumeId,
+	}
+	_, err = mounter.VolumeClient.ResizeVolume(context.Background(), resizeVolumeRequest)
+	if err != nil {
+		return false, err
+	}
+
+	return true, nil
+}
+
+// GetVolumeSizeInBytes returns the size of the volume in bytes
+func (mounter *CSIProxyMounterV2) GetVolumeSizeInBytes(deviceMountPath string) (int64, error) {
+	// Find the volume id
+	getVolumeIdRequest := &volumev2.GetVolumeIDFromTargetPathRequest{
+		TargetPath: util.NormalizeWindowsPath(deviceMountPath),
+	}
+	volumeIdResponse, err := mounter.VolumeClient.GetVolumeIDFromTargetPath(context.Background(), getVolumeIdRequest)
+	if err != nil {
+		return -1, err
+	}
+	volumeId := volumeIdResponse.VolumeID
+
+	// Get size of the volume
+	getVolumeStatsRequest := &volumev2.GetVolumeStatsRequest{
+		VolumeID: volumeId,
+	}
+	resp, err := mounter.VolumeClient.GetVolumeStats(context.Background(), getVolumeStatsRequest)
+	if err != nil {
+		return -1, err
+	}
+
+	return resp.TotalBytes, nil
+}
+
+// GetDeviceSize returns the size of the disk in bytes
+func (mounter *CSIProxyMounterV2) GetDeviceSize(devicePath string) (int64, error) {
+	diskNumber, err := strconv.Atoi(devicePath)
+	if err != nil {
+		return -1, err
+	}
+
+	//Get size of the disk
+	getDiskStatsRequest := &diskv2.GetDiskStatsRequest{
+		DiskNumber: uint32(diskNumber),
+	}
+	resp, err := mounter.DiskClient.GetDiskStats(context.Background(), getDiskStatsRequest)
+	if err != nil {
+		return -1, err
+	}
+
+	return resp.TotalBytes, nil
+}
+
+func (mounter *CSIProxyMounterV2) CanSafelySkipMountPointCheck() bool {
+	return false
+}
+
+func (mounter *CSIProxyMounterV2) FindDevicePath(devicePath, volumeID, _, _ string) (string, error) {
+	response, err := mounter.DiskClient.ListDiskIDs(context.TODO(), &diskv2.ListDiskIDsRequest{})
+	if err != nil {
+		return "", fmt.Errorf("error listing disk ids: %q", err)
+	}
+
+	diskIDs := response.DiskIDs
+
+	foundDiskNumber := ""
+	for diskNumber, diskID := range diskIDs {
+		serialNumber := diskID.SerialNumber
+		cleanVolumeID := strings.ReplaceAll(volumeID, "-", "")
+		if strings.Contains(serialNumber, cleanVolumeID) {
+			foundDiskNumber = strconv.Itoa(int(diskNumber))
+			break
+		}
+	}
+
+	if foundDiskNumber == "" {
+		return "", fmt.Errorf("disk number for device path %q volume id %q not found", devicePath, volumeID)
+	}
+
+	return foundDiskNumber, nil
+}
diff --git a/pkg/mounter/safe_mounter.go b/pkg/mounter/safe_mounter.go
deleted file mode 100644
index 215047b0..00000000
--- a/pkg/mounter/safe_mounter.go
+++ /dev/null
@@ -1,32 +0,0 @@
-//go:build linux || darwin
-// +build linux darwin
-
-/*
-Copyright 2020 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package mounter
-
-import (
-	"k8s.io/mount-utils"
-	utilexec "k8s.io/utils/exec"
-)
-
-func NewSafeMounter() (*mount.SafeFormatAndMount, error) {
-	return &mount.SafeFormatAndMount{
-		Interface: mount.New(""),
-		Exec:      utilexec.New(),
-	}, nil
-}
diff --git a/pkg/util/util.go b/pkg/util/util.go
index fcaae443..488b8396 100644
--- a/pkg/util/util.go
+++ b/pkg/util/util.go
@@ -23,13 +23,15 @@ import (
 	"os"
 	"path/filepath"
 	"regexp"
+	"runtime"
 	"strings"
 
 	csi "github.com/container-storage-interface/spec/lib/go/csi"
 )
 
 const (
-	GiB = int64(1024 * 1024 * 1024)
+	GiB              = int64(1024 * 1024 * 1024)
+	DefaultBlockSize = 4096
 )
 
 var (
@@ -66,7 +68,26 @@ func GiBToBytes(volumeSizeGiB int32) int64 {
 	return int64(volumeSizeGiB) * GiB
 }
 
-func ParseEndpoint(endpoint string) (string, string, error) {
+func ParseEndpoint(endpoint string, hostprocess bool) (string, string, error) {
+	if runtime.GOOS == "windows" && hostprocess {
+		parts := strings.SplitN(endpoint, "://", 2)
+		if len(parts) != 2 {
+			return "", "", fmt.Errorf("invalid endpoint format: %s", endpoint)
+		}
+		scheme := strings.ToLower(parts[0])
+		addr := parts[1]
+
+		// Remove the socket file if it already exists
+		if scheme == "unix" {
+			if _, err := os.Stat(addr); err == nil {
+				if err := os.Remove(addr); err != nil {
+					return "", "", fmt.Errorf("failed to remove existing socket file: %w", err)
+				}
+			}
+		}
+		return scheme, addr, nil
+	}
+
 	u, err := url.Parse(endpoint)
 	if err != nil {
 		return "", "", fmt.Errorf("could not parse endpoint: %w", err)
@@ -114,3 +135,12 @@ func IsSBE(region string) bool {
 func StringIsAlphanumeric(s string) bool {
 	return isAlphanumericRegex(s)
 }
+
+// NormalizeWindowsPath normalizes a Windows path
+func NormalizeWindowsPath(path string) string {
+	normalizedPath := strings.Replace(path, "/", "\\", -1)
+	if strings.HasPrefix(normalizedPath, "\\") {
+		normalizedPath = "c:" + normalizedPath
+	}
+	return normalizedPath
+}


Test patch:
diff --git a/charts/aws-ebs-csi-driver/templates/tests/helm-tester.yaml b/charts/aws-ebs-csi-driver/templates/tests/helm-tester.yaml
index e5b843b0..16a5bf92 100644
--- a/charts/aws-ebs-csi-driver/templates/tests/helm-tester.yaml
+++ b/charts/aws-ebs-csi-driver/templates/tests/helm-tester.yaml
@@ -214,14 +214,11 @@ spec:
           kubectl config set-context kubetest2 --cluster=cluster
           kubectl config set-credentials sa --token=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
           kubectl config set-context kubetest2 --user=sa && kubectl config use-context kubetest2
-          export FOCUS_REGEX='\bebs.csi.aws.com\b.+(validate content|resize volume|offline PVC|AllowedTopologies|store data'
+          export FOCUS_REGEX='\bebs.csi.aws.com\b.+(validate content|resize volume|offline PVC|AllowedTopologies|store data$SNAPSHOTS)'
           if kubectl get crd volumesnapshots.snapshot.storage.k8s.io; then
-            FOCUS_REGEX="${FOCUS_REGEX}|snapshot fields)"
-          else
-            FOCUS_REGEX="${FOCUS_REGEX})"
+            FORCUS_REGEX="${FOCUS_REGEX}|snapshot fields"
           fi
-          export KUBE_VERSION=$(kubectl version --output json | jq -r '.serverVersion.major + "." + .serverVersion.minor')
-          kubetest2 noop --run-id='e2e-kubernetes' --test=ginkgo -- --test-package-version="$(curl -L https://dl.k8s.io/release/stable-${KUBE_VERSION}.txt)" --skip-regex='[Disruptive]|[Serial]' --focus-regex="$FOCUS_REGEX" --parallel=25 --test-args='-storage.testdriver=/etc/config/manifests.yaml'
+          kubetest2 noop --run-id='e2e-kubernetes' --test=ginkgo -- --test-package-version="$(curl -L https://dl.k8s.io/release/stable-1.29.txt)" --skip-regex='[Disruptive]|[Serial]' --focus-regex="$FOCUS_REGEX" --parallel=25 --test-args='-storage.testdriver=/etc/config/manifests.yaml'
       volumeMounts:
       - name: config-vol
         mountPath: /etc/config
diff --git a/hack/e2e/run.sh b/hack/e2e/run.sh
index 8aa987d3..c889c52d 100755
--- a/hack/e2e/run.sh
+++ b/hack/e2e/run.sh
@@ -83,6 +83,7 @@ if [[ "${HELM_CT_TEST}" != true ]]; then
       --set image.repository="${IMAGE_NAME}"
       --set image.tag="${IMAGE_TAG}"
       --set node.enableWindows="${WINDOWS}"
+      --set node.windowsHostProcess="${WINDOWS_HOSTPROCESS}"
       --set=controller.k8sTagClusterId="${CLUSTER_NAME}"
       --timeout 10m0s
       --wait
diff --git a/hack/prow-e2e.sh b/hack/prow-e2e.sh
index 5923f2b7..4487ab23 100755
--- a/hack/prow-e2e.sh
+++ b/hack/prow-e2e.sh
@@ -42,6 +42,12 @@ test-e2e-external-eks-windows)
   export CLUSTER_TYPE="eksctl"
   export WINDOWS="true"
   ;;
+test-e2e-external-windows-hostprocess)
+  TEST="external-windows-hostprocess"
+  export CLUSTER_TYPE="eksctl"
+  export WINDOWS="true"
+  export WINDOWS_HOSTPROCESS="true"
+  ;;
 test-e2e-external-kustomize)
   TEST="external-kustomize"
   ;;
diff --git a/pkg/cloud/cloud_test.go b/pkg/cloud/cloud_test.go
index 65fd1cee..48f11f42 100644
--- a/pkg/cloud/cloud_test.go
+++ b/pkg/cloud/cloud_test.go
@@ -1216,7 +1216,7 @@ func TestCreateDisk(t *testing.T) {
 			defer ctxCancel()
 
 			if tc.expCreateVolumeInput != nil {
-				mockEC2.EXPECT().CreateVolume(gomock.Any(), gomock.Any(), gomock.Any()).Return(&ec2.CreateVolumeOutput{
+				mockEC2.EXPECT().CreateVolume(gomock.Any(), gomock.Any()).Return(&ec2.CreateVolumeOutput{
 					VolumeId:   aws.String(tc.diskOptions.Tags[VolumeNameTagKey]),
 					Size:       aws.Int32(util.BytesToGiB(tc.diskOptions.CapacityBytes)),
 					OutpostArn: aws.String(tc.diskOptions.OutpostArn),
@@ -1234,7 +1234,7 @@ func TestCreateDisk(t *testing.T) {
 				}, tc.expDescVolumeErr).AnyTimes()
 				if tc.diskOptions.AvailabilityZone == "snow" {
 					mockEC2.EXPECT().CreateTags(gomock.Any(), gomock.Any()).Return(&ec2.CreateTagsOutput{}, tc.expCreateTagsErr)
-					mockEC2.EXPECT().DeleteVolume(gomock.Any(), gomock.Any(), gomock.Any()).Return(&ec2.DeleteVolumeOutput{}, nil).AnyTimes()
+					mockEC2.EXPECT().DeleteVolume(gomock.Any(), gomock.Any()).Return(&ec2.DeleteVolumeOutput{}, nil).AnyTimes()
 				}
 				if len(tc.diskOptions.SnapshotID) > 0 {
 					mockEC2.EXPECT().DescribeSnapshots(gomock.Any(), gomock.Any()).Return(&ec2.DescribeSnapshotsOutput{Snapshots: []types.Snapshot{snapshot}}, nil).AnyTimes()
@@ -1313,7 +1313,7 @@ func TestDeleteDisk(t *testing.T) {
 			c := newCloud(mockEC2)
 
 			ctx := context.Background()
-			mockEC2.EXPECT().DeleteVolume(gomock.Any(), gomock.Any(), gomock.Any()).Return(&ec2.DeleteVolumeOutput{}, tc.expErr)
+			mockEC2.EXPECT().DeleteVolume(gomock.Any(), gomock.Any()).Return(&ec2.DeleteVolumeOutput{}, tc.expErr)
 
 			ok, err := c.DeleteDisk(ctx, tc.volumeID)
 			if err != nil && tc.expErr == nil {
@@ -1362,7 +1362,7 @@ func TestAttachDisk(t *testing.T) {
 
 				gomock.InOrder(
 					mockEC2.EXPECT().DescribeInstances(gomock.Any(), gomock.Eq(instanceRequest)).Return(newDescribeInstancesOutput(nodeID), nil),
-					mockEC2.EXPECT().AttachVolume(gomock.Any(), gomock.Eq(attachRequest), gomock.Any()).Return(&ec2.AttachVolumeOutput{
+					mockEC2.EXPECT().AttachVolume(gomock.Any(), gomock.Eq(attachRequest)).Return(&ec2.AttachVolumeOutput{
 						Device:     aws.String(path),
 						InstanceId: aws.String(nodeID),
 						VolumeId:   aws.String(volumeID),
@@ -1385,7 +1385,7 @@ func TestAttachDisk(t *testing.T) {
 
 				gomock.InOrder(
 					mockEC2.EXPECT().DescribeInstances(gomock.Any(), gomock.Eq(instanceRequest)).Return(newDescribeInstancesOutput(nodeID), nil),
-					mockEC2.EXPECT().AttachVolume(gomock.Any(), gomock.Eq(attachRequest), gomock.Any()).Return(&ec2.AttachVolumeOutput{
+					mockEC2.EXPECT().AttachVolume(gomock.Any(), gomock.Eq(attachRequest)).Return(&ec2.AttachVolumeOutput{
 						Device:     aws.String(path),
 						InstanceId: aws.String(nodeID),
 						VolumeId:   aws.String(volumeID),
@@ -1435,7 +1435,7 @@ func TestAttachDisk(t *testing.T) {
 
 				gomock.InOrder(
 					mockEC2.EXPECT().DescribeInstances(gomock.Any(), instanceRequest).Return(newDescribeInstancesOutput(nodeID), nil),
-					mockEC2.EXPECT().AttachVolume(gomock.Any(), attachRequest, gomock.Any()).Return(nil, errors.New("AttachVolume error")),
+					mockEC2.EXPECT().AttachVolume(gomock.Any(), attachRequest).Return(nil, errors.New("AttachVolume error")),
 				)
 			},
 			validateFunc: func(t *testing.T) {
@@ -1454,7 +1454,7 @@ func TestAttachDisk(t *testing.T) {
 
 				gomock.InOrder(
 					mockEC2.EXPECT().DescribeInstances(ctx, instanceRequest).Return(newDescribeInstancesOutput(nodeID), nil),
-					mockEC2.EXPECT().AttachVolume(ctx, attachRequest, gomock.Any()).Return(nil, blockDeviceInUseErr),
+					mockEC2.EXPECT().AttachVolume(ctx, attachRequest).Return(nil, blockDeviceInUseErr),
 				)
 			},
 			validateFunc: func(t *testing.T) {
@@ -1500,7 +1500,7 @@ func TestAttachDisk(t *testing.T) {
 
 				gomock.InOrder(
 					mockEC2.EXPECT().DescribeInstances(ctx, gomock.Eq(instanceRequest)).Return(newDescribeInstancesOutput(nodeID), nil),
-					mockEC2.EXPECT().AttachVolume(ctx, gomock.Eq(attachRequest), gomock.Any()).Return(&ec2.AttachVolumeOutput{
+					mockEC2.EXPECT().AttachVolume(ctx, gomock.Eq(attachRequest)).Return(&ec2.AttachVolumeOutput{
 						Device:     aws.String(path),
 						InstanceId: aws.String(nodeID),
 						VolumeId:   aws.String(volumeID),
@@ -1509,7 +1509,7 @@ func TestAttachDisk(t *testing.T) {
 					mockEC2.EXPECT().DescribeVolumes(ctx, gomock.Eq(volumeRequest)).Return(createDescribeVolumesOutput([]*string{&volumeID}, nodeID, path, "attached"), nil),
 
 					mockEC2.EXPECT().DescribeInstances(ctx, gomock.Eq(createInstanceRequest2)).Return(newDescribeInstancesOutput(nodeID2), nil),
-					mockEC2.EXPECT().AttachVolume(ctx, gomock.Eq(attachRequest2), gomock.Any()).Return(&ec2.AttachVolumeOutput{
+					mockEC2.EXPECT().AttachVolume(ctx, gomock.Eq(attachRequest2)).Return(&ec2.AttachVolumeOutput{
 						Device:     aws.String(path),
 						InstanceId: aws.String(nodeID2),
 						VolumeId:   aws.String(volumeID),
@@ -1580,7 +1580,7 @@ func TestDetachDisk(t *testing.T) {
 
 				gomock.InOrder(
 					mockEC2.EXPECT().DescribeInstances(gomock.Any(), instanceRequest).Return(newDescribeInstancesOutput(nodeID), nil),
-					mockEC2.EXPECT().DetachVolume(gomock.Any(), detachRequest, gomock.Any()).Return(nil, nil),
+					mockEC2.EXPECT().DetachVolume(gomock.Any(), detachRequest).Return(nil, nil),
 					mockEC2.EXPECT().DescribeVolumes(gomock.Any(), volumeRequest).Return(createDescribeVolumesOutput([]*string{&volumeID}, nodeID, "", "detached"), nil),
 				)
 			},
@@ -1596,7 +1596,7 @@ func TestDetachDisk(t *testing.T) {
 
 				gomock.InOrder(
 					mockEC2.EXPECT().DescribeInstances(gomock.Any(), instanceRequest).Return(newDescribeInstancesOutput(nodeID), nil),
-					mockEC2.EXPECT().DetachVolume(gomock.Any(), detachRequest, gomock.Any()).Return(nil, errors.New("DetachVolume error")),
+					mockEC2.EXPECT().DetachVolume(gomock.Any(), detachRequest).Return(nil, errors.New("DetachVolume error")),
 				)
 			},
 		},
@@ -1611,7 +1611,7 @@ func TestDetachDisk(t *testing.T) {
 
 				gomock.InOrder(
 					mockEC2.EXPECT().DescribeInstances(gomock.Any(), instanceRequest).Return(newDescribeInstancesOutput(nodeID), nil),
-					mockEC2.EXPECT().DetachVolume(gomock.Any(), detachRequest, gomock.Any()).Return(nil, ErrNotFound),
+					mockEC2.EXPECT().DetachVolume(gomock.Any(), detachRequest).Return(nil, ErrNotFound),
 				)
 			},
 		},
@@ -1984,7 +1984,7 @@ func TestEnableFastSnapshotRestores(t *testing.T) {
 			c := newCloud(mockEC2)
 
 			ctx := context.Background()
-			mockEC2.EXPECT().EnableFastSnapshotRestores(gomock.Any(), gomock.Any(), gomock.Any()).Return(tc.expOutput, tc.expErr).AnyTimes()
+			mockEC2.EXPECT().EnableFastSnapshotRestores(gomock.Any(), gomock.Any()).Return(tc.expOutput, tc.expErr).AnyTimes()
 
 			response, err := c.EnableFastSnapshotRestores(ctx, tc.availabilityZones, tc.snapshotID)
 
@@ -2101,7 +2101,7 @@ func TestDeleteSnapshot(t *testing.T) {
 			c := newCloud(mockEC2)
 
 			ctx := context.Background()
-			mockEC2.EXPECT().DeleteSnapshot(gomock.Any(), gomock.Any(), gomock.Any()).Return(&ec2.DeleteSnapshotOutput{}, tc.expErr)
+			mockEC2.EXPECT().DeleteSnapshot(gomock.Any(), gomock.Any()).Return(&ec2.DeleteSnapshotOutput{}, tc.expErr)
 
 			_, err := c.DeleteSnapshot(ctx, tc.snapshotName)
 			if err != nil {
@@ -2425,13 +2425,13 @@ func TestResizeOrModifyDisk(t *testing.T) {
 				}
 			}
 			if tc.modifiedVolume != nil || tc.modifiedVolumeError != nil {
-				mockEC2.EXPECT().ModifyVolume(gomock.Any(), gomock.Any(), gomock.Any()).Return(tc.modifiedVolume, tc.modifiedVolumeError).AnyTimes()
+				mockEC2.EXPECT().ModifyVolume(gomock.Any(), gomock.Any()).Return(tc.modifiedVolume, tc.modifiedVolumeError).AnyTimes()
 			}
 			if tc.descModVolume != nil {
-				mockEC2.EXPECT().DescribeVolumesModifications(gomock.Any(), gomock.Any(), gomock.Any()).Return(tc.descModVolume, nil).AnyTimes()
+				mockEC2.EXPECT().DescribeVolumesModifications(gomock.Any(), gomock.Any()).Return(tc.descModVolume, nil).AnyTimes()
 			} else {
 				emptyOutput := &ec2.DescribeVolumesModificationsOutput{}
-				mockEC2.EXPECT().DescribeVolumesModifications(gomock.Any(), gomock.Any(), gomock.Any()).Return(emptyOutput, nil).AnyTimes()
+				mockEC2.EXPECT().DescribeVolumesModifications(gomock.Any(), gomock.Any()).Return(emptyOutput, nil).AnyTimes()
 			}
 
 			newSize, err := c.ResizeOrModifyDisk(ctx, tc.volumeID, util.GiBToBytes(tc.reqSizeGiB), tc.modifyDiskOptions)
@@ -3077,7 +3077,6 @@ func newCloud(mockEC2 EC2API) Cloud {
 		region: "test-region",
 		dm:     dm.NewDeviceManager(),
 		ec2:    mockEC2,
-		rm:     newRetryManager(),
 	}
 	return c
 }
diff --git a/pkg/driver/options_test.go b/pkg/driver/options_test.go
index 2c1d1c9e..c5fc111a 100644
--- a/pkg/driver/options_test.go
+++ b/pkg/driver/options_test.go
@@ -20,12 +20,6 @@ func TestAddFlags(t *testing.T) {
 	if err := f.Set("http-endpoint", ":8080"); err != nil {
 		t.Errorf("error setting http-endpoint: %v", err)
 	}
-	if err := f.Set("metrics-cert-file", "/https.crt"); err != nil {
-		t.Errorf("error setting metrics-cert-file: %v", err)
-	}
-	if err := f.Set("metrics-key-file", "/https.key"); err != nil {
-		t.Errorf("error setting metrics-key-file: %v", err)
-	}
 	if err := f.Set("enable-otel-tracing", "true"); err != nil {
 		t.Errorf("error setting enable-otel-tracing: %v", err)
 	}
@@ -95,7 +89,7 @@ func TestAddFlags(t *testing.T) {
 	}
 }
 
-func TestValidateAttachmentLimits(t *testing.T) {
+func TestValidate(t *testing.T) {
 	tests := []struct {
 		name                string
 		volumeAttachLimit   int64
@@ -133,7 +127,6 @@ func TestValidateAttachmentLimits(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			o := &Options{
-				Mode:                      NodeMode,
 				VolumeAttachLimit:         tt.volumeAttachLimit,
 				ReservedVolumeAttachments: tt.reservedAttachments,
 			}
@@ -149,61 +142,3 @@ func TestValidateAttachmentLimits(t *testing.T) {
 		})
 	}
 }
-
-func TestValidateMetricsHTTPS(t *testing.T) {
-	tests := []struct {
-		name            string
-		httpEndpoint    string
-		metricsCertFile string
-		metricsKeyFile  string
-		expectError     bool
-	}{
-		{
-			name: "disabled",
-		},
-		{
-			name:         "only http",
-			httpEndpoint: ":8080",
-		},
-		{
-			name:            "https with all",
-			httpEndpoint:    ":443",
-			metricsCertFile: "/https.crt",
-			metricsKeyFile:  "/https.key",
-		},
-		{
-			name:            "https with endpoint missing",
-			metricsCertFile: "/https.crt",
-			metricsKeyFile:  "/https.key",
-			expectError:     true,
-		},
-		{
-			name:           "https with cert missing",
-			httpEndpoint:   ":443",
-			metricsKeyFile: "/https.key",
-			expectError:    true,
-		},
-		{
-			name:            "https with key missing",
-			httpEndpoint:    ":443",
-			metricsCertFile: "/https.crt",
-			expectError:     true,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			o := &Options{
-				Mode:            ControllerMode,
-				HttpEndpoint:    tt.httpEndpoint,
-				MetricsCertFile: tt.metricsCertFile,
-				MetricsKeyFile:  tt.metricsKeyFile,
-			}
-
-			err := o.Validate()
-			if (err != nil) != tt.expectError {
-				t.Errorf("Options.Validate() error = %v, wantErr %v", err, tt.expectError)
-			}
-		})
-	}
-}
diff --git a/pkg/mounter/mount_test.go b/pkg/mounter/mount_linux_test.go
similarity index 98%
rename from pkg/mounter/mount_test.go
rename to pkg/mounter/mount_linux_test.go
index 0e9c3b34..c3682664 100644
--- a/pkg/mounter/mount_test.go
+++ b/pkg/mounter/mount_linux_test.go
@@ -94,7 +94,7 @@ func TestMakeDir(t *testing.T) {
 
 	targetPath := filepath.Join(dir, "targetdir")
 
-	mountObj, err := NewNodeMounter()
+	mountObj, err := NewNodeMounter(false)
 	if err != nil {
 		t.Fatalf("error creating mounter %v", err)
 	}
@@ -122,7 +122,7 @@ func TestMakeFile(t *testing.T) {
 
 	targetPath := filepath.Join(dir, "targetfile")
 
-	mountObj, err := NewNodeMounter()
+	mountObj, err := NewNodeMounter(false)
 	if err != nil {
 		t.Fatalf("error creating mounter %v", err)
 	}
@@ -151,7 +151,7 @@ func TestPathExists(t *testing.T) {
 
 	targetPath := filepath.Join(dir, "notafile")
 
-	mountObj, err := NewNodeMounter()
+	mountObj, err := NewNodeMounter(false)
 	if err != nil {
 		t.Fatalf("error creating mounter %v", err)
 	}
@@ -178,7 +178,7 @@ func TestGetDeviceName(t *testing.T) {
 
 	targetPath := filepath.Join(dir, "notafile")
 
-	mountObj, err := NewNodeMounter()
+	mountObj, err := NewNodeMounter(false)
 	if err != nil {
 		t.Fatalf("error creating mounter %v", err)
 	}
diff --git a/pkg/mounter/safe_mounter_test.go b/pkg/mounter/safe_mounter_test.go
deleted file mode 100644
index 3b7dfc7e..00000000
--- a/pkg/mounter/safe_mounter_test.go
+++ /dev/null
@@ -1,33 +0,0 @@
-//go:build linux
-// +build linux
-
-/*
-Copyright 2020 The Kubernetes Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package mounter
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-)
-
-func TestNewSafeMounter(t *testing.T) {
-	resp, err := NewSafeMounter()
-	assert.NotNil(t, resp)
-	require.NoError(t, err)
-}
diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go
index 096446bf..d2f5d1f0 100644
--- a/pkg/util/util_test.go
+++ b/pkg/util/util_test.go
@@ -113,7 +113,7 @@ func TestParseEndpoint(t *testing.T) {
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
-			scheme, addr, err := ParseEndpoint(tc.endpoint)
+			scheme, addr, err := ParseEndpoint(tc.endpoint, false)
 
 			if tc.expErr != nil {
 				if err.Error() != tc.expErr.Error() {
diff --git a/tests/e2e/testsuites/testsuites.go b/tests/e2e/testsuites/testsuites.go
index d4ac74fe..c148111b 100644
--- a/tests/e2e/testsuites/testsuites.go
+++ b/tests/e2e/testsuites/testsuites.go
@@ -658,7 +658,7 @@ func (t *TestPod) Create() {
 }
 
 func (t *TestPod) WaitForSuccess() {
-	err := e2epod.WaitForPodSuccessInNamespace(context.Background(), t.client, t.pod.Name, t.namespace.Name)
+	err := e2epod.WaitForPodSuccessInNamespaceSlow(context.Background(), t.client, t.pod.Name, t.namespace.Name)
 	framework.ExpectNoError(err)
 }
 
@@ -668,7 +668,7 @@ func (t *TestPod) WaitForRunning() {
 }
 
 // Ideally this would be in "k8s.io/kubernetes/test/e2e/framework"
-// Similar to framework.WaitForPodSuccessInNamespace
+// Similar to framework.WaitForPodSuccessInNamespaceSlow
 var podFailedCondition = func(pod *v1.Pod) (bool, error) {
 	switch pod.Status.Phase {
 	case v1.PodFailed: