Skip to content

Commit

Permalink
feat: add feature flag for inline volume support
Browse files Browse the repository at this point in the history
test: add ut

fix

fix

fix

fix

fix
  • Loading branch information
andyzhangx committed Jan 17, 2025
1 parent 8105a9d commit 9df3b58
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 7 deletions.
Binary file modified charts/latest/csi-driver-smb-v0.0.0.tgz
Binary file not shown.
2 changes: 2 additions & 0 deletions charts/latest/csi-driver-smb/templates/csi-smb-driver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ spec:
podInfoOnMount: true
volumeLifecycleModes:
- Persistent
{{- if .Values.feature.enableInlineVolume }}
- Ephemeral
{{- end }}
3 changes: 2 additions & 1 deletion charts/latest/csi-driver-smb/templates/rbac-csi-smb.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ roleRef:
name: {{ .Values.rbac.name }}-external-resizer-role
apiGroup: rbac.authorization.k8s.io
---
{{- if .Values.feature.enableInlineVolume }}
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
Expand All @@ -107,7 +108,6 @@ rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
Expand All @@ -122,4 +122,5 @@ roleRef:
kind: ClusterRole
name: csi-{{ .Values.rbac.name }}-node-secret-role
apiGroup: rbac.authorization.k8s.io
{{- end }}
{{ end }}
1 change: 1 addition & 0 deletions charts/latest/csi-driver-smb/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ driver:

feature:
enableGetVolumeStats: true
enableInlineVolume: true

controller:
name: csi-smb-controller
Expand Down
18 changes: 13 additions & 5 deletions pkg/smb/nodeserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
secrets := req.GetSecrets()
gidPresent := checkGidPresentInMountFlags(mountFlags)

var source, subDir, secretName, secretNamespace string
var source, subDir, secretName, secretNamespace, ephemeralVolMountOptions string
var ephemeralVol bool
subDirReplaceMap := map[string]string{}
for k, v := range context {
switch strings.ToLower(k) {
Expand All @@ -165,6 +166,10 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
secretName = v
case secretNamespaceField:
secretNamespace = v
case ephemeralField:
ephemeralVol = strings.EqualFold(v, trueValue)
case mountOptionsField:
ephemeralVolMountOptions = v
}
}

Expand All @@ -190,7 +195,13 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
}
}

if (username == "" || password == "") && (secretName != "" && secretNamespace != "") {
if ephemeralVol {
mountFlags = strings.Split(ephemeralVolMountOptions, ",")
}

// in guest login, username and password options are not needed
requireUsernamePwdOption := !hasGuestMountOptions(mountFlags)
if ephemeralVol && requireUsernamePwdOption {
klog.V(2).Infof("NodeStageVolume: getting username and password from secret %s in namespace %s", secretName, secretNamespace)
var err error
username, password, domain, err = d.GetUserNamePasswordFromSecret(ctx, secretName, secretNamespace)
Expand All @@ -199,9 +210,6 @@ func (d *Driver) NodeStageVolume(ctx context.Context, req *csi.NodeStageVolumeRe
}
}

// in guest login, username and password options are not needed
requireUsernamePwdOption := !hasGuestMountOptions(mountFlags)

var mountOptions, sensitiveMountOptions []string
if runtime.GOOS == "windows" {
if domain == "" {
Expand Down
31 changes: 31 additions & 0 deletions pkg/smb/nodeserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,37 @@ func TestNodePublishVolume(t *testing.T) {
Readonly: true},
expectedErr: testutil.TestError{},
},
{
desc: "[Error] failed to create ephemeral Volume",
req: &csi.NodePublishVolumeRequest{VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
VolumeId: "vol_1",
TargetPath: targetTest,
StagingTargetPath: sourceTest,
Readonly: true,
VolumeContext: map[string]string{ephemeralField: "true"},
},
expectedErr: testutil.TestError{
DefaultError: status.Error(codes.InvalidArgument, "source field is missing, current context: map[csi.storage.k8s.io/ephemeral:true secretnamespace:]"),
},
},
{
desc: "[error] failed request with ephemeral Volume",
req: &csi.NodePublishVolumeRequest{VolumeCapability: &csi.VolumeCapability{AccessMode: &volumeCap},
VolumeId: "vol_1",
TargetPath: targetTest,
StagingTargetPath: sourceTest,
Readonly: true,
VolumeContext: map[string]string{
ephemeralField: "true",
sourceField: "source",
podNamespaceField: "podnamespace",
},
},
skipOnWindows: true,
expectedErr: testutil.TestError{
DefaultError: status.Error(codes.Internal, "Error getting username and password from secret in namespace podnamespace: could not username and password from secret(): KubeClient is nil"),
},
},
}

// Setup
Expand Down
10 changes: 10 additions & 0 deletions test/e2e/dynamic_provisioning_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,16 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
})

ginkgo.It("should create an CSI inline volume", func(ctx ginkgo.SpecContext) {
if winServerVer == "windows-2022" && !isWindowsHostProcessDeployment {
ginkgo.Skip("Skip inline volume test on Windows Server 2022")
}

secretName := "smbcreds"
ginkgo.By(fmt.Sprintf("creating secret %s in namespace %s", secretName, ns.Name))
tsecret := testsuites.CopyTestSecret(ctx, cs, "default", ns, defaultSmbSecretName)
tsecret.Create(ctx)
defer tsecret.Cleanup(ctx)

pods := []testsuites.PodDetails{
{
Cmd: convertToPowershellCommandIfNecessary("echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data"),
Expand Down
3 changes: 2 additions & 1 deletion test/e2e/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const (
defaultSmbSource = "//smb-server.default.svc.cluster.local/share"
defaultSmbSecretName = "smbcreds"
defaultSmbSecretNamespace = "default"
accountNameForTest = "YW5keXNzZGZpbGUK"
)

var (
Expand Down Expand Up @@ -173,7 +174,7 @@ var _ = ginkgo.BeforeSuite(func() {
}

if isWindowsHostProcessDeployment {
decodedBytes, err := base64.StdEncoding.DecodeString("YW5keXNzZGZpbGUK")
decodedBytes, err := base64.StdEncoding.DecodeString(accountNameForTest)
if err != nil {
log.Printf("Error decoding base64 string: %v\n", err)
return
Expand Down
19 changes: 19 additions & 0 deletions test/e2e/testsuites/testsuites.go
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,25 @@ func NewTestSecret(c clientset.Interface, ns *v1.Namespace, name string, data ma
}
}

func CopyTestSecret(ctx context.Context, c clientset.Interface, sourceNamespace string, targetNamespace *v1.Namespace, secretName string) *TestSecret {
secret, err := c.CoreV1().Secrets(sourceNamespace).Get(ctx, secretName, metav1.GetOptions{})
framework.ExpectNoError(err)

return &TestSecret{
client: c,
namespace: targetNamespace,
secret: &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: targetNamespace.Name,
},
StringData: secret.StringData,
Data: secret.Data,
Type: v1.SecretTypeOpaque,
},
}
}

func (t *TestSecret) Create(ctx context.Context) {
var err error
t.secret, err = t.client.CoreV1().Secrets(t.namespace.Name).Create(ctx, t.secret, metav1.CreateOptions{})
Expand Down

0 comments on commit 9df3b58

Please sign in to comment.