Merge pull request #5273 from StuporHero/master

Use docker cp
This commit is contained in:
Megan Marsh 2017-08-30 13:52:07 -07:00 committed by GitHub
commit 9db2cdc02a
3 changed files with 71 additions and 24 deletions

1
.gitignore vendored
View File

@ -21,3 +21,4 @@ packer-test*.log
.idea/
*.iml
Thumbs.db

View File

@ -60,40 +60,85 @@ func (c *Communicator) Start(remote *packer.RemoteCmd) error {
return nil
}
// Upload uploads a file to the docker container
func (c *Communicator) Upload(dst string, src io.Reader, fi *os.FileInfo) error {
if fi == nil {
return c.uploadReader(dst, src)
}
return c.uploadFile(dst, src, fi)
}
// uploadReader writes an io.Reader to a temporary file before uploading
func (c *Communicator) uploadReader(dst string, src io.Reader) error {
// Create a temporary file to store the upload
tempfile, err := ioutil.TempFile(c.HostDir, "upload")
if err != nil {
return err
return fmt.Errorf("Failed to open temp file for writing: %s", err)
}
defer os.Remove(tempfile.Name())
defer tempfile.Close()
// Copy the contents to the temporary file
_, err = io.Copy(tempfile, src)
if _, err := io.Copy(tempfile, src); err != nil {
return fmt.Errorf("Failed to copy upload file to tempfile: %s", err)
}
tempfile.Seek(0, 0)
fi, err := tempfile.Stat()
if err != nil {
return fmt.Errorf("Error getting tempfile info: %s", err)
}
return c.uploadFile(dst, tempfile, &fi)
}
// uploadFile uses docker cp to copy the file from the host to the container
func (c *Communicator) uploadFile(dst string, src io.Reader, fi *os.FileInfo) error {
// command format: docker cp /path/to/infile containerid:/path/to/outfile
log.Printf("Copying to %s on container %s.", dst, c.ContainerId)
localCmd := exec.Command("docker", "cp", "-",
fmt.Sprintf("%s:%s", c.ContainerId, filepath.Dir(dst)))
stderrP, err := localCmd.StderrPipe()
if err != nil {
return fmt.Errorf("Failed to open pipe: %s", err)
}
stdin, err := localCmd.StdinPipe()
if err != nil {
return fmt.Errorf("Failed to open pipe: %s", err)
}
if err := localCmd.Start(); err != nil {
return err
}
archive := tar.NewWriter(stdin)
header, err := tar.FileInfoHeader(*fi, "")
if err != nil {
return err
}
header.Name = filepath.Base(dst)
archive.WriteHeader(header)
numBytes, err := io.Copy(archive, src)
if err != nil {
return fmt.Errorf("Failed to pipe upload: %s", err)
}
log.Printf("Copied %d bytes for %s", numBytes, dst)
if err := archive.Close(); err != nil {
return fmt.Errorf("Failed to close archive: %s", err)
}
if err := stdin.Close(); err != nil {
return fmt.Errorf("Failed to close stdin: %s", err)
}
stderrOut, err := ioutil.ReadAll(stderrP)
if err != nil {
return err
}
if fi != nil {
tempfile.Chmod((*fi).Mode())
}
tempfile.Close()
// Copy the file into place by copying the temporary file we put
// into the shared folder into the proper location in the container
cmd := &packer.RemoteCmd{
Command: fmt.Sprintf("command cp %s/%s %s", c.ContainerDir,
filepath.Base(tempfile.Name()), dst),
}
if err := c.Start(cmd); err != nil {
return err
}
// Wait for the copy to complete
cmd.Wait()
if cmd.ExitStatus != 0 {
return fmt.Errorf("Upload failed with non-zero exit status: %d", cmd.ExitStatus)
if err := localCmd.Wait(); err != nil {
return fmt.Errorf("Failed to upload to '%s' in container: %s. %s.", dst, stderrOut, err)
}
return nil

View File

@ -2,9 +2,10 @@ package none
import (
"errors"
"github.com/hashicorp/packer/packer"
"io"
"os"
"github.com/hashicorp/packer/packer"
)
type comm struct {