github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/integration-cli/docker_utils_test.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "io" 8 "io/ioutil" 9 "os" 10 "path" 11 "path/filepath" 12 "strconv" 13 "strings" 14 "time" 15 16 "github.com/docker/docker/api/types" 17 "github.com/docker/docker/client" 18 "github.com/docker/docker/integration-cli/checker" 19 "github.com/docker/docker/integration-cli/cli" 20 "github.com/docker/docker/integration-cli/daemon" 21 "github.com/docker/docker/integration-cli/request" 22 "github.com/go-check/check" 23 "github.com/gotestyourself/gotestyourself/icmd" 24 "golang.org/x/net/context" 25 ) 26 27 // Deprecated 28 func daemonHost() string { 29 return request.DaemonHost() 30 } 31 32 func deleteImages(images ...string) error { 33 args := []string{dockerBinary, "rmi", "-f"} 34 return icmd.RunCmd(icmd.Cmd{Command: append(args, images...)}).Error 35 } 36 37 // Deprecated: use cli.Docker or cli.DockerCmd 38 func dockerCmdWithError(args ...string) (string, int, error) { 39 result := cli.Docker(cli.Args(args...)) 40 if result.Error != nil { 41 return result.Combined(), result.ExitCode, result.Compare(icmd.Success) 42 } 43 return result.Combined(), result.ExitCode, result.Error 44 } 45 46 // Deprecated: use cli.Docker or cli.DockerCmd 47 func dockerCmd(c *check.C, args ...string) (string, int) { 48 result := cli.DockerCmd(c, args...) 49 return result.Combined(), result.ExitCode 50 } 51 52 // Deprecated: use cli.Docker or cli.DockerCmd 53 func dockerCmdWithResult(args ...string) *icmd.Result { 54 return cli.Docker(cli.Args(args...)) 55 } 56 57 func findContainerIP(c *check.C, id string, network string) string { 58 out, _ := dockerCmd(c, "inspect", fmt.Sprintf("--format='{{ .NetworkSettings.Networks.%s.IPAddress }}'", network), id) 59 return strings.Trim(out, " \r\n'") 60 } 61 62 func getContainerCount(c *check.C) int { 63 const containers = "Containers:" 64 65 result := icmd.RunCommand(dockerBinary, "info") 66 result.Assert(c, icmd.Success) 67 68 lines := strings.Split(result.Combined(), "\n") 69 for _, line := range lines { 70 if strings.Contains(line, containers) { 71 output := strings.TrimSpace(line) 72 output = strings.TrimLeft(output, containers) 73 output = strings.Trim(output, " ") 74 containerCount, err := strconv.Atoi(output) 75 c.Assert(err, checker.IsNil) 76 return containerCount 77 } 78 } 79 return 0 80 } 81 82 func inspectFieldAndUnmarshall(c *check.C, name, field string, output interface{}) { 83 str := inspectFieldJSON(c, name, field) 84 err := json.Unmarshal([]byte(str), output) 85 if c != nil { 86 c.Assert(err, check.IsNil, check.Commentf("failed to unmarshal: %v", err)) 87 } 88 } 89 90 // Deprecated: use cli.Inspect 91 func inspectFilter(name, filter string) (string, error) { 92 format := fmt.Sprintf("{{%s}}", filter) 93 result := icmd.RunCommand(dockerBinary, "inspect", "-f", format, name) 94 if result.Error != nil || result.ExitCode != 0 { 95 return "", fmt.Errorf("failed to inspect %s: %s", name, result.Combined()) 96 } 97 return strings.TrimSpace(result.Combined()), nil 98 } 99 100 // Deprecated: use cli.Inspect 101 func inspectFieldWithError(name, field string) (string, error) { 102 return inspectFilter(name, fmt.Sprintf(".%s", field)) 103 } 104 105 // Deprecated: use cli.Inspect 106 func inspectField(c *check.C, name, field string) string { 107 out, err := inspectFilter(name, fmt.Sprintf(".%s", field)) 108 if c != nil { 109 c.Assert(err, check.IsNil) 110 } 111 return out 112 } 113 114 // Deprecated: use cli.Inspect 115 func inspectFieldJSON(c *check.C, name, field string) string { 116 out, err := inspectFilter(name, fmt.Sprintf("json .%s", field)) 117 if c != nil { 118 c.Assert(err, check.IsNil) 119 } 120 return out 121 } 122 123 // Deprecated: use cli.Inspect 124 func inspectFieldMap(c *check.C, name, path, field string) string { 125 out, err := inspectFilter(name, fmt.Sprintf("index .%s %q", path, field)) 126 if c != nil { 127 c.Assert(err, check.IsNil) 128 } 129 return out 130 } 131 132 // Deprecated: use cli.Inspect 133 func inspectMountSourceField(name, destination string) (string, error) { 134 m, err := inspectMountPoint(name, destination) 135 if err != nil { 136 return "", err 137 } 138 return m.Source, nil 139 } 140 141 // Deprecated: use cli.Inspect 142 func inspectMountPoint(name, destination string) (types.MountPoint, error) { 143 out, err := inspectFilter(name, "json .Mounts") 144 if err != nil { 145 return types.MountPoint{}, err 146 } 147 148 return inspectMountPointJSON(out, destination) 149 } 150 151 var errMountNotFound = errors.New("mount point not found") 152 153 // Deprecated: use cli.Inspect 154 func inspectMountPointJSON(j, destination string) (types.MountPoint, error) { 155 var mp []types.MountPoint 156 if err := json.Unmarshal([]byte(j), &mp); err != nil { 157 return types.MountPoint{}, err 158 } 159 160 var m *types.MountPoint 161 for _, c := range mp { 162 if c.Destination == destination { 163 m = &c 164 break 165 } 166 } 167 168 if m == nil { 169 return types.MountPoint{}, errMountNotFound 170 } 171 172 return *m, nil 173 } 174 175 // Deprecated: use cli.Inspect 176 func inspectImage(c *check.C, name, filter string) string { 177 args := []string{"inspect", "--type", "image"} 178 if filter != "" { 179 format := fmt.Sprintf("{{%s}}", filter) 180 args = append(args, "-f", format) 181 } 182 args = append(args, name) 183 result := icmd.RunCommand(dockerBinary, args...) 184 result.Assert(c, icmd.Success) 185 return strings.TrimSpace(result.Combined()) 186 } 187 188 func getIDByName(c *check.C, name string) string { 189 id, err := inspectFieldWithError(name, "Id") 190 c.Assert(err, checker.IsNil) 191 return id 192 } 193 194 // Deprecated: use cli.Build 195 func buildImageSuccessfully(c *check.C, name string, cmdOperators ...cli.CmdOperator) { 196 buildImage(name, cmdOperators...).Assert(c, icmd.Success) 197 } 198 199 // Deprecated: use cli.Build 200 func buildImage(name string, cmdOperators ...cli.CmdOperator) *icmd.Result { 201 return cli.Docker(cli.Build(name), cmdOperators...) 202 } 203 204 // Write `content` to the file at path `dst`, creating it if necessary, 205 // as well as any missing directories. 206 // The file is truncated if it already exists. 207 // Fail the test when error occurs. 208 func writeFile(dst, content string, c *check.C) { 209 // Create subdirectories if necessary 210 c.Assert(os.MkdirAll(path.Dir(dst), 0700), check.IsNil) 211 f, err := os.OpenFile(dst, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0700) 212 c.Assert(err, check.IsNil) 213 defer f.Close() 214 // Write content (truncate if it exists) 215 _, err = io.Copy(f, strings.NewReader(content)) 216 c.Assert(err, check.IsNil) 217 } 218 219 // Return the contents of file at path `src`. 220 // Fail the test when error occurs. 221 func readFile(src string, c *check.C) (content string) { 222 data, err := ioutil.ReadFile(src) 223 c.Assert(err, check.IsNil) 224 225 return string(data) 226 } 227 228 func containerStorageFile(containerID, basename string) string { 229 return filepath.Join(testEnv.PlatformDefaults.ContainerStoragePath, containerID, basename) 230 } 231 232 // docker commands that use this function must be run with the '-d' switch. 233 func runCommandAndReadContainerFile(c *check.C, filename string, command string, args ...string) []byte { 234 result := icmd.RunCommand(command, args...) 235 result.Assert(c, icmd.Success) 236 contID := strings.TrimSpace(result.Combined()) 237 if err := waitRun(contID); err != nil { 238 c.Fatalf("%v: %q", contID, err) 239 } 240 return readContainerFile(c, contID, filename) 241 } 242 243 func readContainerFile(c *check.C, containerID, filename string) []byte { 244 f, err := os.Open(containerStorageFile(containerID, filename)) 245 c.Assert(err, checker.IsNil) 246 defer f.Close() 247 248 content, err := ioutil.ReadAll(f) 249 c.Assert(err, checker.IsNil) 250 return content 251 } 252 253 func readContainerFileWithExec(c *check.C, containerID, filename string) []byte { 254 result := icmd.RunCommand(dockerBinary, "exec", containerID, "cat", filename) 255 result.Assert(c, icmd.Success) 256 return []byte(result.Combined()) 257 } 258 259 // daemonTime provides the current time on the daemon host 260 func daemonTime(c *check.C) time.Time { 261 if testEnv.IsLocalDaemon() { 262 return time.Now() 263 } 264 cli, err := client.NewEnvClient() 265 c.Assert(err, check.IsNil) 266 defer cli.Close() 267 268 info, err := cli.Info(context.Background()) 269 c.Assert(err, check.IsNil) 270 271 dt, err := time.Parse(time.RFC3339Nano, info.SystemTime) 272 c.Assert(err, check.IsNil, check.Commentf("invalid time format in GET /info response")) 273 return dt 274 } 275 276 // daemonUnixTime returns the current time on the daemon host with nanoseconds precision. 277 // It return the time formatted how the client sends timestamps to the server. 278 func daemonUnixTime(c *check.C) string { 279 return parseEventTime(daemonTime(c)) 280 } 281 282 func parseEventTime(t time.Time) string { 283 return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())) 284 } 285 286 // appendBaseEnv appends the minimum set of environment variables to exec the 287 // docker cli binary for testing with correct configuration to the given env 288 // list. 289 func appendBaseEnv(isTLS bool, env ...string) []string { 290 preserveList := []string{ 291 // preserve remote test host 292 "DOCKER_HOST", 293 294 // windows: requires preserving SystemRoot, otherwise dial tcp fails 295 // with "GetAddrInfoW: A non-recoverable error occurred during a database lookup." 296 "SystemRoot", 297 298 // testing help text requires the $PATH to dockerd is set 299 "PATH", 300 } 301 if isTLS { 302 preserveList = append(preserveList, "DOCKER_TLS_VERIFY", "DOCKER_CERT_PATH") 303 } 304 305 for _, key := range preserveList { 306 if val := os.Getenv(key); val != "" { 307 env = append(env, fmt.Sprintf("%s=%s", key, val)) 308 } 309 } 310 return env 311 } 312 313 func createTmpFile(c *check.C, content string) string { 314 f, err := ioutil.TempFile("", "testfile") 315 c.Assert(err, check.IsNil) 316 317 filename := f.Name() 318 319 err = ioutil.WriteFile(filename, []byte(content), 0644) 320 c.Assert(err, check.IsNil) 321 322 return filename 323 } 324 325 // waitRun will wait for the specified container to be running, maximum 5 seconds. 326 // Deprecated: use cli.WaitFor 327 func waitRun(contID string) error { 328 return waitInspect(contID, "{{.State.Running}}", "true", 5*time.Second) 329 } 330 331 // waitInspect will wait for the specified container to have the specified string 332 // in the inspect output. It will wait until the specified timeout (in seconds) 333 // is reached. 334 // Deprecated: use cli.WaitFor 335 func waitInspect(name, expr, expected string, timeout time.Duration) error { 336 return waitInspectWithArgs(name, expr, expected, timeout) 337 } 338 339 // Deprecated: use cli.WaitFor 340 func waitInspectWithArgs(name, expr, expected string, timeout time.Duration, arg ...string) error { 341 return daemon.WaitInspectWithArgs(dockerBinary, name, expr, expected, timeout, arg...) 342 } 343 344 func getInspectBody(c *check.C, version, id string) []byte { 345 cli, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion(version)) 346 c.Assert(err, check.IsNil) 347 defer cli.Close() 348 _, body, err := cli.ContainerInspectWithRaw(context.Background(), id, false) 349 c.Assert(err, check.IsNil) 350 return body 351 } 352 353 // Run a long running idle task in a background container using the 354 // system-specific default image and command. 355 func runSleepingContainer(c *check.C, extraArgs ...string) string { 356 return runSleepingContainerInImage(c, defaultSleepImage, extraArgs...) 357 } 358 359 // Run a long running idle task in a background container using the specified 360 // image and the system-specific command. 361 func runSleepingContainerInImage(c *check.C, image string, extraArgs ...string) string { 362 args := []string{"run", "-d"} 363 args = append(args, extraArgs...) 364 args = append(args, image) 365 args = append(args, sleepCommandForDaemonPlatform()...) 366 return strings.TrimSpace(cli.DockerCmd(c, args...).Combined()) 367 } 368 369 // minimalBaseImage returns the name of the minimal base image for the current 370 // daemon platform. 371 func minimalBaseImage() string { 372 return testEnv.PlatformDefaults.BaseImage 373 } 374 375 func getGoroutineNumber() (int, error) { 376 cli, err := client.NewEnvClient() 377 if err != nil { 378 return 0, err 379 } 380 defer cli.Close() 381 382 info, err := cli.Info(context.Background()) 383 if err != nil { 384 return 0, err 385 } 386 return info.NGoroutines, nil 387 } 388 389 func waitForGoroutines(expected int) error { 390 t := time.After(30 * time.Second) 391 for { 392 select { 393 case <-t: 394 n, err := getGoroutineNumber() 395 if err != nil { 396 return err 397 } 398 if n > expected { 399 return fmt.Errorf("leaked goroutines: expected less than or equal to %d, got: %d", expected, n) 400 } 401 default: 402 n, err := getGoroutineNumber() 403 if err != nil { 404 return err 405 } 406 if n <= expected { 407 return nil 408 } 409 time.Sleep(200 * time.Millisecond) 410 } 411 } 412 } 413 414 // getErrorMessage returns the error message from an error API response 415 func getErrorMessage(c *check.C, body []byte) string { 416 var resp types.ErrorResponse 417 c.Assert(json.Unmarshal(body, &resp), check.IsNil) 418 return strings.TrimSpace(resp.Message) 419 } 420 421 func waitAndAssert(c *check.C, timeout time.Duration, f checkF, checker check.Checker, args ...interface{}) { 422 after := time.After(timeout) 423 for { 424 v, comment := f(c) 425 assert, _ := checker.Check(append([]interface{}{v}, args...), checker.Info().Params) 426 select { 427 case <-after: 428 assert = true 429 default: 430 } 431 if assert { 432 if comment != nil { 433 args = append(args, comment) 434 } 435 c.Assert(v, checker, args...) 436 return 437 } 438 time.Sleep(100 * time.Millisecond) 439 } 440 } 441 442 type checkF func(*check.C) (interface{}, check.CommentInterface) 443 type reducer func(...interface{}) interface{} 444 445 func reducedCheck(r reducer, funcs ...checkF) checkF { 446 return func(c *check.C) (interface{}, check.CommentInterface) { 447 var values []interface{} 448 var comments []string 449 for _, f := range funcs { 450 v, comment := f(c) 451 values = append(values, v) 452 if comment != nil { 453 comments = append(comments, comment.CheckCommentString()) 454 } 455 } 456 return r(values...), check.Commentf("%v", strings.Join(comments, ", ")) 457 } 458 } 459 460 func sumAsIntegers(vals ...interface{}) interface{} { 461 var s int 462 for _, v := range vals { 463 s += v.(int) 464 } 465 return s 466 }