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"
2019-06-17 17:50:31 -04:00
"os"
"path/filepath"
2015-02-26 21:23:50 -05:00
"regexp"
"strings"
2019-09-09 17:06:12 -04:00
"testing"
2015-02-26 21:23:50 -05:00
2019-06-17 17:50:31 -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"
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"
2022-03-04 08:49:42 -05:00
"github.com/opencontainers/go-digest"
2020-02-07 08:39:24 -05:00
"gotest.tools/v3/assert"
is "gotest.tools/v3/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 )
2019-08-05 10:53:46 -04:00
pushDigestRegex = regexp . MustCompile ( ` [\S]+: digest: ([\S]+) size: [0-9]+ ` )
digestRegex = regexp . MustCompile ( ` Digest: ([\S]+) ` )
2015-02-26 21:23:50 -05:00
)
2019-09-09 17:05:55 -04:00
func setupImage ( c * testing . T ) ( digest . Digest , error ) {
2015-07-14 02:35:36 -04:00
return setupImageWithTag ( c , "latest" )
2015-02-26 21:23:50 -05:00
}
2019-09-09 17:05:55 -04:00
func setupImageWithTag ( c * testing . T , 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 )
2019-04-04 09:23:19 -04:00
assert . Equal ( c , len ( matches ) , 2 , "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
}
2019-09-09 17:05:55 -04:00
func testPullByTagDisplaysDigest ( c * testing . T ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
pushDigest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "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 )
2019-04-04 09:23:19 -04:00
assert . Equal ( c , len ( matches ) , 2 , "unable to parse digest from push output: %s" , out )
2015-02-26 21:23:50 -05:00
pullDigest := matches [ 1 ]
// make sure the pushed and pull digests match
2019-09-09 17:05:56 -04:00
assert . Equal ( c , pushDigest . String ( ) , pullDigest )
2015-02-26 21:23:50 -05:00
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestPullByTagDisplaysDigest ( c * testing . T ) {
2015-12-18 18:06:23 -05:00
testPullByTagDisplaysDigest ( c )
}
2019-09-09 17:05:55 -04:00
func ( s * DockerSchema1RegistrySuite ) TestPullByTagDisplaysDigest ( c * testing . T ) {
2019-06-17 17:50:31 -04:00
testPullByTagDisplaysDigest ( c )
}
2019-09-09 17:05:55 -04:00
func testPullByDigest ( c * testing . T ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-07-14 02:35:36 -04:00
pushDigest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "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 )
2019-04-04 09:23:19 -04:00
assert . Equal ( c , len ( matches ) , 2 , "unable to parse digest from push output: %s" , out )
2015-02-26 21:23:50 -05:00
pullDigest := matches [ 1 ]
// make sure the pushed and pull digests match
2019-09-09 17:05:56 -04:00
assert . Equal ( c , pushDigest . String ( ) , pullDigest )
2015-02-26 21:23:50 -05:00
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestPullByDigest ( c * testing . T ) {
2015-12-18 18:06:23 -05:00
testPullByDigest ( c )
}
2019-09-09 17:05:55 -04:00
func ( s * DockerSchema1RegistrySuite ) TestPullByDigest ( c * testing . T ) {
2019-06-17 17:50:31 -04:00
testPullByDigest ( c )
}
2019-09-09 17:05:55 -04:00
func testPullByDigestNoFallback ( c * testing . T ) {
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 )
2019-09-09 17:08:22 -04:00
assert . Assert ( c , err != nil , "expected non-zero exit status and correct error message when pulling non-existing image" )
assert . Assert ( c , strings . Contains ( out , fmt . Sprintf ( "manifest for %s not found" , imageReference ) ) , "expected non-zero exit status and correct error message when pulling non-existing image" )
2015-04-29 15:29:50 -04:00
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestPullByDigestNoFallback ( c * testing . T ) {
2015-12-18 18:06:23 -05:00
testPullByDigestNoFallback ( c )
}
2019-09-09 17:05:55 -04:00
func ( s * DockerSchema1RegistrySuite ) TestPullByDigestNoFallback ( c * testing . T ) {
2019-06-17 17:50:31 -04:00
testPullByDigestNoFallback ( c )
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestCreateByDigest ( c * testing . T ) {
2015-07-14 02:35:36 -04:00
pushDigest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "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" )
2019-04-04 09:23:19 -04:00
assert . Equal ( c , res , imageReference )
2015-02-26 21:23:50 -05:00
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestRunByDigest ( c * testing . T ) {
2015-07-14 02:35:36 -04:00
pushDigest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
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 )
2019-09-09 17:08:22 -04:00
assert . Equal ( c , len ( matches ) , 2 , fmt . Sprintf ( "unable to parse digest from pull output: %s" , out ) )
assert . Equal ( c , matches [ 1 ] , "1" , fmt . Sprintf ( "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" )
2019-04-04 09:23:19 -04:00
assert . Equal ( c , res , imageReference )
2015-02-26 21:23:50 -05:00
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestRemoveImageByDigest ( c * testing . T ) {
2015-07-14 02:35:36 -04:00
digest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "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 )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "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" )
2019-11-27 09:36:45 -05:00
// unexpected nil err trying to inspect what should be a non-existent image
2019-04-04 09:23:19 -04:00
assert . ErrorContains ( c , err , "No such object" )
2015-02-26 21:23:50 -05:00
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestBuildByDigest ( c * testing . T ) {
2015-07-14 02:35:36 -04:00
digest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "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 ) ) )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
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
2019-04-04 09:23:19 -04:00
assert . Equal ( c , res , imageID )
2015-02-26 21:23:50 -05:00
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestTagByDigest ( c * testing . T ) {
2015-07-14 02:35:36 -04:00
digest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "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" )
2019-04-04 09:23:19 -04:00
assert . Equal ( c , tagID , expectedID )
2015-02-26 21:23:50 -05:00
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestListImagesWithoutDigests ( c * testing . T ) {
2015-07-14 02:35:36 -04:00
digest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "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" )
2019-09-09 17:08:22 -04:00
assert . Assert ( c , ! strings . Contains ( out , "DIGEST" ) , "list output should not have contained DIGEST header" )
2015-02-26 21:23:50 -05:00
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestListImagesWithDigests ( c * testing . T ) {
2015-02-26 21:23:50 -05:00
// setup image1
2015-07-14 02:35:36 -04:00
digest1 , err := setupImageWithTag ( c , "tag1" )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "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 ` )
2019-09-11 06:57:29 -04:00
assert . Assert ( c , re1 . MatchString ( out ) , "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" )
2019-11-27 09:36:45 -05:00
assert . NilError ( c , err , "error setting up image" )
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
2019-09-11 06:57:29 -04:00
assert . Assert ( c , re1 . MatchString ( out ) , "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 ` )
2019-09-11 06:57:29 -04:00
assert . Assert ( c , re2 . MatchString ( out ) , "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 ` )
2019-09-11 06:57:29 -04:00
assert . Assert ( c , reWithDigest1 . MatchString ( out ) , "expected %q: %s" , reWithDigest1 . String ( ) , out )
2015-02-26 21:23:50 -05:00
// make sure image 2 has repo, <none>, digest
2019-09-11 06:57:29 -04:00
assert . Assert ( c , re2 . MatchString ( out ) , "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
2019-09-11 06:57:29 -04:00
assert . Assert ( c , reWithDigest1 . MatchString ( out ) , "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 ` )
2019-09-11 06:57:29 -04:00
assert . Assert ( c , reWithDigest2 . MatchString ( out ) , "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
2019-09-11 06:57:29 -04:00
assert . Assert ( c , reWithDigest1 . MatchString ( out ) , "expected %q: %s" , reWithDigest1 . String ( ) , out )
2015-02-26 21:23:50 -05:00
// make sure image 2 has repo, tag, digest
2019-09-11 06:57:29 -04:00
assert . Assert ( c , reWithDigest2 . MatchString ( out ) , "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 ` )
2019-09-11 06:57:29 -04:00
assert . Assert ( c , busyboxRe . MatchString ( out ) , "expected %q: %s" , busyboxRe . String ( ) , out )
2015-02-26 21:23:50 -05:00
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestListDanglingImagesWithDigests ( c * testing . T ) {
2016-06-30 12:24:46 -04:00
// setup image1
digest1 , err := setupImageWithTag ( c , "dangle1" )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "error setting up image" )
2016-06-30 12:24:46 -04:00
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 ` )
2019-09-11 06:57:29 -04:00
assert . Assert ( c , re1 . MatchString ( out ) , "expected %q: %s" , re1 . String ( ) , out )
2016-06-30 12:24:46 -04:00
// setup image2
digest2 , err := setupImageWithTag ( c , "dangle2" )
//error setting up image
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
2016-06-30 12:24:46 -04:00
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
2019-09-11 06:57:29 -04:00
assert . Assert ( c , re1 . MatchString ( out ) , "expected %q: %s" , re1 . String ( ) , out )
2016-06-30 12:24:46 -04:00
// make sure repo shown, tag=<none>, digest = $digest2
re2 := regexp . MustCompile ( ` \s* ` + repoName + ` \s*<none>\s* ` + digest2 . String ( ) + ` \s ` )
2019-09-11 06:57:29 -04:00
assert . Assert ( c , re2 . MatchString ( out ) , "expected %q: %s" , re2 . String ( ) , out )
2016-06-30 12:24:46 -04:00
// 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 ` )
2019-09-11 06:57:29 -04:00
assert . Assert ( c , ! reWithDigest1 . MatchString ( out ) , "unexpected %q: %s" , reWithDigest1 . String ( ) , out )
2016-06-30 12:24:46 -04:00
// make sure image 2 has repo, <none>, digest
2019-09-11 06:57:29 -04:00
assert . Assert ( c , re2 . MatchString ( out ) , "expected %q: %s" , re2 . String ( ) , out )
2016-06-30 12:24:46 -04:00
// 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
2019-09-11 06:57:29 -04:00
assert . Assert ( c , reWithDigest1 . MatchString ( out ) , "expected %q: %s" , reWithDigest1 . String ( ) , out )
2016-06-30 12:24:46 -04:00
// make sure image 2 has repo, tag, digest
reWithDigest2 := regexp . MustCompile ( ` \s* ` + repoName + ` \s*dangle2\s* ` + digest2 . String ( ) + ` \s ` )
2019-09-11 06:57:29 -04:00
assert . Assert ( c , reWithDigest2 . MatchString ( out ) , "expected %q: %s" , reWithDigest2 . String ( ) , out )
2016-06-30 12:24:46 -04:00
// 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
2019-09-11 06:57:29 -04:00
assert . Assert ( c , ! reWithDigest1 . MatchString ( out ) , "unexpected %q: %s" , reWithDigest1 . String ( ) , out )
2016-06-30 12:24:46 -04:00
// make sure image 2 has repo, tag, digest
2019-09-11 06:57:29 -04:00
assert . Assert ( c , ! reWithDigest2 . MatchString ( out ) , "unexpected %q: %s" , reWithDigest2 . String ( ) , out )
2016-06-30 12:24:46 -04:00
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestInspectImageWithDigests ( c * testing . T ) {
2015-10-22 06:34:12 -04:00
digest , err := setupImage ( c )
2019-09-09 17:08:22 -04:00
assert . Assert ( c , err == nil , "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 )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err )
2019-09-09 17:05:57 -04:00
assert . Equal ( c , len ( imageJSON ) , 1 )
assert . Equal ( c , len ( imageJSON [ 0 ] . RepoDigests ) , 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
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestPsListContainersFilterAncestorImageByDigest ( c * testing . T ) {
2017-09-08 11:16:15 -04:00
existingContainers := ExistingContainerIDs ( c )
2015-08-20 03:57:15 -04:00
digest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "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 ) )
2019-04-04 09:23:19 -04:00
assert . Equal ( c , strings . TrimSpace ( out ) , "" , "Filter container for ancestor filter should be empty" )
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
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestDeleteImageByIDOnlyPulledByDigest ( c * testing . T ) {
2015-07-14 02:35:36 -04:00
pushDigest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "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" )
2019-04-04 09:23:19 -04:00
assert . ErrorContains ( c , err , "" , "image should have been deleted" )
2015-02-26 21:23:50 -05:00
}
2015-08-01 02:27:19 -04:00
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestDeleteImageWithDigestAndTag ( c * testing . T ) {
2016-01-06 20:57:21 -05:00
pushDigest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "error setting up image" )
2016-01-06 20:57:21 -05:00
// 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" )
2019-04-04 09:23:19 -04:00
assert . ErrorContains ( c , err , "" , "image should have been deleted" )
2016-01-06 20:57:21 -05:00
}
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestDeleteImageWithDigestAndMultiRepoTag ( c * testing . T ) {
2016-06-17 12:18:27 -04:00
pushDigest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "error setting up image" )
2016-06-17 12:18:27 -04:00
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" )
2019-04-04 09:23:19 -04:00
assert . ErrorContains ( c , err , "" , "image digest reference should have been removed" )
2016-06-17 12:18:27 -04:00
_ , err = inspectFieldWithError ( repoTag , "Id" )
2019-04-04 09:23:19 -04:00
assert . ErrorContains ( c , err , "" , "image tag reference should have been removed" )
2016-06-17 12:18:27 -04:00
dockerCmd ( c , "rmi" , repoTag2 )
// rmi should have deleted the tag, the digest reference, and the image itself
_ , err = inspectFieldWithError ( imageID , "Id" )
2019-04-04 09:23:19 -04:00
assert . ErrorContains ( c , err , "" , "image should have been deleted" )
2016-06-17 12:18:27 -04:00
}
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.
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestPullFailsWithAlteredManifest ( c * testing . T ) {
2015-08-28 13:36:42 -04:00
testRequires ( c , DaemonIsLinux )
2015-08-01 02:27:19 -04:00
manifestDigest , err := setupImage ( c )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "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 )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "unable to decode image manifest from blob" )
2015-12-18 18:06:23 -05:00
// 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 , "" , " " )
2019-04-04 09:23:19 -04:00
assert . NilError ( c , err , "unable to encode altered image manifest to JSON" )
2015-12-18 18:06:23 -05:00
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 )
2019-09-09 17:05:56 -04:00
assert . Assert ( c , exitStatus != 0 )
2015-12-18 18:06:23 -05:00
expectedErrorMsg := fmt . Sprintf ( "manifest verification failed for digest %s" , manifestDigest )
2019-04-04 09:23:19 -04:00
assert . Assert ( c , is . Contains ( out , expectedErrorMsg ) )
2015-12-18 18:06:23 -05:00
}
2019-06-17 17:50:31 -04:00
// 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.
2019-09-09 17:05:55 -04:00
func ( s * DockerSchema1RegistrySuite ) TestPullFailsWithAlteredManifest ( c * testing . T ) {
2019-06-17 17:50:31 -04:00
testRequires ( c , DaemonIsLinux )
manifestDigest , err := setupImage ( c )
2019-09-09 17:08:22 -04:00
assert . Assert ( c , err == nil , "error setting up image" )
2019-06-17 17:50:31 -04:00
// Load the target manifest blob.
manifestBlob := s . reg . ReadBlobContents ( c , manifestDigest )
var imgManifest schema1 . Manifest
err = json . Unmarshal ( manifestBlob , & imgManifest )
2019-09-09 17:08:22 -04:00
assert . Assert ( c , err == nil , "unable to decode image manifest from blob" )
2019-06-17 17:50:31 -04:00
// Change a layer in the manifest.
imgManifest . FSLayers [ 0 ] = schema1 . FSLayer {
BlobSum : 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.
undo := s . reg . TempMoveBlobData ( c , manifestDigest )
defer undo ( )
alteredManifestBlob , err := json . MarshalIndent ( imgManifest , "" , " " )
2019-09-09 17:08:22 -04:00
assert . Assert ( c , err == nil , "unable to encode altered image manifest to JSON" )
2019-06-17 17:50:31 -04:00
s . reg . WriteBlobContents ( c , manifestDigest , alteredManifestBlob )
// 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 )
2019-09-09 17:05:56 -04:00
assert . Assert ( c , exitStatus != 0 )
2019-06-17 17:50:31 -04:00
expectedErrorMsg := fmt . Sprintf ( "image verification failed for digest %s" , manifestDigest )
2019-09-09 17:08:22 -04:00
assert . Assert ( c , strings . Contains ( out , expectedErrorMsg ) )
2019-06-17 17:50:31 -04:00
}
// TestPullFailsWithAlteredLayer tests that a `docker pull` fails when
// we have modified a layer blob and its digest cannot be verified.
// This is the schema2 version of the test.
2019-09-09 17:05:55 -04:00
func ( s * DockerRegistrySuite ) TestPullFailsWithAlteredLayer ( c * testing . T ) {
2019-06-17 17:50:31 -04:00
testRequires ( c , DaemonIsLinux )
manifestDigest , err := setupImage ( c )
2019-09-09 17:05:57 -04:00
assert . Assert ( c , err == nil )
2019-06-17 17:50:31 -04:00
// Load the target manifest blob.
manifestBlob := s . reg . ReadBlobContents ( c , manifestDigest )
var imgManifest schema2 . Manifest
err = json . Unmarshal ( manifestBlob , & imgManifest )
2019-09-09 17:05:57 -04:00
assert . Assert ( c , err == nil )
2019-06-17 17:50:31 -04:00
// 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.
undo := s . reg . TempMoveBlobData ( c , targetLayerDigest )
defer undo ( )
// Now make a fake data blob in this directory.
s . reg . WriteBlobContents ( c , targetLayerDigest , [ ] byte ( "This is not the data you are looking for." ) )
// 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
if err := os . RemoveAll ( filepath . Join ( testEnv . DaemonInfo . DockerRootDir , "image" , s . d . StorageDriver ( ) , "distribution" ) ) ; err != nil {
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 )
2019-09-09 17:08:22 -04:00
assert . Assert ( c , exitStatus != 0 , "expected a non-zero exit status" )
2019-06-17 17:50:31 -04:00
expectedErrorMsg := fmt . Sprintf ( "filesystem layer verification failed for digest %s" , targetLayerDigest )
2019-09-11 06:57:29 -04:00
assert . Assert ( c , strings . Contains ( out , expectedErrorMsg ) , "expected error message in output: %s" , out )
2019-06-17 17:50:31 -04:00
}
// 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.
2019-09-09 17:05:55 -04:00
func ( s * DockerSchema1RegistrySuite ) TestPullFailsWithAlteredLayer ( c * testing . T ) {
2019-06-17 17:50:31 -04:00
testRequires ( c , DaemonIsLinux )
manifestDigest , err := setupImage ( c )
2019-09-09 17:05:57 -04:00
assert . Assert ( c , err == nil )
2019-06-17 17:50:31 -04:00
// Load the target manifest blob.
manifestBlob := s . reg . ReadBlobContents ( c , manifestDigest )
var imgManifest schema1 . Manifest
err = json . Unmarshal ( manifestBlob , & imgManifest )
2019-09-09 17:05:57 -04:00
assert . Assert ( c , err == nil )
2019-06-17 17:50:31 -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.
undo := s . reg . TempMoveBlobData ( c , targetLayerDigest )
defer undo ( )
// Now make a fake data blob in this directory.
s . reg . WriteBlobContents ( c , targetLayerDigest , [ ] byte ( "This is not the data you are looking for." ) )
// 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
if err := os . RemoveAll ( filepath . Join ( testEnv . DaemonInfo . DockerRootDir , "image" , s . d . StorageDriver ( ) , "distribution" ) ) ; err != nil {
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 )
2019-09-09 17:08:22 -04:00
assert . Assert ( c , exitStatus != 0 , "expected a non-zero exit status" )
2019-06-17 17:50:31 -04:00
expectedErrorMsg := fmt . Sprintf ( "filesystem layer verification failed for digest %s" , targetLayerDigest )
2019-09-11 06:57:29 -04:00
assert . Assert ( c , strings . Contains ( out , expectedErrorMsg ) , "expected error message in output: %s" , out )
2019-06-17 17:50:31 -04:00
}