github.com/microsoft/docker@v1.5.0-rc2/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 return waitInspect(contID, "{{.State.Running}}", "true", 5) 139 } 140 141 func waitInspect(name, expr, expected string, timeout int) error { 142 after := time.After(time.Duration(timeout) * time.Second) 143 144 for { 145 cmd := exec.Command(dockerBinary, "inspect", "-f", expr, name) 146 out, _, err := runCommandWithOutput(cmd) 147 if err != nil { 148 return fmt.Errorf("error executing docker inspect: %v", err) 149 } 150 151 out = strings.TrimSpace(out) 152 if out == expected { 153 break 154 } 155 156 select { 157 case <-after: 158 return fmt.Errorf("condition \"%q == %q\" not true in time", out, expected) 159 default: 160 } 161 162 time.Sleep(100 * time.Millisecond) 163 } 164 return nil 165 } 166 167 func compareDirectoryEntries(e1 []os.FileInfo, e2 []os.FileInfo) error { 168 var ( 169 e1Entries = make(map[string]struct{}) 170 e2Entries = make(map[string]struct{}) 171 ) 172 for _, e := range e1 { 173 e1Entries[e.Name()] = struct{}{} 174 } 175 for _, e := range e2 { 176 e2Entries[e.Name()] = struct{}{} 177 } 178 if !reflect.DeepEqual(e1Entries, e2Entries) { 179 return fmt.Errorf("entries differ") 180 } 181 return nil 182 } 183 184 func ListTar(f io.Reader) ([]string, error) { 185 tr := tar.NewReader(f) 186 var entries []string 187 188 for { 189 th, err := tr.Next() 190 if err == io.EOF { 191 // end of tar archive 192 return entries, nil 193 } 194 if err != nil { 195 return entries, err 196 } 197 entries = append(entries, th.Name) 198 } 199 } 200 201 type FileServer struct { 202 *httptest.Server 203 } 204 205 func fileServer(files map[string]string) (*FileServer, error) { 206 var handler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) { 207 if filePath, found := files[r.URL.Path]; found { 208 http.ServeFile(w, r, filePath) 209 } else { 210 http.Error(w, http.StatusText(404), 404) 211 } 212 } 213 214 for _, file := range files { 215 if _, err := os.Stat(file); err != nil { 216 return nil, err 217 } 218 } 219 server := httptest.NewServer(handler) 220 return &FileServer{ 221 Server: server, 222 }, nil 223 } 224 225 func copyWithCP(source, target string) error { 226 copyCmd := exec.Command("cp", "-rp", source, target) 227 out, exitCode, err := runCommandWithOutput(copyCmd) 228 if err != nil || exitCode != 0 { 229 return fmt.Errorf("failed to copy: error: %q ,output: %q", err, out) 230 } 231 return nil 232 } 233 234 func makeRandomString(n int) string { 235 // make a really long string 236 letters := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 237 b := make([]byte, n) 238 for i := range b { 239 b[i] = letters[rand.Intn(len(letters))] 240 } 241 return string(b) 242 } 243 244 // Reads chunkSize bytes from reader after every interval. 245 // Returns total read bytes. 246 func consumeWithSpeed(reader io.Reader, chunkSize int, interval time.Duration, stop chan bool) (n int, err error) { 247 buffer := make([]byte, chunkSize) 248 for { 249 select { 250 case <-stop: 251 return 252 default: 253 var readBytes int 254 readBytes, err = reader.Read(buffer) 255 n += readBytes 256 if err != nil { 257 if err == io.EOF { 258 err = nil 259 } 260 return 261 } 262 time.Sleep(interval) 263 } 264 } 265 }