Merge pull request #60565 from WanLinghao/kubectl_cp_slash

Automatic merge from submit-queue (batch tested with PRs 60990, 60947, 45275, 60565, 61091). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

kubectl cp command bug fix

**What this PR does / why we need it**:
	when copy file from host to pod like this:	
        1.kubectl copy /tmp/test-file test-pod:/
	2.kubectl copy /tmp/test-file test-pod:
	example 1 will fail, example 2 will cause a panic.
	This patch fix bugs above.


**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #60564

**Special notes for your reviewer**:

**Release note**:

```release-note
NONE
```
pull/8/head
Kubernetes Submit Queue 2018-03-30 11:53:13 -07:00 committed by GitHub
commit 9ec2860124
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 3 deletions

View File

@ -162,13 +162,13 @@ func checkDestinationIsDir(dest fileSpec, f cmdutil.Factory, cmd *cobra.Command)
}
func copyToPod(f cmdutil.Factory, cmd *cobra.Command, stdout, stderr io.Writer, src, dest fileSpec) error {
if len(src.File) == 0 {
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]
}
@ -209,7 +209,7 @@ func copyToPod(f cmdutil.Factory, cmd *cobra.Command, stdout, stderr io.Writer,
}
func copyFromPod(f cmdutil.Factory, cmd *cobra.Command, cmderr io.Writer, src, dest fileSpec) error {
if len(src.File) == 0 {
if len(src.File) == 0 || len(dest.File) == 0 {
return errFileCannotBeEmpty
}

View File

@ -21,12 +21,22 @@ import (
"bytes"
"io"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
"testing"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/api/legacyscheme"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
"k8s.io/kubernetes/pkg/kubectl/scheme"
)
type FileType int
@ -497,3 +507,72 @@ func TestClean(t *testing.T) {
}
}
}
func TestCopyToPod(t *testing.T) {
tf := cmdtesting.NewTestFactory()
tf.Namespace = "test"
ns := legacyscheme.Codecs
codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...)
tf.Client = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Group: "", Version: "v1"},
NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
responsePod := &v1.Pod{}
return &http.Response{StatusCode: http.StatusNotFound, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, responsePod))))}, nil
}),
}
tf.ClientConfigVal = defaultClientConfig()
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdCp(tf, buf, errBuf)
srcFile, err := ioutil.TempDir("", "test")
if err != nil {
t.Errorf("unexpected error: %v", err)
t.FailNow()
}
defer os.RemoveAll(srcFile)
tests := map[string]struct {
dest string
expectedErr bool
}{
"copy to directory": {
dest: "/tmp/",
expectedErr: false,
},
"copy to root": {
dest: "/",
expectedErr: false,
},
"copy to empty file name": {
dest: "",
expectedErr: true,
},
}
for name, test := range tests {
src := fileSpec{
File: srcFile,
}
dest := fileSpec{
PodNamespace: "pod-ns",
PodName: "pod-name",
File: test.dest,
}
t.Run(name, func(t *testing.T) {
err = copyToPod(tf, cmd, buf, errBuf, src, dest)
//If error is NotFound error , it indicates that the
//request has been sent correctly.
//Treat this as no error.
if test.expectedErr && errors.IsNotFound(err) {
t.Errorf("expected error but didn't get one")
}
if !test.expectedErr && !errors.IsNotFound(err) {
t.Errorf("unexpected error: %v", err)
}
})
}
}