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