github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/integration-cli/docker_cli_inspect_test.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 "strconv" 8 "strings" 9 "time" 10 11 "github.com/docker/docker/api/types" 12 "github.com/docker/docker/api/types/container" 13 "github.com/docker/docker/integration-cli/checker" 14 "github.com/go-check/check" 15 "gotest.tools/assert" 16 "gotest.tools/icmd" 17 ) 18 19 func checkValidGraphDriver(c *check.C, name string) { 20 if name != "devicemapper" && name != "overlay" && name != "vfs" && name != "zfs" && name != "btrfs" && name != "aufs" { 21 c.Fatalf("%v is not a valid graph driver name", name) 22 } 23 } 24 25 func (s *DockerSuite) TestInspectImage(c *check.C) { 26 testRequires(c, DaemonIsLinux) 27 imageTest := "emptyfs" 28 // It is important that this ID remain stable. If a code change causes 29 // it to be different, this is equivalent to a cache bust when pulling 30 // a legacy-format manifest. If the check at the end of this function 31 // fails, fix the difference in the image serialization instead of 32 // updating this hash. 33 imageTestID := "sha256:11f64303f0f7ffdc71f001788132bca5346831939a956e3e975c93267d89a16d" 34 id := inspectField(c, imageTest, "Id") 35 36 c.Assert(id, checker.Equals, imageTestID) 37 } 38 39 func (s *DockerSuite) TestInspectInt64(c *check.C) { 40 dockerCmd(c, "run", "-d", "-m=300M", "--name", "inspectTest", "busybox", "true") 41 inspectOut := inspectField(c, "inspectTest", "HostConfig.Memory") 42 c.Assert(inspectOut, checker.Equals, "314572800") 43 } 44 45 func (s *DockerSuite) TestInspectDefault(c *check.C) { 46 //Both the container and image are named busybox. docker inspect will fetch the container JSON. 47 //If the container JSON is not available, it will go for the image JSON. 48 49 out, _ := dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "true") 50 containerID := strings.TrimSpace(out) 51 52 inspectOut := inspectField(c, "busybox", "Id") 53 c.Assert(strings.TrimSpace(inspectOut), checker.Equals, containerID) 54 } 55 56 func (s *DockerSuite) TestInspectStatus(c *check.C) { 57 out := runSleepingContainer(c, "-d") 58 out = strings.TrimSpace(out) 59 60 inspectOut := inspectField(c, out, "State.Status") 61 c.Assert(inspectOut, checker.Equals, "running") 62 63 // Windows does not support pause/unpause on Windows Server Containers. 64 // (RS1 does for Hyper-V Containers, but production CI is not setup for that) 65 if testEnv.OSType != "windows" { 66 dockerCmd(c, "pause", out) 67 inspectOut = inspectField(c, out, "State.Status") 68 c.Assert(inspectOut, checker.Equals, "paused") 69 70 dockerCmd(c, "unpause", out) 71 inspectOut = inspectField(c, out, "State.Status") 72 c.Assert(inspectOut, checker.Equals, "running") 73 } 74 75 dockerCmd(c, "stop", out) 76 inspectOut = inspectField(c, out, "State.Status") 77 c.Assert(inspectOut, checker.Equals, "exited") 78 79 } 80 81 func (s *DockerSuite) TestInspectTypeFlagContainer(c *check.C) { 82 //Both the container and image are named busybox. docker inspect will fetch container 83 //JSON State.Running field. If the field is true, it's a container. 84 runSleepingContainer(c, "--name=busybox", "-d") 85 86 formatStr := "--format={{.State.Running}}" 87 out, _ := dockerCmd(c, "inspect", "--type=container", formatStr, "busybox") 88 assert.Equal(c, out, "true\n") // not a container JSON 89 } 90 91 func (s *DockerSuite) TestInspectTypeFlagWithNoContainer(c *check.C) { 92 //Run this test on an image named busybox. docker inspect will try to fetch container 93 //JSON. Since there is no container named busybox and --type=container, docker inspect will 94 //not try to get the image JSON. It will throw an error. 95 96 dockerCmd(c, "run", "-d", "busybox", "true") 97 98 _, _, err := dockerCmdWithError("inspect", "--type=container", "busybox") 99 // docker inspect should fail, as there is no container named busybox 100 assert.ErrorContains(c, err, "") 101 } 102 103 func (s *DockerSuite) TestInspectTypeFlagWithImage(c *check.C) { 104 //Both the container and image are named busybox. docker inspect will fetch image 105 //JSON as --type=image. if there is no image with name busybox, docker inspect 106 //will throw an error. 107 108 dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "true") 109 110 out, _ := dockerCmd(c, "inspect", "--type=image", "busybox") 111 c.Assert(out, checker.Not(checker.Contains), "State") // not an image JSON 112 } 113 114 func (s *DockerSuite) TestInspectTypeFlagWithInvalidValue(c *check.C) { 115 //Both the container and image are named busybox. docker inspect will fail 116 //as --type=foobar is not a valid value for the flag. 117 118 dockerCmd(c, "run", "--name=busybox", "-d", "busybox", "true") 119 120 out, exitCode, err := dockerCmdWithError("inspect", "--type=foobar", "busybox") 121 c.Assert(err, checker.NotNil, check.Commentf("%s", exitCode)) 122 c.Assert(exitCode, checker.Equals, 1, check.Commentf("%s", err)) 123 c.Assert(out, checker.Contains, "not a valid value for --type") 124 } 125 126 func (s *DockerSuite) TestInspectImageFilterInt(c *check.C) { 127 testRequires(c, DaemonIsLinux) 128 imageTest := "emptyfs" 129 out := inspectField(c, imageTest, "Size") 130 131 size, err := strconv.Atoi(out) 132 c.Assert(err, checker.IsNil, check.Commentf("failed to inspect size of the image: %s, %v", out, err)) 133 134 //now see if the size turns out to be the same 135 formatStr := fmt.Sprintf("--format={{eq .Size %d}}", size) 136 out, _ = dockerCmd(c, "inspect", formatStr, imageTest) 137 result, err := strconv.ParseBool(strings.TrimSuffix(out, "\n")) 138 assert.NilError(c, err) 139 c.Assert(result, checker.Equals, true) 140 } 141 142 func (s *DockerSuite) TestInspectContainerFilterInt(c *check.C) { 143 result := icmd.RunCmd(icmd.Cmd{ 144 Command: []string{dockerBinary, "run", "-i", "-a", "stdin", "busybox", "cat"}, 145 Stdin: strings.NewReader("blahblah"), 146 }) 147 result.Assert(c, icmd.Success) 148 out := result.Stdout() 149 id := strings.TrimSpace(out) 150 151 out = inspectField(c, id, "State.ExitCode") 152 153 exitCode, err := strconv.Atoi(out) 154 c.Assert(err, checker.IsNil, check.Commentf("failed to inspect exitcode of the container: %s, %v", out, err)) 155 156 //now get the exit code to verify 157 formatStr := fmt.Sprintf("--format={{eq .State.ExitCode %d}}", exitCode) 158 out, _ = dockerCmd(c, "inspect", formatStr, id) 159 inspectResult, err := strconv.ParseBool(strings.TrimSuffix(out, "\n")) 160 assert.NilError(c, err) 161 c.Assert(inspectResult, checker.Equals, true) 162 } 163 164 func (s *DockerSuite) TestInspectImageGraphDriver(c *check.C) { 165 testRequires(c, DaemonIsLinux, Devicemapper) 166 imageTest := "emptyfs" 167 name := inspectField(c, imageTest, "GraphDriver.Name") 168 169 checkValidGraphDriver(c, name) 170 171 deviceID := inspectField(c, imageTest, "GraphDriver.Data.DeviceId") 172 173 _, err := strconv.Atoi(deviceID) 174 c.Assert(err, checker.IsNil, check.Commentf("failed to inspect DeviceId of the image: %s, %v", deviceID, err)) 175 176 deviceSize := inspectField(c, imageTest, "GraphDriver.Data.DeviceSize") 177 178 _, err = strconv.ParseUint(deviceSize, 10, 64) 179 c.Assert(err, checker.IsNil, check.Commentf("failed to inspect DeviceSize of the image: %s, %v", deviceSize, err)) 180 } 181 182 func (s *DockerSuite) TestInspectContainerGraphDriver(c *check.C) { 183 testRequires(c, DaemonIsLinux, Devicemapper) 184 185 out, _ := dockerCmd(c, "run", "-d", "busybox", "true") 186 out = strings.TrimSpace(out) 187 188 name := inspectField(c, out, "GraphDriver.Name") 189 190 checkValidGraphDriver(c, name) 191 192 imageDeviceID := inspectField(c, "busybox", "GraphDriver.Data.DeviceId") 193 194 deviceID := inspectField(c, out, "GraphDriver.Data.DeviceId") 195 196 c.Assert(imageDeviceID, checker.Not(checker.Equals), deviceID) 197 198 _, err := strconv.Atoi(deviceID) 199 c.Assert(err, checker.IsNil, check.Commentf("failed to inspect DeviceId of the image: %s, %v", deviceID, err)) 200 201 deviceSize := inspectField(c, out, "GraphDriver.Data.DeviceSize") 202 203 _, err = strconv.ParseUint(deviceSize, 10, 64) 204 c.Assert(err, checker.IsNil, check.Commentf("failed to inspect DeviceSize of the image: %s, %v", deviceSize, err)) 205 } 206 207 func (s *DockerSuite) TestInspectBindMountPoint(c *check.C) { 208 modifier := ",z" 209 prefix, slash := getPrefixAndSlashFromDaemonPlatform() 210 if testEnv.OSType == "windows" { 211 modifier = "" 212 // Linux creates the host directory if it doesn't exist. Windows does not. 213 os.Mkdir(`c:\data`, os.ModeDir) 214 } 215 216 dockerCmd(c, "run", "-d", "--name", "test", "-v", prefix+slash+"data:"+prefix+slash+"data:ro"+modifier, "busybox", "cat") 217 218 vol := inspectFieldJSON(c, "test", "Mounts") 219 220 var mp []types.MountPoint 221 err := json.Unmarshal([]byte(vol), &mp) 222 assert.NilError(c, err) 223 224 // check that there is only one mountpoint 225 c.Assert(mp, check.HasLen, 1) 226 227 m := mp[0] 228 229 c.Assert(m.Name, checker.Equals, "") 230 c.Assert(m.Driver, checker.Equals, "") 231 c.Assert(m.Source, checker.Equals, prefix+slash+"data") 232 c.Assert(m.Destination, checker.Equals, prefix+slash+"data") 233 if testEnv.OSType != "windows" { // Windows does not set mode 234 c.Assert(m.Mode, checker.Equals, "ro"+modifier) 235 } 236 c.Assert(m.RW, checker.Equals, false) 237 } 238 239 func (s *DockerSuite) TestInspectNamedMountPoint(c *check.C) { 240 prefix, slash := getPrefixAndSlashFromDaemonPlatform() 241 242 dockerCmd(c, "run", "-d", "--name", "test", "-v", "data:"+prefix+slash+"data", "busybox", "cat") 243 244 vol := inspectFieldJSON(c, "test", "Mounts") 245 246 var mp []types.MountPoint 247 err := json.Unmarshal([]byte(vol), &mp) 248 assert.NilError(c, err) 249 250 // check that there is only one mountpoint 251 c.Assert(mp, checker.HasLen, 1) 252 253 m := mp[0] 254 255 c.Assert(m.Name, checker.Equals, "data") 256 c.Assert(m.Driver, checker.Equals, "local") 257 c.Assert(m.Source, checker.Not(checker.Equals), "") 258 c.Assert(m.Destination, checker.Equals, prefix+slash+"data") 259 c.Assert(m.RW, checker.Equals, true) 260 } 261 262 // #14947 263 func (s *DockerSuite) TestInspectTimesAsRFC3339Nano(c *check.C) { 264 out, _ := dockerCmd(c, "run", "-d", "busybox", "true") 265 id := strings.TrimSpace(out) 266 startedAt := inspectField(c, id, "State.StartedAt") 267 finishedAt := inspectField(c, id, "State.FinishedAt") 268 created := inspectField(c, id, "Created") 269 270 _, err := time.Parse(time.RFC3339Nano, startedAt) 271 assert.NilError(c, err) 272 _, err = time.Parse(time.RFC3339Nano, finishedAt) 273 assert.NilError(c, err) 274 _, err = time.Parse(time.RFC3339Nano, created) 275 assert.NilError(c, err) 276 277 created = inspectField(c, "busybox", "Created") 278 279 _, err = time.Parse(time.RFC3339Nano, created) 280 assert.NilError(c, err) 281 } 282 283 // #15633 284 func (s *DockerSuite) TestInspectLogConfigNoType(c *check.C) { 285 dockerCmd(c, "create", "--name=test", "--log-opt", "max-file=42", "busybox") 286 var logConfig container.LogConfig 287 288 out := inspectFieldJSON(c, "test", "HostConfig.LogConfig") 289 290 err := json.NewDecoder(strings.NewReader(out)).Decode(&logConfig) 291 c.Assert(err, checker.IsNil, check.Commentf("%v", out)) 292 293 c.Assert(logConfig.Type, checker.Equals, "json-file") 294 c.Assert(logConfig.Config["max-file"], checker.Equals, "42", check.Commentf("%v", logConfig)) 295 } 296 297 func (s *DockerSuite) TestInspectNoSizeFlagContainer(c *check.C) { 298 299 //Both the container and image are named busybox. docker inspect will fetch container 300 //JSON SizeRw and SizeRootFs field. If there is no flag --size/-s, there are no size fields. 301 302 runSleepingContainer(c, "--name=busybox", "-d") 303 304 formatStr := "--format={{.SizeRw}},{{.SizeRootFs}}" 305 out, _ := dockerCmd(c, "inspect", "--type=container", formatStr, "busybox") 306 c.Assert(strings.TrimSpace(out), check.Equals, "<nil>,<nil>", check.Commentf("Expected not to display size info: %s", out)) 307 } 308 309 func (s *DockerSuite) TestInspectSizeFlagContainer(c *check.C) { 310 runSleepingContainer(c, "--name=busybox", "-d") 311 312 formatStr := "--format='{{.SizeRw}},{{.SizeRootFs}}'" 313 out, _ := dockerCmd(c, "inspect", "-s", "--type=container", formatStr, "busybox") 314 sz := strings.Split(out, ",") 315 316 c.Assert(strings.TrimSpace(sz[0]), check.Not(check.Equals), "<nil>") 317 c.Assert(strings.TrimSpace(sz[1]), check.Not(check.Equals), "<nil>") 318 } 319 320 func (s *DockerSuite) TestInspectTemplateError(c *check.C) { 321 // Template parsing error for both the container and image. 322 323 runSleepingContainer(c, "--name=container1", "-d") 324 325 out, _, err := dockerCmdWithError("inspect", "--type=container", "--format='Format container: {{.ThisDoesNotExist}}'", "container1") 326 c.Assert(err, check.Not(check.IsNil)) 327 c.Assert(out, checker.Contains, "Template parsing error") 328 329 out, _, err = dockerCmdWithError("inspect", "--type=image", "--format='Format container: {{.ThisDoesNotExist}}'", "busybox") 330 c.Assert(err, check.Not(check.IsNil)) 331 c.Assert(out, checker.Contains, "Template parsing error") 332 } 333 334 func (s *DockerSuite) TestInspectJSONFields(c *check.C) { 335 runSleepingContainer(c, "--name=busybox", "-d") 336 out, _, err := dockerCmdWithError("inspect", "--type=container", "--format={{.HostConfig.Dns}}", "busybox") 337 338 assert.NilError(c, err) 339 assert.Equal(c, out, "[]\n") 340 } 341 342 func (s *DockerSuite) TestInspectByPrefix(c *check.C) { 343 id := inspectField(c, "busybox", "Id") 344 assert.Assert(c, strings.HasPrefix(id, "sha256:")) 345 346 id2 := inspectField(c, id[:12], "Id") 347 c.Assert(id, checker.Equals, id2) 348 349 id3 := inspectField(c, strings.TrimPrefix(id, "sha256:")[:12], "Id") 350 c.Assert(id, checker.Equals, id3) 351 } 352 353 func (s *DockerSuite) TestInspectStopWhenNotFound(c *check.C) { 354 runSleepingContainer(c, "--name=busybox1", "-d") 355 runSleepingContainer(c, "--name=busybox2", "-d") 356 result := dockerCmdWithResult("inspect", "--type=container", "--format='{{.Name}}'", "busybox1", "busybox2", "missing") 357 358 c.Assert(result.Error, checker.Not(check.IsNil)) 359 c.Assert(result.Stdout(), checker.Contains, "busybox1") 360 c.Assert(result.Stdout(), checker.Contains, "busybox2") 361 c.Assert(result.Stderr(), checker.Contains, "Error: No such container: missing") 362 363 // test inspect would not fast fail 364 result = dockerCmdWithResult("inspect", "--type=container", "--format='{{.Name}}'", "missing", "busybox1", "busybox2") 365 366 c.Assert(result.Error, checker.Not(check.IsNil)) 367 c.Assert(result.Stdout(), checker.Contains, "busybox1") 368 c.Assert(result.Stdout(), checker.Contains, "busybox2") 369 c.Assert(result.Stderr(), checker.Contains, "Error: No such container: missing") 370 } 371 372 func (s *DockerSuite) TestInspectHistory(c *check.C) { 373 dockerCmd(c, "run", "--name=testcont", "busybox", "echo", "hello") 374 dockerCmd(c, "commit", "-m", "test comment", "testcont", "testimg") 375 out, _, err := dockerCmdWithError("inspect", "--format='{{.Comment}}'", "testimg") 376 assert.NilError(c, err) 377 c.Assert(out, checker.Contains, "test comment") 378 } 379 380 func (s *DockerSuite) TestInspectContainerNetworkDefault(c *check.C) { 381 testRequires(c, DaemonIsLinux) 382 383 contName := "test1" 384 dockerCmd(c, "run", "--name", contName, "-d", "busybox", "top") 385 netOut, _ := dockerCmd(c, "network", "inspect", "--format={{.ID}}", "bridge") 386 out := inspectField(c, contName, "NetworkSettings.Networks") 387 c.Assert(out, checker.Contains, "bridge") 388 out = inspectField(c, contName, "NetworkSettings.Networks.bridge.NetworkID") 389 assert.Equal(c, strings.TrimSpace(out), strings.TrimSpace(netOut)) 390 } 391 392 func (s *DockerSuite) TestInspectContainerNetworkCustom(c *check.C) { 393 testRequires(c, DaemonIsLinux) 394 395 netOut, _ := dockerCmd(c, "network", "create", "net1") 396 dockerCmd(c, "run", "--name=container1", "--net=net1", "-d", "busybox", "top") 397 out := inspectField(c, "container1", "NetworkSettings.Networks") 398 c.Assert(out, checker.Contains, "net1") 399 out = inspectField(c, "container1", "NetworkSettings.Networks.net1.NetworkID") 400 assert.Equal(c, strings.TrimSpace(out), strings.TrimSpace(netOut)) 401 } 402 403 func (s *DockerSuite) TestInspectRootFS(c *check.C) { 404 out, _, err := dockerCmdWithError("inspect", "busybox") 405 assert.NilError(c, err) 406 407 var imageJSON []types.ImageInspect 408 err = json.Unmarshal([]byte(out), &imageJSON) 409 assert.NilError(c, err) 410 assert.Assert(c, len(imageJSON[0].RootFS.Layers) >= 1) 411 } 412 413 func (s *DockerSuite) TestInspectAmpersand(c *check.C) { 414 testRequires(c, DaemonIsLinux) 415 416 name := "test" 417 out, _ := dockerCmd(c, "run", "--name", name, "--env", `TEST_ENV="soanni&rtr"`, "busybox", "env") 418 c.Assert(out, checker.Contains, `soanni&rtr`) 419 out, _ = dockerCmd(c, "inspect", name) 420 c.Assert(out, checker.Contains, `soanni&rtr`) 421 } 422 423 func (s *DockerSuite) TestInspectPlugin(c *check.C) { 424 testRequires(c, DaemonIsLinux, IsAmd64, Network) 425 _, _, err := dockerCmdWithError("plugin", "install", "--grant-all-permissions", pNameWithTag) 426 assert.NilError(c, err) 427 428 out, _, err := dockerCmdWithError("inspect", "--type", "plugin", "--format", "{{.Name}}", pNameWithTag) 429 assert.NilError(c, err) 430 assert.Equal(c, strings.TrimSpace(out), pNameWithTag) 431 432 out, _, err = dockerCmdWithError("inspect", "--format", "{{.Name}}", pNameWithTag) 433 assert.NilError(c, err) 434 assert.Equal(c, strings.TrimSpace(out), pNameWithTag) 435 436 // Even without tag the inspect still work 437 out, _, err = dockerCmdWithError("inspect", "--type", "plugin", "--format", "{{.Name}}", pNameWithTag) 438 assert.NilError(c, err) 439 assert.Equal(c, strings.TrimSpace(out), pNameWithTag) 440 441 out, _, err = dockerCmdWithError("inspect", "--format", "{{.Name}}", pNameWithTag) 442 assert.NilError(c, err) 443 assert.Equal(c, strings.TrimSpace(out), pNameWithTag) 444 445 _, _, err = dockerCmdWithError("plugin", "disable", pNameWithTag) 446 assert.NilError(c, err) 447 448 out, _, err = dockerCmdWithError("plugin", "remove", pNameWithTag) 449 assert.NilError(c, err) 450 c.Assert(out, checker.Contains, pNameWithTag) 451 } 452 453 // Test case for 29185 454 func (s *DockerSuite) TestInspectUnknownObject(c *check.C) { 455 // This test should work on both Windows and Linux 456 out, _, err := dockerCmdWithError("inspect", "foobar") 457 assert.ErrorContains(c, err, "") 458 c.Assert(out, checker.Contains, "Error: No such object: foobar") 459 assert.ErrorContains(c, err, "Error: No such object: foobar") 460 }