github.com/stchris/docker@v1.4.2-0.20150106053530-1510a324dbd5/integration-cli/utils.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "math/rand" 9 "net/http" 10 "net/http/httptest" 11 "os" 12 "os/exec" 13 "reflect" 14 "strings" 15 "syscall" 16 "time" 17 18 "github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar" 19 ) 20 21 func getExitCode(err error) (int, error) { 22 exitCode := 0 23 if exiterr, ok := err.(*exec.ExitError); ok { 24 if procExit := exiterr.Sys().(syscall.WaitStatus); ok { 25 return procExit.ExitStatus(), nil 26 } 27 } 28 return exitCode, fmt.Errorf("failed to get exit code") 29 } 30 31 func processExitCode(err error) (exitCode int) { 32 if err != nil { 33 var exiterr error 34 if exitCode, exiterr = getExitCode(err); exiterr != nil { 35 // TODO: Fix this so we check the error's text. 36 // we've failed to retrieve exit code, so we set it to 127 37 exitCode = 127 38 } 39 } 40 return 41 } 42 43 func runCommandWithOutput(cmd *exec.Cmd) (output string, exitCode int, err error) { 44 exitCode = 0 45 out, err := cmd.CombinedOutput() 46 exitCode = processExitCode(err) 47 output = string(out) 48 return 49 } 50 51 func runCommandWithStdoutStderr(cmd *exec.Cmd) (stdout string, stderr string, exitCode int, err error) { 52 var ( 53 stderrBuffer, stdoutBuffer bytes.Buffer 54 ) 55 exitCode = 0 56 cmd.Stderr = &stderrBuffer 57 cmd.Stdout = &stdoutBuffer 58 err = cmd.Run() 59 exitCode = processExitCode(err) 60 61 stdout = stdoutBuffer.String() 62 stderr = stderrBuffer.String() 63 return 64 } 65 66 var ErrCmdTimeout = fmt.Errorf("command timed out") 67 68 func runCommandWithOutputAndTimeout(cmd *exec.Cmd, timeout time.Duration) (output string, exitCode int, err error) { 69 done := make(chan error) 70 go func() { 71 output, exitCode, err = runCommandWithOutput(cmd) 72 if err != nil || exitCode != 0 { 73 done <- fmt.Errorf("failed to run command: %s", err) 74 return 75 } 76 done <- nil 77 }() 78 select { 79 case <-time.After(timeout): 80 killFailed := cmd.Process.Kill() 81 if killFailed == nil { 82 fmt.Printf("failed to kill (pid=%d): %v\n", cmd.Process.Pid, err) 83 } 84 err = ErrCmdTimeout 85 case <-done: 86 break 87 } 88 return 89 } 90 91 func runCommand(cmd *exec.Cmd) (exitCode int, err error) { 92 exitCode = 0 93 err = cmd.Run() 94 exitCode = processExitCode(err) 95 return 96 } 97 98 func logDone(message string) { 99 fmt.Printf("[PASSED]: %s\n", message) 100 } 101 102 func stripTrailingCharacters(target string) string { 103 return strings.TrimSpace(target) 104 } 105 106 func unmarshalJSON(data []byte, result interface{}) error { 107 err := json.Unmarshal(data, result) 108 if err != nil { 109 return err 110 } 111 112 return nil 113 } 114 115 func convertSliceOfStringsToMap(input []string) map[string]struct{} { 116 output := make(map[string]struct{}) 117 for _, v := range input { 118 output[v] = struct{}{} 119 } 120 return output 121 } 122 123 func waitForContainer(contID string, args ...string) error { 124 args = append([]string{"run", "--name", contID}, args...) 125 cmd := exec.Command(dockerBinary, args...) 126 if _, err := runCommand(cmd); err != nil { 127 return err 128 } 129 130 if err := waitRun(contID); err != nil { 131 return err 132 } 133 134 return nil 135 } 136 137 func waitRun(contID string) error { 138 after := time.After(5 * time.Second) 139 140 for { 141 cmd := exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", contID) 142 out, _, err := runCommandWithOutput(cmd) 143 if err != nil { 144 return fmt.Errorf("error executing docker inspect: %v", err) 145 } 146 147 if strings.Contains(out, "true") { 148 break 149 } 150 151 select { 152 case <-after: 153 return fmt.Errorf("container did not come up in time") 154 default: 155 } 156 157 time.Sleep(100 * time.Millisecond) 158 } 159 160 return nil 161 } 162 163 func compareDirectoryEntries(e1 []os.FileInfo, e2 []os.FileInfo) error { 164 var ( 165 e1Entries = make(map[string]struct{}) 166 e2Entries = make(map[string]struct{}) 167 ) 168 for _, e := range e1 { 169 e1Entries[e.Name()] = struct{}{} 170 } 171 for _, e := range e2 { 172 e2Entries[e.Name()] = struct{}{} 173 } 174 if !reflect.DeepEqual(e1Entries, e2Entries) { 175 return fmt.Errorf("entries differ") 176 } 177 return nil 178 } 179 180 func ListTar(f io.Reader) ([]string, error) { 181 tr := tar.NewReader(f) 182 var entries []string 183 184 for { 185 th, err := tr.Next() 186 if err == io.EOF { 187 // end of tar archive 188 return entries, nil 189 } 190 if err != nil { 191 return entries, err 192 } 193 entries = append(entries, th.Name) 194 } 195 } 196 197 type FileServer struct { 198 *httptest.Server 199 } 200 201 func fileServer(files map[string]string) (*FileServer, error) { 202 var handler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) { 203 if filePath, found := files[r.URL.Path]; found { 204 http.ServeFile(w, r, filePath) 205 } else { 206 http.Error(w, http.StatusText(404), 404) 207 } 208 } 209 210 for _, file := range files { 211 if _, err := os.Stat(file); err != nil { 212 return nil, err 213 } 214 } 215 server := httptest.NewServer(handler) 216 return &FileServer{ 217 Server: server, 218 }, nil 219 } 220 221 func copyWithCP(source, target string) error { 222 copyCmd := exec.Command("cp", "-rp", source, target) 223 out, exitCode, err := runCommandWithOutput(copyCmd) 224 if err != nil || exitCode != 0 { 225 return fmt.Errorf("failed to copy: error: %q ,output: %q", err, out) 226 } 227 return nil 228 } 229 230 func makeRandomString(n int) string { 231 // make a really long string 232 letters := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 233 b := make([]byte, n) 234 for i := range b { 235 b[i] = letters[rand.Intn(len(letters))] 236 } 237 return string(b) 238 } 239 240 // Reads chunkSize bytes from reader after every interval. 241 // Returns total read bytes. 242 func consumeWithSpeed(reader io.Reader, chunkSize int, interval time.Duration, stop chan bool) (n int, err error) { 243 buffer := make([]byte, chunkSize) 244 for { 245 select { 246 case <-stop: 247 return 248 default: 249 var readBytes int 250 readBytes, err = reader.Read(buffer) 251 n += readBytes 252 if err != nil { 253 if err == io.EOF { 254 err = nil 255 } 256 return 257 } 258 time.Sleep(interval) 259 } 260 } 261 }