Skip to content

Commit

Permalink
allow -o mount options
Browse files Browse the repository at this point in the history
  • Loading branch information
songjiaxun committed May 29, 2023
1 parent 9da97fb commit f5bb30d
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 26 deletions.
79 changes: 53 additions & 26 deletions pkg/csi_mounter/csi_mounter.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"net"
"os"
"path/filepath"
"strings"
"sync"
"syscall"
"time"
Expand Down Expand Up @@ -57,29 +58,8 @@ func New(mounterPath string) (mount.Interface, error) {
}, nil
}

func (m *Mounter) Mount(source string, target string, _ string, options []string) error {
// Prepare the mount options
mountOptions := []string{
"nodev",
"nosuid",
"allow_other",
"default_permissions",
"rootmode=40000",
fmt.Sprintf("user_id=%d", os.Getuid()),
fmt.Sprintf("group_id=%d", os.Getgid()),
}

// users may pass options that should be used by Linux mount(8),
// filter out these options and not pass to the sidecar mounter.
validMountOptions := []string{"rw", "ro"}
optionSet := sets.NewString(options...)
for _, o := range validMountOptions {
if optionSet.Has(o) {
mountOptions = append(mountOptions, o)
optionSet.Delete(o)
}
}
options = optionSet.List()
func (m *Mounter) Mount(source string, target string, fstype string, options []string) error {
csiMountOptions, sidecarMountOptions := prepareMountOptions(options)

// Prepare the temp emptyDir path
emptyDirBasePath, err := util.PrepareEmptyDir(target, false)
Expand All @@ -92,10 +72,10 @@ func (m *Mounter) Mount(source string, target string, _ string, options []string
if err != nil {
return fmt.Errorf("failed to open the device /dev/fuse: %w", err)
}
mountOptions = append(mountOptions, fmt.Sprintf("fd=%v", fd))
csiMountOptions = append(csiMountOptions, fmt.Sprintf("fd=%v", fd))

klog.V(4).Info("mounting the fuse filesystem")
err = m.MountSensitiveWithoutSystemdWithMountFlags(source, target, "fuse", mountOptions, nil, []string{"--internal-only"})
err = m.MountSensitiveWithoutSystemdWithMountFlags(source, target, fstype, csiMountOptions, nil, []string{"--internal-only"})
if err != nil {
return fmt.Errorf("failed to mount the fuse filesystem: %w", err)
}
Expand Down Expand Up @@ -148,7 +128,7 @@ func (m *Mounter) Mount(source string, target string, _ string, options []string
// Prepare sidecar mounter MountConfig
mc := sidecarmounter.MountConfig{
BucketName: source,
Options: options,
Options: sidecarMountOptions,
}
mcb, err := json.Marshal(mc)
if err != nil {
Expand Down Expand Up @@ -182,3 +162,50 @@ func (m *Mounter) Mount(source string, target string, _ string, options []string

return nil
}

func prepareMountOptions(options []string) ([]string, []string) {
allowedOptions := map[string]bool{
"exec": true,
"noexec": true,
"atime": true,
"noatime": true,
"sync": true,
"async": true,
"dirsync": true,
}

csiMountOptions := []string{
"nodev",
"nosuid",
"allow_other",
"default_permissions",
"rootmode=40000",
fmt.Sprintf("user_id=%d", os.Getuid()),
fmt.Sprintf("group_id=%d", os.Getgid()),
}

// users may pass options that should be used by Linux mount(8),
// filter out these options and not pass to the sidecar mounter.
validMountOptions := []string{"rw", "ro"}
optionSet := sets.NewString(options...)
for _, o := range validMountOptions {
if optionSet.Has(o) {
csiMountOptions = append(csiMountOptions, o)
optionSet.Delete(o)
}
}

for _, o := range optionSet.List() {
if strings.HasPrefix(o, "o=") {
v := o[2:]
if allowedOptions[v] {
csiMountOptions = append(csiMountOptions, v)
} else {
klog.Warningf("got invalid mount option %q. Will discard invalid options and continue to mount.", v)
}
optionSet.Delete(o)
}
}

return csiMountOptions, optionSet.List()
}
93 changes: 93 additions & 0 deletions pkg/csi_mounter/csi_mounter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
Copyright 2018 The Kubernetes Authors.
Copyright 2022 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package csimounter

import (
"fmt"
"os"
"reflect"
"testing"
)

var defaultCsiMountOptions = []string{
"nodev",
"nosuid",
"allow_other",
"default_permissions",
"rootmode=40000",
fmt.Sprintf("user_id=%d", os.Getuid()),
fmt.Sprintf("group_id=%d", os.Getgid()),
}

func TestPrepareMountArgs(t *testing.T) {
t.Parallel()

testCases := []struct {
name string
inputMountOptions []string
expecteCsiMountOptions []string
expecteSidecarMountOptions []string
}{
{
name: "should return valid options correctly with empty input",
inputMountOptions: []string{},
expecteCsiMountOptions: defaultCsiMountOptions,
expecteSidecarMountOptions: []string{},
},
{
name: "should return valid options correctly with CSI mount options only",
inputMountOptions: []string{"ro", "o=noexec", "o=noatime", "o=invalid"},
expecteCsiMountOptions: append(defaultCsiMountOptions, "ro", "noexec", "noatime"),
expecteSidecarMountOptions: []string{},
},
{
name: "should return valid options correctly with sidecar mount options only",
inputMountOptions: []string{"implicit-dirs", "max-conns-per-host=10"},
expecteCsiMountOptions: defaultCsiMountOptions,
expecteSidecarMountOptions: []string{"implicit-dirs", "max-conns-per-host=10"},
},
{
name: "should return valid options correctly with CSI and sidecar mount options",
inputMountOptions: []string{"ro", "implicit-dirs", "max-conns-per-host=10", "o=noexec", "o=noatime", "o=invalid"},
expecteCsiMountOptions: append(defaultCsiMountOptions, "ro", "noexec", "noatime"),
expecteSidecarMountOptions: []string{"implicit-dirs", "max-conns-per-host=10"},
},
}

for _, tc := range testCases {
t.Logf("test case: %s", tc.name)

c, s := prepareMountOptions(tc.inputMountOptions)
if !reflect.DeepEqual(countOptionOccurrence(c), countOptionOccurrence(tc.expecteCsiMountOptions)) {
t.Errorf("Got options %v, but expected %v", c, tc.expecteCsiMountOptions)
}

if !reflect.DeepEqual(countOptionOccurrence(s), countOptionOccurrence(tc.expecteSidecarMountOptions)) {
t.Errorf("Got options %v, but expected %v", s, tc.expecteSidecarMountOptions)
}
}
}

func countOptionOccurrence(options []string) map[string]int {
dict := make(map[string]int)
for _, o := range options {
dict[o]++
}

return dict
}

0 comments on commit f5bb30d

Please sign in to comment.