2014-02-25 11:17:48 -05:00
package main
import (
2014-11-03 06:11:29 -05:00
"fmt"
2015-12-18 08:03:41 -05:00
"io/ioutil"
"os"
"path/filepath"
2014-11-03 06:11:29 -05:00
"reflect"
"sort"
2014-02-25 11:17:48 -05:00
"strings"
2014-06-23 14:19:52 -04:00
"time"
2015-03-18 10:11:01 -04:00
2016-12-30 12:23:00 -05:00
"github.com/docker/docker/integration-cli/checker"
2017-03-23 13:35:22 -04:00
"github.com/docker/docker/integration-cli/cli/build"
2015-03-24 07:25:26 -04:00
"github.com/docker/docker/pkg/stringid"
2015-04-18 12:46:47 -04:00
"github.com/go-check/check"
2018-06-11 09:32:11 -04:00
"gotest.tools/icmd"
2014-02-25 11:17:48 -05:00
)
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestImagesEnsureImageIsListed ( c * check . C ) {
2015-10-26 14:47:21 -04:00
imagesOut , _ := dockerCmd ( c , "images" )
c . Assert ( imagesOut , checker . Contains , "busybox" )
2014-02-25 11:17:48 -05:00
}
2014-04-03 20:57:41 -04:00
2015-08-08 09:58:48 -04:00
func ( s * DockerSuite ) TestImagesEnsureImageWithTagIsListed ( c * check . C ) {
2015-11-24 21:43:14 -05:00
name := "imagewithtag"
dockerCmd ( c , "tag" , "busybox" , name + ":v1" )
dockerCmd ( c , "tag" , "busybox" , name + ":v1v1" )
dockerCmd ( c , "tag" , "busybox" , name + ":v2" )
2015-08-08 09:58:48 -04:00
2015-11-24 21:43:14 -05:00
imagesOut , _ := dockerCmd ( c , "images" , name + ":v1" )
c . Assert ( imagesOut , checker . Contains , name )
2015-10-26 14:47:21 -04:00
c . Assert ( imagesOut , checker . Contains , "v1" )
c . Assert ( imagesOut , checker . Not ( checker . Contains ) , "v2" )
2015-11-24 21:43:14 -05:00
c . Assert ( imagesOut , checker . Not ( checker . Contains ) , "v1v1" )
2015-08-08 09:58:48 -04:00
2015-11-24 21:43:14 -05:00
imagesOut , _ = dockerCmd ( c , "images" , name )
c . Assert ( imagesOut , checker . Contains , name )
2015-10-26 14:47:21 -04:00
c . Assert ( imagesOut , checker . Contains , "v1" )
2015-11-24 21:43:14 -05:00
c . Assert ( imagesOut , checker . Contains , "v1v1" )
2015-10-26 14:47:21 -04:00
c . Assert ( imagesOut , checker . Contains , "v2" )
2015-08-08 09:58:48 -04:00
}
func ( s * DockerSuite ) TestImagesEnsureImageWithBadTagIsNotListed ( c * check . C ) {
2015-10-26 14:47:21 -04:00
imagesOut , _ := dockerCmd ( c , "images" , "busybox:nonexistent" )
c . Assert ( imagesOut , checker . Not ( checker . Contains ) , "busybox" )
2015-08-08 09:58:48 -04:00
}
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestImagesOrderedByCreationDate ( c * check . C ) {
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , "order:test_a" , build . WithDockerfile ( ` FROM busybox
2017-01-16 05:30:14 -05:00
MAINTAINER dockerio1 ` ) )
id1 := getIDByName ( c , "order:test_a" )
2015-08-11 03:41:11 -04:00
time . Sleep ( 1 * time . Second )
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , "order:test_c" , build . WithDockerfile ( ` FROM busybox
2017-01-16 05:30:14 -05:00
MAINTAINER dockerio2 ` ) )
id2 := getIDByName ( c , "order:test_c" )
2015-08-11 03:41:11 -04:00
time . Sleep ( 1 * time . Second )
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , "order:test_b" , build . WithDockerfile ( ` FROM busybox
2017-01-16 05:30:14 -05:00
MAINTAINER dockerio3 ` ) )
id3 := getIDByName ( c , "order:test_b" )
2014-06-23 14:19:52 -04:00
2015-07-20 02:55:40 -04:00
out , _ := dockerCmd ( c , "images" , "-q" , "--no-trunc" )
2014-06-23 14:19:52 -04:00
imgs := strings . Split ( out , "\n" )
2015-10-26 14:47:21 -04: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 14:19:52 -04:00
}
2014-11-03 06:11:29 -05:00
2015-04-18 12:46:47 -04: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 14:47:21 -04:00
c . Assert ( err , checker . NotNil )
c . Assert ( out , checker . Contains , "Invalid filter" )
2014-11-03 06:11:29 -05:00
}
2015-11-25 20:27:11 -05:00
func ( s * DockerSuite ) TestImagesFilterLabelMatch ( c * check . C ) {
2015-01-06 19:04:10 -05:00
imageName1 := "images_filter_test1"
imageName2 := "images_filter_test2"
imageName3 := "images_filter_test3"
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , imageName1 , build . WithDockerfile ( ` FROM busybox
2017-01-16 05:30:14 -05:00
LABEL match me ` ) )
image1ID := getIDByName ( c , imageName1 )
2015-01-06 19:04:10 -05:00
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , imageName2 , build . WithDockerfile ( ` FROM busybox
2017-01-16 05:30:14 -05:00
LABEL match = "me too" ` ) )
image2ID := getIDByName ( c , imageName2 )
2015-01-06 19:04:10 -05:00
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , imageName3 , build . WithDockerfile ( ` FROM busybox
2017-01-16 05:30:14 -05:00
LABEL nomatch me ` ) )
image3ID := getIDByName ( c , imageName3 )
2015-01-06 19:04:10 -05:00
2015-07-20 02:55:40 -04:00
out , _ := dockerCmd ( c , "images" , "--no-trunc" , "-q" , "-f" , "label=match" )
2015-01-06 19:04:10 -05:00
out = strings . TrimSpace ( out )
2015-11-18 17:20:54 -05: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 19:04:10 -05:00
2015-07-20 02:55:40 -04:00
out , _ = dockerCmd ( c , "images" , "--no-trunc" , "-q" , "-f" , "label=match=me too" )
2015-01-06 19:04:10 -05:00
out = strings . TrimSpace ( out )
2015-08-22 08:06:48 -04: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 08:06:48 -04: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 19:04:10 -05:00
}
2016-05-25 07:49:10 -04:00
func ( s * DockerSuite ) TestImagesFilterSinceAndBefore ( c * check . C ) {
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , "image:1" , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-16 05:30:14 -05:00
LABEL number = 1 ` ) )
imageID1 := getIDByName ( c , "image:1" )
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , "image:2" , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-16 05:30:14 -05:00
LABEL number = 2 ` ) )
imageID2 := getIDByName ( c , "image:2" )
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , "image:3" , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-16 05:30:14 -05:00
LABEL number = 3 ` ) )
imageID3 := getIDByName ( c , "image:3" )
2016-05-25 07:49:10 -04: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 05:30:14 -05:00
// FIXME(vdemeester) should be a unit test on `docker image ls`
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestImagesFilterSpaceTrimCase ( c * check . C ) {
2014-11-03 06:11:29 -05:00
imageName := "images_filter_test"
2017-01-16 05:30:14 -05:00
// Build a image and fail to build so that we have dangling images ?
2017-03-23 13:35:22 -04:00
buildImage ( imageName , build . WithDockerfile ( ` FROM busybox
2015-12-18 08:03:41 -05:00
RUN touch / test / foo
RUN touch / test / bar
2017-01-16 05:30:14 -05:00
RUN touch / test / baz ` ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2014-11-03 06:11:29 -05: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 02:55:40 -04:00
out , _ := dockerCmd ( c , "images" , "-q" , "-f" , filter )
2014-11-03 06:11:29 -05: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-22 20:59:45 -04:00
fmt . Printf ( "out %d\n" , idx )
2014-11-03 06:11:29 -05:00
for _ , image := range errListing {
fmt . Print ( image )
}
fmt . Print ( "" )
}
2015-04-18 12:46:47 -04:00
c . Fatalf ( "All output must be the same" )
2014-11-03 06:11:29 -05:00
}
}
}
2015-03-18 10:11:01 -04:00
2015-04-18 12:46:47 -04:00
func ( s * DockerSuite ) TestImagesEnsureDanglingImageOnlyListedOnce ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-03-18 10:11:01 -04:00
// create container 1
2015-07-20 02:55:40 -04:00
out , _ := dockerCmd ( c , "run" , "-d" , "busybox" , "true" )
2015-07-22 08:59:24 -04:00
containerID1 := strings . TrimSpace ( out )
2015-03-18 10:11:01 -04:00
// tag as foobox
2015-07-22 08:59:24 -04: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 11:16:39 -04:00
dockerCmd ( c , "tag" , "busybox" , "foobox" )
2015-03-18 10:11:01 -04:00
2015-07-20 02:55:40 -04:00
out , _ = dockerCmd ( c , "images" , "-q" , "-f" , "dangling=true" )
2015-12-13 11:00:39 -05:00
// Expect one dangling image
2015-10-26 14:47:21 -04:00
c . Assert ( strings . Count ( out , imageID ) , checker . Equals , 1 )
2016-01-14 01:58:31 -05: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 10:09:32 -04:00
2017-01-16 05:30:14 -05:00
// FIXME(vdemeester) should be a unit test for `docker image ls`
2015-10-16 10:09:32 -04: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 13:13:45 -04:00
func ( s * DockerSuite ) TestImagesEnsureOnlyHeadsImagesShown ( c * check . C ) {
dockerfile := `
2016-08-30 18:20:55 -04:00
FROM busybox
2015-10-09 13:13:45 -04:00
MAINTAINER docker
ENV foo bar `
2017-01-16 05:30:14 -05:00
name := "scratch-image"
2017-03-23 13:35:22 -04:00
result := buildImage ( name , build . WithDockerfile ( dockerfile ) )
2017-01-16 05:30:14 -05:00
result . Assert ( c , icmd . Success )
id := getIDByName ( c , name )
2015-10-09 13:13:45 -04:00
2015-10-11 03:32:52 -04: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 05:30:14 -05:00
split := strings . Split ( result . Combined ( ) , "\n" )
2015-10-09 13:13:45 -04:00
intermediate := strings . TrimSpace ( split [ 5 ] [ 7 : ] )
2017-01-16 05:30:14 -05:00
out , _ := dockerCmd ( c , "images" )
2015-10-26 14:47:21 -04: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 05:30:14 -05:00
c . Assert ( out , checker . Contains , stringid . TruncateID ( id ) )
2015-10-09 13:13:45 -04:00
}
func ( s * DockerSuite ) TestImagesEnsureImagesFromScratchShown ( c * check . C ) {
2016-08-30 18:20:55 -04:00
testRequires ( c , DaemonIsLinux ) // Windows does not support FROM scratch
2015-10-09 13:13:45 -04:00
dockerfile := `
FROM scratch
MAINTAINER docker `
2017-01-16 05:30:14 -05:00
name := "scratch-image"
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( dockerfile ) )
2017-01-16 05:30:14 -05:00
id := getIDByName ( c , name )
2015-10-09 13:13:45 -04:00
out , _ := dockerCmd ( c , "images" )
2015-10-26 14:47:21 -04:00
// images should contain images built from scratch
2015-11-18 17:20:54 -05:00
c . Assert ( out , checker . Contains , stringid . TruncateID ( id ) )
2015-10-09 13:13:45 -04:00
}
2015-11-24 21:43:14 -05:00
2016-08-30 18:20:55 -04: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 05:30:14 -05:00
name := "busybox-image"
2016-08-30 18:20:55 -04:00
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( dockerfile ) )
2017-01-16 05:30:14 -05:00
id := getIDByName ( c , name )
2016-08-30 18:20:55 -04:00
out , _ := dockerCmd ( c , "images" )
// images should contain images built from busybox
c . Assert ( out , checker . Contains , stringid . TruncateID ( id ) )
}
2015-11-24 21:43:14 -05: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 08:03:41 -05: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 12:34:19 -04:00
names = append ( names , lines ... )
2017-01-25 19:54:18 -05:00
c . Assert ( names , checker . DeepEquals , expected , check . Commentf ( "Expected array with truncated names: %v, got: %v" , expected , names ) )
2015-12-18 08:03:41 -05: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 ) )
}