diff --git a/pkg/driver/provisioner.go b/pkg/driver/provisioner.go index df7af550dc..ad882c8f4b 100644 --- a/pkg/driver/provisioner.go +++ b/pkg/driver/provisioner.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "strconv" + "strings" "time" corev1 "k8s.io/api/core/v1" @@ -82,16 +83,23 @@ func (j *provisionerService) Provision(ctx context.Context, options provisioncon return nil, provisioncontroller.ProvisioningFinished, fmt.Errorf("claim Selector is not supported") } - pvName := options.PVName - sc := options.StorageClass - pvMeta := util.NewPVCMeta(*options.PVC) subPath := options.PVName if options.StorageClass.Parameters["pathPattern"] != "" { subPath = pvMeta.StringParser(options.StorageClass.Parameters["pathPattern"]) } - secretName, secretNamespace := sc.Parameters[config.ProvisionerSecretName], sc.Parameters[config.ProvisionerSecretNamespace] - secret, err := j.K8sClient.GetSecret(ctx, secretName, secretNamespace) + + pvName := options.PVName + scParams := make(map[string]string) + for k, v := range options.StorageClass.Parameters { + if strings.HasPrefix(k, "csi.storage.k8s.io/") { + scParams[k] = pvMeta.ResolveSecret(v, pvName) + } else { + scParams[k] = v + } + } + + secret, err := j.K8sClient.GetSecret(ctx, scParams[config.ProvisionerSecretName], scParams[config.ProvisionerSecretNamespace]) if err != nil { klog.Errorf("[PVCReconciler]: Get Secret error: %v", err) return nil, provisioncontroller.ProvisioningFinished, errors.New("unable to provision new pv: " + err.Error()) @@ -104,7 +112,7 @@ func (j *provisionerService) Provision(ctx context.Context, options provisioncon volCtx := make(map[string]string) volCtx["subPath"] = subPath volCtx["capacity"] = strconv.FormatInt(options.PVC.Spec.Resources.Requests.Storage().Value(), 10) - for k, v := range sc.Parameters { + for k, v := range scParams { volCtx[k] = v } pv := &corev1.PersistentVolume{ @@ -123,22 +131,22 @@ func (j *provisionerService) Provision(ctx context.Context, options provisioncon FSType: "juicefs", VolumeAttributes: volCtx, NodePublishSecretRef: &corev1.SecretReference{ - Name: sc.Parameters[config.PublishSecretName], - Namespace: sc.Parameters[config.PublishSecretNamespace], + Name: scParams[config.PublishSecretName], + Namespace: scParams[config.PublishSecretNamespace], }, }, }, AccessModes: options.PVC.Spec.AccessModes, PersistentVolumeReclaimPolicy: *options.StorageClass.ReclaimPolicy, - StorageClassName: sc.Name, + StorageClassName: options.StorageClass.Name, MountOptions: options.StorageClass.MountOptions, VolumeMode: options.PVC.Spec.VolumeMode, }, } - if sc.Parameters[config.ControllerExpandSecretName] != "" && sc.Parameters[config.ControllerExpandSecretNamespace] != "" { + if scParams[config.ControllerExpandSecretName] != "" && scParams[config.ControllerExpandSecretNamespace] != "" { pv.Spec.CSI.ControllerExpandSecretRef = &corev1.SecretReference{ - Name: sc.Parameters[config.ControllerExpandSecretName], - Namespace: sc.Parameters[config.ControllerExpandSecretNamespace], + Name: scParams[config.ControllerExpandSecretName], + Namespace: scParams[config.ControllerExpandSecretNamespace], } } return pv, provisioncontroller.ProvisioningFinished, nil diff --git a/pkg/util/pvc.go b/pkg/util/pvc.go index 6d26f94d21..108a3ae4bc 100644 --- a/pkg/util/pvc.go +++ b/pkg/util/pvc.go @@ -18,6 +18,7 @@ package util import ( "context" + "os" "regexp" "strings" @@ -91,3 +92,24 @@ func CheckForSubPath(ctx context.Context, client *k8s.K8sClient, volume *v1.Pers } return true, nil } + +func (meta *PVCMetadata) ResolveSecret(str string, pvName string) string { + resolved := os.Expand(str, func(k string) string { + switch k { + case "pvc.name": + return meta.data["name"] + case "pvc.namespace": + return meta.data["namespace"] + case "pv.name": + return pvName + } + for ak, av := range meta.annotations { + if k == "pvc.annotations['"+ak+"']" { + return av + } + } + klog.Errorf("Cannot resolve %s. replace it with an empty string", k) + return "" + }) + return resolved +} diff --git a/pkg/util/pvc_test.go b/pkg/util/pvc_test.go index eb6be78775..02707e9762 100644 --- a/pkg/util/pvc_test.go +++ b/pkg/util/pvc_test.go @@ -268,3 +268,93 @@ func TestCheckForSubPath(t *testing.T) { }) } } + +func TestResolveSecret(t *testing.T) { + type fields struct { + data map[string]string + labels map[string]string + annotations map[string]string + } + type args struct { + str string + pvname string + } + tests := []struct { + name string + fields fields + args args + want string + }{ + { + name: "test-pvc-name", + fields: fields{ + data: map[string]string{ + "name": "test", + "namespace": "default", + }, + }, + args: args{ + str: "${pvc.name}", + pvname: "pv-a", + }, + want: "test", + }, + { + name: "test-pvc-namespace", + fields: fields{ + data: map[string]string{ + "name": "test", + "namespace": "default", + }, + }, + args: args{ + str: "${pvc.namespace}", + pvname: "pv-a", + }, + want: "default", + }, + { + name: "test-pvc-annotation", + fields: fields{ + data: map[string]string{ + "name": "test", + "namespace": "default", + }, + annotations: map[string]string{ + "a.a": "b", + }, + }, + args: args{ + str: "${pvc.annotations['a.a']}", + pvname: "pv-a", + }, + want: "b", + }, + { + name: "test-pv-name", + fields: fields{ + data: map[string]string{ + "name": "test", + "namespace": "default", + }, + }, + args: args{ + str: "${pv.name}", + pvname: "pv-a", + }, + want: "pv-a", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + meta := &PVCMetadata{ + data: tt.fields.data, + labels: tt.fields.labels, + annotations: tt.fields.annotations, + } + if got := meta.ResolveSecret(tt.args.str, tt.args.pvname); got != tt.want { + t.Errorf("ResolveSecret() = %v, want %v", got, tt.want) + } + }) + } +}