Fresh dep ensure

This commit is contained in:
Mike Cronce
2018-11-26 13:23:56 -05:00
parent 93cb8a04d7
commit 407478ab9a
9016 changed files with 551394 additions and 279685 deletions

8
vendor/k8s.io/utils/.travis.yml generated vendored
View File

@ -1,9 +1,9 @@
language: go
dist: xenial
go:
- 1.8.x
- 1.9.x
- 1.10.x
- 1.11.x
go_import_path: k8s.io/utils
script:
- diff -u <(echo -n) <(gofmt -d .)
- go tool vet .
- go test -v -race ./...
- make verify

37
vendor/k8s.io/utils/Makefile generated vendored Normal file
View File

@ -0,0 +1,37 @@
# 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.
.PHONY: verify
verify: depend verify-fmt verify-lint vet
go test -v -race ./...
.PHONY: depend
depend:
go get -t -v ./...
.PHONY: verify-fmt
verify-fmt:
./hack/verify-gofmt.sh
.PHONY: verify-lint
verify-lint:
./hack/verify-golint.sh
.PHONY: vet
vet:
go tool vet .
.PHONY: update-fmt
update-fmt:
gofmt -s -w .

18
vendor/k8s.io/utils/OWNERS generated vendored Normal file
View File

@ -0,0 +1,18 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- apelisse
- dashpole
- deads2k
- lavalamp
- mengqiy
- thockin
reviewers:
- apelisse
- dashpole
- deads2k
- lavalamp
- mengqiy
- thockin
- andrewsykim
- cheftako
- mcrute

6
vendor/k8s.io/utils/README.md generated vendored
View File

@ -48,6 +48,12 @@ an existing package to this repository.
- [Pointers](/pointers) provides some functions for pointer-based operations.
- [Io](/io) provides interfaces for working with file IO. Currently it provides
functionality for consistently reading a file.
- [NSEnter](/nsenter) provies interfaces for executing and interacting with
processes running within a namespace.
[Build Status]: https://travis-ci.org/kubernetes/utils.svg?branch=master
[Go standard libs]: https://golang.org/pkg/#stdlib
[api]: https://github.com/kubernetes/api

5
vendor/k8s.io/utils/clock/clock.go generated vendored
View File

@ -44,21 +44,24 @@ func (RealClock) Since(ts time.Time) time.Duration {
return time.Since(ts)
}
// Same as time.After(d).
// After is the same as time.After(d).
func (RealClock) After(d time.Duration) <-chan time.Time {
return time.After(d)
}
// NewTimer is the same as time.NewTimer(d)
func (RealClock) NewTimer(d time.Duration) Timer {
return &realTimer{
timer: time.NewTimer(d),
}
}
// Tick is the same as time.Tick(d)
func (RealClock) Tick(d time.Duration) <-chan time.Time {
return time.Tick(d)
}
// Sleep is the same as time.Sleep(d)
func (RealClock) Sleep(d time.Duration) {
time.Sleep(d)
}

37
vendor/k8s.io/utils/exec/exec.go generated vendored
View File

