From 995b7d3a49cdfcc347110d6e4060f76ab371d157 Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Mon, 8 Oct 2018 00:38:07 -0700 Subject: [PATCH] Delete nsenter and containerized flag --- cmd/kubelet/app/options/options.go | 3 - cmd/kubelet/app/server.go | 11 - pkg/util/mount/nsenter_mount.go | 470 -------------------- pkg/util/mount/nsenter_mount_unsupported.go | 122 ----- pkg/util/nsenter/BUILD | 76 ---- pkg/util/nsenter/OWNERS | 8 - pkg/util/nsenter/exec.go | 67 --- pkg/util/nsenter/exec_unsupported.go | 58 --- pkg/util/nsenter/nsenter.go | 236 ---------- pkg/util/nsenter/nsenter_test.go | 311 ------------- pkg/util/nsenter/nsenter_unsupported.go | 56 --- 11 files changed, 1418 deletions(-) delete mode 100644 pkg/util/mount/nsenter_mount.go delete mode 100644 pkg/util/mount/nsenter_mount_unsupported.go delete mode 100644 pkg/util/nsenter/BUILD delete mode 100644 pkg/util/nsenter/OWNERS delete mode 100644 pkg/util/nsenter/exec.go delete mode 100644 pkg/util/nsenter/exec_unsupported.go delete mode 100644 pkg/util/nsenter/nsenter.go delete mode 100644 pkg/util/nsenter/nsenter_test.go delete mode 100644 pkg/util/nsenter/nsenter_unsupported.go diff --git a/cmd/kubelet/app/options/options.go b/cmd/kubelet/app/options/options.go index e85180e3eb..e9c94b7bdc 100644 --- a/cmd/kubelet/app/options/options.go +++ b/cmd/kubelet/app/options/options.go @@ -123,8 +123,6 @@ type KubeletFlags struct { // Whitelist of unsafe sysctls or sysctl patterns (ending in *). // +optional AllowedUnsafeSysctls []string - // containerized should be set to true if kubelet is running in a container. - Containerized bool // remoteRuntimeEndpoint is the endpoint of remote runtime service RemoteRuntimeEndpoint string // remoteImageEndpoint is the endpoint of remote image service @@ -393,7 +391,6 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) { fs.BoolVar(&f.RegisterNode, "register-node", f.RegisterNode, "Register the node with the apiserver. If --kubeconfig is not provided, this flag is irrelevant, as the Kubelet won't have an apiserver to register with.") fs.Var(utiltaints.NewTaintsVar(&f.RegisterWithTaints), "register-with-taints", "Register the node with the given list of taints (comma separated \"=:\"). No-op if register-node is false.") - fs.BoolVar(&f.Containerized, "containerized", f.Containerized, "Running kubelet in a container.") // EXPERIMENTAL FLAGS fs.StringVar(&f.ExperimentalMounterPath, "experimental-mounter-path", f.ExperimentalMounterPath, "[Experimental] Path of mounter binary. Leave empty to use the default mount.") diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index edf937afef..3163b33e1b 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -88,7 +88,6 @@ import ( "k8s.io/kubernetes/pkg/util/flock" "k8s.io/kubernetes/pkg/util/mount" nodeutil "k8s.io/kubernetes/pkg/util/node" - "k8s.io/kubernetes/pkg/util/nsenter" "k8s.io/kubernetes/pkg/util/oom" "k8s.io/kubernetes/pkg/util/rlimit" "k8s.io/kubernetes/pkg/version" @@ -358,16 +357,6 @@ func UnsecuredDependencies(s *options.KubeletServer) (*kubelet.Dependencies, err mounter := mount.New(s.ExperimentalMounterPath) var pluginRunner = exec.New() - if s.Containerized { - klog.V(2).Info("Running kubelet in containerized mode") - ne, err := nsenter.NewNsenter(nsenter.DefaultHostRootFsPath, exec.New()) - if err != nil { - return nil, err - } - mounter = mount.NewNsenterMounter(s.RootDirectory, ne) - // an exec interface which can use nsenter for flex plugin calls - pluginRunner = nsenter.NewNsenterExecutor(nsenter.DefaultHostRootFsPath, exec.New()) - } var dockerClientConfig *dockershim.ClientConfig if s.ContainerRuntime == kubetypes.DockerContainerRuntime { diff --git a/pkg/util/mount/nsenter_mount.go b/pkg/util/mount/nsenter_mount.go deleted file mode 100644 index ff2eceaf7c..0000000000 --- a/pkg/util/mount/nsenter_mount.go +++ /dev/null @@ -1,470 +0,0 @@ -// +build linux - -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package mount - -import ( - "fmt" - "os" - "path/filepath" - "strings" - "syscall" - - "golang.org/x/sys/unix" - "k8s.io/klog" - utilfile "k8s.io/kubernetes/pkg/util/file" - "k8s.io/kubernetes/pkg/util/nsenter" -) - -const ( - // hostProcMountsPath is the default mount path for rootfs - hostProcMountsPath = "/rootfs/proc/1/mounts" - // hostProcMountinfoPath is the default mount info path for rootfs - hostProcMountinfoPath = "/rootfs/proc/1/mountinfo" -) - -// Currently, all docker containers receive their own mount namespaces. -// NsenterMounter works by executing nsenter to run commands in -// the host's mount namespace. -type NsenterMounter struct { - ne *nsenter.Nsenter - // rootDir is location of /var/lib/kubelet directory. - rootDir string -} - -// 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 -var _ = Interface(&NsenterMounter{}) - -// 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() -func (n *NsenterMounter) Mount(source string, target string, fstype string, options []string) error { - bind, bindOpts, bindRemountOpts := isBind(options) - - if bind { - err := n.doNsenterMount(source, target, fstype, bindOpts) - if err != nil { - return err - } - return n.doNsenterMount(source, target, fstype, bindRemountOpts) - } - - return n.doNsenterMount(source, target, fstype, options) -} - -// doNsenterMount nsenters the host's mount namespace and performs the -// requested mount. -func (n *NsenterMounter) doNsenterMount(source, target, fstype string, options []string) error { - klog.V(5).Infof("nsenter mount %s %s %s %v", source, target, fstype, options) - cmd, args := n.makeNsenterArgs(source, target, fstype, options) - outputBytes, err := n.ne.Exec(cmd, args).CombinedOutput() - if len(outputBytes) != 0 { - klog.V(5).Infof("Output of mounting %s to %s: %v", source, target, string(outputBytes)) - } - return err -} - -// makeNsenterArgs makes a list of argument to nsenter in order to do the -// requested mount. -func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options []string) (string, []string) { - mountCmd := n.ne.AbsHostPath("mount") - mountArgs := makeMountArgs(source, target, fstype, options) - - if systemdRunPath, hasSystemd := n.ne.SupportsSystemd(); hasSystemd { - // Complete command line: - // nsenter --mount=/rootfs/proc/1/ns/mnt -- /bin/systemd-run --description=... --scope -- /bin/mount -t - // Expected flow is: - // * nsenter breaks out of container's mount namespace and executes - // host's systemd-run. - // * systemd-run creates a transient scope (=~ cgroup) and executes its - // argument (/bin/mount) there. - // * mount does its job, forks a fuse daemon if necessary and finishes. - // (systemd-run --scope finishes at this point, returning mount's exit - // code and stdout/stderr - thats one of --scope benefits). - // * systemd keeps the fuse daemon running in the scope (i.e. in its own - // cgroup) until the fuse daemon dies (another --scope benefit). - // Kubelet container can be restarted and the fuse daemon survives. - // * When the daemon dies (e.g. during unmount) systemd removes the - // scope automatically. - mountCmd, mountArgs = addSystemdScope(systemdRunPath, target, mountCmd, mountArgs) - } else { - // Fall back to simple mount when the host has no systemd. - // Complete command line: - // nsenter --mount=/rootfs/proc/1/ns/mnt -- /bin/mount -t - // Expected flow is: - // * nsenter breaks out of container's mount namespace and executes host's /bin/mount. - // * mount does its job, forks a fuse daemon if necessary and finishes. - // * Any fuse daemon runs in cgroup of kubelet docker container, - // restart of kubelet container will kill it! - - // No code here, mountCmd and mountArgs use /bin/mount - } - - return mountCmd, mountArgs -} - -// Unmount runs umount(8) in the host's mount namespace. -func (n *NsenterMounter) Unmount(target string) error { - args := []string{target} - // 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) - // running in any scope. - klog.V(5).Infof("nsenter unmount args: %v", args) - outputBytes, err := n.ne.Exec("umount", args).CombinedOutput() - if len(outputBytes) != 0 { - klog.V(5).Infof("Output of unmounting %s: %v", target, string(outputBytes)) - } - return err -} - -// List returns a list of all mounted filesystems in the host's mount namespace. -func (*NsenterMounter) List() ([]MountPoint, error) { - return listProcMounts(hostProcMountsPath) -} - -func (m *NsenterMounter) IsNotMountPoint(dir string) (bool, error) { - return IsNotMountPoint(m, dir) -} - -func (*NsenterMounter) IsMountPointMatch(mp MountPoint, dir string) bool { - deletedDir := fmt.Sprintf("%s\\040(deleted)", dir) - return (mp.Path == dir) || (mp.Path == deletedDir) -} - -// IsLikelyNotMountPoint determines whether a path is a mountpoint by calling findmnt -// in the host's root mount namespace. -func (n *NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) { - file, err := filepath.Abs(file) - if err != nil { - return true, err - } - - // Check the directory exists - if _, err = os.Stat(file); os.IsNotExist(err) { - klog.V(5).Infof("findmnt: directory %s does not exist", file) - return true, err - } - - // Resolve any symlinks in file, kernel would do the same and use the resolved path in /proc/mounts - resolvedFile, err := n.EvalHostSymlinks(file) - if err != nil { - return true, err - } - - // Add --first-only option: since we are testing for the absence of a mountpoint, it is sufficient to get only - // the first of multiple possible mountpoints using --first-only. - // Also add fstype output to make sure that the output of target file will give the full path - // TODO: Need more refactoring for this function. Track the solution with issue #26996 - args := []string{"-o", "target,fstype", "--noheadings", "--first-only", "--target", resolvedFile} - klog.V(5).Infof("nsenter findmnt args: %v", args) - out, err := n.ne.Exec("findmnt", args).CombinedOutput() - if err != nil { - klog.V(2).Infof("Failed findmnt command for path %s: %s %v", resolvedFile, out, err) - // Different operating systems behave differently for paths which are not mount points. - // On older versions (e.g. 2.20.1) we'd get error, on newer ones (e.g. 2.26.2) we'd get "/". - // It's safer to assume that it's not a mount point. - return true, nil - } - mountTarget, err := parseFindMnt(string(out)) - if err != nil { - return false, err - } - - klog.V(5).Infof("IsLikelyNotMountPoint findmnt output for path %s: %v:", resolvedFile, mountTarget) - - if mountTarget == resolvedFile { - klog.V(5).Infof("IsLikelyNotMountPoint: %s is a mount point", resolvedFile) - return false, nil - } - klog.V(5).Infof("IsLikelyNotMountPoint: %s is not a mount point", resolvedFile) - return true, nil -} - -// parse output of "findmnt -o target,fstype" and return just the target -func parseFindMnt(out string) (string, error) { - // cut trailing newline - out = strings.TrimSuffix(out, "\n") - // cut everything after the last space - it's the filesystem type - i := strings.LastIndex(out, " ") - if i == -1 { - return "", fmt.Errorf("error parsing findmnt output, expected at least one space: %q", out) - } - return out[:i], nil -} - -// DeviceOpened checks if block device in use by calling Open with O_EXCL flag. -// 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 with error if pathname is not a device. -func (n *NsenterMounter) DeviceOpened(pathname string) (bool, error) { - return exclusiveOpenFailsOnDevice(pathname) -} - -// PathIsDevice uses FileInfo returned from os.Stat to check if path refers -// to a device. -func (n *NsenterMounter) PathIsDevice(pathname string) (bool, error) { - pathType, err := n.GetFileType(pathname) - isDevice := pathType == FileTypeCharDev || pathType == FileTypeBlockDev - return isDevice, err -} - -//GetDeviceNameFromMount given a mount point, find the volume id from checking /proc/mounts -func (n *NsenterMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { - return getDeviceNameFromMount(n, mountPath, pluginDir) -} - -func (n *NsenterMounter) MakeRShared(path string) error { - return doMakeRShared(path, hostProcMountinfoPath) -} - -func (mounter *NsenterMounter) GetFileType(pathname string) (FileType, error) { - var pathType FileType - outputBytes, err := mounter.ne.Exec("stat", []string{"-L", "--printf=%F", pathname}).CombinedOutput() - if err != nil { - if strings.Contains(string(outputBytes), "No such file") { - err = fmt.Errorf("%s does not exist", pathname) - } else { - err = fmt.Errorf("stat %s error: %v", pathname, string(outputBytes)) - } - return pathType, err - } - - switch string(outputBytes) { - case "socket": - return FileTypeSocket, nil - case "character special file": - return FileTypeCharDev, nil - case "block special file": - return FileTypeBlockDev, nil - case "directory": - return FileTypeDirectory, nil - case "regular file": - return FileTypeFile, nil - } - - return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device") -} - -func (mounter *NsenterMounter) MakeDir(pathname string) error { - args := []string{"-p", pathname} - if _, err := mounter.ne.Exec("mkdir", args).CombinedOutput(); err != nil { - return err - } - return nil -} - -func (mounter *NsenterMounter) MakeFile(pathname string) error { - args := []string{pathname} - if _, err := mounter.ne.Exec("touch", args).CombinedOutput(); err != nil { - return err - } - return nil -} - -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 - } - kubeletpath := mounter.ne.KubeletPath(hostPath) - return utilfile.FileExists(kubeletpath) -} - -func (mounter *NsenterMounter) EvalHostSymlinks(pathname string) (string, error) { - return mounter.ne.EvalSymlinks(pathname, true) -} - -func (mounter *NsenterMounter) CleanSubPaths(podDir string, volumeName string) error { - return doCleanSubPaths(mounter, podDir, volumeName) -} - -func (mounter *NsenterMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { - // Bind-mount the subpath to avoid using symlinks in subpaths. - newHostPath, err = doNsEnterBindSubPath(mounter, subPath) - - // There is no action when the container starts. Bind-mount will be cleaned - // when container stops by CleanSubPaths. - cleanupAction = nil - return newHostPath, cleanupAction, err -} - -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) { - exists, err := mounter.ExistsPath(pathname) - if err != nil { - return nil, err - } - if !exists { - return []string{}, nil - } - 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) - } - klog.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 { - klog.V(4).Infof("doNsEnterBindSubPath() failed for %q, cleaning up subpath", bindPathTarget) - if cleanErr := cleanSubPath(mounter, subpath); cleanErr != nil { - klog.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! - klog.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 - klog.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) -} diff --git a/pkg/util/mount/nsenter_mount_unsupported.go b/pkg/util/mount/nsenter_mount_unsupported.go deleted file mode 100644 index 87c2e9ec73..0000000000 --- a/pkg/util/mount/nsenter_mount_unsupported.go +++ /dev/null @@ -1,122 +0,0 @@ -// +build !linux - -/* -Copyright 2014 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package mount - -import ( - "errors" - "os" - - "k8s.io/kubernetes/pkg/util/nsenter" -) - -type NsenterMounter struct{} - -func NewNsenterMounter(rootDir string, ne *nsenter.Nsenter) *NsenterMounter { - return &NsenterMounter{} -} - -var _ = Interface(&NsenterMounter{}) - -func (*NsenterMounter) Mount(source string, target string, fstype string, options []string) error { - return nil -} - -func (*NsenterMounter) Unmount(target string) error { - return nil -} - -func (*NsenterMounter) List() ([]MountPoint, error) { - return []MountPoint{}, nil -} - -func (m *NsenterMounter) IsNotMountPoint(dir string) (bool, error) { - return IsNotMountPoint(m, dir) -} - -func (*NsenterMounter) IsMountPointMatch(mp MountPoint, dir string) bool { - return (mp.Path == dir) -} - -func (*NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) { - return true, nil -} - -func (*NsenterMounter) DeviceOpened(pathname string) (bool, error) { - return false, nil -} - -func (*NsenterMounter) PathIsDevice(pathname string) (bool, error) { - return true, nil -} - -func (*NsenterMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) { - return "", nil -} - -func (*NsenterMounter) MakeRShared(path string) error { - return nil -} - -func (*NsenterMounter) GetFileType(_ string) (FileType, error) { - return FileType("fake"), errors.New("not implemented") -} - -func (*NsenterMounter) MakeDir(pathname string) error { - return nil -} - -func (*NsenterMounter) MakeFile(pathname string) error { - return nil -} - -func (*NsenterMounter) ExistsPath(pathname string) (bool, error) { - return true, errors.New("not implemented") -} - -func (*NsenterMounter) EvalHostSymlinks(pathname string) (string, error) { - return "", errors.New("not implemented") -} - -func (*NsenterMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error { - return nil -} - -func (*NsenterMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) { - return subPath.Path, nil, nil -} - -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") -} diff --git a/pkg/util/nsenter/BUILD b/pkg/util/nsenter/BUILD deleted file mode 100644 index 9a94fae101..0000000000 --- a/pkg/util/nsenter/BUILD +++ /dev/null @@ -1,76 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "exec.go", - "exec_unsupported.go", - "nsenter.go", - "nsenter_unsupported.go", - ], - importpath = "k8s.io/kubernetes/pkg/util/nsenter", - visibility = ["//visibility:public"], - deps = select({ - "@io_bazel_rules_go//go/platform:android": [ - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "@io_bazel_rules_go//go/platform:darwin": [ - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "@io_bazel_rules_go//go/platform:dragonfly": [ - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "@io_bazel_rules_go//go/platform:freebsd": [ - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "@io_bazel_rules_go//go/platform:linux": [ - "//vendor/k8s.io/klog:go_default_library", - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "@io_bazel_rules_go//go/platform:nacl": [ - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "@io_bazel_rules_go//go/platform:netbsd": [ - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "@io_bazel_rules_go//go/platform:openbsd": [ - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "@io_bazel_rules_go//go/platform:plan9": [ - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "@io_bazel_rules_go//go/platform:solaris": [ - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "@io_bazel_rules_go//go/platform:windows": [ - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "//conditions:default": [], - }), -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) - -go_test( - name = "go_default_test", - srcs = ["nsenter_test.go"], - embed = [":go_default_library"], - deps = select({ - "@io_bazel_rules_go//go/platform:linux": [ - "//vendor/k8s.io/utils/exec:go_default_library", - ], - "//conditions:default": [], - }), -) diff --git a/pkg/util/nsenter/OWNERS b/pkg/util/nsenter/OWNERS deleted file mode 100644 index c4f27cb438..0000000000 --- a/pkg/util/nsenter/OWNERS +++ /dev/null @@ -1,8 +0,0 @@ -reviewers: - - jsafrane - - msau42 - - cofyc -approvers: - - jsafrane - - msau42 - - cofyc diff --git a/pkg/util/nsenter/exec.go b/pkg/util/nsenter/exec.go deleted file mode 100644 index 134497f0a7..0000000000 --- a/pkg/util/nsenter/exec.go +++ /dev/null @@ -1,67 +0,0 @@ -// +build linux - -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package nsenter - -import ( - "context" - "fmt" - "path/filepath" - - "k8s.io/klog" - "k8s.io/utils/exec" -) - -// Executor wraps executor interface to be executed via nsenter -type Executor struct { - // Exec implementation - executor exec.Interface - // Path to the host's root proc path - hostProcMountNsPath string -} - -// NewNsenterExecutor returns new nsenter based executor -func NewNsenterExecutor(hostRootFsPath string, executor exec.Interface) *Executor { - hostProcMountNsPath := filepath.Join(hostRootFsPath, mountNsPath) - nsExecutor := &Executor{ - hostProcMountNsPath: hostProcMountNsPath, - executor: executor, - } - return nsExecutor -} - -// Command returns a command wrapped with nenter -func (nsExecutor *Executor) Command(cmd string, args ...string) exec.Cmd { - fullArgs := append([]string{fmt.Sprintf("--mount=%s", nsExecutor.hostProcMountNsPath), "--"}, - append([]string{cmd}, args...)...) - klog.V(5).Infof("Running nsenter command: %v %v", nsenterPath, fullArgs) - return nsExecutor.executor.Command(nsenterPath, fullArgs...) -} - -// CommandContext returns a CommandContext wrapped with nsenter -func (nsExecutor *Executor) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd { - fullArgs := append([]string{fmt.Sprintf("--mount=%s", nsExecutor.hostProcMountNsPath), "--"}, - append([]string{cmd}, args...)...) - klog.V(5).Infof("Running nsenter command: %v %v", nsenterPath, fullArgs) - return nsExecutor.executor.CommandContext(ctx, nsenterPath, fullArgs...) -} - -// LookPath returns a LookPath wrapped with nsenter -func (nsExecutor *Executor) LookPath(file string) (string, error) { - return "", fmt.Errorf("not implemented, error looking up : %s", file) -} diff --git a/pkg/util/nsenter/exec_unsupported.go b/pkg/util/nsenter/exec_unsupported.go deleted file mode 100644 index eecbdfc292..0000000000 --- a/pkg/util/nsenter/exec_unsupported.go +++ /dev/null @@ -1,58 +0,0 @@ -// +build !linux - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package nsenter - -import ( - "context" - "fmt" - - "k8s.io/utils/exec" -) - -// Executor wraps executor interface to be executed via nsenter -type Executor struct { - // Exec implementation - executor exec.Interface - // Path to the host's root proc path - hostProcMountNsPath string -} - -// NewNsenterExecutor returns new nsenter based executor -func NewNsenterExecutor(hostRootFsPath string, executor exec.Interface) *Executor { - nsExecutor := &Executor{ - hostProcMountNsPath: hostRootFsPath, - executor: executor, - } - return nsExecutor -} - -// Command returns a command wrapped with nenter -func (nsExecutor *Executor) Command(cmd string, args ...string) exec.Cmd { - return nil -} - -// CommandContext returns a CommandContext wrapped with nsenter -func (nsExecutor *Executor) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd { - return nil -} - -// LookPath returns a LookPath wrapped with nsenter -func (nsExecutor *Executor) LookPath(file string) (string, error) { - return "", fmt.Errorf("not implemented, error looking up : %s", file) -} diff --git a/pkg/util/nsenter/nsenter.go b/pkg/util/nsenter/nsenter.go deleted file mode 100644 index 56361e7846..0000000000 --- a/pkg/util/nsenter/nsenter.go +++ /dev/null @@ -1,236 +0,0 @@ -// +build linux - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package nsenter - -import ( - "context" - "errors" - "fmt" - "os" - "path/filepath" - "strings" - - "k8s.io/utils/exec" - - "k8s.io/klog" -) - -const ( - // 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" -) - -// Nsenter is part of experimental support for running the kubelet -// in a container. -// -// Nsenter requires: -// -// 1. Docker >= 1.6 due to the dependency on the slave propagation mode -// of the bind-mount of the kubelet root directory in the container. -// Docker 1.5 used a private propagation mode for bind-mounts, so mounts -// performed in the host's mount namespace do not propagate out to the -// bind-mount in this docker version. -// 2. The host's root filesystem must be available at /rootfs -// 3. The nsenter binary must be on the Kubelet process' PATH in the container's -// filesystem. -// 4. The Kubelet process must have CAP_SYS_ADMIN (required by nsenter); at -// the present, this effectively means that the kubelet is running in a -// privileged container. -// 5. The volume path used by the Kubelet must be the same inside and outside -// the container and be writable by the container (to initialize volume) -// 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 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(hostRootFsPath string, executor exec.Interface) (*Nsenter, error) { - ne := &Nsenter{ - 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 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(ne.hostRootFsPath, binPath)); err != nil { - continue - } - ne.paths[binary] = binPath - break - } - // 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 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...)...) - klog.V(5).Infof("Running nsenter command: %v %v", nsenterPath, fullArgs) - return ne.executor.Command(nsenterPath, fullArgs...) -} - -// AbsHostPath returns the absolute runnable path for a specified command -func (ne *Nsenter) AbsHostPath(command string) string { - path, ok := ne.paths[command] - if !ok { - return command - } - return path -} - -// SupportsSystemd checks whether command systemd-run exists -func (ne *Nsenter) SupportsSystemd() (string, bool) { - 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 { - klog.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{} diff --git a/pkg/util/nsenter/nsenter_test.go b/pkg/util/nsenter/nsenter_test.go deleted file mode 100644 index 3158a55bbe..0000000000 --- a/pkg/util/nsenter/nsenter_test.go +++ /dev/null @@ -1,311 +0,0 @@ -// +build linux - -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package nsenter - -import ( - "io/ioutil" - "os" - "path/filepath" - "testing" - - "k8s.io/utils/exec" -) - -func TestExec(t *testing.T) { - tests := []struct { - name string - command string - args []string - expectedOutput string - expectError bool - }{ - { - name: "simple command", - command: "echo", - args: []string{"hello", "world"}, - expectedOutput: "hello world\n", - }, - { - name: "nozero exit code", - command: "false", - expectError: true, - }, - } - - executor := fakeExec{ - rootfsPath: "/rootfs", - } - for _, test := range tests { - ns := Nsenter{ - hostRootFsPath: "/rootfs", - executor: executor, - } - cmd := ns.Exec(test.command, test.args) - outBytes, err := cmd.CombinedOutput() - out := string(outBytes) - if err != nil && !test.expectError { - t.Errorf("Test %q: unexpected error: %s", test.name, err) - } - if err == nil && test.expectError { - t.Errorf("Test %q: expected error, got none", test.name) - } - if test.expectedOutput != out { - t.Errorf("test %q: expected output %q, got %q", test.name, test.expectedOutput, out) - } - } -} - -func TestKubeletPath(t *testing.T) { - tests := []struct { - rootfs string - hostpath string - expectedKubeletPath string - }{ - { - // simple join - "/rootfs", - "/some/path", - "/rootfs/some/path", - }, - { - // squash slashes - "/rootfs/", - "//some/path", - "/rootfs/some/path", - }, - } - - for _, test := range tests { - ns := Nsenter{ - hostRootFsPath: test.rootfs, - } - out := ns.KubeletPath(test.hostpath) - if out != test.expectedKubeletPath { - t.Errorf("Expected path %q, got %q", test.expectedKubeletPath, out) - } - - } -} - -func TestEvalSymlinks(t *testing.T) { - tests := []struct { - name string - mustExist bool - prepare func(tmpdir string) (src string, expectedDst string, err error) - expectError bool - }{ - { - name: "simple file /src", - mustExist: true, - prepare: func(tmpdir string) (src string, expectedDst string, err error) { - src = filepath.Join(tmpdir, "src") - err = ioutil.WriteFile(src, []byte{}, 0644) - return src, src, err - }, - }, - { - name: "non-existing file /src", - mustExist: true, - prepare: func(tmpdir string) (src string, expectedDst string, err error) { - src = filepath.Join(tmpdir, "src") - return src, "", nil - }, - expectError: true, - }, - { - name: "non-existing file /src/ with mustExist=false", - mustExist: false, - prepare: func(tmpdir string) (src string, expectedDst string, err error) { - src = filepath.Join(tmpdir, "src") - return src, src, nil - }, - }, - { - name: "non-existing file /existing/path/src with mustExist=false with existing directories", - mustExist: false, - prepare: func(tmpdir string) (src string, expectedDst string, err error) { - src = filepath.Join(tmpdir, "existing/path") - if err := os.MkdirAll(src, 0755); err != nil { - return "", "", err - } - src = filepath.Join(src, "src") - return src, src, nil - }, - }, - { - name: "simple symlink /src -> /dst", - mustExist: false, - prepare: func(tmpdir string) (src string, expectedDst string, err error) { - dst := filepath.Join(tmpdir, "dst") - if err = ioutil.WriteFile(dst, []byte{}, 0644); err != nil { - return "", "", err - } - src = filepath.Join(tmpdir, "src") - err = os.Symlink(dst, src) - return src, dst, err - }, - }, - { - name: "dangling symlink /src -> /non-existing-path", - mustExist: true, - prepare: func(tmpdir string) (src string, expectedDst string, err error) { - dst := filepath.Join(tmpdir, "non-existing-path") - src = filepath.Join(tmpdir, "src") - err = os.Symlink(dst, src) - return src, "", err - }, - expectError: true, - }, - { - name: "dangling symlink /src -> /non-existing-path with mustExist=false", - mustExist: false, - prepare: func(tmpdir string) (src string, expectedDst string, err error) { - dst := filepath.Join(tmpdir, "non-existing-path") - src = filepath.Join(tmpdir, "src") - err = os.Symlink(dst, src) - return src, dst, err - }, - }, - { - name: "symlink to directory /src/file, where /src is link to /dst", - mustExist: true, - prepare: func(tmpdir string) (src string, expectedDst string, err error) { - dst := filepath.Join(tmpdir, "dst") - if err = os.Mkdir(dst, 0755); err != nil { - return "", "", err - } - dstFile := filepath.Join(dst, "file") - if err = ioutil.WriteFile(dstFile, []byte{}, 0644); err != nil { - return "", "", err - } - - src = filepath.Join(tmpdir, "src") - if err = os.Symlink(dst, src); err != nil { - return "", "", err - } - srcFile := filepath.Join(src, "file") - return srcFile, dstFile, nil - }, - }, - { - name: "symlink to non-existing directory: /src/file, where /src is link to /dst and dst does not exist", - mustExist: true, - prepare: func(tmpdir string) (src string, expectedDst string, err error) { - dst := filepath.Join(tmpdir, "dst") - - src = filepath.Join(tmpdir, "src") - if err = os.Symlink(dst, src); err != nil { - return "", "", err - } - srcFile := filepath.Join(src, "file") - return srcFile, "", nil - }, - expectError: true, - }, - { - name: "symlink to non-existing directory: /src/file, where /src is link to /dst and dst does not exist with mustExist=false", - mustExist: false, - prepare: func(tmpdir string) (src string, expectedDst string, err error) { - dst := filepath.Join(tmpdir, "dst") - dstFile := filepath.Join(dst, "file") - - src = filepath.Join(tmpdir, "src") - if err = os.Symlink(dst, src); err != nil { - return "", "", err - } - srcFile := filepath.Join(src, "file") - return srcFile, dstFile, nil - }, - }, - } - - for _, test := range tests { - ns := Nsenter{ - hostRootFsPath: "/rootfs", - executor: fakeExec{ - rootfsPath: "/rootfs", - }, - } - - tmpdir, err := ioutil.TempDir("", "nsenter-hostpath-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) - - src, expectedDst, err := test.prepare(tmpdir) - if err != nil { - t.Error(err) - continue - } - - dst, err := ns.EvalSymlinks(src, test.mustExist) - if err != nil && !test.expectError { - t.Errorf("Test %q: unexpected error: %s", test.name, err) - } - if err == nil && test.expectError { - t.Errorf("Test %q: expected error, got none", test.name) - } - if dst != expectedDst { - t.Errorf("Test %q: expected destination %q, got %q", test.name, expectedDst, dst) - } - } -} - -func TestNewNsenter(t *testing.T) { - // Create a symlink /tmp/xyz/rootfs -> / and use it as rootfs path - // It should resolve all binaries correctly, the test runs on Linux - - tmpdir, err := ioutil.TempDir("", "nsenter-hostpath-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) - - rootfs := filepath.Join(tmpdir, "rootfs") - if err = os.Symlink("/", rootfs); err != nil { - t.Fatal(err) - } - - _, err = NewNsenter(rootfs, exec.New()) - if err != nil { - t.Errorf("Error: %s", err) - } -} - -func TestNewNsenterError(t *testing.T) { - // Create empty dir /tmp/xyz/rootfs and use it as rootfs path - // It should resolve all binaries correctly, the test runs on Linux - - tmpdir, err := ioutil.TempDir("", "nsenter-hostpath-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) - - rootfs := filepath.Join(tmpdir, "rootfs") - if err = os.MkdirAll(rootfs, 0755); err != nil { - t.Fatal(err) - } - - _, err = NewNsenter(rootfs, exec.New()) - if err == nil { - t.Errorf("Expected error, got none") - } -} diff --git a/pkg/util/nsenter/nsenter_unsupported.go b/pkg/util/nsenter/nsenter_unsupported.go deleted file mode 100644 index 0618b9da46..0000000000 --- a/pkg/util/nsenter/nsenter_unsupported.go +++ /dev/null @@ -1,56 +0,0 @@ -// +build !linux - -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package nsenter - -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 { - // a map of commands to their paths on the host filesystem - Paths map[string]string -} - -// NewNsenter constructs a new instance of Nsenter -func NewNsenter(hostRootFsPath string, executor exec.Interface) (*Nsenter, error) { - return &Nsenter{}, nil -} - -// Exec executes nsenter commands in hostProcMountNsPath mount namespace -func (ne *Nsenter) Exec(cmd string, args []string) exec.Cmd { - return nil -} - -// AbsHostPath returns the absolute runnable path for a specified command -func (ne *Nsenter) AbsHostPath(command string) string { - return "" -} - -// SupportsSystemd checks whether command systemd-run exists -func (ne *Nsenter) SupportsSystemd() (string, bool) { - return "", false -}