Fix pkg/volume/util/nsenter linting errors

This commit is contained in:
Travis Rhoden 2019-04-08 10:43:54 -06:00
parent 1c045a09db
commit 2253807760
5 changed files with 111 additions and 65 deletions

View File

@ -374,7 +374,7 @@ func UnsecuredDependencies(s *options.KubeletServer) (*kubelet.Dependencies, err
if err != nil { if err != nil {
return nil, err return nil, err
} }
mounter = nsutil.NewNsenterMounter(s.RootDirectory, ne) mounter = nsutil.NewMounter(s.RootDirectory, ne)
// NSenter only valid on Linux // NSenter only valid on Linux
subpather = subpath.NewNSEnter(mounter, ne, s.RootDirectory) subpather = subpath.NewNSEnter(mounter, ne, s.RootDirectory)
// an exec interface which can use nsenter for flex plugin calls // an exec interface which can use nsenter for flex plugin calls

View File

@ -37,29 +37,30 @@ const (
hostProcMountinfoPath = "/rootfs/proc/1/mountinfo" hostProcMountinfoPath = "/rootfs/proc/1/mountinfo"
) )
// Mounter implements mount.Interface
// Currently, all docker containers receive their own mount namespaces. // Currently, all docker containers receive their own mount namespaces.
// NsenterMounter works by executing nsenter to run commands in // Mounter works by executing nsenter to run commands in
// the host's mount namespace. // the host's mount namespace.
type NsenterMounter struct { type Mounter struct {
ne *nsenter.Nsenter ne *nsenter.Nsenter
// rootDir is location of /var/lib/kubelet directory. // rootDir is location of /var/lib/kubelet directory.
rootDir string rootDir string
} }
// NewNsenterMounter creates a new mounter for kubelet that runs as a container. // NewMounter creates a new mounter for kubelet that runs as a container.
func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter { func NewMounter(rootDir string, ne *nsenter.Nsenter) *Mounter {
return &NsenterMounter{ return &Mounter{
rootDir: rootDir, rootDir: rootDir,
ne: ne, ne: ne,
} }
} }
// NsenterMounter implements mount.Interface // Mounter implements mount.Interface
var _ = mount.Interface(&NsenterMounter{}) var _ = mount.Interface(&Mounter{})
// Mount runs mount(8) in the host's root mount namespace. Aside from this // Mount runs mount(8) in the host's root mount namespace. Aside from this
// aspect, Mount has the same semantics as the mounter returned by mount.New() // aspect, Mount has the same semantics as the mounter returned by mount.New()
func (n *NsenterMounter) Mount(source string, target string, fstype string, options []string) error { func (n *Mounter) Mount(source string, target string, fstype string, options []string) error {
bind, bindOpts, bindRemountOpts := mount.IsBind(options) bind, bindOpts, bindRemountOpts := mount.IsBind(options)
if bind { if bind {
@ -75,7 +76,7 @@ func (n *NsenterMounter) Mount(source string, target string, fstype string, opti
// doNsenterMount nsenters the host's mount namespace and performs the // doNsenterMount nsenters the host's mount namespace and performs the
// requested mount. // requested mount.
func (n *NsenterMounter) doNsenterMount(source, target, fstype string, options []string) error { func (n *Mounter) doNsenterMount(source, target, fstype string, options []string) error {
klog.V(5).Infof("nsenter mount %s %s %s %v", source, target, fstype, options) klog.V(5).Infof("nsenter mount %s %s %s %v", source, target, fstype, options)
cmd, args := n.makeNsenterArgs(source, target, fstype, options) cmd, args := n.makeNsenterArgs(source, target, fstype, options)
outputBytes, err := n.ne.Exec(cmd, args).CombinedOutput() outputBytes, err := n.ne.Exec(cmd, args).CombinedOutput()
@ -87,7 +88,7 @@ func (n *NsenterMounter) doNsenterMount(source, target, fstype string, options [
// makeNsenterArgs makes a list of argument to nsenter in order to do the // makeNsenterArgs makes a list of argument to nsenter in order to do the
// requested mount. // requested mount.
func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options []string) (string, []string) { func (n *Mounter) makeNsenterArgs(source, target, fstype string, options []string) (string, []string) {
mountCmd := n.ne.AbsHostPath("mount") mountCmd := n.ne.AbsHostPath("mount")
mountArgs := mount.MakeMountArgs(source, target, fstype, options) mountArgs := mount.MakeMountArgs(source, target, fstype, options)
@ -125,7 +126,7 @@ func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options
} }
// Unmount runs umount(8) in the host's mount namespace. // Unmount runs umount(8) in the host's mount namespace.
func (n *NsenterMounter) Unmount(target string) error { func (n *Mounter) Unmount(target string) error {
args := []string{target} args := []string{target}
// No need to execute systemd-run here, it's enough that unmount is executed // No need to execute systemd-run here, it's enough that unmount is executed
// in the host's mount namespace. It will finish appropriate fuse daemon(s) // in the host's mount namespace. It will finish appropriate fuse daemon(s)
@ -139,18 +140,19 @@ func (n *NsenterMounter) Unmount(target string) error {
} }
// List returns a list of all mounted filesystems in the host's mount namespace. // List returns a list of all mounted filesystems in the host's mount namespace.
func (*NsenterMounter) List() ([]mount.MountPoint, error) { func (*Mounter) List() ([]mount.MountPoint, error) {
return mount.ListProcMounts(hostProcMountsPath) return mount.ListProcMounts(hostProcMountsPath)
} }
func (*NsenterMounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool { // IsMountPointMatch tests if dir and mp are the same path
func (*Mounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool {
deletedDir := fmt.Sprintf("%s\\040(deleted)", dir) deletedDir := fmt.Sprintf("%s\\040(deleted)", dir)
return (mp.Path == dir) || (mp.Path == deletedDir) return (mp.Path == dir) || (mp.Path == deletedDir)
} }
// IsLikelyNotMountPoint determines whether a path is a mountpoint by calling findmnt // IsLikelyNotMountPoint determines whether a path is a mountpoint by calling findmnt
// in the host's root mount namespace. // in the host's root mount namespace.
func (n *NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) { func (n *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
file, err := filepath.Abs(file) file, err := filepath.Abs(file)
if err != nil { if err != nil {
return true, err return true, err
@ -213,30 +215,32 @@ func parseFindMnt(out string) (string, error) {
// Returns true if open returns errno EBUSY, and false if errno is nil. // Returns true if open returns errno EBUSY, and false if errno is nil.
// Returns an error if errno is any error other than EBUSY. // Returns an error if errno is any error other than EBUSY.
// Returns with error if pathname is not a device. // Returns with error if pathname is not a device.
func (n *NsenterMounter) DeviceOpened(pathname string) (bool, error) { func (n *Mounter) DeviceOpened(pathname string) (bool, error) {
return mount.ExclusiveOpenFailsOnDevice(pathname) return mount.ExclusiveOpenFailsOnDevice(pathname)
} }
// PathIsDevice uses FileInfo returned from os.Stat to check if path refers // PathIsDevice uses FileInfo returned from os.Stat to check if path refers
// to a device. // to a device.
func (n *NsenterMounter) PathIsDevice(pathname string) (bool, error) { func (n *Mounter) PathIsDevice(pathname string) (bool, error) {
pathType, err := n.GetFileType(pathname) pathType, err := n.GetFileType(pathname)
isDevice := pathType == mount.FileTypeCharDev || pathType == mount.FileTypeBlockDev isDevice := pathType == mount.FileTypeCharDev || pathType == mount.FileTypeBlockDev
return isDevice, err return isDevice, err
} }
//GetDeviceNameFromMount given a mount point, find the volume id from checking /proc/mounts //GetDeviceNameFromMount given a mount point, find the volume id from checking /proc/mounts
func (n *NsenterMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { func (n *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) {
return mount.GetDeviceNameFromMountLinux(n, mountPath, pluginDir) return mount.GetDeviceNameFromMountLinux(n, mountPath, pluginDir)
} }
func (n *NsenterMounter) MakeRShared(path string) error { // MakeRShared checks if path is shared and bind-mounts it as rshared if needed.
func (n *Mounter) MakeRShared(path string) error {
return mount.DoMakeRShared(path, hostProcMountinfoPath) return mount.DoMakeRShared(path, hostProcMountinfoPath)
} }
func (mounter *NsenterMounter) GetFileType(pathname string) (mount.FileType, error) { // GetFileType checks for file/directory/socket/block/character devices.
func (n *Mounter) GetFileType(pathname string) (mount.FileType, error) {
var pathType mount.FileType var pathType mount.FileType
outputBytes, err := mounter.ne.Exec("stat", []string{"-L", "--printf=%F", pathname}).CombinedOutput() outputBytes, err := n.ne.Exec("stat", []string{"-L", "--printf=%F", pathname}).CombinedOutput()
if err != nil { if err != nil {
if strings.Contains(string(outputBytes), "No such file") { if strings.Contains(string(outputBytes), "No such file") {
err = fmt.Errorf("%s does not exist", pathname) err = fmt.Errorf("%s does not exist", pathname)
@ -262,69 +266,80 @@ func (mounter *NsenterMounter) GetFileType(pathname string) (mount.FileType, err
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device") return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
} }
func (mounter *NsenterMounter) MakeDir(pathname string) error { // MakeDir creates a new directory.
func (n *Mounter) MakeDir(pathname string) error {
args := []string{"-p", pathname} args := []string{"-p", pathname}
if _, err := mounter.ne.Exec("mkdir", args).CombinedOutput(); err != nil { if _, err := n.ne.Exec("mkdir", args).CombinedOutput(); err != nil {
return err return err
} }
return nil return nil
} }
func (mounter *NsenterMounter) MakeFile(pathname string) error { // MakeFile creates an empty file.
func (n *Mounter) MakeFile(pathname string) error {
args := []string{pathname} args := []string{pathname}
if _, err := mounter.ne.Exec("touch", args).CombinedOutput(); err != nil { if _, err := n.ne.Exec("touch", args).CombinedOutput(); err != nil {
return err return err
} }
return nil return nil
} }
func (mounter *NsenterMounter) ExistsPath(pathname string) (bool, error) { // ExistsPath checks if pathname exists.
// Error is returned on any other error than "file not found".
func (n *Mounter) ExistsPath(pathname string) (bool, error) {
// Resolve the symlinks but allow the target not to exist. EvalSymlinks // Resolve the symlinks but allow the target not to exist. EvalSymlinks
// would return an generic error when the target does not exist. // would return an generic error when the target does not exist.
hostPath, err := mounter.ne.EvalSymlinks(pathname, false /* mustExist */) hostPath, err := n.ne.EvalSymlinks(pathname, false /* mustExist */)
if err != nil { if err != nil {
return false, err return false, err
} }
kubeletpath := mounter.ne.KubeletPath(hostPath) kubeletpath := n.ne.KubeletPath(hostPath)
return utilpath.Exists(utilpath.CheckFollowSymlink, kubeletpath) return utilpath.Exists(utilpath.CheckFollowSymlink, kubeletpath)
} }
func (mounter *NsenterMounter) EvalHostSymlinks(pathname string) (string, error) { // EvalHostSymlinks returns the path name after evaluating symlinks.
return mounter.ne.EvalSymlinks(pathname, true) func (n *Mounter) EvalHostSymlinks(pathname string) (string, error) {
return n.ne.EvalSymlinks(pathname, true)
} }
func (mounter *NsenterMounter) GetMountRefs(pathname string) ([]string, error) { // GetMountRefs finds all mount references to the path, returns a
// list of paths. Path could be a mountpoint path, device or a normal
// directory (for bind mount).
func (n *Mounter) GetMountRefs(pathname string) ([]string, error) {
pathExists, pathErr := mount.PathExists(pathname) pathExists, pathErr := mount.PathExists(pathname)
if !pathExists || mount.IsCorruptedMnt(pathErr) { if !pathExists || mount.IsCorruptedMnt(pathErr) {
return []string{}, nil return []string{}, nil
} else if pathErr != nil { } else if pathErr != nil {
return nil, fmt.Errorf("Error checking path %s: %v", pathname, pathErr) return nil, fmt.Errorf("Error checking path %s: %v", pathname, pathErr)
} }
hostpath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */) hostpath, err := n.ne.EvalSymlinks(pathname, true /* mustExist */)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return mount.SearchMountPoints(hostpath, hostProcMountinfoPath) return mount.SearchMountPoints(hostpath, hostProcMountinfoPath)
} }
func (mounter *NsenterMounter) GetFSGroup(pathname string) (int64, error) { // GetFSGroup returns FSGroup of pathname.
hostPath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */) func (n *Mounter) GetFSGroup(pathname string) (int64, error) {
hostPath, err := n.ne.EvalSymlinks(pathname, true /* mustExist */)
if err != nil { if err != nil {
return -1, err return -1, err
} }
kubeletpath := mounter.ne.KubeletPath(hostPath) kubeletpath := n.ne.KubeletPath(hostPath)
return mount.GetFSGroupLinux(kubeletpath) return mount.GetFSGroupLinux(kubeletpath)
} }
func (mounter *NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) { // GetSELinuxSupport tests if pathname is on a mount that supports SELinux.
func (n *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
return mount.GetSELinux(pathname, hostProcMountsPath) return mount.GetSELinux(pathname, hostProcMountsPath)
} }
func (mounter *NsenterMounter) GetMode(pathname string) (os.FileMode, error) { // GetMode returns permissions of pathname.
hostPath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */) func (n *Mounter) GetMode(pathname string) (os.FileMode, error) {
hostPath, err := n.ne.EvalSymlinks(pathname, true /* mustExist */)
if err != nil { if err != nil {
return 0, err return 0, err
} }
kubeletpath := mounter.ne.KubeletPath(hostPath) kubeletpath := n.ne.KubeletPath(hostPath)
return mount.GetModeLinux(kubeletpath) return mount.GetModeLinux(kubeletpath)
} }

View File

@ -74,7 +74,7 @@ func TestParseFindMnt(t *testing.T) {
} }
} }
func newFakeNsenterMounter(tmpdir string, t *testing.T) (mounter *NsenterMounter, rootfsPath string, varlibPath string, err error) { func newFakeNsenterMounter(tmpdir string, t *testing.T) (mounter *Mounter, rootfsPath string, varlibPath string, err error) {
rootfsPath = filepath.Join(tmpdir, "rootfs") rootfsPath = filepath.Join(tmpdir, "rootfs")
if err := os.Mkdir(rootfsPath, 0755); err != nil { if err := os.Mkdir(rootfsPath, 0755); err != nil {
return nil, "", "", err return nil, "", "", err
@ -89,7 +89,7 @@ func newFakeNsenterMounter(tmpdir string, t *testing.T) (mounter *NsenterMounter
return nil, "", "", err return nil, "", "", err
} }
return NewNsenterMounter(varlibPath, ne), rootfsPath, varlibPath, nil return NewMounter(varlibPath, ne), rootfsPath, varlibPath, nil
} }
func TestNsenterExistsFile(t *testing.T) { func TestNsenterExistsFile(t *testing.T) {

View File

@ -27,82 +27,113 @@ import (
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
) )
type NsenterMounter struct{} // Mounter provides the mount.Interface implementation for unsupported
// platforms.
type Mounter struct{}
func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter { // NewMounter returns a new Mounter for the current system
return &NsenterMounter{} func NewMounter(rootDir string, ne *nsenter.Nsenter) *Mounter {
return &Mounter{}
} }
var _ = mount.Interface(&NsenterMounter{}) var _ = mount.Interface(&Mounter{})
func (*NsenterMounter) Mount(source string, target string, fstype string, options []string) error { // Mount mounts the source to the target. It is a noop for unsupported systems
func (*Mounter) Mount(source string, target string, fstype string, options []string) error {
return nil return nil
} }
func (*NsenterMounter) Unmount(target string) error { // Unmount unmounts the target path from the system. it is a noop for unsupported
// systems
func (*Mounter) Unmount(target string) error {
return nil return nil
} }
func (*NsenterMounter) List() ([]mount.MountPoint, error) { // List returns a list of all mounted filesystems. It is a noop for unsupported systems
func (*Mounter) List() ([]mount.MountPoint, error) {
return []mount.MountPoint{}, nil return []mount.MountPoint{}, nil
} }
func (*NsenterMounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool { // IsMountPointMatch tests if dir and mp are the same path
func (*Mounter) IsMountPointMatch(mp mount.MountPoint, dir string) bool {
return (mp.Path == dir) return (mp.Path == dir)
} }
func (*NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) { // IsLikelyNotMountPoint determines if a directory is not a mountpoint.
// It is a noop on unsupported systems
func (*Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
return true, nil return true, nil
} }
func (*NsenterMounter) DeviceOpened(pathname string) (bool, error) { // DeviceOpened checks if block device in use. I tis a noop for unsupported systems
func (*Mounter) DeviceOpened(pathname string) (bool, error) {
return false, nil return false, nil
} }
func (*NsenterMounter) PathIsDevice(pathname string) (bool, error) { // PathIsDevice checks if pathname refers to a device. It is a noop for unsupported
// systems
func (*Mounter) PathIsDevice(pathname string) (bool, error) {
return true, nil return true, nil
} }
func (*NsenterMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { // GetDeviceNameFromMount finds the device name from its global mount point using the
// given mountpath and plugin location. It is a noop of unsupported platforms
func (*Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) {
return "", nil return "", nil
} }
func (*NsenterMounter) MakeRShared(path string) error { // MakeRShared checks if path is shared and bind-mounts it as rshared if needed.
// It is a noop on unsupported platforms
func (*Mounter) MakeRShared(path string) error {
return nil return nil
} }
func (*NsenterMounter) GetFileType(_ string) (mount.FileType, error) { // GetFileType checks for file/directory/socket/block/character devices.
// Always returns an error and "fake" filetype on unsupported platforms
func (*Mounter) GetFileType(_ string) (mount.FileType, error) {
return mount.FileType("fake"), errors.New("not implemented") return mount.FileType("fake"), errors.New("not implemented")
} }
func (*NsenterMounter) MakeDir(pathname string) error { // MakeDir creates a new directory. Noop on unsupported platforms
func (*Mounter) MakeDir(pathname string) error {
return nil return nil
} }
func (*NsenterMounter) MakeFile(pathname string) error { // MakeFile creats an empty file. Noop on unsupported platforms
func (*Mounter) MakeFile(pathname string) error {
return nil return nil
} }
func (*NsenterMounter) ExistsPath(pathname string) (bool, error) { // ExistsPath checks if pathname exists. Always returns an error on unsupported
// platforms
func (*Mounter) ExistsPath(pathname string) (bool, error) {
return true, errors.New("not implemented") return true, errors.New("not implemented")
} }
func (*NsenterMounter) EvalHostSymlinks(pathname string) (string, error) { // EvalHostSymlinks returns the path name after evaluating symlinks. Always
// returns an error on unsupported platforms
func (*Mounter) EvalHostSymlinks(pathname string) (string, error) {
return "", errors.New("not implemented") return "", errors.New("not implemented")
} }
func (*NsenterMounter) GetMountRefs(pathname string) ([]string, error) { // GetMountRefs finds all mount references to the path, returns a
// list of paths. Always returns an error on unsupported platforms
func (*Mounter) GetMountRefs(pathname string) ([]string, error) {
return nil, errors.New("not implemented") return nil, errors.New("not implemented")
} }
func (*NsenterMounter) GetFSGroup(pathname string) (int64, error) { // GetFSGroup returns FSGroup of pathname. Always returns an error on unsupported platforms
func (*Mounter) GetFSGroup(pathname string) (int64, error) {
return -1, errors.New("not implemented") return -1, errors.New("not implemented")
} }
func (*NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) { // GetSELinuxSupport tests if pathname is on a mount that supports SELinux.
// Always returns an error on unsupported platforms
func (*Mounter) GetSELinuxSupport(pathname string) (bool, error) {
return false, errors.New("not implemented") return false, errors.New("not implemented")
} }
func (*NsenterMounter) GetMode(pathname string) (os.FileMode, error) { // GetMode returns permissions of pathname. Always returns an error on unsupported platforms
func (*Mounter) GetMode(pathname string) (os.FileMode, error) {
return 0, errors.New("not implemented") return 0, errors.New("not implemented")
} }

View File

@ -106,7 +106,7 @@ func TestCheckDeviceInode(t *testing.T) {
} }
} }
func newFakeNsenterMounter(tmpdir string, t *testing.T) (*nsutil.NsenterMounter, string, string, *nsenter.Nsenter, error) { func newFakeNsenterMounter(tmpdir string, t *testing.T) (*nsutil.Mounter, string, string, *nsenter.Nsenter, error) {
rootfsPath := filepath.Join(tmpdir, "rootfs") rootfsPath := filepath.Join(tmpdir, "rootfs")
if err := os.Mkdir(rootfsPath, 0755); err != nil { if err := os.Mkdir(rootfsPath, 0755); err != nil {
return nil, "", "", nil, err return nil, "", "", nil, err
@ -121,7 +121,7 @@ func newFakeNsenterMounter(tmpdir string, t *testing.T) (*nsutil.NsenterMounter,
return nil, "", "", nil, err return nil, "", "", nil, err
} }
return nsutil.NewNsenterMounter(varlibPath, ne), rootfsPath, varlibPath, ne, nil return nsutil.NewMounter(varlibPath, ne), rootfsPath, varlibPath, ne, nil
} }
func TestNsenterSafeMakeDir(t *testing.T) { func TestNsenterSafeMakeDir(t *testing.T) {