@ -60,6 +60,17 @@ type Cmd interface {
SetStdin(in io.Reader)
SetStdout(out io.Writer)
SetStderr(out io.Writer)
SetEnv(env []string)
// StdoutPipe and StderrPipe for getting the process' Stdout and Stderr as
// Readers
StdoutPipe() (io.ReadCloser, error)
StderrPipe() (io.ReadCloser, error)
// Start and Wait are for running a process non-blocking
Start() error
Wait() error
// Stops the command by sending SIGTERM. It is not guaranteed the
// process will stop before this function returns. If the process is not
// responding, an internal timer function will send a SIGKILL to force
@ -121,6 +132,30 @@ func (cmd *cmdWrapper) SetStderr(out io.Writer) {
cmd.Stderr = out
}
func (cmd *cmdWrapper) SetEnv(env []string) {
cmd.Env = env
}
func (cmd *cmdWrapper) StdoutPipe() (io.ReadCloser, error) {
r, err := (*osexec.Cmd)(cmd).StdoutPipe()
return r, handleError(err)
}
func (cmd *cmdWrapper) StderrPipe() (io.ReadCloser, error) {
r, err := (*osexec.Cmd)(cmd).StderrPipe()
return r, handleError(err)
}
func (cmd *cmdWrapper) Start() error {
err := (*osexec.Cmd)(cmd).Start()
return handleError(err)
}
func (cmd *cmdWrapper) Wait() error {
err := (*osexec.Cmd)(cmd).Wait()
return handleError(err)
}
// Run is part of the Cmd interface.
func (cmd *cmdWrapper) Run() error {
err := (*osexec.Cmd)(cmd).Run()
@ -206,10 +241,12 @@ func (e CodeExitError) String() string {
return e.Err.Error()
}
// Exited is to check if the process has finished
func (e CodeExitError) Exited() bool {
return true
}
// ExitStatus is for checking the error code
func (e CodeExitError) ExitStatus() int {
return e.Code
}

View File

@ -18,6 +18,8 @@ package exec
import (
"context"
"io"
"io/ioutil"
osexec "os/exec"
"testing"
"time"
@ -139,3 +141,75 @@ func TestTimeout(t *testing.T) {
t.Errorf("expected %v but got %v", context.DeadlineExceeded, err)
}
}
func TestSetEnv(t *testing.T) {
ex := New()
out, err := ex.Command("/bin/sh", "-c", "echo $FOOBAR").CombinedOutput()
if err != nil {
t.Errorf("expected success, got %+v", err)
}
if string(out) != "\n" {
t.Errorf("unexpected output: %q", string(out))
}
cmd := ex.Command("/bin/sh", "-c", "echo $FOOBAR")
cmd.SetEnv([]string{"FOOBAR=baz"})
out, err = cmd.CombinedOutput()
if err != nil {
t.Errorf("expected success, got %+v", err)
}
if string(out) != "baz\n" {
t.Errorf("unexpected output: %q", string(out))
}
}
func TestStdIOPipes(t *testing.T) {
cmd := New().Command("/bin/sh", "-c", "echo 'OUT'>&1; echo 'ERR'>&2")
stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
t.Fatalf("expected StdoutPipe() not to error, got: %v", err)
}
stderrPipe, err := cmd.StderrPipe()
if err != nil {
t.Fatalf("expected StderrPipe() not to error, got: %v", err)
}
stdout := make(chan string)
stderr := make(chan string)
go func() {
stdout <- readAll(t, stdoutPipe, "StdOut")
}()
go func() {
stderr <- readAll(t, stderrPipe, "StdErr")
}()
if err := cmd.Start(); err != nil {
t.Errorf("expected Start() not to error, got: %v", err)
}
if e, a := "OUT\n", <-stdout; e != a {
t.Errorf("expected StdOut to be '%s', got: '%v'", e, a)
}
if e, a := "ERR\n", <-stderr; e != a {
t.Errorf("expected StdErr to be '%s', got: '%v'", e, a)
}
if err := cmd.Wait(); err != nil {
t.Errorf("expected Wait() not to error, got: %v", err)
}
}
func readAll(t *testing.T, r io.Reader, n string) string {
t.Helper()
b, err := ioutil.ReadAll(r)
if err != nil {
t.Fatalf("unexpected error when reading from %s: %v", n, err)
}
return string(b)
}

55
vendor/k8s.io/utils/exec/stdiopipe_test.go generated vendored Normal file
View File

@ -0,0 +1,55 @@
/*
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 exec_test
import (
"fmt"
"io/ioutil"
"k8s.io/utils/exec"
)
func ExampleNew_stderrPipe() {
cmd := exec.New().Command("/bin/sh", "-c", "echo 'We can read from stderr via pipe!' >&2")
stderrPipe, err := cmd.StderrPipe()
if err != nil {
panic(err)
}
stderr := make(chan []byte)
go func() {
b, err := ioutil.ReadAll(stderrPipe)
if err != nil {
panic(err)
}
stderr <- b
}()
if err := cmd.Start(); err != nil {
panic(err)
}
received := <-stderr
if err := cmd.Wait(); err != nil {
panic(err)
}
fmt.Println(string(received))
// Output: We can read from stderr via pipe!
}

View File

@ -24,7 +24,7 @@ import (
"k8s.io/utils/exec"
)
// A simple scripted Interface type.
// FakeExec is a simple scripted Interface type.
type FakeExec struct {
CommandScript []FakeCommandAction
CommandCalls int
@ -33,8 +33,10 @@ type FakeExec struct {
var _ exec.Interface = &FakeExec{}
// FakeCommandAction is the function to be executed
type FakeCommandAction func(cmd string, args ...string) exec.Cmd
// Command is to track the commands that are executed
func (fake *FakeExec) Command(cmd string, args ...string) exec.Cmd {
if fake.CommandCalls > len(fake.CommandScript)-1 {
panic(fmt.Sprintf("ran out of Command() actions. Could not handle command [%d]: %s args: %v", fake.CommandCalls, cmd, args))
@ -44,15 +46,17 @@ func (fake *FakeExec) Command(cmd string, args ...string) exec.Cmd {
return fake.CommandScript[i](cmd, args...)
}
// CommandContext wraps arguments into exec.Cmd
func (fake *FakeExec) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd {
return fake.Command(cmd, args...)
}
// LookPath is for finding the path of a file
func (fake *FakeExec) LookPath(file string) (string, error) {
return fake.LookPathFunc(file)
}
// A simple scripted Cmd type.
// FakeCmd is a simple scripted Cmd type.
type FakeCmd struct {
Argv []string
CombinedOutputScript []FakeCombinedOutputAction
@ -65,34 +69,84 @@ type FakeCmd struct {
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
Env []string
StdoutPipeResponse FakeStdIOPipeResponse
StderrPipeResponse FakeStdIOPipeResponse
WaitResponse error
StartResponse error
}
var _ exec.Cmd = &FakeCmd{}
// InitFakeCmd is for creating a fake exec.Cmd
func InitFakeCmd(fake *FakeCmd, cmd string, args ...string) exec.Cmd {
fake.Argv = append([]string{cmd}, args...)
return fake
}
// FakeStdIOPipeResponse holds responses to use as fakes for the StdoutPipe and
// StderrPipe method calls
type FakeStdIOPipeResponse struct {
ReadCloser io.ReadCloser
Error error
}
// FakeCombinedOutputAction is a function type
type FakeCombinedOutputAction func() ([]byte, error)
// FakeRunAction is a function type
type FakeRunAction func() ([]byte, []byte, error)
// SetDir sets the directory
func (fake *FakeCmd) SetDir(dir string) {
fake.Dirs = append(fake.Dirs, dir)
}
// SetStdin sets the stdin
func (fake *FakeCmd) SetStdin(in io.Reader) {
fake.Stdin = in
}
// SetStdout sets the stdout
func (fake *FakeCmd) SetStdout(out io.Writer) {
fake.Stdout = out
}
// SetStderr sets the stderr
func (fake *FakeCmd) SetStderr(out io.Writer) {
fake.Stderr = out
}
// SetEnv sets the environment variables
func (fake *FakeCmd) SetEnv(env []string) {
fake.Env = env
}
// StdoutPipe returns an injected ReadCloser & error (via StdoutPipeResponse)
// to be able to inject an output stream on Stdout
func (fake *FakeCmd) StdoutPipe() (io.ReadCloser, error) {
return fake.StdoutPipeResponse.ReadCloser, fake.StdoutPipeResponse.Error
}
// StderrPipe returns an injected ReadCloser & error (via StderrPipeResponse)
// to be able to inject an output stream on Stderr
func (fake *FakeCmd) StderrPipe() (io.ReadCloser, error) {
return fake.StderrPipeResponse.ReadCloser, fake.StderrPipeResponse.Error
}
// Start mimicks starting the process (in the background) and returns the
// injected StartResponse
func (fake *FakeCmd) Start() error {
return fake.StartResponse
}
// Wait mimicks waiting for the process to exit returns the
// injected WaitResponse
func (fake *FakeCmd) Wait() error {
return fake.WaitResponse
}
// Run sets runs the command
func (fake *FakeCmd) Run() error {
if fake.RunCalls > len(fake.RunScript)-1 {
panic("ran out of Run() actions")
@ -113,6 +167,7 @@ func (fake *FakeCmd) Run() error {
return err
}
// CombinedOutput returns the output from the command
func (fake *FakeCmd) CombinedOutput() ([]byte, error) {
if fake.CombinedOutputCalls > len(fake.CombinedOutputScript)-1 {
panic("ran out of CombinedOutput() actions")
@ -126,15 +181,17 @@ func (fake *FakeCmd) CombinedOutput() ([]byte, error) {
return fake.CombinedOutputScript[i]()
}
// Output is the response from the command
func (fake *FakeCmd) Output() ([]byte, error) {
return nil, fmt.Errorf("unimplemented")
}
// Stop is to stop the process
func (fake *FakeCmd) Stop() {
// no-op
}
// A simple fake ExitError type.
// FakeExitError is a simple fake ExitError type.
type FakeExitError struct {
Status int
}
@ -149,10 +206,12 @@ func (fake FakeExitError) Error() string {
return fake.String()
}
// Exited always returns true
func (fake FakeExitError) Exited() bool {
return true
}
// ExitStatus returns the fake status
func (fake FakeExitError) ExitStatus() int {
return fake.Status
}

32
vendor/k8s.io/utils/hack/verify-gofmt.sh generated vendored Executable file
View File

@ -0,0 +1,32 @@
#!/usr/bin/env bash
# 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.
set -o errexit
set -o nounset
set -o pipefail
if ! which gofmt > /dev/null; then
echo "Can not find gofmt"
exit 1
fi
diff=$(gofmt -s -d . 2>&1)
if [[ -n "${diff}" ]]; then
echo "${diff}"
echo
echo "Please run 'make update-fmt'"
exit 1
fi

32
vendor/k8s.io/utils/hack/verify-golint.sh generated vendored Executable file
View File

@ -0,0 +1,32 @@
#!/bin/bash
# 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.
set -o errexit
set -o nounset
set -o pipefail
if ! which golint > /dev/null; then
echo "installing golint"
go get golang.org/x/lint/golint
fi
errors="$(golint ./...)"
if [[ -n "$errors" ]]; then
echo "Errors from golint:"
echo
echo "${errors}"
exit 1
fi

55
vendor/k8s.io/utils/io/consistentread.go generated vendored Normal file
View File

@ -0,0 +1,55 @@
/*
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 io
import (
"bytes"
"fmt"
"io/ioutil"
)
// ConsistentRead repeatedly reads a file until it gets the same content twice.
// This is useful when reading files in /proc that are larger than page size
// and kernel may modify them between individual read() syscalls.
func ConsistentRead(filename string, attempts int) ([]byte, error) {
return consistentReadSync(filename, attempts, nil)
}
// consistentReadSync is the main functionality of ConsistentRead but
// introduces a sync callback that can be used by the tests to mutate the file
// from which the test data is being read
func consistentReadSync(filename string, attempts int, sync func(int)) ([]byte, error) {
oldContent, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
for i := 0; i < attempts; i++ {
if sync != nil {
sync(i)
}
newContent, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
if bytes.Compare(oldContent, newContent) == 0 {
return newContent, nil
}
// Files are different, continue reading
oldContent = newContent
}
return nil, fmt.Errorf("could not get consistent content of %s after %d attempts", filename, attempts)
}

94
vendor/k8s.io/utils/io/consistentread_test.go generated vendored Normal file
View File

@ -0,0 +1,94 @@
/*
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 io
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"syscall"
"testing"
)
func writeToPipe(namedPipe string, flaky bool, i int) {
pipe, err := os.OpenFile(namedPipe, os.O_WRONLY, 0600)
if err != nil {
return
}
// The first two reads should never be consistent but all
// subsequent reads should be
outstr := fmt.Sprintf("Foobar %t", (i <= 0))
if flaky {
outstr = fmt.Sprintf("Foobar %d", i)
}
pipe.Write([]byte(outstr))
pipe.Close()
}
func makePipe(t *testing.T) string {
tmp, err := ioutil.TempDir("", "pipe-test")
if err != nil {
t.Fatal(err)
}
pipe := filepath.Join(tmp, "pipe")
syscall.Mkfifo(pipe, 0600)
return pipe
}
func writer(namedPipe string, flaky bool, c <-chan int, d <-chan bool) {
// Make sure something is in the fifo otherwise the first iteration of
// ConsistentRead will block forever
writeToPipe(namedPipe, flaky, -1)
for {
select {
case i := <-c:
writeToPipe(namedPipe, flaky, i)
case <-d:
os.RemoveAll(namedPipe)
return
}
}
}
func TestConsistentRead(t *testing.T) {
pipe := makePipe(t)
prog, done := make(chan int), make(chan bool)
go writer(pipe, false, prog, done)
if _, err := consistentReadSync(pipe, 3, func(i int) { prog <- i }); err != nil {
t.Fatal(err)
}
done <- true
}
func TestConsistentReadFlakyReader(t *testing.T) {
pipe := makePipe(t)
prog, done := make(chan int), make(chan bool)
go writer(pipe, true, prog, done)
if _, err := consistentReadSync(pipe, 3, func(i int) { prog <- i }); err == nil {
t.Fatal("flaky reader returned consistent results")
}
}

8
vendor/k8s.io/utils/nsenter/OWNERS generated vendored Normal file
View File

@ -0,0 +1,8 @@
reviewers:
- jsafrane
- msau42
- cofyc
approvers:
- jsafrane
- msau42
- cofyc

67
vendor/k8s.io/utils/nsenter/exec.go generated vendored Normal file
View File

@ -0,0 +1,67 @@
// +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"
"github.com/golang/glog"
"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...)...)
glog.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...)...)
glog.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)
}

58
vendor/k8s.io/utils/nsenter/exec_unsupported.go generated vendored Normal file
View File

@ -0,0 +1,58 @@
// +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)
}

236
vendor/k8s.io/utils/nsenter/nsenter.go generated vendored Normal file
View File

@ -0,0 +1,236 @@
// +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"
"github.com/golang/glog"
)
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...)...)
glog.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 {
glog.Infof("failed to resolve symbolic links on %s: %v", pathname, err)
return "", err
}
return strings.TrimSpace(string(outBytes)), nil
}
// KubeletPath returns the path name that can be accessed by containerized
// kubelet. It is recommended to resolve symlinks on the host by EvalSymlinks
// before calling this function
func (ne *Nsenter) KubeletPath(pathname string) string {
return filepath.Join(ne.hostRootFsPath, pathname)
}
// NewFakeNsenter returns a Nsenter that does not run "nsenter --mount=... --",
// but runs everything in the same mount namespace as the unit test binary.
// rootfsPath is supposed to be a symlink, e.g. /tmp/xyz/rootfs -> /.
// This fake Nsenter is enough for most operations, e.g. to resolve symlinks,
// but it's not enough to call /bin/mount - unit tests don't run as root.
func NewFakeNsenter(rootfsPath string) (*Nsenter, error) {
executor := &fakeExec{
rootfsPath: rootfsPath,
}
// prepare /rootfs/bin, usr/bin and usr/sbin
bin := filepath.Join(rootfsPath, "bin")
if err := os.Symlink("/bin", bin); err != nil {
return nil, err
}
usr := filepath.Join(rootfsPath, "usr")
if err := os.Mkdir(usr, 0755); err != nil {
return nil, err
}
usrbin := filepath.Join(usr, "bin")
if err := os.Symlink("/usr/bin", usrbin); err != nil {
return nil, err
}
usrsbin := filepath.Join(usr, "sbin")
if err := os.Symlink("/usr/sbin", usrsbin); err != nil {
return nil, err
}
return NewNsenter(rootfsPath, executor)
}
type fakeExec struct {
rootfsPath string
}
func (f fakeExec) Command(cmd string, args ...string) exec.Cmd {
// This will intentionaly panic if Nsenter does not provide enough arguments.
realCmd := args[2]
realArgs := args[3:]
return exec.New().Command(realCmd, realArgs...)
}
func (fakeExec) LookPath(file string) (string, error) {
return "", errors.New("not implemented")
}
func (fakeExec) CommandContext(ctx context.Context, cmd string, args ...string) exec.Cmd {
return nil
}
var _ exec.Interface = fakeExec{}

311
vendor/k8s.io/utils/nsenter/nsenter_test.go generated vendored Normal file
View File

@ -0,0 +1,311 @@
// +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")
}
}

56
vendor/k8s.io/utils/nsenter/nsenter_unsupported.go generated vendored Normal file
View File

@ -0,0 +1,56 @@
// +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
}

9
vendor/k8s.io/utils/pointer/OWNERS generated vendored Normal file
View File

@ -0,0 +1,9 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- apelisse
- stewart-yu
- thockin
reviewers:
- apelisse
- stewart-yu
- thockin

View File

@ -74,3 +74,13 @@ func BoolPtr(b bool) *bool {
func StringPtr(s string) *string {
return &s
}
// Float32Ptr returns a pointer to the passed float32.
func Float32Ptr(i float32) *float32 {
return &i
}
// Float64Ptr returns a pointer to the passed float64.
func Float64Ptr(i float64) *float64 {
return &i
}

View File

@ -17,6 +17,8 @@ limitations under the License.
package pointer
import (
"fmt"
"reflect"
"testing"
)
@ -59,8 +61,12 @@ func TestAllPtrFieldsNil(t *testing.T) {
{(*struct{})(nil), true},
}
for i, tc := range testCases {
if AllPtrFieldsNil(tc.obj) != tc.expected {
t.Errorf("case[%d]: expected %t, got %t", i, tc.expected, !tc.expected)
}
name := fmt.Sprintf("case[%d]", i)
t.Run(name, func(t *testing.T) {
actualErr := AllPtrFieldsNil(tc.obj)
if !reflect.DeepEqual(tc.expected, actualErr) {
t.Errorf("%s: expected %t, got %t", name, tc.expected, !tc.expected)
}
})
}
}

14
vendor/k8s.io/utils/temp/dir.go generated vendored
View File

@ -34,29 +34,29 @@ type Directory interface {
Delete() error
}
// TempDir is wrapping an temporary directory on disk.
type TempDir struct {
// Dir is wrapping an temporary directory on disk.
type Dir struct {
// Name is the name (full path) of the created directory.
Name string
}
var _ Directory = &TempDir{}
var _ Directory = &Dir{}
// CreateTempDir returns a new Directory wrapping a temporary directory
// on disk.
func CreateTempDir(prefix string) (*TempDir, error) {
func CreateTempDir(prefix string) (*Dir, error) {
name, err := ioutil.TempDir("", fmt.Sprintf("%s-", prefix))
if err != nil {
return nil, err
}
return &TempDir{
return &Dir{
Name: name,
}, nil
}
// NewFile creates a new file in the specified directory.
func (d *TempDir) NewFile(name string) (io.WriteCloser, error) {
func (d *Dir) NewFile(name string) (io.WriteCloser, error) {
return os.OpenFile(
filepath.Join(d.Name, name),
os.O_WRONLY|os.O_CREATE|os.O_TRUNC|os.O_EXCL,
@ -65,6 +65,6 @@ func (d *TempDir) NewFile(name string) (io.WriteCloser, error) {
}
// Delete the underlying directory, and all of its content.
func (d *TempDir) Delete() error {
func (d *Dir) Delete() error {
return os.RemoveAll(d.Name)
}

View File

@ -45,11 +45,11 @@ func Example() {
}
if dir.Deleted == false {
panic(errors.New("Directory should have been deleted."))
panic(errors.New("Directory should have been deleted"))
}
if dir.Files["filename"] == nil {
panic(errors.New(`"filename" should have been created.`))
panic(errors.New(`"filename" should have been created`))
}
fmt.Println(dir.Files["filename"].Buffer.String())