mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
Fresh dep ensure
This commit is contained in:
8
vendor/k8s.io/utils/.travis.yml
generated
vendored
8
vendor/k8s.io/utils/.travis.yml
generated
vendored
@ -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
37
vendor/k8s.io/utils/Makefile
generated
vendored
Normal 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
18
vendor/k8s.io/utils/OWNERS
generated
vendored
Normal 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
6
vendor/k8s.io/utils/README.md
generated
vendored
@ -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
5
vendor/k8s.io/utils/clock/clock.go
generated
vendored
@ -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
37
vendor/k8s.io/utils/exec/exec.go
generated
vendored
@ -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
|
||||
}
|
||||
|
74
vendor/k8s.io/utils/exec/exec_test.go
generated
vendored
74
vendor/k8s.io/utils/exec/exec_test.go
generated
vendored
@ -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
55
vendor/k8s.io/utils/exec/stdiopipe_test.go
generated
vendored
Normal 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!
|
||||
}
|
65
vendor/k8s.io/utils/exec/testing/fake_exec.go
generated
vendored
65
vendor/k8s.io/utils/exec/testing/fake_exec.go
generated
vendored
@ -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
32
vendor/k8s.io/utils/hack/verify-gofmt.sh
generated
vendored
Executable 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
32
vendor/k8s.io/utils/hack/verify-golint.sh
generated
vendored
Executable 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
55
vendor/k8s.io/utils/io/consistentread.go
generated
vendored
Normal 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
94
vendor/k8s.io/utils/io/consistentread_test.go
generated
vendored
Normal 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
8
vendor/k8s.io/utils/nsenter/OWNERS
generated
vendored
Normal 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
67
vendor/k8s.io/utils/nsenter/exec.go
generated
vendored
Normal 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
58
vendor/k8s.io/utils/nsenter/exec_unsupported.go
generated
vendored
Normal 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
236
vendor/k8s.io/utils/nsenter/nsenter.go
generated
vendored
Normal 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
311
vendor/k8s.io/utils/nsenter/nsenter_test.go
generated
vendored
Normal 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
56
vendor/k8s.io/utils/nsenter/nsenter_unsupported.go
generated
vendored
Normal 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
9
vendor/k8s.io/utils/pointer/OWNERS
generated
vendored
Normal 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
|
10
vendor/k8s.io/utils/pointer/pointer.go
generated
vendored
10
vendor/k8s.io/utils/pointer/pointer.go
generated
vendored
@ -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
|
||||
}
|
||||
|
12
vendor/k8s.io/utils/pointer/pointer_test.go
generated
vendored
12
vendor/k8s.io/utils/pointer/pointer_test.go
generated
vendored
@ -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
14
vendor/k8s.io/utils/temp/dir.go
generated
vendored
@ -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)
|
||||
}
|
||||
|
4
vendor/k8s.io/utils/temp/temptest/example_test.go
generated
vendored
4
vendor/k8s.io/utils/temp/temptest/example_test.go
generated
vendored
@ -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())
|
||||
|
Reference in New Issue
Block a user