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 icmd "github.com/docker/docker/pkg/testutil/cmd"
17 "github.com/go-check/check"
20 func (s *DockerSuite) TestImagesEnsureImageIsListed(c *check.C) {
21 imagesOut, _ := dockerCmd(c, "images")
22 c.Assert(imagesOut, checker.Contains, "busybox")
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")
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")
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")
44 func (s *DockerSuite) TestImagesEnsureImageWithBadTagIsNotListed(c *check.C) {
45 imagesOut, _ := dockerCmd(c, "images", "busybox:nonexistent")
46 c.Assert(imagesOut, checker.Not(checker.Contains), "busybox")
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")
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]))
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")
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
81 image1ID := getIDByName(c, imageName1)
83 buildImageSuccessfully(c, imageName2, build.WithDockerfile(`FROM busybox
84 LABEL match="me too"`))
85 image2ID := getIDByName(c, imageName2)
87 buildImageSuccessfully(c, imageName3, build.WithDockerfile(`FROM busybox
89 image3ID := getIDByName(c, imageName3)
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))
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)
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)
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)
115 func (s *DockerSuite) TestImagesFilterSinceAndBefore(c *check.C) {
116 buildImageSuccessfully(c, "image:1", build.WithDockerfile(`FROM `+minimalBaseImage()+`
118 imageID1 := getIDByName(c, "image:1")
119 buildImageSuccessfully(c, "image:2", build.WithDockerfile(`FROM `+minimalBaseImage()+`
121 imageID2 := getIDByName(c, "image:2")
122 buildImageSuccessfully(c, "image:3", build.WithDockerfile(`FROM `+minimalBaseImage()+`
124 imageID3 := getIDByName(c, "image:3")
126 expected := []string{imageID3, imageID2}
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))
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))
134 expected = []string{imageID3}
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))
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))
142 expected = []string{imageID2, imageID1}
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))
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))
150 expected = []string{imageID1}
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))
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))
159 func assertImageList(out string, expected []string) bool {
160 lines := strings.Split(strings.Trim(out, "\n "), "\n")
162 if len(lines)-1 != len(expected) {
166 imageIDIndex := strings.Index(lines[0], "IMAGE ID")
167 for i := 0; i < len(expected); i++ {
168 imageID := lines[i+1][imageIDIndex : imageIDIndex+12]
170 for _, e := range expected {
171 if imageID == e[7:19] {
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
191 RUN touch /test/baz`)).Assert(c, icmd.Expected{
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
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 {
220 c.Fatalf("All output must be the same")
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)
232 out, _ = dockerCmd(c, "commit", containerID1, "foobox")
233 imageID := stringid.TruncateID(strings.TrimSpace(out))
235 // overwrite the tag, making the previous image dangling
236 dockerCmd(c, "tag", "busybox", "foobox")
238 out, _ = dockerCmd(c, "images", "-q", "-f", "dangling=true")
239 // Expect one dangling image
240 c.Assert(strings.Count(out, imageID), checker.Equals, 1)
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)
246 out, _ = dockerCmd(c, "images")
247 //docker images still include dangling images
248 c.Assert(out, checker.Contains, imageID)
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")
259 func (s *DockerSuite) TestImagesEnsureOnlyHeadsImagesShown(c *check.C) {
264 name := "scratch-image"
265 result := buildImage(name, build.WithDockerfile(dockerfile))
266 result.Assert(c, icmd.Success)
267 id := getIDByName(c, name)
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:])
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))
282 func (s *DockerSuite) TestImagesEnsureImagesFromScratchShown(c *check.C) {
283 testRequires(c, DaemonIsLinux) // Windows does not support FROM scratch
288 name := "scratch-image"
289 buildImageSuccessfully(c, name, build.WithDockerfile(dockerfile))
290 id := getIDByName(c, name)
292 out, _ := dockerCmd(c, "images")
293 // images should contain images built from scratch
294 c.Assert(out, checker.Contains, stringid.TruncateID(id))
297 // For W2W - equivalent to TestImagesEnsureImagesFromScratchShown but Windows
298 // doesn't support from scratch
299 func (s *DockerSuite) TestImagesEnsureImagesFromBusyboxShown(c *check.C) {
303 name := "busybox-image"
305 buildImageSuccessfully(c, name, build.WithDockerfile(dockerfile))
306 id := getIDByName(c, name)
308 out, _ := dockerCmd(c, "images")
309 // images should contain images built from busybox
310 c.Assert(out, checker.Contains, stringid.TruncateID(id))
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)
320 out, _ = dockerCmd(c, "images", tag+":latest")
321 c.Assert(out, checker.Contains, tag)
323 out, _ = dockerCmd(c, "images", tag+":no-such-tag")
324 c.Assert(out, checker.Not(checker.Contains), tag)
327 func (s *DockerSuite) TestImagesFormat(c *check.C) {
328 // testRequires(c, DaemonIsLinux)
330 dockerCmd(c, "tag", "busybox", tag+":v1")
331 dockerCmd(c, "tag", "busybox", tag+":v2")
333 out, _ := dockerCmd(c, "images", "--format", "{{.Repository}}", tag)
334 lines := strings.Split(strings.TrimSpace(string(out)), "\n")
336 expected := []string{"myimage", "myimage"}
338 names = append(names, lines...)
339 c.Assert(names, checker.DeepEquals, expected, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
342 // ImagesDefaultFormatAndQuiet
343 func (s *DockerSuite) TestImagesFormatDefaultFormat(c *check.C) {
344 testRequires(c, DaemonIsLinux)
346 // create container 1
347 out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
348 containerID1 := strings.TrimSpace(out)
351 out, _ = dockerCmd(c, "commit", containerID1, "myimage")
352 imageID := stringid.TruncateID(strings.TrimSpace(out))
355 "imagesFormat": "{{ .ID }} default"
357 d, err := ioutil.TempDir("", "integration-cli-")
358 c.Assert(err, checker.IsNil)
359 defer os.RemoveAll(d)
361 err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644)
362 c.Assert(err, checker.IsNil)
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))