From ce5a2a09d7111b0e3d45b07e69741d5737fbeec7 Mon Sep 17 00:00:00 2001
From: Tobi Nehrlich <tobi@anothertobi.io>
Date: Sun, 23 Apr 2023 00:20:49 +0200
Subject: [PATCH] Add ReadWriteOncePod support for NodePath volumes

This explicitly allows provisioning of NodePath-backed volumes with
access mode ReadWriteOncePod.

SharedFileSystemPath already implicitly supported the access mode.

Signed-off-by: Tobi Nehrlich <tobi@anothertobi.io>
---
 .../pod-with-rwop-volume/kustomization.yaml    |  5 +++++
 examples/pod-with-rwop-volume/pod.yaml         | 18 ++++++++++++++++++
 .../kustomization.yaml                         |  4 ++++
 examples/pvc-with-rwop-access-mode/pvc.yaml    | 13 +++++++++++++
 provisioner.go                                 |  4 ++--
 test/pod_test.go                               |  6 ++++++
 .../pod-with-rwop-volume/kustomization.yaml    | 10 ++++++++++
 7 files changed, 58 insertions(+), 2 deletions(-)
 create mode 100644 examples/pod-with-rwop-volume/kustomization.yaml
 create mode 100644 examples/pod-with-rwop-volume/pod.yaml
 create mode 100644 examples/pvc-with-rwop-access-mode/kustomization.yaml
 create mode 100644 examples/pvc-with-rwop-access-mode/pvc.yaml
 create mode 100644 test/testdata/pod-with-rwop-volume/kustomization.yaml

diff --git a/examples/pod-with-rwop-volume/kustomization.yaml b/examples/pod-with-rwop-volume/kustomization.yaml
new file mode 100644
index 00000000..9a737779
--- /dev/null
+++ b/examples/pod-with-rwop-volume/kustomization.yaml
@@ -0,0 +1,5 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- ../pvc-with-rwop-access-mode
+- pod.yaml
diff --git a/examples/pod-with-rwop-volume/pod.yaml b/examples/pod-with-rwop-volume/pod.yaml
new file mode 100644
index 00000000..20300859
--- /dev/null
+++ b/examples/pod-with-rwop-volume/pod.yaml
@@ -0,0 +1,18 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: volume-test
+spec:
+  containers:
+  - name: volume-test
+    image: nginx:stable-alpine
+    imagePullPolicy: IfNotPresent
+    volumeMounts:
+    - name: volv
+      mountPath: /data
+    ports:
+    - containerPort: 80
+  volumes:
+  - name: volv
+    persistentVolumeClaim:
+      claimName: local-rwop-volume-pvc
diff --git a/examples/pvc-with-rwop-access-mode/kustomization.yaml b/examples/pvc-with-rwop-access-mode/kustomization.yaml
new file mode 100644
index 00000000..7bfd4518
--- /dev/null
+++ b/examples/pvc-with-rwop-access-mode/kustomization.yaml
@@ -0,0 +1,4 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- pvc.yaml
diff --git a/examples/pvc-with-rwop-access-mode/pvc.yaml b/examples/pvc-with-rwop-access-mode/pvc.yaml
new file mode 100644
index 00000000..25ad8bef
--- /dev/null
+++ b/examples/pvc-with-rwop-access-mode/pvc.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: local-rwop-volume-pvc
+  annotations:
+    volumeType: local
+spec:
+  accessModes:
+    - ReadWriteOncePod
+  storageClassName: local-path
+  resources:
+    requests:
+      storage: 128Mi
diff --git a/provisioner.go b/provisioner.go
index 42297d48..8f13467d 100644
--- a/provisioner.go
+++ b/provisioner.go
@@ -255,8 +255,8 @@ func (p *LocalPathProvisioner) Provision(ctx context.Context, opts pvController.
 			return nil, pvController.ProvisioningFinished, fmt.Errorf("claim.Spec.Selector is not supported")
 		}
 		for _, accessMode := range pvc.Spec.AccessModes {
-			if accessMode != v1.ReadWriteOnce {
-				return nil, pvController.ProvisioningFinished, fmt.Errorf("Only support ReadWriteOnce access mode")
+			if accessMode != v1.ReadWriteOnce && accessMode != v1.ReadWriteOncePod {
+				return nil, pvController.ProvisioningFinished, fmt.Errorf("NodePath only supports ReadWriteOnce and ReadWriteOncePod (1.22+) access modes")
 			}
 		}
 		if node == nil {
diff --git a/test/pod_test.go b/test/pod_test.go
index 6e78d2e6..5f0b0b3a 100644
--- a/test/pod_test.go
+++ b/test/pod_test.go
@@ -102,6 +102,12 @@ func (p *PodTestSuite) TestPodWithNodeAffinity() {
 	runTest(p, []string{p.config.IMAGE}, "ready", hostPathVolumeType)
 }
 
+func (p *PodTestSuite) TestPodWithRWOPVolume() {
+	p.kustomizeDir = "pod-with-rwop-volume"
+
+	runTest(p, []string{p.config.IMAGE}, "ready", localVolumeType)
+}
+
 func (p *PodTestSuite) TestPodWithSecurityContext() {
 	p.kustomizeDir = "pod-with-security-context"
 	kustomizeDir := testdataFile(p.kustomizeDir)
diff --git a/test/testdata/pod-with-rwop-volume/kustomization.yaml b/test/testdata/pod-with-rwop-volume/kustomization.yaml
new file mode 100644
index 00000000..d650c985
--- /dev/null
+++ b/test/testdata/pod-with-rwop-volume/kustomization.yaml
@@ -0,0 +1,10 @@
+apiVersion: kustomize.config.k8s.io/v1beta1
+kind: Kustomization
+resources:
+- ../../../deploy
+- ../../../examples/pod-with-rwop-volume
+commonLabels:
+  app: local-path-provisioner
+images:
+- name: rancher/local-path-provisioner
+  newTag: dev
-- 
GitLab