mirror of https://github.com/k3s-io/k3s
replace pkg/util/nsenter with k8s.io/utils/nsenter
parent
123590d911
commit
2ea82cea20
|
@ -75,7 +75,6 @@ go_library(
|
||||||
"//pkg/util/flock:go_default_library",
|
"//pkg/util/flock:go_default_library",
|
||||||
"//pkg/util/mount:go_default_library",
|
"//pkg/util/mount:go_default_library",
|
||||||
"//pkg/util/node:go_default_library",
|
"//pkg/util/node:go_default_library",
|
||||||
"//pkg/util/nsenter:go_default_library",
|
|
||||||
"//pkg/util/oom:go_default_library",
|
"//pkg/util/oom:go_default_library",
|
||||||
"//pkg/util/rlimit:go_default_library",
|
"//pkg/util/rlimit:go_default_library",
|
||||||
"//pkg/version:go_default_library",
|
"//pkg/version:go_default_library",
|
||||||
|
@ -142,6 +141,7 @@ go_library(
|
||||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||||
] + select({
|
] + select({
|
||||||
"@io_bazel_rules_go//go/platform:linux": [
|
"@io_bazel_rules_go//go/platform:linux": [
|
||||||
"//vendor/github.com/sigma/go-inotify:go_default_library",
|
"//vendor/github.com/sigma/go-inotify:go_default_library",
|
||||||
|
|
|
@ -91,12 +91,12 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/util/flock"
|
"k8s.io/kubernetes/pkg/util/flock"
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
nodeutil "k8s.io/kubernetes/pkg/util/node"
|
nodeutil "k8s.io/kubernetes/pkg/util/node"
|
||||||
"k8s.io/kubernetes/pkg/util/nsenter"
|
|
||||||
"k8s.io/kubernetes/pkg/util/oom"
|
"k8s.io/kubernetes/pkg/util/oom"
|
||||||
"k8s.io/kubernetes/pkg/util/rlimit"
|
"k8s.io/kubernetes/pkg/util/rlimit"
|
||||||
"k8s.io/kubernetes/pkg/version"
|
"k8s.io/kubernetes/pkg/version"
|
||||||
"k8s.io/kubernetes/pkg/version/verflag"
|
"k8s.io/kubernetes/pkg/version/verflag"
|
||||||
"k8s.io/utils/exec"
|
"k8s.io/utils/exec"
|
||||||
|
"k8s.io/utils/nsenter"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -317,7 +317,6 @@
|
||||||
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util",
|
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util",
|
||||||
"k8s.io/kubernetes/pkg/scheduler/volumebinder",
|
"k8s.io/kubernetes/pkg/scheduler/volumebinder",
|
||||||
"k8s.io/kubernetes/pkg/scheduler/internal/cache",
|
"k8s.io/kubernetes/pkg/scheduler/internal/cache",
|
||||||
"k8s.io/kubernetes/pkg/util/nsenter",
|
|
||||||
"k8s.io/kubernetes/pkg/util/resizefs",
|
"k8s.io/kubernetes/pkg/util/resizefs",
|
||||||
"k8s.io/kubernetes/pkg/util/version",
|
"k8s.io/kubernetes/pkg/util/version",
|
||||||
"k8s.io/kubernetes/pkg/apis/apps",
|
"k8s.io/kubernetes/pkg/apis/apps",
|
||||||
|
|
|
@ -136,7 +136,6 @@
|
||||||
"k8s.io/kubernetes/pkg/util/mount",
|
"k8s.io/kubernetes/pkg/util/mount",
|
||||||
"k8s.io/kubernetes/pkg/util/net/sets",
|
"k8s.io/kubernetes/pkg/util/net/sets",
|
||||||
"k8s.io/kubernetes/pkg/util/node",
|
"k8s.io/kubernetes/pkg/util/node",
|
||||||
"k8s.io/kubernetes/pkg/util/nsenter",
|
|
||||||
"k8s.io/kubernetes/pkg/util/parsers",
|
"k8s.io/kubernetes/pkg/util/parsers",
|
||||||
"k8s.io/kubernetes/pkg/util/slice",
|
"k8s.io/kubernetes/pkg/util/slice",
|
||||||
"k8s.io/kubernetes/pkg/util/taints",
|
"k8s.io/kubernetes/pkg/util/taints",
|
||||||
|
|
|
@ -41,7 +41,6 @@ filegroup(
|
||||||
"//pkg/util/netsh:all-srcs",
|
"//pkg/util/netsh:all-srcs",
|
||||||
"//pkg/util/node:all-srcs",
|
"//pkg/util/node:all-srcs",
|
||||||
"//pkg/util/normalizer:all-srcs",
|
"//pkg/util/normalizer:all-srcs",
|
||||||
"//pkg/util/nsenter:all-srcs",
|
|
||||||
"//pkg/util/oom:all-srcs",
|
"//pkg/util/oom:all-srcs",
|
||||||
"//pkg/util/parsers:all-srcs",
|
"//pkg/util/parsers:all-srcs",
|
||||||
"//pkg/util/pod:all-srcs",
|
"//pkg/util/pod:all-srcs",
|
||||||
|
|
|
@ -23,42 +23,42 @@ go_library(
|
||||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
] + select({
|
] + select({
|
||||||
"@io_bazel_rules_go//go/platform:android": [
|
"@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": [
|
"@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": [
|
"@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": [
|
"@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": [
|
"@io_bazel_rules_go//go/platform:linux": [
|
||||||
"//pkg/util/file:go_default_library",
|
"//pkg/util/file:go_default_library",
|
||||||
"//pkg/util/nsenter:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||||
"//vendor/k8s.io/utils/io: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": [
|
"@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": [
|
"@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": [
|
"@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": [
|
"@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": [
|
"@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": [
|
"@io_bazel_rules_go//go/platform:windows": [
|
||||||
"//pkg/util/file:go_default_library",
|
"//pkg/util/file:go_default_library",
|
||||||
"//pkg/util/nsenter:go_default_library",
|
"//vendor/k8s.io/utils/nsenter:go_default_library",
|
||||||
],
|
],
|
||||||
"//conditions:default": [],
|
"//conditions:default": [],
|
||||||
}),
|
}),
|
||||||
|
@ -80,10 +80,10 @@ go_test(
|
||||||
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||||
] + select({
|
] + select({
|
||||||
"@io_bazel_rules_go//go/platform:linux": [
|
"@io_bazel_rules_go//go/platform:linux": [
|
||||||
"//pkg/util/nsenter:go_default_library",
|
|
||||||
"//vendor/golang.org/x/sys/unix:go_default_library",
|
"//vendor/golang.org/x/sys/unix:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
"//vendor/k8s.io/utils/exec: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": [
|
"@io_bazel_rules_go//go/platform:windows": [
|
||||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||||
|
|
|
@ -28,7 +28,7 @@ import (
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
utilfile "k8s.io/kubernetes/pkg/util/file"
|
utilfile "k8s.io/kubernetes/pkg/util/file"
|
||||||
"k8s.io/kubernetes/pkg/util/nsenter"
|
"k8s.io/utils/nsenter"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -27,7 +27,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"k8s.io/kubernetes/pkg/util/nsenter"
|
"k8s.io/utils/nsenter"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseFindMnt(t *testing.T) {
|
func TestParseFindMnt(t *testing.T) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/nsenter"
|
"k8s.io/utils/nsenter"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NsenterMounter struct{}
|
type NsenterMounter struct{}
|
||||||
|
|
|
@ -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": [],
|
|
||||||
}),
|
|
||||||
)
|
|
|
@ -1,10 +0,0 @@
|
||||||
reviewers:
|
|
||||||
- jsafrane
|
|
||||||
- msau42
|
|
||||||
- cofyc
|
|
||||||
- dixudx
|
|
||||||
approvers:
|
|
||||||
- jsafrane
|
|
||||||
- msau42
|
|
||||||
- cofyc
|
|
||||||
- dixudx
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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{}
|
|
|
@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
Loading…
Reference in New Issue