|
|
|
|
@ -60,40 +60,86 @@ 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 err
|
|
|
|
|
return fmt.Errorf("Error getting tempfile info: %s", err)
|
|
|
|
|
}
|
|
|
|
|
return c.uploadFile(dst, tempfile, &fi)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if fi != nil {
|
|
|
|
|
tempfile.Chmod((*fi).Mode())
|
|
|
|
|
}
|
|
|
|
|
tempfile.Close()
|
|
|
|
|
// 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 {
|
|
|
|
|
|
|
|
|
|
// 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 to %s on container %s.", dst, c.ContainerId)
|
|
|
|
|
|
|
|
|
|
log.Printf("Copying %s to %s on container %s.", tempfile.Name(), dst, c.ContainerId)
|
|
|
|
|
if err := cmd.Start(); err != nil {
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := cmd.Wait(); err != nil {
|
|
|
|
|
err = fmt.Errorf("Error uploading %s: %s",
|
|
|
|
|
tempfile.Name(),
|
|
|
|
|
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 err := localCmd.Wait(); err != nil {
|
|
|
|
|
return fmt.Errorf("Failed to upload to '%s' in container: %s. %s.", dst, stderrOut, err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|