github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/integration-cli/docker_cli_images_test.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "reflect" 9 "sort" 10 "strings" 11 "time" 12 13 "github.com/docker/docker/integration-cli/checker" 14 "github.com/docker/docker/integration-cli/cli/build" 15 "github.com/docker/docker/pkg/stringid" 16 "github.com/go-check/check" 17 "gotest.tools/assert" 18 is "gotest.tools/assert/cmp" 19 "gotest.tools/icmd" 20 ) 21 22 func (s *DockerSuite) TestImagesEnsureImageIsListed(c *check.C) { 23 imagesOut, _ := dockerCmd(c, "images") 24 c.Assert(imagesOut, checker.Contains, "busybox") 25 } 26 27 func (s *DockerSuite) TestImagesEnsureImageWithTagIsListed(c *check.C) { 28 name := "imagewithtag" 29 dockerCmd(c, "tag", "busybox", name+":v1") 30 dockerCmd(c, "tag", "busybox", name+":v1v1") 31 dockerCmd(c, "tag", "busybox", name+":v2") 32 33 imagesOut, _ := dockerCmd(c, "images", name+":v1") 34 c.Assert(imagesOut, checker.Contains, name) 35 c.Assert(imagesOut, checker.Contains, "v1") 36 c.Assert(imagesOut, checker.Not(checker.Contains), "v2") 37 c.Assert(imagesOut, checker.Not(checker.Contains), "v1v1") 38 39 imagesOut, _ = dockerCmd(c, "images", name) 40 c.Assert(imagesOut, checker.Contains, name) 41 c.Assert(imagesOut, checker.Contains, "v1") 42 c.Assert(imagesOut, checker.Contains, "v1v1") 43 c.Assert(imagesOut, checker.Contains, "v2") 44 } 45 46 func (s *DockerSuite) TestImagesEnsureImageWithBadTagIsNotListed(c *check.C) { 47 imagesOut, _ := dockerCmd(c, "images", "busybox:nonexistent") 48 c.Assert(imagesOut, checker.Not(checker.Contains), "busybox") 49 } 50 51 func (s *DockerSuite) TestImagesOrderedByCreationDate(c *check.C) { 52 buildImageSuccessfully(c, "order:test_a", build.WithDockerfile(`FROM busybox 53 MAINTAINER dockerio1`)) 54 id1 := getIDByName(c, "order:test_a") 55 time.Sleep(1 * time.Second) 56 buildImageSuccessfully(c, "order:test_c", build.WithDockerfile(`FROM busybox 57 MAINTAINER dockerio2`)) 58 id2 := getIDByName(c, "order:test_c") 59 time.Sleep(1 * time.Second) 60 buildImageSuccessfully(c, "order:test_b", build.WithDockerfile(`FROM busybox 61 MAINTAINER dockerio3`)) 62 id3 := getIDByName(c, "order:test_b") 63 64 out, _ := dockerCmd(c, "images", "-q", "--no-trunc") 65 imgs := strings.Split(out, "\n") 66 c.Assert(imgs[0], checker.Equals, id3, check.Commentf("First image must be %s, got %s", id3, imgs[0])) 67 c.Assert(imgs[1], checker.Equals, id2, check.Commentf("First image must be %s, got %s", id2, imgs[1])) 68 c.Assert(imgs[2], checker.Equals, id1, check.Commentf("First image must be %s, got %s", id1, imgs[2])) 69 } 70 71 func (s *DockerSuite) TestImagesErrorWithInvalidFilterNameTest(c *check.C) { 72 out, _, err := dockerCmdWithError("images", "-f", "FOO=123") 73 assert.ErrorContains(c, err, "") 74 c.Assert(out, checker.Contains, "Invalid filter") 75 } 76 77 func (s *DockerSuite) TestImagesFilterLabelMatch(c *check.C) { 78 imageName1 := "images_filter_test1" 79 imageName2 := "images_filter_test2" 80 imageName3 := "images_filter_test3" 81 buildImageSuccessfully(c, imageName1, build.WithDockerfile(`FROM busybox 82 LABEL match me`)) 83 image1ID := getIDByName(c, imageName1) 84 85 buildImageSuccessfully(c, imageName2, build.WithDockerfile(`FROM busybox 86 LABEL match="me too"`)) 87 image2ID := getIDByName(c, imageName2) 88 89 buildImageSuccessfully(c, imageName3, build.WithDockerfile(`FROM busybox 90 LABEL nomatch me`)) 91 image3ID := getIDByName(c, imageName3) 92 93 out, _ := dockerCmd(c, "images", "--no-trunc", "-q", "-f", "label=match") 94 out = strings.TrimSpace(out) 95 c.Assert(out, check.Matches, fmt.Sprintf("[\\s\\w:]*%s[\\s\\w:]*", image1ID)) 96 c.Assert(out, check.Matches, fmt.Sprintf("[\\s\\w:]*%s[\\s\\w:]*", image2ID)) 97 c.Assert(out, check.Not(check.Matches), fmt.Sprintf("[\\s\\w:]*%s[\\s\\w:]*", image3ID)) 98 99 out, _ = dockerCmd(c, "images", "--no-trunc", "-q", "-f", "label=match=me too") 100 out = strings.TrimSpace(out) 101 assert.Equal(c, out, image2ID) 102 } 103 104 // Regression : #15659 105 func (s *DockerSuite) TestCommitWithFilterLabel(c *check.C) { 106 // Create a container 107 dockerCmd(c, "run", "--name", "bar", "busybox", "/bin/sh") 108 // Commit with labels "using changes" 109 out, _ := dockerCmd(c, "commit", "-c", "LABEL foo.version=1.0.0-1", "-c", "LABEL foo.name=bar", "-c", "LABEL foo.author=starlord", "bar", "bar:1.0.0-1") 110 imageID := strings.TrimSpace(out) 111 112 out, _ = dockerCmd(c, "images", "--no-trunc", "-q", "-f", "label=foo.version=1.0.0-1") 113 out = strings.TrimSpace(out) 114 assert.Equal(c, out, imageID) 115 } 116 117 func (s *DockerSuite) TestImagesFilterSinceAndBefore(c *check.C) { 118 buildImageSuccessfully(c, "image:1", build.WithDockerfile(`FROM `+minimalBaseImage()+` 119 LABEL number=1`)) 120 imageID1 := getIDByName(c, "image:1") 121 buildImageSuccessfully(c, "image:2", build.WithDockerfile(`FROM `+minimalBaseImage()+` 122 LABEL number=2`)) 123 imageID2 := getIDByName(c, "image:2") 124 buildImageSuccessfully(c, "image:3", build.WithDockerfile(`FROM `+minimalBaseImage()+` 125 LABEL number=3`)) 126 imageID3 := getIDByName(c, "image:3") 127 128 expected := []string{imageID3, imageID2} 129 130 out, _ := dockerCmd(c, "images", "-f", "since=image:1", "image") 131 c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Image list is not in the correct order: %v\n%s", expected, out)) 132 133 out, _ = dockerCmd(c, "images", "-f", "since="+imageID1, "image") 134 c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Image list is not in the correct order: %v\n%s", expected, out)) 135 136 expected = []string{imageID3} 137 138 out, _ = dockerCmd(c, "images", "-f", "since=image:2", "image") 139 c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Image list is not in the correct order: %v\n%s", expected, out)) 140 141 out, _ = dockerCmd(c, "images", "-f", "since="+imageID2, "image") 142 c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Image list is not in the correct order: %v\n%s", expected, out)) 143 144 expected = []string{imageID2, imageID1} 145 146 out, _ = dockerCmd(c, "images", "-f", "before=image:3", "image") 147 c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Image list is not in the correct order: %v\n%s", expected, out)) 148 149 out, _ = dockerCmd(c, "images", "-f", "before="+imageID3, "image") 150 c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Image list is not in the correct order: %v\n%s", expected, out)) 151 152 expected = []string{imageID1} 153 154 out, _ = dockerCmd(c, "images", "-f", "before=image:2", "image") 155 c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Image list is not in the correct order: %v\n%s", expected, out)) 156 157 out, _ = dockerCmd(c, "images", "-f", "before="+imageID2, "image") 158 c.Assert(assertImageList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Image list is not in the correct order: %v\n%s", expected, out)) 159 } 160 161 func assertImageList(out string, expected []string) bool { 162 lines := strings.Split(strings.Trim(out, "\n "), "\n") 163 164 if len(lines)-1 != len(expected) { 165 return false 166 } 167 168 imageIDIndex := strings.Index(lines[0], "IMAGE ID") 169 for i := 0; i < len(expected); i++ { 170 imageID := lines[i+1][imageIDIndex : imageIDIndex+12] 171 found := false 172 for _, e := range expected { 173 if imageID == e[7:19] { 174 found = true 175 break 176 } 177 } 178 if !found { 179 return false 180 } 181 } 182 183 return true 184 } 185 186 // FIXME(vdemeester) should be a unit test on `docker image ls` 187 func (s *DockerSuite) TestImagesFilterSpaceTrimCase(c *check.C) { 188 imageName := "images_filter_test" 189 // Build a image and fail to build so that we have dangling images ? 190 buildImage(imageName, build.WithDockerfile(`FROM busybox 191 RUN touch /test/foo 192 RUN touch /test/bar 193 RUN touch /test/baz`)).Assert(c, icmd.Expected{ 194 ExitCode: 1, 195 }) 196 197 filters := []string{ 198 "dangling=true", 199 "Dangling=true", 200 " dangling=true", 201 "dangling=true ", 202 "dangling = true", 203 } 204 205 imageListings := make([][]string, 5, 5) 206 for idx, filter := range filters { 207 out, _ := dockerCmd(c, "images", "-q", "-f", filter) 208 listing := strings.Split(out, "\n") 209 sort.Strings(listing) 210 imageListings[idx] = listing 211 } 212 213 for idx, listing := range imageListings { 214 if idx < 4 && !reflect.DeepEqual(listing, imageListings[idx+1]) { 215 for idx, errListing := range imageListings { 216 fmt.Printf("out %d\n", idx) 217 for _, image := range errListing { 218 fmt.Print(image) 219 } 220 fmt.Print("") 221 } 222 c.Fatalf("All output must be the same") 223 } 224 } 225 } 226 227 func (s *DockerSuite) TestImagesEnsureDanglingImageOnlyListedOnce(c *check.C) { 228 testRequires(c, DaemonIsLinux) 229 // create container 1 230 out, _ := dockerCmd(c, "run", "-d", "busybox", "true") 231 containerID1 := strings.TrimSpace(out) 232 233 // tag as foobox 234 out, _ = dockerCmd(c, "commit", containerID1, "foobox") 235 imageID := stringid.TruncateID(strings.TrimSpace(out)) 236 237 // overwrite the tag, making the previous image dangling 238 dockerCmd(c, "tag", "busybox", "foobox") 239 240 out, _ = dockerCmd(c, "images", "-q", "-f", "dangling=true") 241 // Expect one dangling image 242 c.Assert(strings.Count(out, imageID), checker.Equals, 1) 243 244 out, _ = dockerCmd(c, "images", "-q", "-f", "dangling=false") 245 //dangling=false would not include dangling images 246 c.Assert(out, checker.Not(checker.Contains), imageID) 247 248 out, _ = dockerCmd(c, "images") 249 //docker images still include dangling images 250 c.Assert(out, checker.Contains, imageID) 251 252 } 253 254 // FIXME(vdemeester) should be a unit test for `docker image ls` 255 func (s *DockerSuite) TestImagesWithIncorrectFilter(c *check.C) { 256 out, _, err := dockerCmdWithError("images", "-f", "dangling=invalid") 257 assert.ErrorContains(c, err, "") 258 c.Assert(out, checker.Contains, "Invalid filter") 259 } 260 261 func (s *DockerSuite) TestImagesEnsureOnlyHeadsImagesShown(c *check.C) { 262 dockerfile := ` 263 FROM busybox 264 MAINTAINER docker 265 ENV foo bar` 266 name := "scratch-image" 267 result := buildImage(name, build.WithDockerfile(dockerfile)) 268 result.Assert(c, icmd.Success) 269 id := getIDByName(c, name) 270 271 // this is just the output of docker build 272 // we're interested in getting the image id of the MAINTAINER instruction 273 // and that's located at output, line 5, from 7 to end 274 split := strings.Split(result.Combined(), "\n") 275 intermediate := strings.TrimSpace(split[5][7:]) 276 277 out, _ := dockerCmd(c, "images") 278 // images shouldn't show non-heads images 279 c.Assert(out, checker.Not(checker.Contains), intermediate) 280 // images should contain final built images 281 c.Assert(out, checker.Contains, stringid.TruncateID(id)) 282 } 283 284 func (s *DockerSuite) TestImagesEnsureImagesFromScratchShown(c *check.C) { 285 testRequires(c, DaemonIsLinux) // Windows does not support FROM scratch 286 dockerfile := ` 287 FROM scratch 288 MAINTAINER docker` 289 290 name := "scratch-image" 291 buildImageSuccessfully(c, name, build.WithDockerfile(dockerfile)) 292 id := getIDByName(c, name) 293 294 out, _ := dockerCmd(c, "images") 295 // images should contain images built from scratch 296 c.Assert(out, checker.Contains, stringid.TruncateID(id)) 297 } 298 299 // For W2W - equivalent to TestImagesEnsureImagesFromScratchShown but Windows 300 // doesn't support from scratch 301 func (s *DockerSuite) TestImagesEnsureImagesFromBusyboxShown(c *check.C) { 302 dockerfile := ` 303 FROM busybox 304 MAINTAINER docker` 305 name := "busybox-image" 306 307 buildImageSuccessfully(c, name, build.WithDockerfile(dockerfile)) 308 id := getIDByName(c, name) 309 310 out, _ := dockerCmd(c, "images") 311 // images should contain images built from busybox 312 c.Assert(out, checker.Contains, stringid.TruncateID(id)) 313 } 314 315 // #18181 316 func (s *DockerSuite) TestImagesFilterNameWithPort(c *check.C) { 317 tag := "a.b.c.d:5000/hello" 318 dockerCmd(c, "tag", "busybox", tag) 319 out, _ := dockerCmd(c, "images", tag) 320 c.Assert(out, checker.Contains, tag) 321 322 out, _ = dockerCmd(c, "images", tag+":latest") 323 c.Assert(out, checker.Contains, tag) 324 325 out, _ = dockerCmd(c, "images", tag+":no-such-tag") 326 c.Assert(out, checker.Not(checker.Contains), tag) 327 } 328 329 func (s *DockerSuite) TestImagesFormat(c *check.C) { 330 // testRequires(c, DaemonIsLinux) 331 tag := "myimage" 332 dockerCmd(c, "tag", "busybox", tag+":v1") 333 dockerCmd(c, "tag", "busybox", tag+":v2") 334 335 out, _ := dockerCmd(c, "images", "--format", "{{.Repository}}", tag) 336 lines := strings.Split(strings.TrimSpace(string(out)), "\n") 337 338 expected := []string{"myimage", "myimage"} 339 var names []string 340 names = append(names, lines...) 341 assert.Assert(c, is.DeepEqual(names, expected), "Expected array with truncated names: %v, got: %v", expected, names) 342 } 343 344 // ImagesDefaultFormatAndQuiet 345 func (s *DockerSuite) TestImagesFormatDefaultFormat(c *check.C) { 346 testRequires(c, DaemonIsLinux) 347 348 // create container 1 349 out, _ := dockerCmd(c, "run", "-d", "busybox", "true") 350 containerID1 := strings.TrimSpace(out) 351 352 // tag as foobox 353 out, _ = dockerCmd(c, "commit", containerID1, "myimage") 354 imageID := stringid.TruncateID(strings.TrimSpace(out)) 355 356 config := `{ 357 "imagesFormat": "{{ .ID }} default" 358 }` 359 d, err := ioutil.TempDir("", "integration-cli-") 360 assert.NilError(c, err) 361 defer os.RemoveAll(d) 362 363 err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644) 364 assert.NilError(c, err) 365 366 out, _ = dockerCmd(c, "--config", d, "images", "-q", "myimage") 367 assert.Equal(c, out, imageID+"\n", "Expected to print only the image id, got %v\n", out) 368 }