diff --git a/pkg/kubectl/cmd/cp/cp.go b/pkg/kubectl/cmd/cp/cp.go index db3eb645b6..c734374d82 100644 --- a/pkg/kubectl/cmd/cp/cp.go +++ b/pkg/kubectl/cmd/cp/cp.go @@ -338,65 +338,71 @@ func makeTar(srcPath, destPath string, writer io.Writer) error { } func recursiveTar(srcBase, srcFile, destBase, destFile string, tw *tar.Writer) error { - fpath := path.Join(srcBase, srcFile) - stat, err := os.Lstat(fpath) + srcPath := path.Join(srcBase, srcFile) + matchedPaths, err := filepath.Glob(srcPath) if err != nil { return err } - if stat.IsDir() { - files, err := ioutil.ReadDir(fpath) + for _, fpath := range matchedPaths { + stat, err := os.Lstat(fpath) if err != nil { return err } - if len(files) == 0 { - //case empty directory + if stat.IsDir() { + files, err := ioutil.ReadDir(fpath) + if err != nil { + return err + } + if len(files) == 0 { + //case empty directory + hdr, _ := tar.FileInfoHeader(stat, fpath) + hdr.Name = destFile + if err := tw.WriteHeader(hdr); err != nil { + return err + } + } + for _, f := range files { + if err := recursiveTar(srcBase, path.Join(srcFile, f.Name()), destBase, path.Join(destFile, f.Name()), tw); err != nil { + return err + } + } + return nil + } else if stat.Mode()&os.ModeSymlink != 0 { + //case soft link hdr, _ := tar.FileInfoHeader(stat, fpath) + target, err := os.Readlink(fpath) + if err != nil { + return err + } + + hdr.Linkname = target hdr.Name = destFile if err := tw.WriteHeader(hdr); err != nil { return err } - } - for _, f := range files { - if err := recursiveTar(srcBase, path.Join(srcFile, f.Name()), destBase, path.Join(destFile, f.Name()), tw); err != nil { + } else { + //case regular file or other file type like pipe + hdr, err := tar.FileInfoHeader(stat, fpath) + if err != nil { return err } - } - return nil - } else if stat.Mode()&os.ModeSymlink != 0 { - //case soft link - hdr, _ := tar.FileInfoHeader(stat, fpath) - target, err := os.Readlink(fpath) - if err != nil { - return err - } + hdr.Name = destFile - hdr.Linkname = target - hdr.Name = destFile - if err := tw.WriteHeader(hdr); err != nil { - return err - } - } else { - //case regular file or other file type like pipe - hdr, err := tar.FileInfoHeader(stat, fpath) - if err != nil { - return err - } - hdr.Name = destFile + if err := tw.WriteHeader(hdr); err != nil { + return err + } - if err := tw.WriteHeader(hdr); err != nil { - return err - } + f, err := os.Open(fpath) + if err != nil { + return err + } + defer f.Close() - f, err := os.Open(fpath) - if err != nil { - return err + if _, err := io.Copy(tw, f); err != nil { + return err + } + return f.Close() } - defer f.Close() - - if _, err := io.Copy(tw, f); err != nil { - return err - } - return f.Close() } return nil } diff --git a/pkg/kubectl/cmd/cp/cp_test.go b/pkg/kubectl/cmd/cp/cp_test.go index b8a14dfc54..766320d10c 100644 --- a/pkg/kubectl/cmd/cp/cp_test.go +++ b/pkg/kubectl/cmd/cp/cp_test.go @@ -46,6 +46,7 @@ type FileType int const ( RegularFile FileType = 0 SymLink FileType = 1 + RegexFile FileType = 2 ) func TestExtractFileSpec(t *testing.T) { @@ -209,6 +210,7 @@ func TestTarUntar(t *testing.T) { files := []struct { name string + nameList []string data string fileType FileType }{ @@ -237,6 +239,12 @@ func TestTarUntar(t *testing.T) { data: "/tmp/gakki", fileType: SymLink, }, + { + name: "blah*", + nameList: []string{"blah1", "blah2"}, + data: "regexp file name", + fileType: RegexFile, + }, } for _, file := range files { @@ -245,26 +253,19 @@ func TestTarUntar(t *testing.T) { t.Fatalf("unexpected error: %v", err) } if file.fileType == RegularFile { - f, err := os.Create(filepath) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - defer f.Close() - if _, err := io.Copy(f, bytes.NewBuffer([]byte(file.data))); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if err := f.Close(); err != nil { - t.Fatal(err) - } + createTmpFile(t, filepath, file.data) } else if file.fileType == SymLink { err := os.Symlink(file.data, filepath) if err != nil { t.Fatalf("unexpected error: %v", err) } + } else if file.fileType == RegexFile { + for _, fileName := range file.nameList { + createTmpFile(t, path.Join(dir, fileName), file.data) + } } else { t.Fatalf("unexpected file type: %v", file) } - } writer := &bytes.Buffer{} @@ -282,22 +283,7 @@ func TestTarUntar(t *testing.T) { filePath := filepath.Join(absPath, file.name) if file.fileType == RegularFile { - f, err := os.Open(filePath) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - defer f.Close() - buff := &bytes.Buffer{} - if _, err := io.Copy(buff, f); err != nil { - t.Fatal(err) - } - if err := f.Close(); err != nil { - t.Fatal(err) - } - if file.data != string(buff.Bytes()) { - t.Fatalf("expected: %s, saw: %s", file.data, string(buff.Bytes())) - } + cmpFileData(t, filePath, file.data) } else if file.fileType == SymLink { dest, err := os.Readlink(filePath) @@ -308,6 +294,10 @@ func TestTarUntar(t *testing.T) { if file.data != dest { t.Fatalf("expected: %s, saw: %s", file.data, dest) } + } else if file.fileType == RegexFile { + for _, fileName := range file.nameList { + cmpFileData(t, path.Join(dir, fileName), file.data) + } } else { t.Fatalf("unexpected file type: %v", file) } @@ -362,17 +352,7 @@ func TestCopyToLocalFileOrDir(t *testing.T) { t.Errorf("unexpected error: %v", err) t.FailNow() } - srcFile, err := os.Create(srcFilePath) - if err != nil { - t.Errorf("unexpected error: %v", err) - t.FailNow() - } - defer srcFile.Close() - - if _, err := io.Copy(srcFile, bytes.NewBuffer([]byte(file.data))); err != nil { - t.Errorf("unexpected error: %v", err) - t.FailNow() - } + createTmpFile(t, srcFilePath, file.data) if file.destDirExists { if err := os.MkdirAll(destPath, 0755); err != nil { t.Errorf("unexpected error: %v", err) @@ -400,7 +380,6 @@ func TestCopyToLocalFileOrDir(t *testing.T) { t.Errorf("unexpected error: %v", err) t.FailNow() } - actualDestFilePath := destPath if file.destDirExists { actualDestFilePath = filepath.Join(destPath, filepath.Base(srcFilePath)) @@ -409,17 +388,7 @@ func TestCopyToLocalFileOrDir(t *testing.T) { if err != nil && os.IsNotExist(err) { t.Errorf("expecting %s exists, but actually it's missing", actualDestFilePath) } - destFile, err := os.Open(actualDestFilePath) - if err != nil { - t.Errorf("unexpected error: %v", err) - t.FailNow() - } - defer destFile.Close() - buff := &bytes.Buffer{} - io.Copy(buff, destFile) - if file.data != string(buff.Bytes()) { - t.Errorf("expected: %s, actual: %s", file.data, string(buff.Bytes())) - } + cmpFileData(t, actualDestFilePath, file.data) }() } @@ -470,16 +439,7 @@ func TestTarDestinationName(t *testing.T) { t.Errorf("unexpected error: %v", err) t.FailNow() } - f, err := os.Create(filepath) - if err != nil { - t.Errorf("unexpected error: %v", err) - t.FailNow() - } - defer f.Close() - if _, err := io.Copy(f, bytes.NewBuffer([]byte(file.data))); err != nil { - t.Errorf("unexpected error: %v", err) - t.FailNow() - } + createTmpFile(t, filepath, file.data) } reader, writer := io.Pipe() @@ -743,3 +703,36 @@ func TestValidate(t *testing.T) { }) } } + +func createTmpFile(t *testing.T, filepath, data string) { + f, err := os.Create(filepath) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + defer f.Close() + if _, err := io.Copy(f, bytes.NewBuffer([]byte(data))); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if err := f.Close(); err != nil { + t.Fatal(err) + } +} + +func cmpFileData(t *testing.T, filePath, data string) { + f, err := os.Open(filePath) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + defer f.Close() + buff := &bytes.Buffer{} + if _, err := io.Copy(buff, f); err != nil { + t.Fatal(err) + } + if err := f.Close(); err != nil { + t.Fatal(err) + } + if data != string(buff.Bytes()) { + t.Fatalf("expected: %s, saw: %s", data, string(buff.Bytes())) + } +}