Skip to content

Commit 45e7f52

Browse files
committed
feat: support pv/pvc metadata in subDir parameter
refine
1 parent 8d38502 commit 45e7f52

File tree

9 files changed

+104
-10
lines changed

9 files changed

+104
-10
lines changed
15 Bytes
Binary file not shown.

charts/latest/csi-driver-smb/templates/csi-smb-controller.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ spec:
5757
- "--csi-address=$(ADDRESS)"
5858
- "--leader-election"
5959
- "--leader-election-namespace={{ .Release.Namespace }}"
60+
- "--extra-create-metadata=true"
6061
env:
6162
- name: ADDRESS
6263
value: /csi/csi.sock

deploy/csi-smb-controller.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ spec:
3737
- "--csi-address=$(ADDRESS)"
3838
- "--leader-election"
3939
- "--leader-election-namespace=kube-system"
40+
- "--extra-create-metadata=true"
4041
env:
4142
- name: ADDRESS
4243
value: /csi/csi.sock

docs/driver-parameters.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ kubectl create secret generic smbcreds --from-literal username=USERNAME --from-l
2828
```
2929

3030
### Tips
31+
#### `subDir` parameter supports following pv/pvc metadata transform
32+
> if `subDir` value contains following string, it would transforms into corresponding pv/pvc name or namespace
33+
- `${pvc.metadata.name}`
34+
- `${pvc.metadata.namespace}`
35+
- `${pv.metadata.name}`
36+
3137
#### provide `mountOptions` for `DeleteVolume`
3238
> since `DeleteVolumeRequest` does not provide `mountOptions`, following is the workaround to provide `mountOptions` for `DeleteVolume`
3339
- create a secret `smbcreds` with `mountOptions`

pkg/smb/controllerserver.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ func getInternalMountPath(workingMountDir string, vol *smbVolume) string {
302302
// Convert VolumeCreate parameters to an smbVolume
303303
func newSMBVolume(name string, size int64, params map[string]string) (*smbVolume, error) {
304304
var source, subDir string
305+
subDirReplaceMap := map[string]string{}
305306

306307
// validate parameters (case-insensitive).
307308
for k, v := range params {
@@ -310,6 +311,12 @@ func newSMBVolume(name string, size int64, params map[string]string) (*smbVolume
310311
source = v
311312
case subDirField:
312313
subDir = v
314+
case pvcNamespaceKey:
315+
subDirReplaceMap[pvcNamespaceMetadata] = v
316+
case pvcNameKey:
317+
subDirReplaceMap[pvcNameMetadata] = v
318+
case pvNameKey:
319+
subDirReplaceMap[pvNameMetadata] = v
313320
default:
314321
return nil, fmt.Errorf("invalid parameter %s in storage class", k)
315322
}
@@ -327,7 +334,8 @@ func newSMBVolume(name string, size int64, params map[string]string) (*smbVolume
327334
// use pv name by default if not specified
328335
vol.subDir = name
329336
} else {
330-
vol.subDir = subDir
337+
// replace pv/pvc name namespace metadata in subDir
338+
vol.subDir = replaceWithMap(subDir, subDirReplaceMap)
331339
// make volume id unique if subDir is provided
332340
vol.uuid = name
333341
}

pkg/smb/nodeserver.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,19 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
130130
gidPresent := checkGidPresentInMountFlags(mountFlags)
131131

132132
var source, subDir string
133+
subDirReplaceMap := map[string]string{}
133134
for k, v := range context {
134135
switch strings.ToLower(k) {
135136
case sourceField:
136137
source = v
137138
case subDirField:
138139
subDir = v
140+
case pvcNamespaceKey:
141+
subDirReplaceMap[pvcNamespaceMetadata] = v
142+
case pvcNameKey:
143+
subDirReplaceMap[pvcNameMetadata] = v
144+
case pvNameKey:
145+
subDirReplaceMap[pvNameMetadata] = v
139146
}
140147
}
141148

@@ -205,6 +212,9 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
205212
return nil, fmt.Errorf("prepare stage path failed for %s with error: %v", targetPath, err)
206213
}
207214
if subDir != "" {
215+
// replace pv/pvc name namespace metadata in subDir
216+
subDir = replaceWithMap(subDir, subDirReplaceMap)
217+
208218
source = strings.TrimRight(source, "/")
209219
source = fmt.Sprintf("%s/%s", source, subDir)
210220
}

pkg/smb/smb.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,20 @@ import (
2929
)
3030

3131
const (
32-
DefaultDriverName = "smb.csi.k8s.io"
33-
usernameField = "username"
34-
passwordField = "password"
35-
sourceField = "source"
36-
subDirField = "subdir"
37-
domainField = "domain"
38-
mountOptionsField = "mountoptions"
39-
defaultDomainName = "AZURE"
32+
DefaultDriverName = "smb.csi.k8s.io"
33+
usernameField = "username"
34+
passwordField = "password"
35+
sourceField = "source"
36+
subDirField = "subdir"
37+
domainField = "domain"
38+
mountOptionsField = "mountoptions"
39+
defaultDomainName = "AZURE"
40+
pvcNameKey = "csi.storage.k8s.io/pvc/name"
41+
pvcNamespaceKey = "csi.storage.k8s.io/pvc/namespace"
42+
pvNameKey = "csi.storage.k8s.io/pv/name"
43+
pvcNameMetadata = "${pvc.metadata.name}"
44+
pvcNamespaceMetadata = "${pvc.metadata.namespace}"
45+
pvNameMetadata = "${pv.metadata.name}"
4046
)
4147

4248
// DriverOptions defines driver parameters specified in driver deployment
@@ -156,3 +162,13 @@ func setKeyValueInMap(m map[string]string, key, value string) {
156162
}
157163
m[key] = value
158164
}
165+
166+
// replaceWithMap replace key with value for str
167+
func replaceWithMap(str string, m map[string]string) string {
168+
for k, v := range m {
169+
if k != "" {
170+
str = strings.ReplaceAll(str, k, v)
171+
}
172+
}
173+
return str
174+
}

pkg/smb/smb_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,55 @@ func TestSetKeyValueInMap(t *testing.T) {
230230
}
231231
}
232232
}
233+
234+
func TestReplaceWithMap(t *testing.T) {
235+
tests := []struct {
236+
desc string
237+
str string
238+
m map[string]string
239+
expected string
240+
}{
241+
{
242+
desc: "empty string",
243+
str: "",
244+
expected: "",
245+
},
246+
{
247+
desc: "empty map",
248+
str: "",
249+
m: map[string]string{},
250+
expected: "",
251+
},
252+
{
253+
desc: "empty key",
254+
str: "prefix-" + pvNameMetadata,
255+
m: map[string]string{"": "pv"},
256+
expected: "prefix-" + pvNameMetadata,
257+
},
258+
{
259+
desc: "empty value",
260+
str: "prefix-" + pvNameMetadata,
261+
m: map[string]string{pvNameMetadata: ""},
262+
expected: "prefix-",
263+
},
264+
{
265+
desc: "one replacement",
266+
str: "prefix-" + pvNameMetadata,
267+
m: map[string]string{pvNameMetadata: "pv"},
268+
expected: "prefix-pv",
269+
},
270+
{
271+
desc: "multiple replacements",
272+
str: pvcNamespaceMetadata + pvcNameMetadata,
273+
m: map[string]string{pvcNamespaceMetadata: "namespace", pvcNameMetadata: "pvcname"},
274+
expected: "namespacepvcname",
275+
},
276+
}
277+
278+
for _, test := range tests {
279+
result := replaceWithMap(test.str, test.m)
280+
if result != test.expected {
281+
t.Errorf("test[%s]: unexpected output: %v, expected result: %v", test.desc, result, test.expected)
282+
}
283+
}
284+
}

test/e2e/suite_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ var (
5656
}
5757
subDirStorageClassParameters = map[string]string{
5858
"source": "//smb-server.default.svc.cluster.local/share",
59-
"subDir": "subDirectory",
59+
"subDir": "subDirectory-${pvc.metadata.name}",
6060
"csi.storage.k8s.io/provisioner-secret-name": "smbcreds",
6161
"csi.storage.k8s.io/provisioner-secret-namespace": "default",
6262
"csi.storage.k8s.io/node-stage-secret-name": "smbcreds",

0 commit comments

Comments
 (0)