Files
KubePi/pkg/util/podtool/copytopod.go
2022-06-15 16:28:40 +08:00

159 lines
3.5 KiB
Go

package podtool
import (
"archive/tar"
"bytes"
"fmt"
"io"
"io/ioutil"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
"os"
"path"
"path/filepath"
)
func (p *PodTool) CopyToContainer(destPath string) error {
if p.ExecConfig.NoPreserve {
p.ExecConfig.Command = []string{"tar", "--no-same-permissions", "--no-same-owner", "-xmf", "-"}
} else {
p.ExecConfig.Command = []string{"tar", "-xmf", "-"}
}
if len(destPath) > 0 {
p.ExecConfig.Command = append(p.ExecConfig.Command, "-C", destPath)
}
p.ExecConfig.Tty = false
var stderr bytes.Buffer
p.ExecConfig.Stderr = &stderr
err := p.Exec(Exec)
var stdout bytes.Buffer
p.ExecConfig.Stdout = &stdout
if err != nil {
result := ""
if len(stdout.Bytes()) != 0 {
result = stdout.String()
}
if len(stderr.Bytes()) != 0 {
result = stderr.String()
}
return fmt.Errorf(err.Error(), result)
}
return nil
}
func (p *PodTool) CopyToPod(srcPath, destPath string) error {
reader, writer := io.Pipe()
go func() {
defer writer.Close()
cmdutil.CheckErr(MakeTar(srcPath, destPath, writer))
}()
config := ExecConfig{
Tty: false,
NoPreserve: false,
Stdin: reader,
}
if config.NoPreserve {
config.Command = []string{"tar", "--no-same-permissions", "--no-same-owner", "-xmf", "-"}
} else {
config.Command = []string{"tar", "-xmf", "-"}
}
var stdout bytes.Buffer
config.Stdout = &stdout
dest := path.Dir(destPath)
config.Command = append(config.Command, "-C", dest)
var stderr bytes.Buffer
config.Stderr = &stderr
p.ExecConfig = config
err := p.Exec(Exec)
if err != nil {
result := ""
if len(stdout.Bytes()) != 0 {
result = stdout.String()
}
if len(stderr.Bytes()) != 0 {
result = stderr.String()
}
return fmt.Errorf(err.Error(), result)
}
return nil
}
func MakeTar(srcPath, destPath string, writer io.Writer) error {
tarWriter := tar.NewWriter(writer)
defer tarWriter.Close()
srcPath = path.Clean(srcPath)
destPath = path.Clean(destPath)
return recursiveTar(path.Dir(srcPath), path.Base(srcPath), path.Dir(destPath), path.Base(destPath), tarWriter)
}
func recursiveTar(srcBase, srcFile, destBase, destFile string, tw *tar.Writer) error {
srcPath := path.Join(srcBase, srcFile)
matchedPaths, err := filepath.Glob(srcPath)
if err != nil {
return err
}
for _, fpath := range matchedPaths {
stat, err := os.Lstat(fpath)
if err != nil {
return err
}
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
}
} 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
}
f, err := os.Open(fpath)
if err != nil {
return err
}
defer f.Close()
if _, err := io.Copy(tw, f); err != nil {
return err
}
return f.Close()
}
}
return nil
}