mirror of https://github.com/k3s-io/k3s
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
commit
9ec2860124
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue