diff --git a/pkg/modifier/csi_modifier.go b/pkg/modifier/csi_modifier.go index dffe777c..f16e4c5c 100644 --- a/pkg/modifier/csi_modifier.go +++ b/pkg/modifier/csi_modifier.go @@ -24,10 +24,17 @@ import ( "github.com/kubernetes-csi/external-resizer/pkg/csi" v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" ) +const ( + // annotations set by the external-provisioner when a modify secret is configured + modifySecretNameAnn = "volume.kubernetes.io/controller-modify-secret-name" + modifySecretNamespaceAnn = "volume.kubernetes.io/controller-modify-secret-namespace" +) + var ModifyNotSupportErr = errors.New("CSI driver does not support controller modify") func NewModifierFromClient( @@ -69,7 +76,7 @@ func (r *csiModifier) Name() string { return r.name } -func (r *csiModifier) Modify(pv *v1.PersistentVolume, mutableParameters map[string]string) error { +func (r *csiModifier) Modify(ctx context.Context, pv *v1.PersistentVolume, mutableParameters map[string]string) error { var volumeID string var source *v1.CSIPersistentVolumeSource @@ -86,18 +93,48 @@ func (r *csiModifier) Modify(pv *v1.PersistentVolume, mutableParameters map[stri return errors.New("empty volume handle") } - var secrets map[string]string + secrets, err := r.getModifyCredentials(ctx, source.ControllerExpandSecretRef, pv.Annotations) + if err != nil { + return err + } ctx, cancel := timeoutCtx(r.timeout) - defer cancel() - err := r.client.Modify(ctx, volumeID, secrets, mutableParameters) + + err = r.client.Modify(ctx, volumeID, secrets, mutableParameters) if err != nil { return err } + return nil } +// getModifyCredentials fetches the credential from the secret referenced in the annotations. When missing, +// the default secretRef (CSIPersistentVolumeSource.ControllerExpandSecretRef) is used. +func (r *csiModifier) getModifyCredentials(ctx context.Context, secretRef *v1.SecretReference, annotations map[string]string) (map[string]string, error) { + secretName := annotations[modifySecretNameAnn] + secretNamespace := annotations[modifySecretNamespaceAnn] + if secretNamespace == "" || secretName == "" { + if secretRef == nil { + return nil, nil + } + + secretName = secretRef.Name + secretNamespace = secretRef.Namespace + } + + secret, err := r.k8sClient.CoreV1().Secrets(secretNamespace).Get(ctx, secretName, metav1.GetOptions{}) + if err != nil { + return nil, fmt.Errorf("error getting secret %s in namespace %s: %v", secretName, secretNamespace, err) + } + + credentials := map[string]string{} + for key, value := range secret.Data { + credentials[key] = string(value) + } + return credentials, nil +} + func supportsControllerModify(client csi.Client, timeout time.Duration) (bool, error) { ctx, cancel := timeoutCtx(timeout) defer cancel() diff --git a/pkg/modifier/modifier.go b/pkg/modifier/modifier.go index b7fc8509..539178c6 100644 --- a/pkg/modifier/modifier.go +++ b/pkg/modifier/modifier.go @@ -17,6 +17,8 @@ limitations under the License. package modifier import ( + "context" + v1 "k8s.io/api/core/v1" ) @@ -25,5 +27,5 @@ type Modifier interface { // Name returns the modifier's name. Name() string // Modify executes the modify operation of this PVC. - Modify(pv *v1.PersistentVolume, mutableParameters map[string]string) error + Modify(ctx context.Context, pv *v1.PersistentVolume, mutableParameters map[string]string) error } diff --git a/pkg/modifycontroller/modify_volume.go b/pkg/modifycontroller/modify_volume.go index df05ec59..a531e14c 100644 --- a/pkg/modifycontroller/modify_volume.go +++ b/pkg/modifycontroller/modify_volume.go @@ -17,6 +17,7 @@ limitations under the License. package modifycontroller import ( + "context" "fmt" "maps" "slices" @@ -73,6 +74,7 @@ func (ctrl *modifyController) modify(pvc *v1.PersistentVolumeClaim, pv *v1.Persi return pvc, pv, err, false } + ctx := context.TODO() inUncertainState := false if inProgress { _, inUncertainState = ctrl.uncertainPVCs.Load(pvcKey) @@ -89,10 +91,10 @@ func (ctrl *modifyController) modify(pvc *v1.PersistentVolumeClaim, pv *v1.Persi if err != nil { return pvc, pv, err, false } - return ctrl.controllerModifyVolumeWithTarget(pvc, pv, vac) + return ctrl.controllerModifyVolumeWithTarget(ctx, pvc, pv, vac) } - return ctrl.validateVACAndModifyVolumeWithTarget(pvc, pv) + return ctrl.validateVACAndModifyVolumeWithTarget(ctx, pvc, pv) } func (ctrl *modifyController) rolledBack(pvc *v1.PersistentVolumeClaim) (*v1.PersistentVolumeClaim, error) { @@ -123,6 +125,7 @@ func (ctrl *modifyController) getTargetVAC(pvc *v1.PersistentVolumeClaim, vacNam // func validateVACAndModifyVolumeWithTarget validate the VAC. The function sets pvc.Status.ModifyVolumeStatus // to Pending if VAC does not exist and proceeds to trigger ModifyVolume if VAC exists func (ctrl *modifyController) validateVACAndModifyVolumeWithTarget( + ctx context.Context, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume) (*v1.PersistentVolumeClaim, *v1.PersistentVolume, error, bool) { @@ -141,18 +144,19 @@ func (ctrl *modifyController) validateVACAndModifyVolumeWithTarget( // Record an event to indicate that external resizer is modifying this volume. ctrl.eventRecorder.Event(pvc, v1.EventTypeNormal, util.VolumeModify, fmt.Sprintf("external resizer is modifying volume %s with vac %s", pvc.Name, vac.Name)) - return ctrl.controllerModifyVolumeWithTarget(pvc, pv, vac) + return ctrl.controllerModifyVolumeWithTarget(ctx, pvc, pv, vac) } // func controllerModifyVolumeWithTarget trigger the CSI ControllerModifyVolume API call // and handle both success and error scenarios func (ctrl *modifyController) controllerModifyVolumeWithTarget( + ctx context.Context, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume, vacObj *storagev1.VolumeAttributesClass, ) (*v1.PersistentVolumeClaim, *v1.PersistentVolume, error, bool) { var err error - pvc, pv, err = ctrl.callModifyVolumeOnPlugin(pvc, pv, vacObj) + pvc, pv, err = ctrl.callModifyVolumeOnPlugin(ctx, pvc, pv, vacObj) if err == nil { klog.V(4).Infof("Update volumeAttributesClass of PV %q to %s succeeded", pv.Name, vacObj.Name) // Record an event to indicate that modify operation is successful. @@ -195,6 +199,7 @@ func (ctrl *modifyController) controllerModifyVolumeWithTarget( } func (ctrl *modifyController) callModifyVolumeOnPlugin( + ctx context.Context, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume, vac *storagev1.VolumeAttributesClass) (*v1.PersistentVolumeClaim, *v1.PersistentVolume, error) { @@ -209,7 +214,7 @@ func (ctrl *modifyController) callModifyVolumeOnPlugin( parameters[pvcNamespaceKey] = pvc.GetNamespace() parameters[pvNameKey] = pv.GetName() } - err := ctrl.modifier.Modify(pv, parameters) + err := ctrl.modifier.Modify(ctx, pv, parameters) if err != nil { return pvc, pv, err