Skip to content

Commit

Permalink
Merge pull request hashicorp#5426 from hashicorp/fix_4915
Browse files Browse the repository at this point in the history
Fix 4915
  • Loading branch information
mwhooker authored Feb 5, 2018
2 parents 8827df1 + 52c0be2 commit ff64ccd
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 9 deletions.
15 changes: 15 additions & 0 deletions builder/docker/communicator.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,21 @@ func (c *Communicator) uploadReader(dst string, src io.Reader) error {

// 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 {
// find out if it's a directory
testDirectoryCommand := fmt.Sprintf(`test -d "%s"`, dst)
cmd := &packer.RemoteCmd{Command: testDirectoryCommand}

err := c.Start(cmd)

if err != nil {
log.Printf("Unable to check whether remote path is a dir: %s", err)
return err
}
cmd.Wait()
if cmd.ExitStatus == 0 {
log.Printf("path is a directory; copying file into directory.")
dst = filepath.Join(dst, filepath.Base((*fi).Name()))
}

// command format: docker cp /path/to/infile containerid:/path/to/outfile
log.Printf("Copying to %s on container %s.", dst, c.ContainerID)
Expand Down
18 changes: 18 additions & 0 deletions builder/lxc/communicator.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,24 @@ func (c *LxcAttachCommunicator) Upload(dst string, r io.Reader, fi *os.FileInfo)
return err
}

if fi != nil {
tfDir := filepath.Dir(tf.Name())
// rename tempfile to match original file name. This makes sure that if file is being
// moved into a directory, the filename is preserved instead of a temp name.
adjustedTempName := filepath.Join(tfDir, (*fi).Name())
mvCmd, err := c.CmdWrapper(fmt.Sprintf("sudo mv %s %s", tf.Name(), adjustedTempName))
if err != nil {
return err
}
defer os.Remove(adjustedTempName)
ShellCommand(mvCmd).Run()
// change cpCmd to use new file name as source
cpCmd, err = c.CmdWrapper(fmt.Sprintf("sudo cp %s %s", adjustedTempName, dst))
if err != nil {
return err
}
}

log.Printf("Running copy command: %s", dst)

return ShellCommand(cpCmd).Run()
Expand Down
19 changes: 18 additions & 1 deletion builder/lxd/communicator.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,24 @@ func (c *Communicator) Start(cmd *packer.RemoteCmd) error {
}

func (c *Communicator) Upload(dst string, r io.Reader, fi *os.FileInfo) error {
cpCmd, err := c.CmdWrapper(fmt.Sprintf("lxc file push - %s", filepath.Join(c.ContainerName, dst)))
fileDestination := filepath.Join(c.ContainerName, dst)
// find out if the place we are pushing to is a directory
testDirectoryCommand := fmt.Sprintf(`test -d "%s"`, dst)
cmd := &packer.RemoteCmd{Command: testDirectoryCommand}
err := c.Start(cmd)

if err != nil {
log.Printf("Unable to check whether remote path is a dir: %s", err)
return err
}
cmd.Wait()

if cmd.ExitStatus == 0 {
log.Printf("path is a directory; copying file into directory.")
fileDestination = filepath.Join(c.ContainerName, dst, (*fi).Name())
}

cpCmd, err := c.CmdWrapper(fmt.Sprintf("lxc file push - %s", fileDestination))
if err != nil {
return err
}
Expand Down
47 changes: 40 additions & 7 deletions communicator/ssh/communicator.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,15 +402,31 @@ func (c *comm) connectToAgent() {

func (c *comm) sftpUploadSession(path string, input io.Reader, fi *os.FileInfo) error {
sftpFunc := func(client *sftp.Client) error {
return sftpUploadFile(path, input, client, fi)
return c.sftpUploadFile(path, input, client, fi)
}

return c.sftpSession(sftpFunc)
}

func sftpUploadFile(path string, input io.Reader, client *sftp.Client, fi *os.FileInfo) error {
func (c *comm) sftpUploadFile(path string, input io.Reader, client *sftp.Client, fi *os.FileInfo) error {
log.Printf("[DEBUG] sftp: uploading %s", path)

// find out if destination is a directory (this is to replicate rsync behavior)
testDirectoryCommand := fmt.Sprintf(`test -d "%s"`, path)
cmd := &packer.RemoteCmd{Command: testDirectoryCommand}

err := c.Start(cmd)

if err != nil {
log.Printf("Unable to check whether remote path is a dir: %s", err)
return err
}
cmd.Wait()
if cmd.ExitStatus == 0 {
log.Printf("path is a directory; copying file into directory.")
path = filepath.Join(path, filepath.Base((*fi).Name()))
}

f, err := client.Create(path)
if err != nil {
return err
Expand Down Expand Up @@ -461,7 +477,7 @@ func (c *comm) sftpUploadDirSession(dst string, src string, excl []string) error
return nil
}

return sftpVisitFile(finalDst, path, info, client)
return c.sftpVisitFile(finalDst, path, info, client)
}

return filepath.Walk(src, walkFunc)
Expand All @@ -470,7 +486,7 @@ func (c *comm) sftpUploadDirSession(dst string, src string, excl []string) error
return c.sftpSession(sftpFunc)
}

func sftpMkdir(path string, client *sftp.Client, fi os.FileInfo) error {
func (c *comm) sftpMkdir(path string, client *sftp.Client, fi os.FileInfo) error {
log.Printf("[DEBUG] sftp: creating dir %s", path)

if err := client.Mkdir(path); err != nil {
Expand All @@ -488,16 +504,16 @@ func sftpMkdir(path string, client *sftp.Client, fi os.FileInfo) error {
return nil
}

func sftpVisitFile(dst string, src string, fi os.FileInfo, client *sftp.Client) error {
func (c *comm) sftpVisitFile(dst string, src string, fi os.FileInfo, client *sftp.Client) error {
if !fi.IsDir() {
f, err := os.Open(src)
if err != nil {
return err
}
defer f.Close()
return sftpUploadFile(dst, f, client, &fi)
return c.sftpUploadFile(dst, f, client, &fi)
} else {
err := sftpMkdir(dst, client, fi)
err := c.sftpMkdir(dst, client, fi)
return err
}
}
Expand Down Expand Up @@ -558,6 +574,23 @@ func (c *comm) scpUploadSession(path string, input io.Reader, fi *os.FileInfo) e
target_dir := filepath.Dir(path)
target_file := filepath.Base(path)

// find out if destination is a directory (this is to replicate rsync behavior)
testDirectoryCommand := fmt.Sprintf(`test -d "%s"`, path)
cmd := &packer.RemoteCmd{Command: testDirectoryCommand}

err := c.Start(cmd)

if err != nil {
log.Printf("Unable to check whether remote path is a dir: %s", err)
return err
}
cmd.Wait()
if cmd.ExitStatus == 0 {
log.Printf("path is a directory; copying file into directory.")
target_dir = path
target_file = filepath.Base((*fi).Name())
}

// On windows, filepath.Dir uses backslash seperators (ie. "\tmp").
// This does not work when the target host is unix. Switch to forward slash
// which works for unix and windows
Expand Down
19 changes: 18 additions & 1 deletion communicator/winrm/communicator.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,28 @@ func runCommand(shell *winrm.Shell, cmd *winrm.Command, rc *packer.RemoteCmd) {
}

// Upload implementation of communicator.Communicator interface
func (c *Communicator) Upload(path string, input io.Reader, _ *os.FileInfo) error {
func (c *Communicator) Upload(path string, input io.Reader, fi *os.FileInfo) error {
wcp, err := c.newCopyClient()
if err != nil {
return err
}

// Get information about destination path
endpoint := winrm.NewEndpoint(c.endpoint.Host, c.endpoint.Port, c.config.Https, c.config.Insecure, nil, nil, nil, c.config.Timeout)
client, err := winrm.NewClient(endpoint, c.config.Username, c.config.Password)
if err != nil {
return fmt.Errorf("Was unable to create winrm client: %s", err)
}
stdout, _, _, err := client.RunWithString(fmt.Sprintf("powershell -Command \"(Get-Item %s) -is [System.IO.DirectoryInfo]\"", path), "")
if err != nil {
return fmt.Errorf("Couldn't determine whether destination was a folder or file: %s", err)
}
if strings.Contains(stdout, "True") {
// The path exists and is a directory.
// Upload file into the directory instead of overwriting.
path = filepath.Join(path, filepath.Base((*fi).Name()))
}

log.Printf("Uploading file to '%s'", path)
return wcp.Write(path, input)
}
Expand Down
6 changes: 6 additions & 0 deletions communicator/winrm/communicator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ func newMockWinRMServer(t *testing.T) *winrmtest.Remote {
func(out, err io.Writer) int {
return 0
})
wrm.CommandFunc(
winrmtest.MatchText(`powershell -Command "(Get-Item C:/Temp/packer.cmd) -is [System.IO.DirectoryInfo]"`),
func(out, err io.Writer) int {
out.Write([]byte("False"))
return 0
})

return wrm
}
Expand Down

0 comments on commit ff64ccd

Please sign in to comment.