From 2ea82cea200cb2e4bf79b0488855b31e8f52b3ad Mon Sep 17 00:00:00 2001 From: Andrew Kim Date: Wed, 23 Jan 2019 21:32:26 -0500 Subject: [PATCH] replace pkg/util/nsenter with k8s.io/utils/nsenter --- cmd/kubelet/app/BUILD | 2 +- cmd/kubelet/app/server.go | 2 +- pkg/controller/.import-restrictions | 1 - pkg/kubectl/.import-restrictions | 1 - pkg/util/BUILD | 1 - pkg/util/mount/BUILD | 24 +- pkg/util/mount/nsenter_mount.go | 2 +- pkg/util/mount/nsenter_mount_test.go | 2 +- pkg/util/mount/nsenter_mount_unsupported.go | 2 +- pkg/util/nsenter/BUILD | 76 ----- pkg/util/nsenter/OWNERS | 10 - 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 ---- 16 files changed, 17 insertions(+), 834 deletions(-) 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/BUILD b/cmd/kubelet/app/BUILD index 59e5a93605..9fc77d79b0 100644 --- a/cmd/kubelet/app/BUILD +++ b/cmd/kubelet/app/BUILD @@ -75,7 +75,6 @@ go_library( "//pkg/util/flock:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/util/node:go_default_library", - "//pkg/util/nsenter:go_default_library", "//pkg/util/oom:go_default_library", "//pkg/util/rlimit:go_default_library", "//pkg/version:go_default_library", @@ -142,6 +141,7 @@ go_library( "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ] + select({ "@io_bazel_rules_go//go/platform:linux": [ "//vendor/github.com/sigma/go-inotify:go_default_library", diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index c84979fd61..bedd78500b 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -91,12 +91,12 @@ 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" "k8s.io/kubernetes/pkg/version/verflag" "k8s.io/utils/exec" + "k8s.io/utils/nsenter" ) const ( diff --git a/pkg/controller/.import-restrictions b/pkg/controller/.import-restrictions index 11cfe737a3..ea8e754077 100644 --- a/pkg/controller/.import-restrictions +++ b/pkg/controller/.import-restrictions @@ -317,7 +317,6 @@ "k8s.io/kubernetes/pkg/kubeapiserver/admission/util", "k8s.io/kubernetes/pkg/scheduler/volumebinder", "k8s.io/kubernetes/pkg/scheduler/internal/cache", - "k8s.io/kubernetes/pkg/util/nsenter", "k8s.io/kubernetes/pkg/util/resizefs", "k8s.io/kubernetes/pkg/util/version", "k8s.io/kubernetes/pkg/apis/apps", diff --git a/pkg/kubectl/.import-restrictions b/pkg/kubectl/.import-restrictions index ea5dcc52d3..f69dc9f281 100644 --- a/pkg/kubectl/.import-restrictions +++ b/pkg/kubectl/.import-restrictions @@ -136,7 +136,6 @@ "k8s.io/kubernetes/pkg/util/mount", "k8s.io/kubernetes/pkg/util/net/sets", "k8s.io/kubernetes/pkg/util/node", - "k8s.io/kubernetes/pkg/util/nsenter", "k8s.io/kubernetes/pkg/util/parsers", "k8s.io/kubernetes/pkg/util/slice", "k8s.io/kubernetes/pkg/util/taints", diff --git a/pkg/util/BUILD b/pkg/util/BUILD index 335e605f07..b2620448b6 100644 --- a/pkg/util/BUILD +++ b/pkg/util/BUILD @@ -41,7 +41,6 @@ filegroup( "//pkg/util/netsh:all-srcs", "//pkg/util/node:all-srcs", "//pkg/util/normalizer:all-srcs", - "//pkg/util/nsenter:all-srcs", "//pkg/util/oom:all-srcs", "//pkg/util/parsers:all-srcs", "//pkg/util/pod:all-srcs", diff --git a/pkg/util/mount/BUILD b/pkg/util/mount/BUILD index 5e77382eec..60998c1d22 100644 --- a/pkg/util/mount/BUILD +++ b/pkg/util/mount/BUILD @@ -23,42 +23,42 @@ go_library( "//vendor/k8s.io/utils/exec:go_default_library", ] + select({ "@io_bazel_rules_go//go/platform:android": [ - "//pkg/util/nsenter:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ], "@io_bazel_rules_go//go/platform:darwin": [ - "//pkg/util/nsenter:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ], "@io_bazel_rules_go//go/platform:dragonfly": [ - "//pkg/util/nsenter:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ], "@io_bazel_rules_go//go/platform:freebsd": [ - "//pkg/util/nsenter:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ], "@io_bazel_rules_go//go/platform:linux": [ "//pkg/util/file:go_default_library", - "//pkg/util/nsenter:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/k8s.io/utils/io:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ], "@io_bazel_rules_go//go/platform:nacl": [ - "//pkg/util/nsenter:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ], "@io_bazel_rules_go//go/platform:netbsd": [ - "//pkg/util/nsenter:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ], "@io_bazel_rules_go//go/platform:openbsd": [ - "//pkg/util/nsenter:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ], "@io_bazel_rules_go//go/platform:plan9": [ - "//pkg/util/nsenter:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ], "@io_bazel_rules_go//go/platform:solaris": [ - "//pkg/util/nsenter:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ], "@io_bazel_rules_go//go/platform:windows": [ "//pkg/util/file:go_default_library", - "//pkg/util/nsenter:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ], "//conditions:default": [], }), @@ -80,10 +80,10 @@ 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/golang.org/x/sys/unix:go_default_library", "//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library", + "//vendor/k8s.io/utils/nsenter:go_default_library", ], "@io_bazel_rules_go//go/platform:windows": [ "//vendor/github.com/stretchr/testify/assert:go_default_library", diff --git a/pkg/util/mount/nsenter_mount.go b/pkg/util/mount/nsenter_mount.go index 215da6174f..e77ee6f75f 100644 --- a/pkg/util/mount/nsenter_mount.go +++ b/pkg/util/mount/nsenter_mount.go @@ -28,7 +28,7 @@ import ( "golang.org/x/sys/unix" "k8s.io/klog" utilfile "k8s.io/kubernetes/pkg/util/file" - "k8s.io/kubernetes/pkg/util/nsenter" + "k8s.io/utils/nsenter" ) const ( diff --git a/pkg/util/mount/nsenter_mount_test.go b/pkg/util/mount/nsenter_mount_test.go index 164eab2f1c..1ed4bd222b 100644 --- a/pkg/util/mount/nsenter_mount_test.go +++ b/pkg/util/mount/nsenter_mount_test.go @@ -27,7 +27,7 @@ import ( "testing" "golang.org/x/sys/unix" - "k8s.io/kubernetes/pkg/util/nsenter" + "k8s.io/utils/nsenter" ) func TestParseFindMnt(t *testing.T) { diff --git a/pkg/util/mount/nsenter_mount_unsupported.go b/pkg/util/mount/nsenter_mount_unsupported.go index ddc44742e8..d68f751af8 100644 --- a/pkg/util/mount/nsenter_mount_unsupported.go +++ b/pkg/util/mount/nsenter_mount_unsupported.go @@ -22,7 +22,7 @@ import ( "errors" "os" - "k8s.io/kubernetes/pkg/util/nsenter" + "k8s.io/utils/nsenter" ) type NsenterMounter struct{} 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 273520d2c7..0000000000 --- a/pkg/util/nsenter/OWNERS +++ /dev/null @@ -1,10 +0,0 @@ -reviewers: - - jsafrane - - msau42 - - cofyc - - dixudx -approvers: - - jsafrane - - msau42 - - cofyc - - dixudx 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 -}