From 4a433102751d3a2ab6f84b5d65254f21fd4aac84 Mon Sep 17 00:00:00 2001 From: bruceauyeung Date: Tue, 10 Oct 2017 09:59:56 +0800 Subject: [PATCH] kubectl cp support colons-in-filename --- pkg/kubectl/cmd/cp.go | 51 ++++++++++++++++++++------------------ pkg/kubectl/cmd/cp_test.go | 7 +++++- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/pkg/kubectl/cmd/cp.go b/pkg/kubectl/cmd/cp.go index c2ba1c20795..aaa066dc2f2 100644 --- a/pkg/kubectl/cmd/cp.go +++ b/pkg/kubectl/cmd/cp.go @@ -113,30 +113,25 @@ 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 @@ -177,13 +172,21 @@ func (o *CopyOptions) Run(args []string) error { 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 o.copyFromPod(srcSpec, destSpec) } if len(destSpec.PodName) != 0 { return o.copyToPod(srcSpec, destSpec) } - return fmt.Errorf("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 diff --git a/pkg/kubectl/cmd/cp_test.go b/pkg/kubectl/cmd/cp_test.go index 656c53ea97a..a01747e8089 100644 --- a/pkg/kubectl/cmd/cp_test.go +++ b/pkg/kubectl/cmd/cp_test.go @@ -71,13 +71,18 @@ func TestExtractFileSpec(t *testing.T) { expectedFile: "/some/file", }, { - spec: "some:bad:spec", + spec: ":file:not:exist:in:local:filesystem", expectErr: true, }, { spec: "namespace/pod/invalid:/some/file", expectErr: true, }, + { + spec: "pod:/some/filenamewith:in", + expectedPod: "pod", + expectedFile: "/some/filenamewith:in", + }, } for _, test := range tests { spec, err := extractFileSpec(test.spec)