2014-02-25 18:17:48 +02:00
package main
import (
2014-11-03 20:11:29 +09:00
"fmt"
2015-12-18 14:03:41 +01:00
"io/ioutil"
"os"
"path/filepath"
2014-11-03 20:11:29 +09:00
"reflect"
"sort"
2014-02-25 18:17:48 +02:00
"strings"
2014-06-23 22:19:52 +04:00
"time"
2015-03-18 10:11:01 -04:00
2016-12-30 18:23:00 +01:00
"github.com/docker/docker/integration-cli/checker"
2017-03-23 18:35:22 +01:00
"github.com/docker/docker/integration-cli/cli/build"
2015-03-24 12:25:26 +01:00
"github.com/docker/docker/pkg/stringid"
2015-04-18 09:46:47 -07:00
"github.com/go-check/check"
2017-08-23 17:01:29 -04:00
"github.com/gotestyourself/gotestyourself/icmd"
2014-02-25 18:17:48 +02:00
)
2015-04-18 09:46:47 -07:00
func ( s * DockerSuite ) TestImagesEnsureImageIsListed ( c * check . C ) {
2015-10-26 13:47:21 -05:00
imagesOut , _ := dockerCmd ( c , "images" )
c . Assert ( imagesOut , checker . Contains , "busybox" )
2014-02-25 18:17:48 +02:00
}
2014-04-04 00:57:41 +00:00
2015-08-08 15:58:48 +02:00
func ( s * DockerSuite ) TestImagesEnsureImageWithTagIsListed ( c * check . C ) {
2015-11-25 10:43:14 +08:00
name := "imagewithtag"
dockerCmd ( c , "tag" , "busybox" , name + ":v1" )
dockerCmd ( c , "tag" , "busybox" , name + ":v1v1" )
dockerCmd ( c , "tag" , "busybox" , name + ":v2" )
2015-08-08 15:58:48 +02:00
2015-11-25 10:43:14 +08:00
imagesOut , _ := dockerCmd ( c , "images" , name + ":v1" )
c . Assert ( imagesOut , checker . Contains , name )
2015-10-26 13:47:21 -05:00
c . Assert ( imagesOut , checker . Contains , "v1" )
c . Assert ( imagesOut , checker . Not ( checker . Contains ) , "v2" )
2015-11-25 10:43:14 +08:00
c . Assert ( imagesOut , checker . Not ( checker . Contains ) , "v1v1" )
2015-08-08 15:58:48 +02:00
2015-11-25 10:43:14 +08:00
imagesOut , _ = dockerCmd ( c , "images" , name )
c . Assert ( imagesOut , checker . Contains , name )
2015-10-26 13:47:21 -05:00
c . Assert ( imagesOut , checker . Contains , "v1" )
2015-11-25 10:43:14 +08:00
c . Assert ( imagesOut , checker . Contains , "v1v1" )
2015-10-26 13:47:21 -05:00
c . Assert ( imagesOut , checker . Contains , "v2" )
2015-08-08 15:58:48 +02:00
}
func ( s * DockerSuite ) TestImagesEnsureImageWithBadTagIsNotListed ( c * check . C ) {
2015-10-26 13:47:21 -05:00
imagesOut , _ := dockerCmd ( c , "images" , "busybox:nonexistent" )
c . Assert ( imagesOut , checker . Not ( checker . Contains ) , "busybox" )
2015-08-08 15:58:48 +02:00
}
2015-04-18 09:46:47 -07:00
func ( s * DockerSuite ) TestImagesOrderedByCreationDate ( c * check . C ) {
2017-03-23 18:35:22 +01:00
buildImageSuccessfully ( c , "order:test_a" , build . WithDockerfile ( ` FROM busybox
2017-01-16 11:30:14 +01:00
MAINTAINER dockerio1 ` ) )
id1 := getIDByName ( c , "order:test_a" )
2015-08-11 09:41:11 +02:00
time . Sleep ( 1 * time . Second )
2017-03-23 18:35:22 +01:00
buildImageSuccessfully ( c , "order:test_c" , build . WithDockerfile ( ` FROM busybox
2017-01-16 11:30:14 +01:00
MAINTAINER dockerio2 ` ) )
id2 := getIDByName ( c , "order:test_c" )
2015-08-11 09:41:11 +02:00
time . Sleep ( 1 * time . Second )
2017-03-23 18:35:22 +01:00
buildImageSuccessfully ( c , "order:test_b" , build . WithDockerfile ( ` FROM busybox
2017-01-16 11:30:14 +01:00
MAINTAINER dockerio3 ` ) )
id3 := getIDByName ( c , "order:test_b" )
2014-06-23 22:19:52 +04:00
2015-07-20 14:55:40 +08:00
out , _ := dockerCmd ( c , "images" , "-q" , "--no-trunc" )
2014-06-23 22:19:52 +04:00
imgs := strings . Split ( out , "\n" )
2015-10-26 13:47:21 -05:00
c . Assert ( imgs [ 0 ] , checker . Equals , id3 , check . Commentf ( "First image must be %s, got %s" , id3 , imgs [ 0 ] ) )
c . Assert ( imgs [ 1 ] , checker . Equals , id2 , check . Commentf ( "First image must be %s, got %s" , id2 , imgs [ 1 ] ) )
c . Assert ( imgs [ 2 ] , checker . Equals , id1 , check . Commentf ( "First image must be %s, got %s" , id1 , imgs [ 2 ] ) )
2014-06-23 22:19:52 +04:00
}
2014-11-03 20:11:29 +09:00
2015-04-18 09:46:47 -07:00
func ( s * DockerSuite ) TestImagesErrorWithInvalidFilterNameTest ( c * check . C ) {
2015-07-27 14:13:25 -04:00
out , _ , err := dockerCmdWithError ( "images" , "-f" , "FOO=123" )
2015-10-26 13:47:21 -05:00
c . Assert ( err , checker . NotNil )
c . Assert ( out , checker . Contains , "Invalid filter" )
2014-11-03 20:11:29 +09:00
}
2015-11-25 20:27:11 -05:00
func ( s * DockerSuite ) TestImagesFilterLabelMatch ( c * check . C ) {
2015-01-06 17:04:10 -07:00
imageName1 := "images_filter_test1"
imageName2 := "images_filter_test2"
imageName3 := "images_filter_test3"
2017-03-23 18:35:22 +01:00
buildImageSuccessfully ( c , imageName1 , build . WithDockerfile ( ` FROM busybox
2017-01-16 11:30:14 +01:00
LABEL match me ` ) )
image1ID := getIDByName ( c , imageName1 )
2015-01-06 17:04:10 -07:00
2017-03-23 18:35:22 +01:00
buildImageSuccessfully ( c , imageName2 , build . WithDockerfile ( ` FROM busybox
2017-01-16 11:30:14 +01:00
LABEL match = "me too" ` ) )
image2ID := getIDByName ( c , imageName2 )
2015-01-06 17:04:10 -07:00
2017-03-23 18:35:22 +01:00
buildImageSuccessfully ( c , imageName3 , build . WithDockerfile ( ` FROM busybox
2017-01-16 11:30:14 +01:00
LABEL nomatch me ` ) )
image3ID := getIDByName ( c , imageName3 )
2015-01-06 17:04:10 -07:00
2015-07-20 14:55:40 +08:00
out , _ := dockerCmd ( c , "images" , "--no-trunc" , "-q" , "-f" , "label=match" )
2015-01-06 17:04:10 -07:00
out = strings . TrimSpace ( out )
2015-11-18 14:20:54 -08:00
c . Assert ( out , check . Matches , fmt . Sprintf ( "[\\s\\w:]*%s[\\s\\w:]*" , image1ID ) )
c . Assert ( out , check . Matches , fmt . Sprintf ( "[\\s\\w:]*%s[\\s\\w:]*" , image2ID ) )
c . Assert ( out , check . Not ( check . Matches ) , fmt . Sprintf ( "[\\s\\w:]*%s[\\s\\w:]*" , image3ID ) )
2015-01-06 17:04:10 -07:00
2015-07-20 14:55:40 +08:00
out , _ = dockerCmd ( c , "images" , "--no-trunc" , "-q" , "-f" , "label=match=me too" )
2015-01-06 17:04:10 -07:00
out = strings . TrimSpace ( out )
2015-08-22 14:06:48 +02:00
c . Assert ( out , check . Equals , image2ID )
}
// Regression : #15659
2017-04-13 18:44:36 -04:00
func ( s * DockerSuite ) TestCommitWithFilterLabel ( c * check . C ) {
2015-08-22 14:06:48 +02:00
// Create a container
dockerCmd ( c , "run" , "--name" , "bar" , "busybox" , "/bin/sh" )
// Commit with labels "using changes"
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" )
imageID := strings . TrimSpace ( out )
out , _ = dockerCmd ( c , "images" , "--no-trunc" , "-q" , "-f" , "label=foo.version=1.0.0-1" )
out = strings . TrimSpace ( out )
c . Assert ( out , check . Equals , imageID )
2015-01-06 17:04:10 -07:00
}
2016-05-25 13:49:10 +02:00
func ( s * DockerSuite ) TestImagesFilterSinceAndBefore ( c * check . C ) {
2017-03-23 18:35:22 +01:00
buildImageSuccessfully ( c , "image:1" , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-16 11:30:14 +01:00
LABEL number = 1 ` ) )
imageID1 := getIDByName ( c , "image:1" )
2017-03-23 18:35:22 +01:00
buildImageSuccessfully ( c , "image:2" , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-16 11:30:14 +01:00
LABEL number = 2 ` ) )
imageID2 := getIDByName ( c , "image:2" )
2017-03-23 18:35:22 +01:00
buildImageSuccessfully ( c , "image:3" , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-16 11:30:14 +01:00
LABEL number = 3 ` ) )
imageID3 := getIDByName ( c , "image:3" )
2016-05-25 13:49:10 +02:00
expected := [ ] string { imageID3 , imageID2 }
out , _ := dockerCmd ( c , "images" , "-f" , "since=image:1" , "image" )
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 ) )
out , _ = dockerCmd ( c , "images" , "-f" , "since=" + imageID1 , "image" )
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 ) )
expected = [ ] string { imageID3 }
out , _ = dockerCmd ( c , "images" , "-f" , "since=image:2" , "image" )
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 ) )
out , _ = dockerCmd ( c , "images" , "-f" , "since=" + imageID2 , "image" )
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 ) )
expected = [ ] string { imageID2 , imageID1 }
out , _ = dockerCmd ( c , "images" , "-f" , "before=image:3" , "image" )
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 ) )
out , _ = dockerCmd ( c , "images" , "-f" , "before=" + imageID3 , "image" )
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 ) )
expected = [ ] string { imageID1 }
out , _ = dockerCmd ( c , "images" , "-f" , "before=image:2" , "image" )
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 ) )
out , _ = dockerCmd ( c , "images" , "-f" , "before=" + imageID2 , "image" )
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 ) )
}
func assertImageList ( out string , expected [ ] string ) bool {
lines := strings . Split ( strings . Trim ( out , "\n " ) , "\n" )
if len ( lines ) - 1 != len ( expected ) {
return false
}
imageIDIndex := strings . Index ( lines [ 0 ] , "IMAGE ID" )
for i := 0 ; i < len ( expected ) ; i ++ {
imageID := lines [ i + 1 ] [ imageIDIndex : imageIDIndex + 12 ]
found := false
for _ , e := range expected {
if imageID == e [ 7 : 19 ] {
found = true
break
}
}
if ! found {
return false
}
}
return true
}
2017-01-16 11:30:14 +01:00
// FIXME(vdemeester) should be a unit test on `docker image ls`
2015-04-18 09:46:47 -07:00
func ( s * DockerSuite ) TestImagesFilterSpaceTrimCase ( c * check . C ) {
2014-11-03 20:11:29 +09:00
imageName := "images_filter_test"
2017-01-16 11:30:14 +01:00
// Build a image and fail to build so that we have dangling images ?
2017-03-23 18:35:22 +01:00
buildImage ( imageName , build . WithDockerfile ( ` FROM busybox
2015-12-18 14:03:41 +01:00
RUN touch / test / foo
RUN touch / test / bar
2017-01-16 11:30:14 +01:00
RUN touch / test / baz ` ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2014-11-03 20:11:29 +09:00
filters := [ ] string {
"dangling=true" ,
"Dangling=true" ,
" dangling=true" ,
"dangling=true " ,
"dangling = true" ,
}
imageListings := make ( [ ] [ ] string , 5 , 5 )
for idx , filter := range filters {
2015-07-20 14:55:40 +08:00
out , _ := dockerCmd ( c , "images" , "-q" , "-f" , filter )
2014-11-03 20:11:29 +09:00
listing := strings . Split ( out , "\n" )
sort . Strings ( listing )
imageListings [ idx ] = listing
}
for idx , listing := range imageListings {
if idx < 4 && ! reflect . DeepEqual ( listing , imageListings [ idx + 1 ] ) {
for idx , errListing := range imageListings {
2016-08-23 08:59:45 +08:00
fmt . Printf ( "out %d\n" , idx )
2014-11-03 20:11:29 +09:00
for _ , image := range errListing {
fmt . Print ( image )
}
fmt . Print ( "" )
}
2015-04-18 09:46:47 -07:00
c . Fatalf ( "All output must be the same" )
2014-11-03 20:11:29 +09:00
}
}
}
2015-03-18 10:11:01 -04:00
2015-04-18 09:46:47 -07:00
func ( s * DockerSuite ) TestImagesEnsureDanglingImageOnlyListedOnce ( c * check . C ) {
2015-08-28 10:36:42 -07:00
testRequires ( c , DaemonIsLinux )
2015-03-18 10:11:01 -04:00
// create container 1
2015-07-20 14:55:40 +08:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "true" )
2015-07-22 13:59:24 +01:00
containerID1 := strings . TrimSpace ( out )
2015-03-18 10:11:01 -04:00
// tag as foobox
2015-07-22 13:59:24 +01:00
out , _ = dockerCmd ( c , "commit" , containerID1 , "foobox" )
imageID := stringid . TruncateID ( strings . TrimSpace ( out ) )
2015-03-18 10:11:01 -04:00
// overwrite the tag, making the previous image dangling
2016-05-29 08:16:39 -07:00
dockerCmd ( c , "tag" , "busybox" , "foobox" )
2015-03-18 10:11:01 -04:00
2015-07-20 14:55:40 +08:00
out , _ = dockerCmd ( c , "images" , "-q" , "-f" , "dangling=true" )
2015-12-13 18:00:39 +02:00
// Expect one dangling image
2015-10-26 13:47:21 -05:00
c . Assert ( strings . Count ( out , imageID ) , checker . Equals , 1 )
2016-01-14 06:58:31 +00:00
out , _ = dockerCmd ( c , "images" , "-q" , "-f" , "dangling=false" )
//dangling=false would not include dangling images
c . Assert ( out , checker . Not ( checker . Contains ) , imageID )
out , _ = dockerCmd ( c , "images" )
//docker images still include dangling images
c . Assert ( out , checker . Contains , imageID )
2015-03-18 10:11:01 -04:00
}
2015-10-16 22:09:32 +08:00
2017-01-16 11:30:14 +01:00
// FIXME(vdemeester) should be a unit test for `docker image ls`
2015-10-16 22:09:32 +08:00
func ( s * DockerSuite ) TestImagesWithIncorrectFilter ( c * check . C ) {
out , _ , err := dockerCmdWithError ( "images" , "-f" , "dangling=invalid" )
c . Assert ( err , check . NotNil )
c . Assert ( out , checker . Contains , "Invalid filter" )
}
2015-10-09 19:13:45 +02:00
func ( s * DockerSuite ) TestImagesEnsureOnlyHeadsImagesShown ( c * check . C ) {
dockerfile := `
2016-08-30 15:20:55 -07:00
FROM busybox
2015-10-09 19:13:45 +02:00
MAINTAINER docker
ENV foo bar `
2017-01-16 11:30:14 +01:00
name := "scratch-image"
2017-03-23 18:35:22 +01:00
result := buildImage ( name , build . WithDockerfile ( dockerfile ) )
2017-01-16 11:30:14 +01:00
result . Assert ( c , icmd . Success )
id := getIDByName ( c , name )
2015-10-09 19:13:45 +02:00
2015-10-11 09:32:52 +02:00
// this is just the output of docker build
// we're interested in getting the image id of the MAINTAINER instruction
// and that's located at output, line 5, from 7 to end
2017-01-16 11:30:14 +01:00
split := strings . Split ( result . Combined ( ) , "\n" )
2015-10-09 19:13:45 +02:00
intermediate := strings . TrimSpace ( split [ 5 ] [ 7 : ] )
2017-01-16 11:30:14 +01:00
out , _ := dockerCmd ( c , "images" )
2015-10-26 13:47:21 -05:00
// images shouldn't show non-heads images
c . Assert ( out , checker . Not ( checker . Contains ) , intermediate )
// images should contain final built images
2017-01-16 11:30:14 +01:00
c . Assert ( out , checker . Contains , stringid . TruncateID ( id ) )
2015-10-09 19:13:45 +02:00
}
func ( s * DockerSuite ) TestImagesEnsureImagesFromScratchShown ( c * check . C ) {
2016-08-30 15:20:55 -07:00
testRequires ( c , DaemonIsLinux ) // Windows does not support FROM scratch
2015-10-09 19:13:45 +02:00
dockerfile := `
FROM scratch
MAINTAINER docker `
2017-01-16 11:30:14 +01:00
name := "scratch-image"
2017-03-23 18:35:22 +01:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( dockerfile ) )
2017-01-16 11:30:14 +01:00
id := getIDByName ( c , name )
2015-10-09 19:13:45 +02:00
out , _ := dockerCmd ( c , "images" )
2015-10-26 13:47:21 -05:00
// images should contain images built from scratch
2015-11-18 14:20:54 -08:00
c . Assert ( out , checker . Contains , stringid . TruncateID ( id ) )
2015-10-09 19:13:45 +02:00
}
2015-11-25 10:43:14 +08:00
2016-08-30 15:20:55 -07:00
// For W2W - equivalent to TestImagesEnsureImagesFromScratchShown but Windows
// doesn't support from scratch
func ( s * DockerSuite ) TestImagesEnsureImagesFromBusyboxShown ( c * check . C ) {
dockerfile := `
FROM busybox
MAINTAINER docker `
2017-01-16 11:30:14 +01:00
name := "busybox-image"
2016-08-30 15:20:55 -07:00
2017-03-23 18:35:22 +01:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( dockerfile ) )
2017-01-16 11:30:14 +01:00
id := getIDByName ( c , name )
2016-08-30 15:20:55 -07:00
out , _ := dockerCmd ( c , "images" )
// images should contain images built from busybox
c . Assert ( out , checker . Contains , stringid . TruncateID ( id ) )
}
2015-11-25 10:43:14 +08:00
// #18181
func ( s * DockerSuite ) TestImagesFilterNameWithPort ( c * check . C ) {
tag := "a.b.c.d:5000/hello"
dockerCmd ( c , "tag" , "busybox" , tag )
out , _ := dockerCmd ( c , "images" , tag )
c . Assert ( out , checker . Contains , tag )
out , _ = dockerCmd ( c , "images" , tag + ":latest" )
c . Assert ( out , checker . Contains , tag )
out , _ = dockerCmd ( c , "images" , tag + ":no-such-tag" )
c . Assert ( out , checker . Not ( checker . Contains ) , tag )
}
2015-12-18 14:03:41 +01:00
func ( s * DockerSuite ) TestImagesFormat ( c * check . C ) {
// testRequires(c, DaemonIsLinux)
tag := "myimage"
dockerCmd ( c , "tag" , "busybox" , tag + ":v1" )
dockerCmd ( c , "tag" , "busybox" , tag + ":v2" )
out , _ := dockerCmd ( c , "images" , "--format" , "{{.Repository}}" , tag )
lines := strings . Split ( strings . TrimSpace ( string ( out ) ) , "\n" )
expected := [ ] string { "myimage" , "myimage" }
var names [ ] string
2016-10-13 09:34:19 -07:00
names = append ( names , lines ... )
2017-01-25 16:54:18 -08:00
c . Assert ( names , checker . DeepEquals , expected , check . Commentf ( "Expected array with truncated names: %v, got: %v" , expected , names ) )
2015-12-18 14:03:41 +01:00
}
// ImagesDefaultFormatAndQuiet
func ( s * DockerSuite ) TestImagesFormatDefaultFormat ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
// create container 1
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "true" )
containerID1 := strings . TrimSpace ( out )
// tag as foobox
out , _ = dockerCmd ( c , "commit" , containerID1 , "myimage" )
imageID := stringid . TruncateID ( strings . TrimSpace ( out ) )
config := ` {
"imagesFormat" : "{{ .ID }} default"
} `
d , err := ioutil . TempDir ( "" , "integration-cli-" )
c . Assert ( err , checker . IsNil )
defer os . RemoveAll ( d )
err = ioutil . WriteFile ( filepath . Join ( d , "config.json" ) , [ ] byte ( config ) , 0644 )
c . Assert ( err , checker . IsNil )
out , _ = dockerCmd ( c , "--config" , d , "images" , "-q" , "myimage" )
c . Assert ( out , checker . Equals , imageID + "\n" , check . Commentf ( "Expected to print only the image id, got %v\n" , out ) )
}