Repository: kubernetes-csi/external-provisioner (go)

Issue:
Support  secret in NodeExpansion Call.
In different use cases we need "secret" passed to the CSI driver to perform NodeExpansion which is missing atm . One of the very visible use case is that, the expansion on LUKS enabled device, which needs the passphrase in order to resize the device on the node.

One other use case is that, at times we need to check the actual size of the image ( for ex: RBD image size in Ceph Cluster) before proceeding on FS resize to avoid false positive returns on fs resize operation. For that we have to connect to the backend cluster which need secret in the request.

Reference#
CSI spec issue # container-storage-interface/spec#445
CSI spec PR # container-storage-interface/spec#457
k/k issue # https://github.com/kubernetes/kubernetes/issues/95367

Pull request description:
feat: Support secret in NodeExpansion Call
**What type of PR is this?**
/kind feature


**What this PR does / why we need it**:
Support secret in NodeExpansion Call

**Which issue(s) this PR fixes**:
Fixes #499 

**Special notes for your reviewer**:

**Does this PR introduce a user-facing change?**:
```release-note
This release add the support for  CSINodeExpandSecret feature (https://github.com/kubernetes/enhancements/issues/3107). The CSI drivers can make use of the secret as part of the nodeExpandVolume RPC call from now onwards.
```


Patch:
diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go
index 6437bf07e..fb6d6e2e2 100644
--- a/pkg/controller/controller.go
+++ b/pkg/controller/controller.go
@@ -95,6 +95,9 @@ const (
 	prefixedControllerExpandSecretNameKey      = csiParameterPrefix + "controller-expand-secret-name"
 	prefixedControllerExpandSecretNamespaceKey = csiParameterPrefix + "controller-expand-secret-namespace"
 
+	prefixedNodeExpandSecretNameKey      = csiParameterPrefix + "node-expand-secret-name"
+	prefixedNodeExpandSecretNamespaceKey = csiParameterPrefix + "node-expand-secret-namespace"
+
 	// [Deprecated] CSI Parameters that are put into fields but
 	// NOT stripped from the parameters passed to CreateVolume
 	provisionerSecretNameKey      = "csiProvisionerSecretName"
@@ -188,6 +191,12 @@ var (
 		secretNameKey:      prefixedControllerExpandSecretNameKey,
 		secretNamespaceKey: prefixedControllerExpandSecretNamespaceKey,
 	}
+
+	nodeExpandSecretParams = secretParamsMap{
+		name:               "NodeExpand",
+		secretNameKey:      prefixedNodeExpandSecretNameKey,
+		secretNamespaceKey: prefixedNodeExpandSecretNamespaceKey,
+	}
 )
 
 // ProvisionerCSITranslator contains the set of CSI Translation functionality
@@ -687,6 +696,10 @@ func (p *csiProvisioner) prepareProvision(ctx context.Context, claim *v1.Persist
 	if err != nil {
 		return nil, controller.ProvisioningNoChange, err
 	}
+	nodeExpandSecretRef, err := getSecretReference(nodeExpandSecretParams, sc.Parameters, pvName, claim)
+	if err != nil {
+		return nil, controller.ProvisioningNoChange, err
+	}
 	csiPVSource := &v1.CSIPersistentVolumeSource{
 		Driver: p.driverName,
 		// VolumeHandle and VolumeAttributes will be added after provisioning.
@@ -694,6 +707,7 @@ func (p *csiProvisioner) prepareProvision(ctx context.Context, claim *v1.Persist
 		NodeStageSecretRef:         nodeStageSecretRef,
 		NodePublishSecretRef:       nodePublishSecretRef,
 		ControllerExpandSecretRef:  controllerExpandSecretRef,
+		NodeExpandSecretRef:        nodeExpandSecretRef,
 	}
 
 	req.Parameters, err = removePrefixedParameters(sc.Parameters)
@@ -947,6 +961,8 @@ func removePrefixedParameters(param map[string]string) (map[string]string, error
 			case prefixedControllerExpandSecretNamespaceKey:
 			case prefixedDefaultSecretNameKey:
 			case prefixedDefaultSecretNamespaceKey:
+			case prefixedNodeExpandSecretNameKey:
+			case prefixedNodeExpandSecretNamespaceKey:
 			default:
 				return map[string]string{}, fmt.Errorf("found unknown parameter key \"%s\" with reserved namespace %s", k, csiParameterPrefix)
 			}


Test patch:
diff --git a/pkg/controller/controller_test.go b/pkg/controller/controller_test.go
index 6efc1415d..ce3632365 100644
--- a/pkg/controller/controller_test.go
+++ b/pkg/controller/controller_test.go
@@ -226,6 +226,8 @@ func TestStripPrefixedCSIParams(t *testing.T) {
 				prefixedControllerExpandSecretNamespaceKey:  "csiBar",
 				prefixedDefaultSecretNameKey:                "csiBar",
 				prefixedDefaultSecretNamespaceKey:           "csiBar",
+				prefixedNodeExpandSecretNameKey:             "csiBar",
+				prefixedNodeExpandSecretNamespaceKey:        "csiBar",
 			},
 			expectedParams: map[string]string{},
 		},
@@ -876,6 +878,8 @@ func getDefaultStorageClassSecretParameters() map[string]string {
 		prefixedControllerExpandSecretNamespaceKey: defaultSecretNsName,
 		prefixedProvisionerSecretNameKey:           "provisionersecret",
 		prefixedProvisionerSecretNamespaceKey:      defaultSecretNsName,
+		prefixedNodeExpandSecretNameKey:            "nodeexpandsecret",
+		prefixedNodeExpandSecretNamespaceKey:       defaultSecretNsName,
 	}
 }
 
@@ -906,6 +910,11 @@ func getDefaultSecretObjects() []runtime.Object {
 				Name:      "provisionersecret",
 				Namespace: defaultSecretNsName,
 			},
+		}, &v1.Secret{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      "nodeexpandsecret",
+				Namespace: defaultSecretNsName,
+			},
 		},
 	}
 }
@@ -1597,6 +1606,10 @@ func provisionTestcases() (int64, map[string]provisioningTestcase) {
 						Name:      "controllerexpandsecret",
 						Namespace: "default",
 					},
+					NodeExpandSecretRef: &v1.SecretReference{
+						Name:      "nodeexpandsecret",
+						Namespace: "default",
+					},
 				},
 			},
 			expectState: controller.ProvisioningFinished,
@@ -1652,6 +1665,10 @@ func provisionTestcases() (int64, map[string]provisioningTestcase) {
 						Name:      "default-secret",
 						Namespace: "default-ns",
 					},
+					NodeExpandSecretRef: &v1.SecretReference{
+						Name:      "default-secret",
+						Namespace: "default-ns",
+					},
 				},
 			},
 			expectState: controller.ProvisioningFinished,
@@ -1707,6 +1724,10 @@ func provisionTestcases() (int64, map[string]provisioningTestcase) {
 						Name:      "my-pvc",
 						Namespace: "default-ns",
 					},
+					NodeExpandSecretRef: &v1.SecretReference{
+						Name:      "my-pvc",
+						Namespace: "default-ns",
+					},
 				},
 			},
 			expectState: controller.ProvisioningFinished,