docker: stream uploads over stdin
Only write to a tempfile if we don't have a stat struct
This commit is contained in:
parent
c8db128dc5
commit
4edbd5322c
|
@ -60,39 +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()
|
||||
|
||||
// Use docker cp to copy the file from the host to the container
|
||||
// command format: docker cp /path/to/infile containerid:/path/to/outfile
|
||||
cmd := exec.Command("docker", "cp", tempfile.Name(), fmt.Sprintf("%s:%s", c.ContainerId, dst))
|
||||
|
||||
log.Printf("Copying %s to %s on container %s.", tempfile.Name(), dst, c.ContainerId)
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := cmd.Wait(); err != nil {
|
||||
err = fmt.Errorf("Error uploading %s: %s",
|
||||
tempfile.Name(),
|
||||
err)
|
||||
return err
|
||||
if err := localCmd.Wait(); err != nil {
|
||||
return fmt.Errorf("Failed to upload to '%s' in container: %s. %s.", dst, stderrOut, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -2,9 +2,10 @@ package none
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type comm struct {
|
||||
|
|
Loading…
Reference in New Issue