vendor update for CSI 0.3.0

This commit is contained in:
gman
2018-07-18 16:47:22 +02:00
parent 6f484f92fc
commit 8ea659f0d5
6810 changed files with 438061 additions and 193861 deletions

View File

@ -18,7 +18,6 @@ package cmd
import (
"archive/tar"
"bytes"
"errors"
"fmt"
"io"
@ -28,10 +27,15 @@ import (
"path/filepath"
"strings"
restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
"bytes"
"github.com/renstrom/dedent"
"github.com/spf13/cobra"
)
@ -61,8 +65,26 @@ var (
/file/path for a local file`)
)
type CopyOptions struct {
Container string
Namespace string
ClientConfig *restclient.Config
Clientset internalclientset.Interface
genericclioptions.IOStreams
}
func NewCopyOptions(ioStreams genericclioptions.IOStreams) *CopyOptions {
return &CopyOptions{
IOStreams: ioStreams,
}
}
// NewCmdCp creates a new Copy command.
func NewCmdCp(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Command {
func NewCmdCp(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
o := NewCopyOptions(ioStreams)
cmd := &cobra.Command{
Use: "cp <file-spec-src> <file-spec-dest>",
DisableFlagsInUseLine: true,
@ -70,10 +92,11 @@ func NewCmdCp(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Command {
Long: "Copy files and directories to and from containers.",
Example: cpExample,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(runCopy(f, cmd, cmdOut, cmdErr, args))
cmdutil.CheckErr(o.Complete(f, cmd))
cmdutil.CheckErr(o.Run(args))
},
}
cmd.Flags().StringP("container", "c", "", "Container name. If omitted, the first container in the pod will be chosen")
cmd.Flags().StringVarP(&o.Container, "container", "c", o.Container, "Container name. If omitted, the first container in the pod will be chosen")
return cmd
}
@ -90,39 +113,60 @@ var (
)
func extractFileSpec(arg string) (fileSpec, error) {
pieces := strings.Split(arg, ":")
if len(pieces) == 1 {
if i := strings.Index(arg, ":"); i == -1 {
return fileSpec{File: arg}, nil
}
if len(pieces) != 2 {
// FIXME Kubernetes can't copy files that contain a ':'
// character.
return fileSpec{}, errFileSpecDoesntMatchFormat
}
file := pieces[1]
pieces = strings.Split(pieces[0], "/")
if len(pieces) == 1 {
return fileSpec{
PodName: pieces[0],
File: file,
}, nil
}
if len(pieces) == 2 {
return fileSpec{
PodNamespace: pieces[0],
PodName: pieces[1],
File: file,
}, nil
} else if i > 0 {
file := arg[i+1:]
pod := arg[:i]
pieces := strings.Split(pod, "/")
if len(pieces) == 1 {
return fileSpec{
PodName: pieces[0],
File: file,
}, nil
}
if len(pieces) == 2 {
return fileSpec{
PodNamespace: pieces[0],
PodName: pieces[1],
File: file,
}, nil
}
}
return fileSpec{}, errFileSpecDoesntMatchFormat
}
func runCopy(f cmdutil.Factory, cmd *cobra.Command, out, cmderr io.Writer, args []string) error {
func (o *CopyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
var err error
o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}
o.Clientset, err = f.ClientSet()
if err != nil {
return err
}
o.ClientConfig, err = f.ToRESTConfig()
if err != nil {
return err
}
return nil
}
func (o *CopyOptions) Validate(cmd *cobra.Command, args []string) error {
if len(args) != 2 {
return cmdutil.UsageErrorf(cmd, cpUsageStr)
}
return nil
}
func (o *CopyOptions) Run(args []string) error {
if len(args) < 2 {
return fmt.Errorf("source and destination are required")
}
srcSpec, err := extractFileSpec(args[0])
if err != nil {
return err
@ -131,24 +175,34 @@ func runCopy(f cmdutil.Factory, cmd *cobra.Command, out, cmderr io.Writer, args
if err != nil {
return err
}
if len(srcSpec.PodName) != 0 && len(destSpec.PodName) != 0 {
if _, err := os.Stat(args[0]); err == nil {
return o.copyToPod(fileSpec{File: args[0]}, destSpec)
}
return fmt.Errorf("src doesn't exist in local filesystem")
}
if len(srcSpec.PodName) != 0 {
return copyFromPod(f, cmd, cmderr, srcSpec, destSpec)
return o.copyFromPod(srcSpec, destSpec)
}
if len(destSpec.PodName) != 0 {
return copyToPod(f, cmd, out, cmderr, srcSpec, destSpec)
return o.copyToPod(srcSpec, destSpec)
}
return cmdutil.UsageErrorf(cmd, "One of src or dest must be a remote file specification")
return fmt.Errorf("one of src or dest must be a remote file specification")
}
// checkDestinationIsDir receives a destination fileSpec and
// determines if the provided destination path exists on the
// pod. If the destination path does not exist or is _not_ a
// directory, an error is returned with the exit code received.
func checkDestinationIsDir(dest fileSpec, f cmdutil.Factory, cmd *cobra.Command) error {
func (o *CopyOptions) checkDestinationIsDir(dest fileSpec) error {
options := &ExecOptions{
StreamOptions: StreamOptions{
Out: bytes.NewBuffer([]byte{}),
Err: bytes.NewBuffer([]byte{}),
IOStreams: genericclioptions.IOStreams{
Out: bytes.NewBuffer([]byte{}),
ErrOut: bytes.NewBuffer([]byte{}),
},
Namespace: dest.PodNamespace,
PodName: dest.PodName,
@ -158,21 +212,21 @@ func checkDestinationIsDir(dest fileSpec, f cmdutil.Factory, cmd *cobra.Command)
Executor: &DefaultRemoteExecutor{},
}
return execute(f, cmd, options)
return o.execute(options)
}
func copyToPod(f cmdutil.Factory, cmd *cobra.Command, stdout, stderr io.Writer, src, dest fileSpec) error {
if len(src.File) == 0 {
func (o *CopyOptions) copyToPod(src, dest fileSpec) error {
if len(src.File) == 0 || len(dest.File) == 0 {
return errFileCannotBeEmpty
}
reader, writer := io.Pipe()
// strip trailing slash (if any)
if strings.HasSuffix(string(dest.File[len(dest.File)-1]), "/") {
if dest.File != "/" && strings.HasSuffix(string(dest.File[len(dest.File)-1]), "/") {
dest.File = dest.File[:len(dest.File)-1]
}
if err := checkDestinationIsDir(dest, f, cmd); err == nil {
if err := o.checkDestinationIsDir(dest); err == nil {
// If no error, dest.File was found to be a directory.
// Copy specified src into it
dest.File = dest.File + "/" + path.Base(src.File)
@ -193,9 +247,11 @@ func copyToPod(f cmdutil.Factory, cmd *cobra.Command, stdout, stderr io.Writer,
options := &ExecOptions{
StreamOptions: StreamOptions{
In: reader,
Out: stdout,
Err: stderr,
IOStreams: genericclioptions.IOStreams{
In: reader,
Out: o.Out,
ErrOut: o.ErrOut,
},
Stdin: true,
Namespace: dest.PodNamespace,
@ -205,20 +261,22 @@ func copyToPod(f cmdutil.Factory, cmd *cobra.Command, stdout, stderr io.Writer,
Command: cmdArr,
Executor: &DefaultRemoteExecutor{},
}
return execute(f, cmd, options)
return o.execute(options)
}
func copyFromPod(f cmdutil.Factory, cmd *cobra.Command, cmderr io.Writer, src, dest fileSpec) error {
if len(src.File) == 0 {
func (o *CopyOptions) copyFromPod(src, dest fileSpec) error {
if len(src.File) == 0 || len(dest.File) == 0 {
return errFileCannotBeEmpty
}
reader, outStream := io.Pipe()
options := &ExecOptions{
StreamOptions: StreamOptions{
In: nil,
Out: outStream,
Err: cmderr,
IOStreams: genericclioptions.IOStreams{
In: nil,
Out: outStream,
ErrOut: o.Out,
},
Namespace: src.PodNamespace,
PodName: src.PodName,
@ -231,13 +289,26 @@ func copyFromPod(f cmdutil.Factory, cmd *cobra.Command, cmderr io.Writer, src, d
go func() {
defer outStream.Close()
execute(f, cmd, options)
o.execute(options)
}()
prefix := getPrefix(src.File)
prefix = path.Clean(prefix)
// remove extraneous path shortcuts - these could occur if a path contained extra "../"
// and attempted to navigate beyond "/" in a remote filesystem
prefix = stripPathShortcuts(prefix)
return untarAll(reader, dest.File, prefix)
}
// stripPathShortcuts removes any leading or trailing "../" from a given path
func stripPathShortcuts(p string) string {
newPath := path.Clean(p)
if len(newPath) > 0 && string(newPath[0]) == "/" {
return newPath[1:]
}
return newPath
}
func makeTar(srcPath, destPath string, writer io.Writer) error {
// TODO: use compression here?
tarWriter := tar.NewWriter(writer)
@ -312,6 +383,12 @@ func recursiveTar(srcBase, srcFile, destBase, destFile string, tw *tar.Writer) e
return nil
}
// clean prevents path traversals by stripping them out.
// This is adapted from https://golang.org/src/net/http/fs.go#L74
func clean(fileName string) string {
return path.Clean(string(os.PathSeparator) + fileName)
}
func untarAll(reader io.Reader, destFile, prefix string) error {
entrySeq := -1
@ -327,7 +404,7 @@ func untarAll(reader io.Reader, destFile, prefix string) error {
}
entrySeq++
mode := header.FileInfo().Mode()
outFileName := path.Join(destFile, header.Name[len(prefix):])
outFileName := path.Join(destFile, clean(header.Name[len(prefix):]))
baseName := path.Dir(outFileName)
if err := os.MkdirAll(baseName, 0755); err != nil {
return err
@ -346,7 +423,7 @@ func untarAll(reader io.Reader, destFile, prefix string) error {
return err
}
if exists {
outFileName = filepath.Join(outFileName, path.Base(header.Name))
outFileName = filepath.Join(outFileName, path.Base(clean(header.Name)))
}
}
@ -383,31 +460,17 @@ func getPrefix(file string) string {
return strings.TrimLeft(file, "/")
}
func execute(f cmdutil.Factory, cmd *cobra.Command, options *ExecOptions) error {
func (o *CopyOptions) execute(options *ExecOptions) error {
if len(options.Namespace) == 0 {
namespace, _, err := f.DefaultNamespace()
if err != nil {
return err
}
options.Namespace = namespace
options.Namespace = o.Namespace
}
container := cmdutil.GetFlagString(cmd, "container")
if len(container) > 0 {
options.ContainerName = container
if len(o.Container) > 0 {
options.ContainerName = o.Container
}
config, err := f.ClientConfig()
if err != nil {
return err
}
options.Config = config
clientset, err := f.ClientSet()
if err != nil {
return err
}
options.PodClient = clientset.Core()
options.Config = o.ClientConfig
options.PodClient = o.Clientset.Core()
if err := options.Validate(); err != nil {
return err