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