Update go dependencies
This commit is contained in:
parent
d5cf22c129
commit
063cc68d1c
1321 changed files with 52830 additions and 31081 deletions
1
vendor/k8s.io/kubernetes/pkg/util/BUILD
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/util/BUILD
generated
vendored
|
|
@ -45,6 +45,7 @@ filegroup(
|
|||
"//pkg/util/nsenter:all-srcs",
|
||||
"//pkg/util/oom:all-srcs",
|
||||
"//pkg/util/parsers:all-srcs",
|
||||
"//pkg/util/pod:all-srcs",
|
||||
"//pkg/util/pointer:all-srcs",
|
||||
"//pkg/util/procfs:all-srcs",
|
||||
"//pkg/util/reflector/prometheus:all-srcs",
|
||||
|
|
|
|||
5
vendor/k8s.io/kubernetes/pkg/util/filesystem/defaultfs.go
generated
vendored
5
vendor/k8s.io/kubernetes/pkg/util/filesystem/defaultfs.go
generated
vendored
|
|
@ -72,6 +72,11 @@ func (DefaultFs) ReadFile(filename string) ([]byte, error) {
|
|||
return ioutil.ReadFile(filename)
|
||||
}
|
||||
|
||||
// TempDir via ioutil.TempDir
|
||||
func (DefaultFs) TempDir(dir, prefix string) (string, error) {
|
||||
return ioutil.TempDir(dir, prefix)
|
||||
}
|
||||
|
||||
// TempFile via ioutil.TempFile
|
||||
func (DefaultFs) TempFile(dir, prefix string) (File, error) {
|
||||
file, err := ioutil.TempFile(dir, prefix)
|
||||
|
|
|
|||
5
vendor/k8s.io/kubernetes/pkg/util/filesystem/fakefs.go
generated
vendored
5
vendor/k8s.io/kubernetes/pkg/util/filesystem/fakefs.go
generated
vendored
|
|
@ -68,6 +68,11 @@ func (fs *fakeFs) ReadFile(filename string) ([]byte, error) {
|
|||
return fs.a.ReadFile(filename)
|
||||
}
|
||||
|
||||
// TempDir via afero.TempDir
|
||||
func (fs *fakeFs) TempDir(dir, prefix string) (string, error) {
|
||||
return fs.a.TempDir(dir, prefix)
|
||||
}
|
||||
|
||||
// TempFile via afero.TempFile
|
||||
func (fs *fakeFs) TempFile(dir, prefix string) (File, error) {
|
||||
file, err := fs.a.TempFile(dir, prefix)
|
||||
|
|
|
|||
1
vendor/k8s.io/kubernetes/pkg/util/filesystem/filesystem.go
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/util/filesystem/filesystem.go
generated
vendored
|
|
@ -35,6 +35,7 @@ type Filesystem interface {
|
|||
|
||||
// from "io/ioutil"
|
||||
ReadFile(filename string) ([]byte, error)
|
||||
TempDir(dir, prefix string) (string, error)
|
||||
TempFile(dir, prefix string) (File, error)
|
||||
ReadDir(dirname string) ([]os.FileInfo, error)
|
||||
Walk(root string, walkFn filepath.WalkFunc) error
|
||||
|
|
|
|||
17
vendor/k8s.io/kubernetes/pkg/util/io/writer.go
generated
vendored
17
vendor/k8s.io/kubernetes/pkg/util/io/writer.go
generated
vendored
|
|
@ -50,15 +50,24 @@ func (writer *StdWriter) WriteFile(filename string, data []byte, perm os.FileMod
|
|||
// it will not see the mounted device in its own namespace. To work around this
|
||||
// limitation one has to first enter hosts namespace (by using 'nsenter') and
|
||||
// only then write data.
|
||||
type NsenterWriter struct{}
|
||||
type NsenterWriter struct {
|
||||
ne *nsenter.Nsenter
|
||||
}
|
||||
|
||||
// NewNsenterWriter creates a new Writer that allows writing data to file using
|
||||
// nsenter command.
|
||||
func NewNsenterWriter(ne *nsenter.Nsenter) *NsenterWriter {
|
||||
return &NsenterWriter{
|
||||
ne: ne,
|
||||
}
|
||||
}
|
||||
|
||||
// WriteFile calls 'nsenter cat - > <the file>' and 'nsenter chmod' to create a
|
||||
// file on the host.
|
||||
func (writer *NsenterWriter) WriteFile(filename string, data []byte, perm os.FileMode) error {
|
||||
ne := nsenter.NewNsenter()
|
||||
echoArgs := []string{"-c", fmt.Sprintf("cat > %s", filename)}
|
||||
glog.V(5).Infof("nsenter: write data to file %s by nsenter", filename)
|
||||
command := ne.Exec("sh", echoArgs)
|
||||
command := writer.ne.Exec("sh", echoArgs)
|
||||
command.SetStdin(bytes.NewBuffer(data))
|
||||
outputBytes, err := command.CombinedOutput()
|
||||
if err != nil {
|
||||
|
|
@ -68,7 +77,7 @@ func (writer *NsenterWriter) WriteFile(filename string, data []byte, perm os.Fil
|
|||
|
||||
chmodArgs := []string{fmt.Sprintf("%o", perm), filename}
|
||||
glog.V(5).Infof("nsenter: change permissions of file %s to %s", filename, chmodArgs[0])
|
||||
outputBytes, err = ne.Exec("chmod", chmodArgs).CombinedOutput()
|
||||
outputBytes, err = writer.ne.Exec("chmod", chmodArgs).CombinedOutput()
|
||||
if err != nil {
|
||||
glog.Errorf("Output from chmod command: %v", string(outputBytes))
|
||||
return err
|
||||
|
|
|
|||
34
vendor/k8s.io/kubernetes/pkg/util/mount/BUILD
generated
vendored
34
vendor/k8s.io/kubernetes/pkg/util/mount/BUILD
generated
vendored
|
|
@ -71,12 +71,44 @@ go_library(
|
|||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:android": [
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:darwin": [
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:dragonfly": [
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:freebsd": [
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//pkg/util/file:go_default_library",
|
||||
"//pkg/util/io:go_default_library",
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:nacl": [
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:netbsd": [
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:openbsd": [
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:plan9": [
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:solaris": [
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"//pkg/util/file:go_default_library",
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
|
@ -101,7 +133,9 @@ go_test(
|
|||
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//pkg/util/nsenter:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
|
|
|
|||
1
vendor/k8s.io/kubernetes/pkg/util/mount/OWNERS
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/util/mount/OWNERS
generated
vendored
|
|
@ -3,6 +3,7 @@ reviewers:
|
|||
- saad-ali
|
||||
- jsafrane
|
||||
- msau42
|
||||
- andyzhangx
|
||||
approvers:
|
||||
- jingxu97
|
||||
- saad-ali
|
||||
|
|
|
|||
18
vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount.go
generated
vendored
18
vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount.go
generated
vendored
|
|
@ -136,7 +136,7 @@ func (m *execMounter) MakeDir(pathname string) error {
|
|||
return m.wrappedMounter.MakeDir(pathname)
|
||||
}
|
||||
|
||||
func (m *execMounter) ExistsPath(pathname string) bool {
|
||||
func (m *execMounter) ExistsPath(pathname string) (bool, error) {
|
||||
return m.wrappedMounter.ExistsPath(pathname)
|
||||
}
|
||||
|
||||
|
|
@ -151,3 +151,19 @@ func (m *execMounter) CleanSubPaths(podDir string, volumeName string) error {
|
|||
func (m *execMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
return m.wrappedMounter.SafeMakeDir(pathname, base, perm)
|
||||
}
|
||||
|
||||
func (m *execMounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
return m.wrappedMounter.GetMountRefs(pathname)
|
||||
}
|
||||
|
||||
func (m *execMounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return m.wrappedMounter.GetFSGroup(pathname)
|
||||
}
|
||||
|
||||
func (m *execMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return m.wrappedMounter.GetSELinuxSupport(pathname)
|
||||
}
|
||||
|
||||
func (m *execMounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
return m.wrappedMounter.GetMode(pathname)
|
||||
}
|
||||
|
|
|
|||
20
vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount_unsupported.go
generated
vendored
20
vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount_unsupported.go
generated
vendored
|
|
@ -83,8 +83,8 @@ func (mounter *execMounter) MakeFile(pathname string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (mounter *execMounter) ExistsPath(pathname string) bool {
|
||||
return true
|
||||
func (mounter *execMounter) ExistsPath(pathname string) (bool, error) {
|
||||
return true, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *execMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) {
|
||||
|
|
@ -98,3 +98,19 @@ func (mounter *execMounter) CleanSubPaths(podDir string, volumeName string) erro
|
|||
func (mounter *execMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mounter *execMounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *execMounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return -1, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *execMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *execMounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
return 0, errors.New("not implemented")
|
||||
}
|
||||
|
|
|
|||
26
vendor/k8s.io/kubernetes/pkg/util/mount/fake.go
generated
vendored
26
vendor/k8s.io/kubernetes/pkg/util/mount/fake.go
generated
vendored
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package mount
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
|
@ -200,8 +201,8 @@ func (f *FakeMounter) MakeFile(pathname string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) ExistsPath(pathname string) bool {
|
||||
return false
|
||||
func (f *FakeMounter) ExistsPath(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (f *FakeMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) {
|
||||
|
|
@ -214,3 +215,24 @@ func (f *FakeMounter) CleanSubPaths(podDir string, volumeName string) error {
|
|||
func (mounter *FakeMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeMounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
realpath, err := filepath.EvalSymlinks(pathname)
|
||||
if err != nil {
|
||||
// Ignore error in FakeMounter, because we actually didn't create files.
|
||||
realpath = pathname
|
||||
}
|
||||
return getMountRefsByDev(f, realpath)
|
||||
}
|
||||
|
||||
func (f *FakeMounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return -1, errors.New("GetFSGroup not implemented")
|
||||
}
|
||||
|
||||
func (f *FakeMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("GetSELinuxSupport not implemented")
|
||||
}
|
||||
|
||||
func (f *FakeMounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
return 0, errors.New("not implemented")
|
||||
}
|
||||
|
|
|
|||
60
vendor/k8s.io/kubernetes/pkg/util/mount/mount.go
generated
vendored
60
vendor/k8s.io/kubernetes/pkg/util/mount/mount.go
generated
vendored
|
|
@ -23,7 +23,6 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type FileType string
|
||||
|
|
@ -85,16 +84,18 @@ type Interface interface {
|
|||
// MakeDir creates a new directory.
|
||||
// Will operate in the host mount namespace if kubelet is running in a container
|
||||
MakeDir(pathname string) error
|
||||
// SafeMakeDir makes sure that the created directory does not escape given
|
||||
// base directory mis-using symlinks. The directory is created in the same
|
||||
// mount namespace as where kubelet is running. Note that the function makes
|
||||
// sure that it creates the directory somewhere under the base, nothing
|
||||
// else. E.g. if the directory already exists, it may exists outside of the
|
||||
// base due to symlinks.
|
||||
SafeMakeDir(pathname string, base string, perm os.FileMode) error
|
||||
// ExistsPath checks whether the path exists.
|
||||
// Will operate in the host mount namespace if kubelet is running in a container
|
||||
ExistsPath(pathname string) bool
|
||||
// SafeMakeDir creates subdir within given base. It makes sure that the
|
||||
// created directory does not escape given base directory mis-using
|
||||
// symlinks. Note that the function makes sure that it creates the directory
|
||||
// somewhere under the base, nothing else. E.g. if the directory already
|
||||
// exists, it may exist outside of the base due to symlinks.
|
||||
// This method should be used if the directory to create is inside volume
|
||||
// that's under user control. User must not be able to use symlinks to
|
||||
// escape the volume to create directories somewhere else.
|
||||
SafeMakeDir(subdir string, base string, perm os.FileMode) error
|
||||
// Will operate in the host mount namespace if kubelet is running in a container.
|
||||
// Error is returned on any other error than "file not found".
|
||||
ExistsPath(pathname string) (bool, error)
|
||||
// CleanSubPaths removes any bind-mounts created by PrepareSafeSubpath in given
|
||||
// pod volume directory.
|
||||
CleanSubPaths(podDir string, volumeName string) error
|
||||
|
|
@ -109,6 +110,17 @@ type Interface interface {
|
|||
// subpath starts. On the other hand, Interface.CleanSubPaths must be called
|
||||
// when the pod finishes.
|
||||
PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err 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).
|
||||
GetMountRefs(pathname string) ([]string, error)
|
||||
// GetFSGroup returns FSGroup of the path.
|
||||
GetFSGroup(pathname string) (int64, error)
|
||||
// GetSELinuxSupport returns true if given path is on a mount that supports
|
||||
// SELinux.
|
||||
GetSELinuxSupport(pathname string) (bool, error)
|
||||
// GetMode returns permissions of the path.
|
||||
GetMode(pathname string) (os.FileMode, error)
|
||||
}
|
||||
|
||||
type Subpath struct {
|
||||
|
|
@ -124,8 +136,6 @@ type Subpath struct {
|
|||
PodDir string
|
||||
// Name of the container
|
||||
ContainerName string
|
||||
// True if the mount needs to be readonly
|
||||
ReadOnly bool
|
||||
}
|
||||
|
||||
// Exec executes command where mount utilities are. This can be either the host,
|
||||
|
|
@ -169,22 +179,19 @@ func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string,
|
|||
return mounter.formatAndMount(source, target, fstype, options)
|
||||
}
|
||||
|
||||
// GetMountRefsByDev finds all references to the device provided
|
||||
// getMountRefsByDev finds all references to the device provided
|
||||
// by mountPath; returns a list of paths.
|
||||
func GetMountRefsByDev(mounter Interface, mountPath string) ([]string, error) {
|
||||
// Note that mountPath should be path after the evaluation of any symblolic links.
|
||||
func getMountRefsByDev(mounter Interface, mountPath string) ([]string, error) {
|
||||
mps, err := mounter.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
slTarget, err := filepath.EvalSymlinks(mountPath)
|
||||
if err != nil {
|
||||
slTarget = mountPath
|
||||
}
|
||||
|
||||
// Finding the device mounted to mountPath
|
||||
diskDev := ""
|
||||
for i := range mps {
|
||||
if slTarget == mps[i].Path {
|
||||
if mountPath == mps[i].Path {
|
||||
diskDev = mps[i].Device
|
||||
break
|
||||
}
|
||||
|
|
@ -193,8 +200,8 @@ func GetMountRefsByDev(mounter Interface, mountPath string) ([]string, error) {
|
|||
// Find all references to the device.
|
||||
var refs []string
|
||||
for i := range mps {
|
||||
if mps[i].Device == diskDev || mps[i].Device == slTarget {
|
||||
if mps[i].Path != slTarget {
|
||||
if mps[i].Device == diskDev || mps[i].Device == mountPath {
|
||||
if mps[i].Path != mountPath {
|
||||
refs = append(refs, mps[i].Path)
|
||||
}
|
||||
}
|
||||
|
|
@ -235,13 +242,6 @@ func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, e
|
|||
return device, refCount, nil
|
||||
}
|
||||
|
||||
func isNotDirErr(err error) bool {
|
||||
if e, ok := err.(*os.PathError); ok && e.Err == syscall.ENOTDIR {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsNotMountPoint determines if a directory is a mountpoint.
|
||||
// It should return ErrNotExist when the directory does not exist.
|
||||
// This method uses the List() of all mountpoints
|
||||
|
|
@ -257,7 +257,7 @@ func IsNotMountPoint(mounter Interface, file string) (bool, error) {
|
|||
notMnt = true
|
||||
notMntErr = nil
|
||||
}
|
||||
if notMntErr != nil && isNotDirErr(notMntErr) {
|
||||
if notMntErr != nil {
|
||||
return notMnt, notMntErr
|
||||
}
|
||||
// identified as mountpoint, so return this fact
|
||||
|
|
|
|||
404
vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go
generated
vendored
404
vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go
generated
vendored
|
|
@ -33,6 +33,7 @@ import (
|
|||
"github.com/golang/glog"
|
||||
"golang.org/x/sys/unix"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
||||
utilio "k8s.io/kubernetes/pkg/util/io"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
|
@ -42,6 +43,8 @@ const (
|
|||
maxListTries = 3
|
||||
// Number of fields per line in /proc/mounts as per the fstab man page.
|
||||
expectedNumFieldsPerLine = 6
|
||||
// At least number of fields per line in /proc/<pid>/mountinfo.
|
||||
expectedAtLeastNumFieldsPerMountInfo = 10
|
||||
// Location of the mount file to use
|
||||
procMountsPath = "/proc/mounts"
|
||||
// Location of the mountinfo file
|
||||
|
|
@ -447,12 +450,8 @@ func (mounter *Mounter) MakeFile(pathname string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) ExistsPath(pathname string) bool {
|
||||
_, err := os.Stat(pathname)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
||||
return utilfile.FileExists(pathname)
|
||||
}
|
||||
|
||||
// formatAndMount uses unix utils to format and mount the given disk
|
||||
|
|
@ -511,7 +510,11 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||
}
|
||||
|
||||
if fstype == "ext4" || fstype == "ext3" {
|
||||
args = []string{"-F", source}
|
||||
args = []string{
|
||||
"-F", // Force flag
|
||||
"-m0", // Zero blocks reserved for super-user
|
||||
source,
|
||||
}
|
||||
}
|
||||
glog.Infof("Disk %q appears to be unformatted, attempting to format as type: %q with options: %v", source, fstype, args)
|
||||
_, err := mounter.Exec.Run("mkfs."+fstype, args...)
|
||||
|
|
@ -591,27 +594,14 @@ func (mounter *SafeFormatAndMount) GetDiskFormat(disk string) (string, error) {
|
|||
|
||||
// isShared returns true, if given path is on a mount point that has shared
|
||||
// mount propagation.
|
||||
func isShared(path string, filename string) (bool, error) {
|
||||
infos, err := parseMountInfo(filename)
|
||||
func isShared(mount string, mountInfoPath string) (bool, error) {
|
||||
info, err := findMountInfo(mount, mountInfoPath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// process /proc/xxx/mountinfo in backward order and find the first mount
|
||||
// point that is prefix of 'path' - that's the mount where path resides
|
||||
var info *mountInfo
|
||||
for i := len(infos) - 1; i >= 0; i-- {
|
||||
if strings.HasPrefix(path, infos[i].mountPoint) {
|
||||
info = &infos[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if info == nil {
|
||||
return false, fmt.Errorf("cannot find mount point for %q", path)
|
||||
}
|
||||
|
||||
// parse optional parameters
|
||||
for _, opt := range info.optional {
|
||||
for _, opt := range info.optionalFields {
|
||||
if strings.HasPrefix(opt, "shared:") {
|
||||
return true, nil
|
||||
}
|
||||
|
|
@ -619,11 +609,28 @@ func isShared(path string, filename string) (bool, error) {
|
|||
return false, nil
|
||||
}
|
||||
|
||||
// This represents a single line in /proc/<pid>/mountinfo.
|
||||
type mountInfo struct {
|
||||
// Path of the mount point
|
||||
// Unique ID for the mount (maybe reused after umount).
|
||||
id int
|
||||
// The ID of the parent mount (or of self for the root of this mount namespace's mount tree).
|
||||
parentID int
|
||||
// The value of `st_dev` for files on this filesystem.
|
||||
majorMinor string
|
||||
// The pathname of the directory in the filesystem which forms the root of this mount.
|
||||
root string
|
||||
// Mount source, filesystem-specific information. e.g. device, tmpfs name.
|
||||
source string
|
||||
// Mount point, the pathname of the mount point.
|
||||
mountPoint string
|
||||
// list of "optional parameters", mount propagation is one of them
|
||||
optional []string
|
||||
// Optional fieds, zero or more fields of the form "tag[:value]".
|
||||
optionalFields []string
|
||||
// The filesystem type in the form "type[.subtype]".
|
||||
fsType string
|
||||
// Per-mount options.
|
||||
mountOptions []string
|
||||
// Per-superblock options.
|
||||
superOptions []string
|
||||
}
|
||||
|
||||
// parseMountInfo parses /proc/xxx/mountinfo.
|
||||
|
|
@ -642,22 +649,64 @@ func parseMountInfo(filename string) ([]mountInfo, error) {
|
|||
}
|
||||
// See `man proc` for authoritative description of format of the file.
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 7 {
|
||||
return nil, fmt.Errorf("wrong number of fields in (expected %d, got %d): %s", 8, len(fields), line)
|
||||
if len(fields) < expectedAtLeastNumFieldsPerMountInfo {
|
||||
return nil, fmt.Errorf("wrong number of fields in (expected at least %d, got %d): %s", expectedAtLeastNumFieldsPerMountInfo, len(fields), line)
|
||||
}
|
||||
id, err := strconv.Atoi(fields[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parentID, err := strconv.Atoi(fields[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info := mountInfo{
|
||||
mountPoint: fields[4],
|
||||
optional: []string{},
|
||||
id: id,
|
||||
parentID: parentID,
|
||||
majorMinor: fields[2],
|
||||
root: fields[3],
|
||||
mountPoint: fields[4],
|
||||
mountOptions: strings.Split(fields[5], ","),
|
||||
}
|
||||
// All fields until "-" are "optional fields".
|
||||
for i := 6; i < len(fields) && fields[i] != "-"; i++ {
|
||||
info.optional = append(info.optional, fields[i])
|
||||
i := 6
|
||||
for ; i < len(fields) && fields[i] != "-"; i++ {
|
||||
info.optionalFields = append(info.optionalFields, fields[i])
|
||||
}
|
||||
// Parse the rest 3 fields.
|
||||
i += 1
|
||||
if len(fields)-i < 3 {
|
||||
return nil, fmt.Errorf("expect 3 fields in %s, got %d", line, len(fields)-i)
|
||||
}
|
||||
info.fsType = fields[i]
|
||||
info.source = fields[i+1]
|
||||
info.superOptions = strings.Split(fields[i+2], ",")
|
||||
infos = append(infos, info)
|
||||
}
|
||||
return infos, nil
|
||||
}
|
||||
|
||||
func findMountInfo(path, mountInfoPath string) (mountInfo, error) {
|
||||
infos, err := parseMountInfo(mountInfoPath)
|
||||
if err != nil {
|
||||
return mountInfo{}, err
|
||||
}
|
||||
|
||||
// process /proc/xxx/mountinfo in backward order and find the first mount
|
||||
// point that is prefix of 'path' - that's the mount where path resides
|
||||
var info *mountInfo
|
||||
for i := len(infos) - 1; i >= 0; i-- {
|
||||
if pathWithinBase(path, infos[i].mountPoint) {
|
||||
info = &infos[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if info == nil {
|
||||
return mountInfo{}, fmt.Errorf("cannot find mount point for %q", path)
|
||||
}
|
||||
return *info, nil
|
||||
}
|
||||
|
||||
// doMakeRShared is common implementation of MakeRShared on Linux. It checks if
|
||||
// path is shared and bind-mounts it as rshared if needed. mountCmd and
|
||||
// mountArgs are expected to contain mount-like command, doMakeRShared will add
|
||||
|
|
@ -686,8 +735,30 @@ func doMakeRShared(path string, mountInfoFilename string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// getSELinuxSupport is common implementation of GetSELinuxSupport on Linux.
|
||||
func getSELinuxSupport(path string, mountInfoFilename string) (bool, error) {
|
||||
info, err := findMountInfo(path, mountInfoFilename)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// "seclabel" can be both in mount options and super options.
|
||||
for _, opt := range info.superOptions {
|
||||
if opt == "seclabel" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
for _, opt := range info.mountOptions {
|
||||
if opt == "seclabel" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) {
|
||||
newHostPath, err = doBindSubPath(mounter, subPath, os.Getpid())
|
||||
newHostPath, err = doBindSubPath(mounter, subPath)
|
||||
|
||||
// There is no action when the container starts. Bind-mount will be cleaned
|
||||
// when container stops by CleanSubPaths.
|
||||
cleanupAction = nil
|
||||
|
|
@ -695,30 +766,107 @@ func (mounter *Mounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string,
|
|||
}
|
||||
|
||||
// This implementation is shared between Linux and NsEnterMounter
|
||||
// kubeletPid is PID of kubelet in the PID namespace where bind-mount is done,
|
||||
// i.e. pid on the *host* if kubelet runs in a container.
|
||||
func doBindSubPath(mounter Interface, subpath Subpath, kubeletPid int) (hostPath string, err error) {
|
||||
// Check early for symlink. This is just a pre-check to avoid bind-mount
|
||||
// before the final check.
|
||||
evalSubPath, err := filepath.EvalSymlinks(subpath.Path)
|
||||
func safeOpenSubPath(mounter Interface, subpath Subpath) (int, error) {
|
||||
if !pathWithinBase(subpath.Path, subpath.VolumePath) {
|
||||
return -1, fmt.Errorf("subpath %q not within volume path %q", subpath.Path, subpath.VolumePath)
|
||||
}
|
||||
fd, err := doSafeOpen(subpath.Path, subpath.VolumePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("evalSymlinks %q failed: %v", subpath.Path, err)
|
||||
return -1, fmt.Errorf("error opening subpath %v: %v", subpath.Path, err)
|
||||
}
|
||||
glog.V(5).Infof("doBindSubPath %q, full subpath %q for volumepath %q", subpath.Path, evalSubPath, subpath.VolumePath)
|
||||
return fd, nil
|
||||
}
|
||||
|
||||
evalSubPath = filepath.Clean(evalSubPath)
|
||||
if !pathWithinBase(evalSubPath, subpath.VolumePath) {
|
||||
return "", fmt.Errorf("subpath %q not within volume path %q", evalSubPath, subpath.VolumePath)
|
||||
// prepareSubpathTarget creates target for bind-mount of subpath. It returns
|
||||
// "true" when the target already exists and something is mounted there.
|
||||
// Given Subpath must have all paths with already resolved symlinks and with
|
||||
// paths relevant to kubelet (when it runs in a container).
|
||||
// This function is called also by NsEnterMounter. It works because
|
||||
// /var/lib/kubelet is mounted from the host into the container with Kubelet as
|
||||
// /var/lib/kubelet too.
|
||||
func prepareSubpathTarget(mounter Interface, subpath Subpath) (bool, string, error) {
|
||||
// Early check for already bind-mounted subpath.
|
||||
bindPathTarget := getSubpathBindTarget(subpath)
|
||||
notMount, err := IsNotMountPoint(mounter, bindPathTarget)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return false, "", fmt.Errorf("error checking path %s for mount: %s", bindPathTarget, err)
|
||||
}
|
||||
// Ignore ErrorNotExist: the file/directory will be created below if it does not exist yet.
|
||||
notMount = true
|
||||
}
|
||||
if !notMount {
|
||||
// It's already mounted
|
||||
glog.V(5).Infof("Skipping bind-mounting subpath %s: already mounted", bindPathTarget)
|
||||
return true, bindPathTarget, nil
|
||||
}
|
||||
|
||||
// Prepare directory for bind mounts
|
||||
// containerName is DNS label, i.e. safe as a directory name.
|
||||
bindDir := filepath.Join(subpath.PodDir, containerSubPathDirectoryName, subpath.VolumeName, subpath.ContainerName)
|
||||
err = os.MkdirAll(bindDir, 0750)
|
||||
// bindPathTarget is in /var/lib/kubelet and thus reachable without any
|
||||
// translation even to containerized kubelet.
|
||||
bindParent := filepath.Dir(bindPathTarget)
|
||||
err = os.MkdirAll(bindParent, 0750)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return "", fmt.Errorf("error creating directory %s: %s", bindDir, err)
|
||||
return false, "", fmt.Errorf("error creating directory %s: %s", bindParent, err)
|
||||
}
|
||||
|
||||
t, err := os.Lstat(subpath.Path)
|
||||
if err != nil {
|
||||
return false, "", fmt.Errorf("lstat %s failed: %s", subpath.Path, err)
|
||||
}
|
||||
|
||||
if t.Mode()&os.ModeDir > 0 {
|
||||
if err = os.Mkdir(bindPathTarget, 0750); err != nil && !os.IsExist(err) {
|
||||
return false, "", fmt.Errorf("error creating directory %s: %s", bindPathTarget, err)
|
||||
}
|
||||
} else {
|
||||
// "/bin/touch <bindPathTarget>".
|
||||
// A file is enough for all possible targets (symlink, device, pipe,
|
||||
// socket, ...), bind-mounting them into a file correctly changes type
|
||||
// of the target file.
|
||||
if err = ioutil.WriteFile(bindPathTarget, []byte{}, 0640); err != nil {
|
||||
return false, "", fmt.Errorf("error creating file %s: %s", bindPathTarget, err)
|
||||
}
|
||||
}
|
||||
return false, bindPathTarget, nil
|
||||
}
|
||||
|
||||
func getSubpathBindTarget(subpath Subpath) string {
|
||||
// containerName is DNS label, i.e. safe as a directory name.
|
||||
return filepath.Join(subpath.PodDir, containerSubPathDirectoryName, subpath.VolumeName, subpath.ContainerName, strconv.Itoa(subpath.VolumeMountIndex))
|
||||
}
|
||||
|
||||
func doBindSubPath(mounter Interface, subpath Subpath) (hostPath string, err error) {
|
||||
// Linux, kubelet runs on the host:
|
||||
// - safely open the subpath
|
||||
// - bind-mount /proc/<pid of kubelet>/fd/<fd> to subpath target
|
||||
// User can't change /proc/<pid of kubelet>/fd/<fd> to point to a bad place.
|
||||
|
||||
// Evaluate all symlinks here once for all subsequent functions.
|
||||
newVolumePath, err := filepath.EvalSymlinks(subpath.VolumePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error resolving symlinks in %q: %v", subpath.VolumePath, err)
|
||||
}
|
||||
newPath, err := filepath.EvalSymlinks(subpath.Path)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error resolving symlinks in %q: %v", subpath.Path, err)
|
||||
}
|
||||
glog.V(5).Infof("doBindSubPath %q (%q) for volumepath %q", subpath.Path, newPath, subpath.VolumePath)
|
||||
subpath.VolumePath = newVolumePath
|
||||
subpath.Path = newPath
|
||||
|
||||
fd, err := safeOpenSubPath(mounter, subpath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer syscall.Close(fd)
|
||||
|
||||
alreadyMounted, bindPathTarget, err := prepareSubpathTarget(mounter, subpath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if alreadyMounted {
|
||||
return bindPathTarget, nil
|
||||
}
|
||||
bindPathTarget := filepath.Join(bindDir, strconv.Itoa(subpath.VolumeMountIndex))
|
||||
|
||||
success := false
|
||||
defer func() {
|
||||
|
|
@ -731,63 +879,17 @@ func doBindSubPath(mounter Interface, subpath Subpath, kubeletPid int) (hostPath
|
|||
}
|
||||
}()
|
||||
|
||||
// Check it's not already bind-mounted
|
||||
notMount, err := IsNotMountPoint(mounter, bindPathTarget)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return "", fmt.Errorf("error checking path %s for mount: %s", bindPathTarget, err)
|
||||
}
|
||||
// Ignore ErrorNotExist: the file/directory will be created below if it does not exist yet.
|
||||
notMount = true
|
||||
}
|
||||
if !notMount {
|
||||
// It's already mounted
|
||||
glog.V(5).Infof("Skipping bind-mounting subpath %s: already mounted", bindPathTarget)
|
||||
success = true
|
||||
return bindPathTarget, nil
|
||||
}
|
||||
|
||||
// Create target of the bind mount. A directory for directories, empty file
|
||||
// for everything else.
|
||||
t, err := os.Lstat(subpath.Path)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("lstat %s failed: %s", subpath.Path, err)
|
||||
}
|
||||
if t.Mode()&os.ModeDir > 0 {
|
||||
if err = os.Mkdir(bindPathTarget, 0750); err != nil && !os.IsExist(err) {
|
||||
return "", fmt.Errorf("error creating directory %s: %s", bindPathTarget, err)
|
||||
}
|
||||
} else {
|
||||
// "/bin/touch <bindDir>".
|
||||
// A file is enough for all possible targets (symlink, device, pipe,
|
||||
// socket, ...), bind-mounting them into a file correctly changes type
|
||||
// of the target file.
|
||||
if err = ioutil.WriteFile(bindPathTarget, []byte{}, 0640); err != nil {
|
||||
return "", fmt.Errorf("error creating file %s: %s", bindPathTarget, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Safe open subpath and get the fd
|
||||
fd, err := doSafeOpen(evalSubPath, subpath.VolumePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error opening subpath %v: %v", evalSubPath, err)
|
||||
}
|
||||
defer syscall.Close(fd)
|
||||
|
||||
kubeletPid := os.Getpid()
|
||||
mountSource := fmt.Sprintf("/proc/%d/fd/%v", kubeletPid, fd)
|
||||
|
||||
// Do the bind mount
|
||||
options := []string{"bind"}
|
||||
if subpath.ReadOnly {
|
||||
options = append(options, "ro")
|
||||
}
|
||||
|
||||
glog.V(5).Infof("bind mounting %q at %q", mountSource, bindPathTarget)
|
||||
if err = mounter.Mount(mountSource, bindPathTarget, "" /*fstype*/, options); err != nil {
|
||||
return "", fmt.Errorf("error mounting %s: %s", subpath.Path, err)
|
||||
}
|
||||
|
||||
success = true
|
||||
|
||||
glog.V(3).Infof("Bound SubPath %s into %s", subpath.Path, bindPathTarget)
|
||||
return bindPathTarget, nil
|
||||
}
|
||||
|
|
@ -922,11 +1024,62 @@ func removeEmptyDirs(baseDir, endDir string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
return doSafeMakeDir(pathname, base, perm)
|
||||
func (mounter *Mounter) SafeMakeDir(subdir string, base string, perm os.FileMode) error {
|
||||
realBase, err := filepath.EvalSymlinks(base)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error resolving symlinks in %s: %s", base, err)
|
||||
}
|
||||
|
||||
realFullPath := filepath.Join(realBase, subdir)
|
||||
|
||||
return doSafeMakeDir(realFullPath, realBase, perm)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
realpath, err := filepath.EvalSymlinks(pathname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return searchMountPoints(realpath, procMountInfoPath)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return getSELinuxSupport(pathname, procMountInfoPath)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) {
|
||||
realpath, err := filepath.EvalSymlinks(pathname)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return getFSGroup(realpath)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
return getMode(pathname)
|
||||
}
|
||||
|
||||
// This implementation is shared between Linux and NsEnterMounter
|
||||
func getFSGroup(pathname string) (int64, error) {
|
||||
info, err := os.Stat(pathname)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(info.Sys().(*syscall.Stat_t).Gid), nil
|
||||
}
|
||||
|
||||
// This implementation is shared between Linux and NsEnterMounter
|
||||
func getMode(pathname string) (os.FileMode, error) {
|
||||
info, err := os.Stat(pathname)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return info.Mode(), nil
|
||||
}
|
||||
|
||||
// This implementation is shared between Linux and NsEnterMounter. Both pathname
|
||||
// and base must be either already resolved symlinks or thet will be resolved in
|
||||
// kubelet's mount namespace (in case it runs containerized).
|
||||
func doSafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
glog.V(4).Infof("Creating directory %q within base %q", pathname, base)
|
||||
|
||||
|
|
@ -1080,6 +1233,9 @@ func findExistingPrefix(base, pathname string) (string, []string, error) {
|
|||
// Symlinks are disallowed (pathname must already resolve symlinks),
|
||||
// and the path must be within the base directory.
|
||||
func doSafeOpen(pathname string, base string) (int, error) {
|
||||
pathname = filepath.Clean(pathname)
|
||||
base = filepath.Clean(base)
|
||||
|
||||
// Calculate segments to follow
|
||||
subpath, err := filepath.Rel(base, pathname)
|
||||
if err != nil {
|
||||
|
|
@ -1151,3 +1307,51 @@ func doSafeOpen(pathname string, base string) (int, error) {
|
|||
|
||||
return finalFD, nil
|
||||
}
|
||||
|
||||
// searchMountPoints finds all mount references to the source, returns a list of
|
||||
// mountpoints.
|
||||
// This function assumes source cannot be device.
|
||||
// Some filesystems may share a source name, e.g. tmpfs. And for bind mounting,
|
||||
// it's possible to mount a non-root path of a filesystem, so we need to use
|
||||
// root path and major:minor to represent mount source uniquely.
|
||||
// This implementation is shared between Linux and NsEnterMounter
|
||||
func searchMountPoints(hostSource, mountInfoPath string) ([]string, error) {
|
||||
mis, err := parseMountInfo(mountInfoPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mountID := 0
|
||||
rootPath := ""
|
||||
majorMinor := ""
|
||||
|
||||
// Finding the underlying root path and major:minor if possible.
|
||||
// We need search in backward order because it's possible for later mounts
|
||||
// to overlap earlier mounts.
|
||||
for i := len(mis) - 1; i >= 0; i-- {
|
||||
if hostSource == mis[i].mountPoint || pathWithinBase(hostSource, mis[i].mountPoint) {
|
||||
// If it's a mount point or path under a mount point.
|
||||
mountID = mis[i].id
|
||||
rootPath = filepath.Join(mis[i].root, strings.TrimPrefix(hostSource, mis[i].mountPoint))
|
||||
majorMinor = mis[i].majorMinor
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if rootPath == "" || majorMinor == "" {
|
||||
return nil, fmt.Errorf("failed to get root path and major:minor for %s", hostSource)
|
||||
}
|
||||
|
||||
var refs []string
|
||||
for i := range mis {
|
||||
if mis[i].id == mountID {
|
||||
// Ignore mount entry for mount source itself.
|
||||
continue
|
||||
}
|
||||
if mis[i].root == rootPath && mis[i].majorMinor == majorMinor {
|
||||
refs = append(refs, mis[i].mountPoint)
|
||||
}
|
||||
}
|
||||
|
||||
return refs, nil
|
||||
}
|
||||
|
|
|
|||
56
vendor/k8s.io/kubernetes/pkg/util/mount/mount_unsupported.go
generated
vendored
56
vendor/k8s.io/kubernetes/pkg/util/mount/mount_unsupported.go
generated
vendored
|
|
@ -27,6 +27,8 @@ type Mounter struct {
|
|||
mounterPath string
|
||||
}
|
||||
|
||||
var unsupportedErr = errors.New("util/mount on this platform is not supported")
|
||||
|
||||
// New returns a mount.Interface for the current system.
|
||||
// It provides options to override the default mounter behavior.
|
||||
// mounterPath allows using an alternative to `/bin/mount` for mounting.
|
||||
|
|
@ -37,21 +39,21 @@ func New(mounterPath string) Interface {
|
|||
}
|
||||
|
||||
func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error {
|
||||
return nil
|
||||
return unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) Unmount(target string) error {
|
||||
return nil
|
||||
return unsupportedErr
|
||||
}
|
||||
|
||||
// GetMountRefs finds all other references to the device referenced
|
||||
// by mountPath; returns a list of paths.
|
||||
func GetMountRefs(mounter Interface, mountPath string) ([]string, error) {
|
||||
return []string{}, nil
|
||||
return []string{}, unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) List() ([]MountPoint, error) {
|
||||
return []MountPoint{}, nil
|
||||
return []MountPoint{}, unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) IsMountPointMatch(mp MountPoint, dir string) bool {
|
||||
|
|
@ -63,27 +65,27 @@ func (mounter *Mounter) IsNotMountPoint(dir string) (bool, error) {
|
|||
}
|
||||
|
||||
func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return true, nil
|
||||
return true, unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) {
|
||||
return "", nil
|
||||
return "", unsupportedErr
|
||||
}
|
||||
|
||||
func getDeviceNameFromMount(mounter Interface, mountPath, pluginDir string) (string, error) {
|
||||
return "", nil
|
||||
return "", unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) DeviceOpened(pathname string) (bool, error) {
|
||||
return false, nil
|
||||
return false, unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) PathIsDevice(pathname string) (bool, error) {
|
||||
return true, nil
|
||||
return true, unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) MakeRShared(path string) error {
|
||||
return nil
|
||||
return unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
|
||||
|
|
@ -91,33 +93,49 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||
}
|
||||
|
||||
func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) {
|
||||
return true, nil
|
||||
return true, unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
|
||||
return FileType("fake"), errors.New("not implemented")
|
||||
return FileType("fake"), unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) MakeDir(pathname string) error {
|
||||
return nil
|
||||
return unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) MakeFile(pathname string) error {
|
||||
return nil
|
||||
return unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) ExistsPath(pathname string) bool {
|
||||
return true
|
||||
func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
||||
return true, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *Mounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) {
|
||||
return subPath.Path, nil, nil
|
||||
return subPath.Path, nil, unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) CleanSubPaths(podDir string, volumeName string) error {
|
||||
return nil
|
||||
return unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
return nil
|
||||
return unsupportedErr
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return -1, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
return 0, errors.New("not implemented")
|
||||
}
|
||||
|
|
|
|||
72
vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows.go
generated
vendored
72
vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows.go
generated
vendored
|
|
@ -29,6 +29,8 @@ import (
|
|||
"syscall"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
||||
)
|
||||
|
||||
// Mounter provides the default implementation of mount.Interface
|
||||
|
|
@ -145,7 +147,15 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
|||
}
|
||||
// If current file is a symlink, then it is a mountpoint.
|
||||
if stat.Mode()&os.ModeSymlink != 0 {
|
||||
return false, nil
|
||||
target, err := os.Readlink(file)
|
||||
if err != nil {
|
||||
return true, fmt.Errorf("readlink error: %v", err)
|
||||
}
|
||||
exists, err := mounter.ExistsPath(target)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return !exists, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
|
|
@ -228,12 +238,8 @@ func (mounter *Mounter) MakeFile(pathname string) error {
|
|||
}
|
||||
|
||||
// ExistsPath checks whether the path exists
|
||||
func (mounter *Mounter) ExistsPath(pathname string) bool {
|
||||
_, err := os.Stat(pathname)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
func (mounter *Mounter) ExistsPath(pathname string) (bool, error) {
|
||||
return utilfile.FileExists(pathname)
|
||||
}
|
||||
|
||||
// check whether hostPath is within volume path
|
||||
|
|
@ -358,10 +364,23 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
|
|||
glog.V(4).Infof("Attempting to formatAndMount disk: %s %s %s", fstype, source, target)
|
||||
|
||||
if err := ValidateDiskNumber(source); err != nil {
|
||||
glog.Errorf("azureMount: formatAndMount failed, err: %v\n", err)
|
||||
glog.Errorf("diskMount: formatAndMount failed, err: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if len(fstype) == 0 {
|
||||
// Use 'NTFS' as the default
|
||||
fstype = "NTFS"
|
||||
}
|
||||
|
||||
// format disk if it is unformatted(raw)
|
||||
cmd := fmt.Sprintf("Get-Disk -Number %s | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru"+
|
||||
" | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem %s -Confirm:$false", source, fstype)
|
||||
if output, err := mounter.Exec.Run("powershell", "/c", cmd); err != nil {
|
||||
return fmt.Errorf("diskMount: format disk failed, error: %v, output: %q", err, string(output))
|
||||
}
|
||||
glog.V(4).Infof("diskMount: Disk successfully formatted, disk: %q, fstype: %q", source, fstype)
|
||||
|
||||
driveLetter, err := getDriveLetterByDiskNumber(source, mounter.Exec)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -438,9 +457,42 @@ func getAllParentLinks(path string) ([]string, error) {
|
|||
return links, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
realpath, err := filepath.EvalSymlinks(pathname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return getMountRefsByDev(mounter, realpath)
|
||||
}
|
||||
|
||||
// Note that on windows, it always returns 0. We actually don't set FSGroup on
|
||||
// windows platform, see SetVolumeOwnership implementation.
|
||||
func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
// Windows does not support SELinux.
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
info, err := os.Stat(pathname)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return info.Mode(), nil
|
||||
}
|
||||
|
||||
// SafeMakeDir makes sure that the created directory does not escape given base directory mis-using symlinks.
|
||||
func (mounter *Mounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
return doSafeMakeDir(pathname, base, perm)
|
||||
func (mounter *Mounter) SafeMakeDir(subdir string, base string, perm os.FileMode) error {
|
||||
realBase, err := filepath.EvalSymlinks(base)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error resolving symlinks in %s: %s", base, err)
|
||||
}
|
||||
|
||||
realFullPath := filepath.Join(realBase, subdir)
|
||||
return doSafeMakeDir(realFullPath, realBase, perm)
|
||||
}
|
||||
|
||||
func doSafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
|
|
|
|||
209
vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount.go
generated
vendored
209
vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount.go
generated
vendored
|
|
@ -22,12 +22,12 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/golang/glog"
|
||||
utilio "k8s.io/kubernetes/pkg/util/io"
|
||||
"golang.org/x/sys/unix"
|
||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
||||
"k8s.io/kubernetes/pkg/util/nsenter"
|
||||
)
|
||||
|
||||
|
|
@ -36,13 +36,6 @@ const (
|
|||
hostProcMountsPath = "/rootfs/proc/1/mounts"
|
||||
// hostProcMountinfoPath is the default mount info path for rootfs
|
||||
hostProcMountinfoPath = "/rootfs/proc/1/mountinfo"
|
||||
// hostProcSelfStatusPath is the default path to /proc/self/status on the host
|
||||
hostProcSelfStatusPath = "/rootfs/proc/self/status"
|
||||
)
|
||||
|
||||
var (
|
||||
// pidRegExp matches "Pid: <pid>" in /proc/self/status
|
||||
pidRegExp = regexp.MustCompile(`\nPid:\t([0-9]*)\n`)
|
||||
)
|
||||
|
||||
// Currently, all docker containers receive their own mount namespaces.
|
||||
|
|
@ -50,10 +43,16 @@ var (
|
|||
// the host's mount namespace.
|
||||
type NsenterMounter struct {
|
||||
ne *nsenter.Nsenter
|
||||
// rootDir is location of /var/lib/kubelet directory.
|
||||
rootDir string
|
||||
}
|
||||
|
||||
func NewNsenterMounter() *NsenterMounter {
|
||||
return &NsenterMounter{ne: nsenter.NewNsenter()}
|
||||
// NewNsenterMounter creates a new mounter for kubelet that runs as a container.
|
||||
func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter {
|
||||
return &NsenterMounter{
|
||||
rootDir: rootDir,
|
||||
ne: ne,
|
||||
}
|
||||
}
|
||||
|
||||
// NsenterMounter implements mount.Interface
|
||||
|
|
@ -277,42 +276,24 @@ func (mounter *NsenterMounter) MakeFile(pathname string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (mounter *NsenterMounter) ExistsPath(pathname string) bool {
|
||||
args := []string{pathname}
|
||||
_, err := mounter.ne.Exec("ls", args).CombinedOutput()
|
||||
if err == nil {
|
||||
return true
|
||||
func (mounter *NsenterMounter) ExistsPath(pathname string) (bool, error) {
|
||||
// Resolve the symlinks but allow the target not to exist. EvalSymlinks
|
||||
// would return an generic error when the target does not exist.
|
||||
hostPath, err := mounter.ne.EvalSymlinks(pathname, false /* mustExist */)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return false
|
||||
kubeletpath := mounter.ne.KubeletPath(hostPath)
|
||||
return utilfile.FileExists(kubeletpath)
|
||||
}
|
||||
|
||||
func (mounter *NsenterMounter) CleanSubPaths(podDir string, volumeName string) error {
|
||||
return doCleanSubPaths(mounter, podDir, volumeName)
|
||||
}
|
||||
|
||||
// getPidOnHost returns kubelet's pid in the host pid namespace
|
||||
func (mounter *NsenterMounter) getPidOnHost(procStatusPath string) (int, error) {
|
||||
// Get the PID from /rootfs/proc/self/status
|
||||
statusBytes, err := utilio.ConsistentRead(procStatusPath, maxListTries)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error reading %s: %s", procStatusPath, err)
|
||||
}
|
||||
matches := pidRegExp.FindSubmatch(statusBytes)
|
||||
if len(matches) < 2 {
|
||||
return 0, fmt.Errorf("cannot parse %s: no Pid:", procStatusPath)
|
||||
}
|
||||
return strconv.Atoi(string(matches[1]))
|
||||
}
|
||||
|
||||
func (mounter *NsenterMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) {
|
||||
hostPid, err := mounter.getPidOnHost(hostProcSelfStatusPath)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
glog.V(4).Infof("Kubelet's PID on the host is %d", hostPid)
|
||||
|
||||
// Bind-mount the subpath to avoid using symlinks in subpaths.
|
||||
newHostPath, err = doBindSubPath(mounter, subPath, hostPid)
|
||||
newHostPath, err = doNsEnterBindSubPath(mounter, subPath)
|
||||
|
||||
// There is no action when the container starts. Bind-mount will be cleaned
|
||||
// when container stops by CleanSubPaths.
|
||||
|
|
@ -320,6 +301,152 @@ func (mounter *NsenterMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath
|
|||
return newHostPath, cleanupAction, err
|
||||
}
|
||||
|
||||
func (mounter *NsenterMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
return doSafeMakeDir(pathname, base, perm)
|
||||
func (mounter *NsenterMounter) SafeMakeDir(subdir string, base string, perm os.FileMode) error {
|
||||
fullSubdirPath := filepath.Join(base, subdir)
|
||||
evaluatedSubdirPath, err := mounter.ne.EvalSymlinks(fullSubdirPath, false /* mustExist */)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error resolving symlinks in %s: %s", fullSubdirPath, err)
|
||||
}
|
||||
evaluatedSubdirPath = filepath.Clean(evaluatedSubdirPath)
|
||||
|
||||
evaluatedBase, err := mounter.ne.EvalSymlinks(base, true /* mustExist */)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error resolving symlinks in %s: %s", base, err)
|
||||
}
|
||||
evaluatedBase = filepath.Clean(evaluatedBase)
|
||||
|
||||
rootDir := filepath.Clean(mounter.rootDir)
|
||||
if pathWithinBase(evaluatedBase, rootDir) {
|
||||
// Base is in /var/lib/kubelet. This directory is shared between the
|
||||
// container with kubelet and the host. We don't need to add '/rootfs'.
|
||||
// This is useful when /rootfs is mounted as read-only - we can still
|
||||
// create subpaths for paths in /var/lib/kubelet.
|
||||
return doSafeMakeDir(evaluatedSubdirPath, evaluatedBase, perm)
|
||||
}
|
||||
|
||||
// Base is somewhere on the host's filesystem. Add /rootfs and try to make
|
||||
// the directory there.
|
||||
// This requires /rootfs to be writable.
|
||||
kubeletSubdirPath := mounter.ne.KubeletPath(evaluatedSubdirPath)
|
||||
kubeletBase := mounter.ne.KubeletPath(evaluatedBase)
|
||||
return doSafeMakeDir(kubeletSubdirPath, kubeletBase, perm)
|
||||
}
|
||||
|
||||
func (mounter *NsenterMounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
hostpath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return searchMountPoints(hostpath, hostProcMountinfoPath)
|
||||
}
|
||||
|
||||
func doNsEnterBindSubPath(mounter *NsenterMounter, subpath Subpath) (hostPath string, err error) {
|
||||
// Linux, kubelet runs in a container:
|
||||
// - safely open the subpath
|
||||
// - bind-mount the subpath to target (this can be unsafe)
|
||||
// - check that we mounted the right thing by comparing device ID and inode
|
||||
// of the subpath (via safely opened fd) and the target (that's under our
|
||||
// control)
|
||||
|
||||
// Evaluate all symlinks here once for all subsequent functions.
|
||||
evaluatedHostVolumePath, err := mounter.ne.EvalSymlinks(subpath.VolumePath, true /*mustExist*/)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error resolving symlinks in %q: %v", subpath.VolumePath, err)
|
||||
}
|
||||
evaluatedHostSubpath, err := mounter.ne.EvalSymlinks(subpath.Path, true /*mustExist*/)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error resolving symlinks in %q: %v", subpath.Path, err)
|
||||
}
|
||||
glog.V(5).Infof("doBindSubPath %q (%q) for volumepath %q", subpath.Path, evaluatedHostSubpath, subpath.VolumePath)
|
||||
subpath.VolumePath = mounter.ne.KubeletPath(evaluatedHostVolumePath)
|
||||
subpath.Path = mounter.ne.KubeletPath(evaluatedHostSubpath)
|
||||
|
||||
// Check the subpath is correct and open it
|
||||
fd, err := safeOpenSubPath(mounter, subpath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer syscall.Close(fd)
|
||||
|
||||
alreadyMounted, bindPathTarget, err := prepareSubpathTarget(mounter, subpath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if alreadyMounted {
|
||||
return bindPathTarget, nil
|
||||
}
|
||||
|
||||
success := false
|
||||
defer func() {
|
||||
// Cleanup subpath on error
|
||||
if !success {
|
||||
glog.V(4).Infof("doNsEnterBindSubPath() failed for %q, cleaning up subpath", bindPathTarget)
|
||||
if cleanErr := cleanSubPath(mounter, subpath); cleanErr != nil {
|
||||
glog.Errorf("Failed to clean subpath %q: %v", bindPathTarget, cleanErr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Leap of faith: optimistically expect that nobody has modified previously
|
||||
// expanded evalSubPath with evil symlinks and bind-mount it.
|
||||
// Mount is done on the host! don't use kubelet path!
|
||||
glog.V(5).Infof("bind mounting %q at %q", evaluatedHostSubpath, bindPathTarget)
|
||||
if err = mounter.Mount(evaluatedHostSubpath, bindPathTarget, "" /*fstype*/, []string{"bind"}); err != nil {
|
||||
return "", fmt.Errorf("error mounting %s: %s", evaluatedHostSubpath, err)
|
||||
}
|
||||
|
||||
// Check that the bind-mount target is the same inode and device as the
|
||||
// source that we keept open, i.e. we mounted the right thing.
|
||||
err = checkDeviceInode(fd, bindPathTarget)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error checking bind mount for subpath %s: %s", subpath.VolumePath, err)
|
||||
}
|
||||
|
||||
success = true
|
||||
glog.V(3).Infof("Bound SubPath %s into %s", subpath.Path, bindPathTarget)
|
||||
return bindPathTarget, nil
|
||||
}
|
||||
|
||||
// checkDeviceInode checks that opened file and path represent the same file.
|
||||
func checkDeviceInode(fd int, path string) error {
|
||||
var srcStat, dstStat unix.Stat_t
|
||||
err := unix.Fstat(fd, &srcStat)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error running fstat on subpath FD: %v", err)
|
||||
}
|
||||
|
||||
err = unix.Stat(path, &dstStat)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error running fstat on %s: %v", path, err)
|
||||
}
|
||||
|
||||
if srcStat.Dev != dstStat.Dev {
|
||||
return fmt.Errorf("different device number")
|
||||
}
|
||||
if srcStat.Ino != dstStat.Ino {
|
||||
return fmt.Errorf("different inode")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mounter *NsenterMounter) GetFSGroup(pathname string) (int64, error) {
|
||||
hostPath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
kubeletpath := mounter.ne.KubeletPath(hostPath)
|
||||
return getFSGroup(kubeletpath)
|
||||
}
|
||||
|
||||
func (mounter *NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return getSELinuxSupport(pathname, hostProcMountsPath)
|
||||
}
|
||||
|
||||
func (mounter *NsenterMounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
hostPath, err := mounter.ne.EvalSymlinks(pathname, true /* mustExist */)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
kubeletpath := mounter.ne.KubeletPath(hostPath)
|
||||
return getMode(kubeletpath)
|
||||
}
|
||||
|
|
|
|||
24
vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_unsupported.go
generated
vendored
24
vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_unsupported.go
generated
vendored
|
|
@ -21,11 +21,13 @@ package mount
|
|||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/nsenter"
|
||||
)
|
||||
|
||||
type NsenterMounter struct{}
|
||||
|
||||
func NewNsenterMounter() *NsenterMounter {
|
||||
func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter {
|
||||
return &NsenterMounter{}
|
||||
}
|
||||
|
||||
|
|
@ -83,8 +85,8 @@ func (*NsenterMounter) MakeFile(pathname string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (*NsenterMounter) ExistsPath(pathname string) bool {
|
||||
return true
|
||||
func (*NsenterMounter) ExistsPath(pathname string) (bool, error) {
|
||||
return true, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (*NsenterMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
|
|
@ -98,3 +100,19 @@ func (*NsenterMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string,
|
|||
func (*NsenterMounter) CleanSubPaths(podDir string, volumeName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*NsenterMounter) GetMountRefs(pathname string) ([]string, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (*NsenterMounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return -1, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (*NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (*NsenterMounter) GetMode(pathname string) (os.FileMode, error) {
|
||||
return 0, errors.New("not implemented")
|
||||
}
|
||||
|
|
|
|||
19
vendor/k8s.io/kubernetes/pkg/util/nsenter/BUILD
generated
vendored
19
vendor/k8s.io/kubernetes/pkg/util/nsenter/BUILD
generated
vendored
|
|
@ -1,4 +1,4 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
|
|
@ -92,3 +92,20 @@ filegroup(
|
|||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = select({
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"nsenter_test.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
embed = [":go_default_library"],
|
||||
deps = select({
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
|
|
|||
170
vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter.go
generated
vendored
170
vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter.go
generated
vendored
|
|
@ -19,9 +19,12 @@ limitations under the License.
|
|||
package nsenter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"k8s.io/utils/exec"
|
||||
|
||||
|
|
@ -29,9 +32,11 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
hostRootFsPath = "/rootfs"
|
||||
// hostProcMountNsPath is the default mount namespace for rootfs
|
||||
hostProcMountNsPath = "/rootfs/proc/1/ns/mnt"
|
||||
// DefaultHostRootFsPath is path to host's filesystem mounted into container
|
||||
// with kubelet.
|
||||
DefaultHostRootFsPath = "/rootfs"
|
||||
// mountNsPath is the default mount namespace of the host
|
||||
mountNsPath = "/proc/1/ns/mnt"
|
||||
// nsenterPath is the default nsenter command
|
||||
nsenterPath = "nsenter"
|
||||
)
|
||||
|
|
@ -57,55 +62,73 @@ const (
|
|||
// contents. TODO: remove this requirement.
|
||||
// 6. The host image must have "mount", "findmnt", "umount", "stat", "touch",
|
||||
// "mkdir", "ls", "sh" and "chmod" binaries in /bin, /usr/sbin, or /usr/bin
|
||||
// 7. The host image should have systemd-run in /bin, /usr/sbin, or /usr/bin
|
||||
// 7. The host image should have systemd-run in /bin, /usr/sbin, or /usr/bin if
|
||||
// systemd is installed/enabled in the operating system.
|
||||
// For more information about mount propagation modes, see:
|
||||
// https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt
|
||||
type Nsenter struct {
|
||||
// a map of commands to their paths on the host filesystem
|
||||
paths map[string]string
|
||||
|
||||
// Path to the host filesystem, typically "/rootfs". Used only for testing.
|
||||
hostRootFsPath string
|
||||
|
||||
// Exec implementation, used only for testing
|
||||
executor exec.Interface
|
||||
}
|
||||
|
||||
// NewNsenter constructs a new instance of Nsenter
|
||||
func NewNsenter() *Nsenter {
|
||||
func NewNsenter(hostRootFsPath string, executor exec.Interface) (*Nsenter, error) {
|
||||
ne := &Nsenter{
|
||||
paths: map[string]string{
|
||||
"mount": "",
|
||||
"findmnt": "",
|
||||
"umount": "",
|
||||
"systemd-run": "",
|
||||
"stat": "",
|
||||
"touch": "",
|
||||
"mkdir": "",
|
||||
"ls": "",
|
||||
"sh": "",
|
||||
"chmod": "",
|
||||
},
|
||||
hostRootFsPath: hostRootFsPath,
|
||||
executor: executor,
|
||||
}
|
||||
if err := ne.initPaths(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ne, nil
|
||||
}
|
||||
|
||||
func (ne *Nsenter) initPaths() error {
|
||||
ne.paths = map[string]string{}
|
||||
binaries := []string{
|
||||
"mount",
|
||||
"findmnt",
|
||||
"umount",
|
||||
"systemd-run",
|
||||
"stat",
|
||||
"touch",
|
||||
"mkdir",
|
||||
"sh",
|
||||
"chmod",
|
||||
"realpath",
|
||||
}
|
||||
// search for the required commands in other locations besides /usr/bin
|
||||
for binary := range ne.paths {
|
||||
// default to root
|
||||
ne.paths[binary] = filepath.Join("/", binary)
|
||||
for _, path := range []string{"/bin", "/usr/sbin", "/usr/bin"} {
|
||||
for _, binary := range binaries {
|
||||
// check for binary under the following directories
|
||||
for _, path := range []string{"/", "/bin", "/usr/sbin", "/usr/bin"} {
|
||||
binPath := filepath.Join(path, binary)
|
||||
if _, err := os.Stat(filepath.Join(hostRootFsPath, binPath)); err != nil {
|
||||
if _, err := os.Stat(filepath.Join(ne.hostRootFsPath, binPath)); err != nil {
|
||||
continue
|
||||
}
|
||||
ne.paths[binary] = binPath
|
||||
break
|
||||
}
|
||||
// TODO: error, so that the kubelet can stop if the paths don't exist
|
||||
// (don't forget that systemd-run is optional)
|
||||
// systemd-run is optional, bailout if we don't find any of the other binaries
|
||||
if ne.paths[binary] == "" && binary != "systemd-run" {
|
||||
return fmt.Errorf("unable to find %v", binary)
|
||||
}
|
||||
}
|
||||
return ne
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exec executes nsenter commands in hostProcMountNsPath mount namespace
|
||||
func (ne *Nsenter) Exec(cmd string, args []string) exec.Cmd {
|
||||
hostProcMountNsPath := filepath.Join(ne.hostRootFsPath, mountNsPath)
|
||||
fullArgs := append([]string{fmt.Sprintf("--mount=%s", hostProcMountNsPath), "--"},
|
||||
append([]string{ne.AbsHostPath(cmd)}, args...)...)
|
||||
glog.V(5).Infof("Running nsenter command: %v %v", nsenterPath, fullArgs)
|
||||
exec := exec.New()
|
||||
return exec.Command(nsenterPath, fullArgs...)
|
||||
return ne.executor.Command(nsenterPath, fullArgs...)
|
||||
}
|
||||
|
||||
// AbsHostPath returns the absolute runnable path for a specified command
|
||||
|
|
@ -119,6 +142,95 @@ func (ne *Nsenter) AbsHostPath(command string) string {
|
|||
|
||||
// SupportsSystemd checks whether command systemd-run exists
|
||||
func (ne *Nsenter) SupportsSystemd() (string, bool) {
|
||||
systemdRunPath, hasSystemd := ne.paths["systemd-run"]
|
||||
return systemdRunPath, hasSystemd
|
||||
systemdRunPath, ok := ne.paths["systemd-run"]
|
||||
return systemdRunPath, ok && systemdRunPath != ""
|
||||
}
|
||||
|
||||
// EvalSymlinks returns the path name on the host after evaluating symlinks on the
|
||||
// host.
|
||||
// mustExist makes EvalSymlinks to return error when the path does not
|
||||
// exist. When it's false, it evaluates symlinks of the existing part and
|
||||
// blindly adds the non-existing part:
|
||||
// pathname: /mnt/volume/non/existing/directory
|
||||
// /mnt/volume exists
|
||||
// non/existing/directory does not exist
|
||||
// -> It resolves symlinks in /mnt/volume to say /mnt/foo and returns
|
||||
// /mnt/foo/non/existing/directory.
|
||||
//
|
||||
// BEWARE! EvalSymlinks is not able to detect symlink looks with mustExist=false!
|
||||
// If /tmp/link is symlink to /tmp/link, EvalSymlinks(/tmp/link/foo) returns /tmp/link/foo.
|
||||
func (ne *Nsenter) EvalSymlinks(pathname string, mustExist bool) (string, error) {
|
||||
var args []string
|
||||
if mustExist {
|
||||
// "realpath -e: all components of the path must exist"
|
||||
args = []string{"-e", pathname}
|
||||
} else {
|
||||
// "realpath -m: no path components need exist or be a directory"
|
||||
args = []string{"-m", pathname}
|
||||
}
|
||||
outBytes, err := ne.Exec("realpath", args).CombinedOutput()
|
||||
if err != nil {
|
||||
glog.Infof("failed to resolve symbolic links on %s: %v", pathname, err)
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimSpace(string(outBytes)), nil
|
||||
}
|
||||
|
||||
// KubeletPath returns the path name that can be accessed by containerized
|
||||
// kubelet. It is recommended to resolve symlinks on the host by EvalSymlinks
|
||||
// before calling this function
|
||||
func (ne *Nsenter) KubeletPath(pathname string) string {
|
||||
return filepath.Join(ne.hostRootFsPath, pathname)
|
||||
}
|
||||
|
||||
// NewFakeNsenter returns a Nsenter that does not run "nsenter --mount=... --",
|
||||
// but runs everything in the same mount namespace as the unit test binary.
|
||||
// rootfsPath is supposed to be a symlink, e.g. /tmp/xyz/rootfs -> /.
|
||||
// This fake Nsenter is enough for most operations, e.g. to resolve symlinks,
|
||||
// but it's not enough to call /bin/mount - unit tests don't run as root.
|
||||
func NewFakeNsenter(rootfsPath string) (*Nsenter, error) {
|
||||
executor := &fakeExec{
|
||||
rootfsPath: rootfsPath,
|
||||
}
|
||||
// prepare /rootfs/bin, usr/bin and usr/sbin
|
||||
bin := filepath.Join(rootfsPath, "bin")
|
||||
if err := os.Symlink("/bin", bin); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
usr := filepath.Join(rootfsPath, "usr")
|
||||
if err := os.Mkdir(usr, 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
usrbin := filepath.Join(usr, "bin")
|
||||
if err := os.Symlink("/usr/bin", usrbin); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
usrsbin := filepath.Join(usr, "sbin")
|
||||
if err := os.Symlink("/usr/sbin", usrsbin); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewNsenter(rootfsPath, executor)
|
||||
}
|
||||
|
||||
type fakeExec struct {
|
||||
rootfsPath string
|
||||
}
|
||||
|
||||
func (f fakeExec) Command(cmd string, args ...string) exec.Cmd {
|
||||
// This will intentionaly panic if Nsenter does not provide enough arguments.
|
||||
realCmd := args[2]
|
||||
realArgs := args[3:]
|
||||
return exec.New().Command(realCmd, realArgs...)
|
||||
}
|
||||
|
||||
func (fakeExec) LookPath(file string) (string, error) {
|
||||
return "", errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (fakeExec) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ exec.Interface = fakeExec{}
|
||||
|
|
|
|||
10
vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter_unsupported.go
generated
vendored
10
vendor/k8s.io/kubernetes/pkg/util/nsenter/nsenter_unsupported.go
generated
vendored
|
|
@ -22,6 +22,12 @@ import (
|
|||
"k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultHostRootFsPath is path to host's filesystem mounted into container
|
||||
// with kubelet.
|
||||
DefaultHostRootFsPath = "/rootfs"
|
||||
)
|
||||
|
||||
// Nsenter is part of experimental support for running the kubelet
|
||||
// in a container.
|
||||
type Nsenter struct {
|
||||
|
|
@ -30,8 +36,8 @@ type Nsenter struct {
|
|||
}
|
||||
|
||||
// NewNsenter constructs a new instance of Nsenter
|
||||
func NewNsenter() *Nsenter {
|
||||
return &Nsenter{}
|
||||
func NewNsenter(hostRootFsPath string, executor exec.Interface) (*Nsenter, error) {
|
||||
return &Nsenter{}, nil
|
||||
}
|
||||
|
||||
// Exec executes nsenter commands in hostProcMountNsPath mount namespace
|
||||
|
|
|
|||
11
vendor/k8s.io/kubernetes/pkg/util/pointer/pointer.go
generated
vendored
11
vendor/k8s.io/kubernetes/pkg/util/pointer/pointer.go
generated
vendored
|
|
@ -48,8 +48,12 @@ func AllPtrFieldsNil(obj interface{}) bool {
|
|||
|
||||
// Int32Ptr returns a pointer to an int32
|
||||
func Int32Ptr(i int32) *int32 {
|
||||
o := i
|
||||
return &o
|
||||
return &i
|
||||
}
|
||||
|
||||
// Int64Ptr returns a pointer to an int64
|
||||
func Int64Ptr(i int64) *int64 {
|
||||
return &i
|
||||
}
|
||||
|
||||
// Int32PtrDerefOr dereference the int32 ptr and returns it i not nil,
|
||||
|
|
@ -63,6 +67,5 @@ func Int32PtrDerefOr(ptr *int32, def int32) int32 {
|
|||
|
||||
// BoolPtr returns a pointer to a bool
|
||||
func BoolPtr(b bool) *bool {
|
||||
o := b
|
||||
return &o
|
||||
return &b
|
||||
}
|
||||
|
|
|
|||
4
vendor/k8s.io/kubernetes/pkg/util/verify-util-pkg.sh
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/util/verify-util-pkg.sh
generated
vendored
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2017 The Kubernetes Authors.
|
||||
#
|
||||
|
|
@ -41,7 +41,7 @@ pushd "${BASH_DIR}" > /dev/null
|
|||
done
|
||||
popd > /dev/null
|
||||
|
||||
if [[ ${ret} > 0 ]]; then
|
||||
if [[ ${ret} -gt 0 ]]; then
|
||||
exit ${ret}
|
||||
fi
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue