github.com/supr/packer@v0.3.10-0.20131015195147-7b09e24ac3c1/builder/amazon/chroot/communicator.go (about) 1 package chroot 2 3 import ( 4 "fmt" 5 "github.com/mitchellh/packer/packer" 6 "io" 7 "io/ioutil" 8 "log" 9 "os" 10 "os/exec" 11 "path/filepath" 12 "syscall" 13 ) 14 15 // Communicator is a special communicator that works by executing 16 // commands locally but within a chroot. 17 type Communicator struct { 18 Chroot string 19 CmdWrapper CommandWrapper 20 } 21 22 func (c *Communicator) Start(cmd *packer.RemoteCmd) error { 23 command, err := c.CmdWrapper( 24 fmt.Sprintf("chroot %s %s", c.Chroot, cmd.Command)) 25 if err != nil { 26 return err 27 } 28 29 localCmd := ShellCommand(command) 30 localCmd.Stdin = cmd.Stdin 31 localCmd.Stdout = cmd.Stdout 32 localCmd.Stderr = cmd.Stderr 33 log.Printf("Executing: %s %#v", localCmd.Path, localCmd.Args) 34 if err := localCmd.Start(); err != nil { 35 return err 36 } 37 38 go func() { 39 exitStatus := 0 40 if err := localCmd.Wait(); err != nil { 41 if exitErr, ok := err.(*exec.ExitError); ok { 42 exitStatus = 1 43 44 // There is no process-independent way to get the REAL 45 // exit status so we just try to go deeper. 46 if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { 47 exitStatus = status.ExitStatus() 48 } 49 } 50 } 51 52 log.Printf( 53 "Chroot execution exited with '%d': '%s'", 54 exitStatus, cmd.Command) 55 cmd.SetExited(exitStatus) 56 }() 57 58 return nil 59 } 60 61 func (c *Communicator) Upload(dst string, r io.Reader) error { 62 dst = filepath.Join(c.Chroot, dst) 63 log.Printf("Uploading to chroot dir: %s", dst) 64 tf, err := ioutil.TempFile("", "packer-amazon-chroot") 65 if err != nil { 66 return fmt.Errorf("Error preparing shell script: %s", err) 67 } 68 defer os.Remove(tf.Name()) 69 io.Copy(tf, r) 70 71 cpCmd, err := c.CmdWrapper(fmt.Sprintf("cp %s %s", tf.Name(), dst)) 72 if err != nil { 73 return err 74 } 75 76 return ShellCommand(cpCmd).Run() 77 } 78 79 func (c *Communicator) UploadDir(dst string, src string, exclude []string) error { 80 // TODO: remove any file copied if it appears in `exclude` 81 chrootDest := filepath.Join(c.Chroot, dst) 82 log.Printf("Uploading directory '%s' to '%s'", src, chrootDest) 83 cpCmd, err := c.CmdWrapper(fmt.Sprintf("cp -R %s* %s", src, chrootDest)) 84 if err != nil { 85 return err 86 } 87 88 return ShellCommand(cpCmd).Run() 89 } 90 91 func (c *Communicator) Download(src string, w io.Writer) error { 92 src = filepath.Join(c.Chroot, src) 93 log.Printf("Downloading from chroot dir: %s", src) 94 f, err := os.Open(src) 95 if err != nil { 96 return err 97 } 98 defer f.Close() 99 100 if _, err := io.Copy(w, f); err != nil { 101 return err 102 } 103 104 return nil 105 }