2015-02-26 21:23:50 -05:00
package main
import (
2015-08-01 02:27:19 -04:00
"encoding/json"
2015-02-26 21:23:50 -05:00
"fmt"
2015-11-18 17:20:54 -05:00
"os"
"path/filepath"
2015-02-26 21:23:50 -05:00
"regexp"
"strings"
2015-10-30 20:46:25 -04:00
"github.com/docker/distribution/manifest/schema1"
2015-12-18 18:06:23 -05:00
"github.com/docker/distribution/manifest/schema2"
2016-09-06 14:18:12 -04:00
"github.com/docker/docker/api/types"
2016-12-30 12:23:00 -05:00
"github.com/docker/docker/integration-cli/checker"
2017-04-11 13:42:54 -04:00
"github.com/docker/docker/integration-cli/cli"
2017-03-23 13:35:22 -04:00
"github.com/docker/docker/integration-cli/cli/build"
2015-04-18 12:46:47 -04:00
"github.com/go-check/check"
2017-01-06 20:23:18 -05:00
"github.com/opencontainers/go-digest"
2018-06-11 09:32:11 -04:00
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
2015-02-26 21:23:50 -05:00
)
var (
2015-08-01 02:27:19 -04:00
remoteRepoName = "dockercli/busybox-by-dgst"
2016-01-10 13:10:45 -05:00
repoName = fmt . Sprintf ( "%s/%s" , privateRegistryURL , remoteRepoName )
2015-07-15 16:42:45 -04:00
pushDigestRegex = regexp . MustCompile ( "[\\S]+: digest: ([\\S]+) size: [0-9]+" )
digestRegex = regexp . MustCompile ( "Digest: ([\\S]+)" )
2015-02-26 21:23:50 -05:00
)
2015-08-01 02:27:19 -04:00
func setupImage ( c * check . C ) ( digest . Digest , error ) {
2015-07-14 02:35:36 -04:00
return setupImageWithTag ( c , "latest" )
2015-02-26 21:23:50 -05:00
}
2015-08-01 02:27:19 -04:00
func setupImageWithTag ( c * check . C , tag string ) ( digest . Digest , error ) {
2015-02-26 21:23:50 -05:00
containerName := "busyboxbydigest"
2017-02-17 13:34:33 -05:00
// new file is committed because this layer is used for detecting malicious
// changes. if this was committed as empty layer it would be skipped on pull
// and malicious changes would never be detected.
2017-04-11 13:42:54 -04:00
cli . DockerCmd ( c , "run" , "-e" , "digest=1" , "--name" , containerName , "busybox" , "touch" , "anewfile" )
2015-02-26 21:23:50 -05:00
// tag the image to upload it to the private registry
2015-11-18 17:20:54 -05:00
repoAndTag := repoName + ":" + tag
2017-04-11 13:42:54 -04:00
cli . DockerCmd ( c , "commit" , containerName , repoAndTag )
2015-02-26 21:23:50 -05:00
// delete the container as we don't need it any more
2017-04-11 13:42:54 -04:00
cli . DockerCmd ( c , "rm" , "-fv" , containerName )
2015-02-26 21:23:50 -05:00
// push the image
2017-04-11 13:42:54 -04:00
out := cli . DockerCmd ( c , "push" , repoAndTag ) . Combined ( )
2015-02-26 21:23:50 -05:00
// delete our local repo that we previously tagged
2017-04-11 13:42:54 -04:00
cli . DockerCmd ( c , "rmi" , repoAndTag )
2015-02-26 21:23:50 -05:00
2015-07-15 16:42:45 -04:00
matches := pushDigestRegex . FindStringSubmatch ( out )
2015-10-27 16:59:13 -04:00
c . Assert ( matches , checker . HasLen , 2 , check . Commentf ( "unable to parse digest from push output: %s" , out ) )
2015-02-26 21:23:50 -05:00
pushDigest := matches [ 1 ]
2015-08-01 02:27:19 -04:00
return digest . Digest ( pushDigest ) , nil
2015-02-26 21:23:50 -05:00
}
2015-12-18 18:06:23 -05:00
func testPullByTagDisplaysDigest ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
pushDigest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
2015-02-26 21:23:50 -05:00
// pull from the registry using the tag
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "pull" , repoName )
2015-02-26 21:23:50 -05:00
// the pull output includes "Digest: <digest>", so find that
matches := digestRegex . FindStringSubmatch ( out )
2015-10-27 16:59:13 -04:00
c . Assert ( matches , checker . HasLen , 2 , check . Commentf ( "unable to parse digest from pull output: %s" , out ) )
2015-02-26 21:23:50 -05:00
pullDigest := matches [ 1 ]
// make sure the pushed and pull digests match
2015-10-27 16:59:13 -04:00
c . Assert ( pushDigest . String ( ) , checker . Equals , pullDigest )
2015-02-26 21:23:50 -05:00
}
2015-12-18 18:06:23 -05:00
func ( s * DockerRegistrySuite ) TestPullByTagDisplaysDigest ( c * check . C ) {
testPullByTagDisplaysDigest ( c )
}
func ( s * DockerSchema1RegistrySuite ) TestPullByTagDisplaysDigest ( c * check . C ) {
testPullByTagDisplaysDigest ( c )
}
func testPullByDigest ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
pushDigest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
2015-02-26 21:23:50 -05:00
// pull from the registry using the <name>@<digest> reference
imageReference := fmt . Sprintf ( "%s@%s" , repoName , pushDigest )
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "pull" , imageReference )
2015-02-26 21:23:50 -05:00
// the pull output includes "Digest: <digest>", so find that
matches := digestRegex . FindStringSubmatch ( out )
2015-10-27 16:59:13 -04:00
c . Assert ( matches , checker . HasLen , 2 , check . Commentf ( "unable to parse digest from pull output: %s" , out ) )
2015-02-26 21:23:50 -05:00
pullDigest := matches [ 1 ]
// make sure the pushed and pull digests match
2015-10-27 16:59:13 -04:00
c . Assert ( pushDigest . String ( ) , checker . Equals , pullDigest )
2015-02-26 21:23:50 -05:00
}
2015-12-18 18:06:23 -05:00
func ( s * DockerRegistrySuite ) TestPullByDigest ( c * check . C ) {
testPullByDigest ( c )
}
func ( s * DockerSchema1RegistrySuite ) TestPullByDigest ( c * check . C ) {
testPullByDigest ( c )
}
func testPullByDigestNoFallback ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-04-29 15:29:50 -04:00
// pull from the registry using the <name>@<digest> reference
imageReference := fmt . Sprintf ( "%s@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" , repoName )
2015-07-27 14:13:25 -04:00
out , _ , err := dockerCmdWithError ( "pull" , imageReference )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . NotNil , check . Commentf ( "expected non-zero exit status and correct error message when pulling non-existing image" ) )
2016-11-10 18:14:33 -05:00
c . Assert ( out , checker . Contains , fmt . Sprintf ( "manifest for %s not found" , imageReference ) , check . Commentf ( "expected non-zero exit status and correct error message when pulling non-existing image" ) )
2015-04-29 15:29:50 -04:00
}
2015-12-18 18:06:23 -05:00
func ( s * DockerRegistrySuite ) TestPullByDigestNoFallback ( c * check . C ) {
testPullByDigestNoFallback ( c )
}
func ( s * DockerSchema1RegistrySuite ) TestPullByDigestNoFallback ( c * check . C ) {
testPullByDigestNoFallback ( c )
}
2015-04-24 17:16:56 -04:00
func ( s * DockerRegistrySuite ) TestCreateByDigest ( c * check . C ) {
2015-07-14 02:35:36 -04:00
pushDigest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
2015-02-26 21:23:50 -05:00
imageReference := fmt . Sprintf ( "%s@%s" , repoName , pushDigest )
containerName := "createByDigest"
2016-01-28 09:19:25 -05:00
dockerCmd ( c , "create" , "--name" , containerName , imageReference )
2015-02-26 21:23:50 -05:00
2016-01-28 09:19:25 -05:00
res := inspectField ( c , containerName , "Config.Image" )
2015-10-27 16:59:13 -04:00
c . Assert ( res , checker . Equals , imageReference )
2015-02-26 21:23:50 -05:00
}
2015-04-24 17:16:56 -04:00
func ( s * DockerRegistrySuite ) TestRunByDigest ( c * check . C ) {
2015-07-14 02:35:36 -04:00
pushDigest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil )
2015-02-26 21:23:50 -05:00
imageReference := fmt . Sprintf ( "%s@%s" , repoName , pushDigest )
containerName := "runByDigest"
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "run" , "--name" , containerName , imageReference , "sh" , "-c" , "echo found=$digest" )
2015-02-26 21:23:50 -05:00
foundRegex := regexp . MustCompile ( "found=([^\n]+)" )
matches := foundRegex . FindStringSubmatch ( out )
2015-10-27 16:59:13 -04:00
c . Assert ( matches , checker . HasLen , 2 , check . Commentf ( "unable to parse digest from pull output: %s" , out ) )
c . Assert ( matches [ 1 ] , checker . Equals , "1" , check . Commentf ( "Expected %q, got %q" , "1" , matches [ 1 ] ) )
2015-02-26 21:23:50 -05:00
2016-01-28 09:19:25 -05:00
res := inspectField ( c , containerName , "Config.Image" )
2015-10-27 16:59:13 -04:00
c . Assert ( res , checker . Equals , imageReference )
2015-02-26 21:23:50 -05:00
}
2015-04-24 17:16:56 -04:00
func ( s * DockerRegistrySuite ) TestRemoveImageByDigest ( c * check . C ) {
2015-07-14 02:35:36 -04:00
digest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
2015-02-26 21:23:50 -05:00
imageReference := fmt . Sprintf ( "%s@%s" , repoName , digest )
// pull from the registry using the <name>@<digest> reference
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "pull" , imageReference )
2015-02-26 21:23:50 -05:00
// make sure inspect runs ok
2016-01-28 09:19:25 -05:00
inspectField ( c , imageReference , "Id" )
2015-02-26 21:23:50 -05:00
// do the delete
2015-10-27 16:59:13 -04:00
err = deleteImages ( imageReference )
c . Assert ( err , checker . IsNil , check . Commentf ( "unexpected error deleting image" ) )
2015-02-26 21:23:50 -05:00
// try to inspect again - it should error this time
2016-01-28 09:19:25 -05:00
_ , err = inspectFieldWithError ( imageReference , "Id" )
2015-10-27 16:59:13 -04:00
//unexpected nil err trying to inspect what should be a non-existent image
c . Assert ( err , checker . NotNil )
2016-06-16 00:41:54 -04:00
c . Assert ( err . Error ( ) , checker . Contains , "No such object" )
2015-02-26 21:23:50 -05:00
}
2015-04-24 17:16:56 -04:00
func ( s * DockerRegistrySuite ) TestBuildByDigest ( c * check . C ) {
2015-07-14 02:35:36 -04:00
digest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
2015-02-26 21:23:50 -05:00
imageReference := fmt . Sprintf ( "%s@%s" , repoName , digest )
// pull from the registry using the <name>@<digest> reference
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "pull" , imageReference )
2015-02-26 21:23:50 -05:00
// get the image id
2016-01-28 09:19:25 -05:00
imageID := inspectField ( c , imageReference , "Id" )
2015-02-26 21:23:50 -05:00
// do the build
name := "buildbydigest"
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( fmt . Sprintf (
2015-02-26 21:23:50 -05:00
` FROM % s
2017-01-16 05:30:14 -05:00
CMD [ "/bin/echo" , "Hello World" ] ` , imageReference ) ) )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil )
2015-02-26 21:23:50 -05:00
// get the build's image id
2016-01-28 09:19:25 -05:00
res := inspectField ( c , name , "Config.Image" )
2015-02-26 21:23:50 -05:00
// make sure they match
2015-10-27 16:59:13 -04:00
c . Assert ( res , checker . Equals , imageID )
2015-02-26 21:23:50 -05:00
}
2015-04-24 17:16:56 -04:00
func ( s * DockerRegistrySuite ) TestTagByDigest ( c * check . C ) {
2015-07-14 02:35:36 -04:00
digest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
2015-02-26 21:23:50 -05:00
imageReference := fmt . Sprintf ( "%s@%s" , repoName , digest )
// pull from the registry using the <name>@<digest> reference
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "pull" , imageReference )
2015-02-26 21:23:50 -05:00
// tag it
tag := "tagbydigest"
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "tag" , imageReference , tag )
2015-02-26 21:23:50 -05:00
2016-01-28 09:19:25 -05:00
expectedID := inspectField ( c , imageReference , "Id" )
2015-02-26 21:23:50 -05:00
2016-01-28 09:19:25 -05:00
tagID := inspectField ( c , tag , "Id" )
2015-10-27 16:59:13 -04:00
c . Assert ( tagID , checker . Equals , expectedID )
2015-02-26 21:23:50 -05:00
}
2015-04-24 17:16:56 -04:00
func ( s * DockerRegistrySuite ) TestListImagesWithoutDigests ( c * check . C ) {
2015-07-14 02:35:36 -04:00
digest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
2015-02-26 21:23:50 -05:00
imageReference := fmt . Sprintf ( "%s@%s" , repoName , digest )
// pull from the registry using the <name>@<digest> reference
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "pull" , imageReference )
2015-02-26 21:23:50 -05:00
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "images" )
2015-10-27 16:59:13 -04:00
c . Assert ( out , checker . Not ( checker . Contains ) , "DIGEST" , check . Commentf ( "list output should not have contained DIGEST header" ) )
2015-02-26 21:23:50 -05:00
}
2015-04-24 17:16:56 -04:00
func ( s * DockerRegistrySuite ) TestListImagesWithDigests ( c * check . C ) {
2015-02-26 21:23:50 -05:00
// setup image1
2015-07-14 02:35:36 -04:00
digest1 , err := setupImageWithTag ( c , "tag1" )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
2015-02-26 21:23:50 -05:00
imageReference1 := fmt . Sprintf ( "%s@%s" , repoName , digest1 )
2015-04-18 12:46:47 -04:00
c . Logf ( "imageReference1 = %s" , imageReference1 )
2015-02-26 21:23:50 -05:00
// pull image1 by digest
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "pull" , imageReference1 )
2015-02-26 21:23:50 -05:00
// list images
2015-07-14 02:35:36 -04:00
out , _ := dockerCmd ( c , "images" , "--digests" )
2015-02-26 21:23:50 -05:00
// make sure repo shown, tag=<none>, digest = $digest1
2015-08-01 02:27:19 -04:00
re1 := regexp . MustCompile ( ` \s* ` + repoName + ` \s*<none>\s* ` + digest1 . String ( ) + ` \s ` )
2015-10-27 16:59:13 -04:00
c . Assert ( re1 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , re1 . String ( ) , out ) )
2015-02-26 21:23:50 -05:00
// setup image2
2015-07-14 02:35:36 -04:00
digest2 , err := setupImageWithTag ( c , "tag2" )
2015-10-27 16:59:13 -04:00
//error setting up image
c . Assert ( err , checker . IsNil )
2015-02-26 21:23:50 -05:00
imageReference2 := fmt . Sprintf ( "%s@%s" , repoName , digest2 )
2015-04-18 12:46:47 -04:00
c . Logf ( "imageReference2 = %s" , imageReference2 )
2015-02-26 21:23:50 -05:00
// pull image1 by digest
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "pull" , imageReference1 )
2015-02-26 21:23:50 -05:00
// pull image2 by digest
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "pull" , imageReference2 )
2015-02-26 21:23:50 -05:00
// list images
2015-07-14 02:35:36 -04:00
out , _ = dockerCmd ( c , "images" , "--digests" )
2015-02-26 21:23:50 -05:00
// make sure repo shown, tag=<none>, digest = $digest1
2015-10-27 16:59:13 -04:00
c . Assert ( re1 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , re1 . String ( ) , out ) )
2015-02-26 21:23:50 -05:00
// make sure repo shown, tag=<none>, digest = $digest2
2015-08-01 02:27:19 -04:00
re2 := regexp . MustCompile ( ` \s* ` + repoName + ` \s*<none>\s* ` + digest2 . String ( ) + ` \s ` )
2015-10-27 16:59:13 -04:00
c . Assert ( re2 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , re2 . String ( ) , out ) )
2015-02-26 21:23:50 -05:00
// pull tag1
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "pull" , repoName + ":tag1" )
2015-02-26 21:23:50 -05:00
// list images
2015-07-14 02:35:36 -04:00
out , _ = dockerCmd ( c , "images" , "--digests" )
2015-02-26 21:23:50 -05:00
// make sure image 1 has repo, tag, <none> AND repo, <none>, digest
2016-06-15 01:44:49 -04:00
reWithDigest1 := regexp . MustCompile ( ` \s* ` + repoName + ` \s*tag1\s* ` + digest1 . String ( ) + ` \s ` )
2015-10-27 16:59:13 -04:00
c . Assert ( reWithDigest1 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , reWithDigest1 . String ( ) , out ) )
2015-02-26 21:23:50 -05:00
// make sure image 2 has repo, <none>, digest
2015-10-27 16:59:13 -04:00
c . Assert ( re2 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , re2 . String ( ) , out ) )
2015-02-26 21:23:50 -05:00
// pull tag 2
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "pull" , repoName + ":tag2" )
2015-02-26 21:23:50 -05:00
// list images
2015-07-14 02:35:36 -04:00
out , _ = dockerCmd ( c , "images" , "--digests" )
2015-02-26 21:23:50 -05:00
// make sure image 1 has repo, tag, digest
2016-06-15 01:44:49 -04:00
c . Assert ( reWithDigest1 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , reWithDigest1 . String ( ) , out ) )
2015-02-26 21:23:50 -05:00
// make sure image 2 has repo, tag, digest
2016-06-15 01:44:49 -04:00
reWithDigest2 := regexp . MustCompile ( ` \s* ` + repoName + ` \s*tag2\s* ` + digest2 . String ( ) + ` \s ` )
2015-10-27 16:59:13 -04:00
c . Assert ( reWithDigest2 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , reWithDigest2 . String ( ) , out ) )
2015-02-26 21:23:50 -05:00
// list images
2015-07-14 02:35:36 -04:00
out , _ = dockerCmd ( c , "images" , "--digests" )
2015-02-26 21:23:50 -05:00
// make sure image 1 has repo, tag, digest
2016-06-15 01:44:49 -04:00
c . Assert ( reWithDigest1 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , reWithDigest1 . String ( ) , out ) )
2015-02-26 21:23:50 -05:00
// make sure image 2 has repo, tag, digest
2016-06-15 01:44:49 -04:00
c . Assert ( reWithDigest2 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , reWithDigest2 . String ( ) , out ) )
2015-02-26 21:23:50 -05:00
// make sure busybox has tag, but not digest
busyboxRe := regexp . MustCompile ( ` \s*busybox\s*latest\s*<none>\s ` )
2015-10-27 16:59:13 -04:00
c . Assert ( busyboxRe . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , busyboxRe . String ( ) , out ) )
2015-02-26 21:23:50 -05:00
}
2016-06-30 12:24:46 -04:00
func ( s * DockerRegistrySuite ) TestListDanglingImagesWithDigests ( c * check . C ) {
// setup image1
digest1 , err := setupImageWithTag ( c , "dangle1" )
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
imageReference1 := fmt . Sprintf ( "%s@%s" , repoName , digest1 )
c . Logf ( "imageReference1 = %s" , imageReference1 )
// pull image1 by digest
dockerCmd ( c , "pull" , imageReference1 )
// list images
out , _ := dockerCmd ( c , "images" , "--digests" )
// make sure repo shown, tag=<none>, digest = $digest1
re1 := regexp . MustCompile ( ` \s* ` + repoName + ` \s*<none>\s* ` + digest1 . String ( ) + ` \s ` )
c . Assert ( re1 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , re1 . String ( ) , out ) )
// setup image2
digest2 , err := setupImageWithTag ( c , "dangle2" )
//error setting up image
c . Assert ( err , checker . IsNil )
imageReference2 := fmt . Sprintf ( "%s@%s" , repoName , digest2 )
c . Logf ( "imageReference2 = %s" , imageReference2 )
// pull image1 by digest
dockerCmd ( c , "pull" , imageReference1 )
// pull image2 by digest
dockerCmd ( c , "pull" , imageReference2 )
// list images
2016-09-13 14:53:11 -04:00
out , _ = dockerCmd ( c , "images" , "--digests" , "--filter=dangling=true" )
2016-06-30 12:24:46 -04:00
// make sure repo shown, tag=<none>, digest = $digest1
c . Assert ( re1 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , re1 . String ( ) , out ) )
// make sure repo shown, tag=<none>, digest = $digest2
re2 := regexp . MustCompile ( ` \s* ` + repoName + ` \s*<none>\s* ` + digest2 . String ( ) + ` \s ` )
c . Assert ( re2 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , re2 . String ( ) , out ) )
// pull dangle1 tag
dockerCmd ( c , "pull" , repoName + ":dangle1" )
// list images
2016-09-13 14:53:11 -04:00
out , _ = dockerCmd ( c , "images" , "--digests" , "--filter=dangling=true" )
2016-06-30 12:24:46 -04:00
// make sure image 1 has repo, tag, <none> AND repo, <none>, digest
reWithDigest1 := regexp . MustCompile ( ` \s* ` + repoName + ` \s*dangle1\s* ` + digest1 . String ( ) + ` \s ` )
c . Assert ( reWithDigest1 . MatchString ( out ) , checker . False , check . Commentf ( "unexpected %q: %s" , reWithDigest1 . String ( ) , out ) )
// make sure image 2 has repo, <none>, digest
c . Assert ( re2 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , re2 . String ( ) , out ) )
// pull dangle2 tag
dockerCmd ( c , "pull" , repoName + ":dangle2" )
// list images, show tagged images
out , _ = dockerCmd ( c , "images" , "--digests" )
// make sure image 1 has repo, tag, digest
c . Assert ( reWithDigest1 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , reWithDigest1 . String ( ) , out ) )
// make sure image 2 has repo, tag, digest
reWithDigest2 := regexp . MustCompile ( ` \s* ` + repoName + ` \s*dangle2\s* ` + digest2 . String ( ) + ` \s ` )
c . Assert ( reWithDigest2 . MatchString ( out ) , checker . True , check . Commentf ( "expected %q: %s" , reWithDigest2 . String ( ) , out ) )
// list images, no longer dangling, should not match
2016-09-13 14:53:11 -04:00
out , _ = dockerCmd ( c , "images" , "--digests" , "--filter=dangling=true" )
2016-06-30 12:24:46 -04:00
// make sure image 1 has repo, tag, digest
c . Assert ( reWithDigest1 . MatchString ( out ) , checker . False , check . Commentf ( "unexpected %q: %s" , reWithDigest1 . String ( ) , out ) )
// make sure image 2 has repo, tag, digest
c . Assert ( reWithDigest2 . MatchString ( out ) , checker . False , check . Commentf ( "unexpected %q: %s" , reWithDigest2 . String ( ) , out ) )
}
2015-10-22 06:34:12 -04:00
func ( s * DockerRegistrySuite ) TestInspectImageWithDigests ( c * check . C ) {
digest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , check . IsNil , check . Commentf ( "error setting up image" ) )
2015-10-22 06:34:12 -04:00
imageReference := fmt . Sprintf ( "%s@%s" , repoName , digest )
// pull from the registry using the <name>@<digest> reference
dockerCmd ( c , "pull" , imageReference )
out , _ := dockerCmd ( c , "inspect" , imageReference )
var imageJSON [ ] types . ImageInspect
2015-10-27 16:59:13 -04:00
err = json . Unmarshal ( [ ] byte ( out ) , & imageJSON )
c . Assert ( err , checker . IsNil )
c . Assert ( imageJSON , checker . HasLen , 1 )
c . Assert ( imageJSON [ 0 ] . RepoDigests , checker . HasLen , 1 )
2018-03-13 15:28:34 -04:00
assert . Check ( c , is . Contains ( imageJSON [ 0 ] . RepoDigests , imageReference ) )
2015-10-22 06:34:12 -04:00
}
2015-08-20 03:57:15 -04:00
func ( s * DockerRegistrySuite ) TestPsListContainersFilterAncestorImageByDigest ( c * check . C ) {
2017-09-08 11:16:15 -04:00
existingContainers := ExistingContainerIDs ( c )
2015-08-20 03:57:15 -04:00
digest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
2015-08-20 03:57:15 -04:00
imageReference := fmt . Sprintf ( "%s@%s" , repoName , digest )
// pull from the registry using the <name>@<digest> reference
dockerCmd ( c , "pull" , imageReference )
2016-05-07 21:36:10 -04:00
// build an image from it
2015-08-20 03:57:15 -04:00
imageName1 := "images_ps_filter_test"
2017-03-23 13:35:22 -04:00
buildImageSuccessfully ( c , imageName1 , build . WithDockerfile ( fmt . Sprintf (
2015-08-20 03:57:15 -04:00
` FROM % s
2017-01-16 05:30:14 -05:00
LABEL match me 1 ` , imageReference ) ) )
2015-08-20 03:57:15 -04:00
// run a container based on that
2016-02-28 05:47:37 -05:00
dockerCmd ( c , "run" , "--name=test1" , imageReference , "echo" , "hello" )
2017-01-16 05:30:14 -05:00
expectedID := getIDByName ( c , "test1" )
2015-08-20 03:57:15 -04:00
// run a container based on the a descendant of that too
2016-02-28 05:47:37 -05:00
dockerCmd ( c , "run" , "--name=test2" , imageName1 , "echo" , "hello" )
2017-01-16 05:30:14 -05:00
expectedID1 := getIDByName ( c , "test2" )
2015-08-20 03:57:15 -04:00
expectedIDs := [ ] string { expectedID , expectedID1 }
// Invalid imageReference
2016-02-28 05:47:37 -05:00
out , _ := dockerCmd ( c , "ps" , "-a" , "-q" , "--no-trunc" , fmt . Sprintf ( "--filter=ancestor=busybox@%s" , digest ) )
2015-10-27 16:59:13 -04:00
// Filter container for ancestor filter should be empty
c . Assert ( strings . TrimSpace ( out ) , checker . Equals , "" )
2015-08-20 03:57:15 -04:00
// Valid imageReference
out , _ = dockerCmd ( c , "ps" , "-a" , "-q" , "--no-trunc" , "--filter=ancestor=" + imageReference )
2017-09-08 11:16:15 -04:00
checkPsAncestorFilterOutput ( c , RemoveOutputForExistingElements ( out , existingContainers ) , imageReference , expectedIDs )
2015-08-20 03:57:15 -04:00
}
2015-04-24 17:16:56 -04:00
func ( s * DockerRegistrySuite ) TestDeleteImageByIDOnlyPulledByDigest ( c * check . C ) {
2015-07-14 02:35:36 -04:00
pushDigest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
2015-02-26 21:23:50 -05:00
// pull from the registry using the <name>@<digest> reference
imageReference := fmt . Sprintf ( "%s@%s" , repoName , pushDigest )
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "pull" , imageReference )
2015-02-26 21:23:50 -05:00
// just in case...
2016-06-17 12:18:27 -04:00
dockerCmd ( c , "tag" , imageReference , repoName + ":sometag" )
2016-01-28 09:19:25 -05:00
imageID := inspectField ( c , imageReference , "Id" )
2015-02-26 21:23:50 -05:00
2015-07-14 02:35:36 -04:00
dockerCmd ( c , "rmi" , imageID )
2016-06-17 12:18:27 -04:00
_ , err = inspectFieldWithError ( imageID , "Id" )
c . Assert ( err , checker . NotNil , check . Commentf ( "image should have been deleted" ) )
2015-02-26 21:23:50 -05:00
}
2015-08-01 02:27:19 -04:00
2016-01-06 20:57:21 -05:00
func ( s * DockerRegistrySuite ) TestDeleteImageWithDigestAndTag ( c * check . C ) {
pushDigest , err := setupImage ( c )
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
// pull from the registry using the <name>@<digest> reference
imageReference := fmt . Sprintf ( "%s@%s" , repoName , pushDigest )
dockerCmd ( c , "pull" , imageReference )
2016-01-28 09:19:25 -05:00
imageID := inspectField ( c , imageReference , "Id" )
2016-01-06 20:57:21 -05:00
repoTag := repoName + ":sometag"
repoTag2 := repoName + ":othertag"
dockerCmd ( c , "tag" , imageReference , repoTag )
dockerCmd ( c , "tag" , imageReference , repoTag2 )
dockerCmd ( c , "rmi" , repoTag2 )
// rmi should have deleted only repoTag2, because there's another tag
2016-01-28 09:19:25 -05:00
inspectField ( c , repoTag , "Id" )
2016-01-06 20:57:21 -05:00
dockerCmd ( c , "rmi" , repoTag )
// rmi should have deleted the tag, the digest reference, and the image itself
2016-01-28 09:19:25 -05:00
_ , err = inspectFieldWithError ( imageID , "Id" )
2016-01-06 20:57:21 -05:00
c . Assert ( err , checker . NotNil , check . Commentf ( "image should have been deleted" ) )
}
2016-06-17 12:18:27 -04:00
func ( s * DockerRegistrySuite ) TestDeleteImageWithDigestAndMultiRepoTag ( c * check . C ) {
pushDigest , err := setupImage ( c )
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
repo2 := fmt . Sprintf ( "%s/%s" , repoName , "repo2" )
// pull from the registry using the <name>@<digest> reference
imageReference := fmt . Sprintf ( "%s@%s" , repoName , pushDigest )
dockerCmd ( c , "pull" , imageReference )
imageID := inspectField ( c , imageReference , "Id" )
repoTag := repoName + ":sometag"
repoTag2 := repo2 + ":othertag"
dockerCmd ( c , "tag" , imageReference , repoTag )
dockerCmd ( c , "tag" , imageReference , repoTag2 )
dockerCmd ( c , "rmi" , repoTag )
// rmi should have deleted repoTag and image reference, but left repoTag2
inspectField ( c , repoTag2 , "Id" )
_ , err = inspectFieldWithError ( imageReference , "Id" )
c . Assert ( err , checker . NotNil , check . Commentf ( "image digest reference should have been removed" ) )
_ , err = inspectFieldWithError ( repoTag , "Id" )
c . Assert ( err , checker . NotNil , check . Commentf ( "image tag reference should have been removed" ) )
dockerCmd ( c , "rmi" , repoTag2 )
// rmi should have deleted the tag, the digest reference, and the image itself
_ , err = inspectFieldWithError ( imageID , "Id" )
c . Assert ( err , checker . NotNil , check . Commentf ( "image should have been deleted" ) )
}
2015-08-01 02:27:19 -04:00
// TestPullFailsWithAlteredManifest tests that a `docker pull` fails when
// we have modified a manifest blob and its digest cannot be verified.
2015-12-18 18:06:23 -05:00
// This is the schema2 version of the test.
2015-08-01 02:27:19 -04:00
func ( s * DockerRegistrySuite ) TestPullFailsWithAlteredManifest ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-08-01 02:27:19 -04:00
manifestDigest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
2015-08-01 02:27:19 -04:00
// Load the target manifest blob.
2016-12-30 13:10:04 -05:00
manifestBlob := s . reg . ReadBlobContents ( c , manifestDigest )
2015-08-01 02:27:19 -04:00
2015-12-18 18:06:23 -05:00
var imgManifest schema2 . Manifest
err = json . Unmarshal ( manifestBlob , & imgManifest )
c . Assert ( err , checker . IsNil , check . Commentf ( "unable to decode image manifest from blob" ) )
// Change a layer in the manifest.
imgManifest . Layers [ 0 ] . Digest = digest . Digest ( "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" )
// Move the existing data file aside, so that we can replace it with a
// malicious blob of data. NOTE: we defer the returned undo func.
2016-12-30 13:10:04 -05:00
undo := s . reg . TempMoveBlobData ( c , manifestDigest )
2015-12-18 18:06:23 -05:00
defer undo ( )
alteredManifestBlob , err := json . MarshalIndent ( imgManifest , "" , " " )
c . Assert ( err , checker . IsNil , check . Commentf ( "unable to encode altered image manifest to JSON" ) )
2016-12-30 13:10:04 -05:00
s . reg . WriteBlobContents ( c , manifestDigest , alteredManifestBlob )
2015-12-18 18:06:23 -05:00
// Now try pulling that image by digest. We should get an error about
// digest verification for the manifest digest.
// Pull from the registry using the <name>@<digest> reference.
imageReference := fmt . Sprintf ( "%s@%s" , repoName , manifestDigest )
out , exitStatus , _ := dockerCmdWithError ( "pull" , imageReference )
c . Assert ( exitStatus , checker . Not ( check . Equals ) , 0 )
expectedErrorMsg := fmt . Sprintf ( "manifest verification failed for digest %s" , manifestDigest )
c . Assert ( out , checker . Contains , expectedErrorMsg )
}
// TestPullFailsWithAlteredManifest tests that a `docker pull` fails when
// we have modified a manifest blob and its digest cannot be verified.
// This is the schema1 version of the test.
func ( s * DockerSchema1RegistrySuite ) TestPullFailsWithAlteredManifest ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
manifestDigest , err := setupImage ( c )
c . Assert ( err , checker . IsNil , check . Commentf ( "error setting up image" ) )
// Load the target manifest blob.
2016-12-30 13:10:04 -05:00
manifestBlob := s . reg . ReadBlobContents ( c , manifestDigest )
2015-12-18 18:06:23 -05:00
2015-10-30 20:46:25 -04:00
var imgManifest schema1 . Manifest
2015-10-27 16:59:13 -04:00
err = json . Unmarshal ( manifestBlob , & imgManifest )
c . Assert ( err , checker . IsNil , check . Commentf ( "unable to decode image manifest from blob" ) )
2015-08-01 02:27:19 -04:00
2015-10-30 20:46:25 -04:00
// Change a layer in the manifest.
imgManifest . FSLayers [ 0 ] = schema1 . FSLayer {
2015-08-01 02:27:19 -04:00
BlobSum : digest . Digest ( "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" ) ,
2015-10-30 20:46:25 -04:00
}
2015-08-01 02:27:19 -04:00
// Move the existing data file aside, so that we can replace it with a
// malicious blob of data. NOTE: we defer the returned undo func.
2016-12-30 13:10:04 -05:00
undo := s . reg . TempMoveBlobData ( c , manifestDigest )
2015-08-01 02:27:19 -04:00
defer undo ( )
2015-10-30 20:46:25 -04:00
alteredManifestBlob , err := json . MarshalIndent ( imgManifest , "" , " " )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil , check . Commentf ( "unable to encode altered image manifest to JSON" ) )
2015-08-01 02:27:19 -04:00
2016-12-30 13:10:04 -05:00
s . reg . WriteBlobContents ( c , manifestDigest , alteredManifestBlob )
2015-08-01 02:27:19 -04:00
// Now try pulling that image by digest. We should get an error about
// digest verification for the manifest digest.
// Pull from the registry using the <name>@<digest> reference.
imageReference := fmt . Sprintf ( "%s@%s" , repoName , manifestDigest )
out , exitStatus , _ := dockerCmdWithError ( "pull" , imageReference )
2015-10-27 16:59:13 -04:00
c . Assert ( exitStatus , checker . Not ( check . Equals ) , 0 )
2015-08-01 02:27:19 -04:00
expectedErrorMsg := fmt . Sprintf ( "image verification failed for digest %s" , manifestDigest )
2015-10-27 16:59:13 -04:00
c . Assert ( out , checker . Contains , expectedErrorMsg )
2015-08-01 02:27:19 -04:00
}
// TestPullFailsWithAlteredLayer tests that a `docker pull` fails when
// we have modified a layer blob and its digest cannot be verified.
2015-12-18 18:06:23 -05:00
// This is the schema2 version of the test.
2015-08-01 02:27:19 -04:00
func ( s * DockerRegistrySuite ) TestPullFailsWithAlteredLayer ( c * check . C ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-08-01 02:27:19 -04:00
manifestDigest , err := setupImage ( c )
2015-10-27 16:59:13 -04:00
c . Assert ( err , checker . IsNil )
2015-08-01 02:27:19 -04:00
// Load the target manifest blob.
2016-12-30 13:10:04 -05:00
manifestBlob := s . reg . ReadBlobContents ( c , manifestDigest )
2015-08-01 02:27:19 -04:00
2015-12-18 18:06:23 -05:00
var imgManifest schema2 . Manifest
err = json . Unmarshal ( manifestBlob , & imgManifest )
c . Assert ( err , checker . IsNil )
// Next, get the digest of one of the layers from the manifest.
targetLayerDigest := imgManifest . Layers [ 0 ] . Digest
// Move the existing data file aside, so that we can replace it with a
// malicious blob of data. NOTE: we defer the returned undo func.
2016-12-30 13:10:04 -05:00
undo := s . reg . TempMoveBlobData ( c , targetLayerDigest )
2015-12-18 18:06:23 -05:00
defer undo ( )
// Now make a fake data blob in this directory.
2016-12-30 13:10:04 -05:00
s . reg . WriteBlobContents ( c , targetLayerDigest , [ ] byte ( "This is not the data you are looking for." ) )
2015-12-18 18:06:23 -05:00
// Now try pulling that image by digest. We should get an error about
// digest verification for the target layer digest.
// Remove distribution cache to force a re-pull of the blobs
2018-01-15 09:28:10 -05:00
if err := os . RemoveAll ( filepath . Join ( testEnv . DaemonInfo . DockerRootDir , "image" , s . d . StorageDriver ( ) , "distribution" ) ) ; err != nil {
2015-12-18 18:06:23 -05:00
c . Fatalf ( "error clearing distribution cache: %v" , err )
}
// Pull from the registry using the <name>@<digest> reference.
imageReference := fmt . Sprintf ( "%s@%s" , repoName , manifestDigest )
out , exitStatus , _ := dockerCmdWithError ( "pull" , imageReference )
2016-06-21 04:21:13 -04:00
c . Assert ( exitStatus , checker . Not ( check . Equals ) , 0 , check . Commentf ( "expected a non-zero exit status" ) )
2015-12-18 18:06:23 -05:00
expectedErrorMsg := fmt . Sprintf ( "filesystem layer verification failed for digest %s" , targetLayerDigest )
c . Assert ( out , checker . Contains , expectedErrorMsg , check . Commentf ( "expected error message in output: %s" , out ) )
}
// TestPullFailsWithAlteredLayer tests that a `docker pull` fails when
// we have modified a layer blob and its digest cannot be verified.
// This is the schema1 version of the test.
func ( s * DockerSchema1RegistrySuite ) TestPullFailsWithAlteredLayer ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
manifestDigest , err := setupImage ( c )
c . Assert ( err , checker . IsNil )
// Load the target manifest blob.
2016-12-30 13:10:04 -05:00
manifestBlob := s . reg . ReadBlobContents ( c , manifestDigest )
2015-12-18 18:06:23 -05:00
2015-10-30 20:46:25 -04:00
var imgManifest schema1 . Manifest
2015-10-27 16:59:13 -04:00
err = json . Unmarshal ( manifestBlob , & imgManifest )
c . Assert ( err , checker . IsNil )
2015-08-01 02:27:19 -04:00
// Next, get the digest of one of the layers from the manifest.
targetLayerDigest := imgManifest . FSLayers [ 0 ] . BlobSum
// Move the existing data file aside, so that we can replace it with a
// malicious blob of data. NOTE: we defer the returned undo func.
2016-12-30 13:10:04 -05:00
undo := s . reg . TempMoveBlobData ( c , targetLayerDigest )
2015-08-01 02:27:19 -04:00
defer undo ( )
// Now make a fake data blob in this directory.
2016-12-30 13:10:04 -05:00
s . reg . WriteBlobContents ( c , targetLayerDigest , [ ] byte ( "This is not the data you are looking for." ) )
2015-08-01 02:27:19 -04:00
// Now try pulling that image by digest. We should get an error about
// digest verification for the target layer digest.
2015-11-18 17:20:54 -05:00
// Remove distribution cache to force a re-pull of the blobs
2018-01-15 09:28:10 -05:00
if err := os . RemoveAll ( filepath . Join ( testEnv . DaemonInfo . DockerRootDir , "image" , s . d . StorageDriver ( ) , "distribution" ) ) ; err != nil {
2015-11-18 17:20:54 -05:00
c . Fatalf ( "error clearing distribution cache: %v" , err )
}
2015-08-01 02:27:19 -04:00
// Pull from the registry using the <name>@<digest> reference.
imageReference := fmt . Sprintf ( "%s@%s" , repoName , manifestDigest )
out , exitStatus , _ := dockerCmdWithError ( "pull" , imageReference )
2016-06-21 04:21:13 -04:00
c . Assert ( exitStatus , checker . Not ( check . Equals ) , 0 , check . Commentf ( "expected a non-zero exit status" ) )
2015-08-01 02:27:19 -04:00
expectedErrorMsg := fmt . Sprintf ( "filesystem layer verification failed for digest %s" , targetLayerDigest )
2015-10-27 16:59:13 -04:00
c . Assert ( out , checker . Contains , expectedErrorMsg , check . Commentf ( "expected error message in output: %s" , out ) )
2015-08-01 02:27:19 -04:00
}