github.com/ves/terraform@v0.8.0-beta2/communicator/remote/command.go (about) 1 package remote 2 3 import ( 4 "io" 5 "sync" 6 ) 7 8 // Cmd represents a remote command being prepared or run. 9 type Cmd struct { 10 // Command is the command to run remotely. This is executed as if 11 // it were a shell command, so you are expected to do any shell escaping 12 // necessary. 13 Command string 14 15 // Stdin specifies the process's standard input. If Stdin is 16 // nil, the process reads from an empty bytes.Buffer. 17 Stdin io.Reader 18 19 // Stdout and Stderr represent the process's standard output and 20 // error. 21 // 22 // If either is nil, it will be set to ioutil.Discard. 23 Stdout io.Writer 24 Stderr io.Writer 25 26 // This will be set to true when the remote command has exited. It 27 // shouldn't be set manually by the user, but there is no harm in 28 // doing so. 29 Exited bool 30 31 // Once Exited is true, this will contain the exit code of the process. 32 ExitStatus int 33 34 // Internal fields 35 exitCh chan struct{} 36 37 // This thing is a mutex, lock when making modifications concurrently 38 sync.Mutex 39 } 40 41 // SetExited is a helper for setting that this process is exited. This 42 // should be called by communicators who are running a remote command in 43 // order to set that the command is done. 44 func (r *Cmd) SetExited(status int) { 45 r.Lock() 46 defer r.Unlock() 47 48 if r.exitCh == nil { 49 r.exitCh = make(chan struct{}) 50 } 51 52 r.Exited = true 53 r.ExitStatus = status 54 close(r.exitCh) 55 } 56 57 // Wait waits for the remote command to complete. 58 func (r *Cmd) Wait() { 59 // Make sure our condition variable is initialized. 60 r.Lock() 61 if r.exitCh == nil { 62 r.exitCh = make(chan struct{}) 63 } 64 r.Unlock() 65 66 <-r.exitCh 67 }