integration-cli: DockerRegistrySuite: replace dockerCmd

Also renaming vars that collided with package-level vars
and using consts for fixed values.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2023-07-27 20:01:09 +02:00
parent c867ac4527
commit 89d7b77022
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
5 changed files with 214 additions and 202 deletions

View file

@ -20,9 +20,12 @@ import (
"gotest.tools/v3/skip" "gotest.tools/v3/skip"
) )
const (
remoteRepoName = "dockercli/busybox-by-dgst"
repoName = privateRegistryURL + "/" + remoteRepoName
)
var ( var (
remoteRepoName = "dockercli/busybox-by-dgst"
repoName = fmt.Sprintf("%s/%s", privateRegistryURL, remoteRepoName)
pushDigestRegex = regexp.MustCompile(`[\S]+: digest: ([\S]+) size: [0-9]+`) pushDigestRegex = regexp.MustCompile(`[\S]+: digest: ([\S]+) size: [0-9]+`)
digestRegex = regexp.MustCompile(`Digest: ([\S]+)`) digestRegex = regexp.MustCompile(`Digest: ([\S]+)`)
) )
@ -32,7 +35,7 @@ func setupImage(c *testing.T) (digest.Digest, error) {
} }
func setupImageWithTag(c *testing.T, tag string) (digest.Digest, error) { func setupImageWithTag(c *testing.T, tag string) (digest.Digest, error) {
containerName := "busyboxbydigest" const containerName = "busyboxbydigest"
// new file is committed because this layer is used for detecting malicious // 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 // changes. if this was committed as empty layer it would be skipped on pull
@ -65,7 +68,7 @@ func testPullByTagDisplaysDigest(c *testing.T) {
assert.NilError(c, err, "error setting up image") assert.NilError(c, err, "error setting up image")
// pull from the registry using the tag // pull from the registry using the tag
out, _ := dockerCmd(c, "pull", repoName) out := cli.DockerCmd(c, "pull", repoName).Combined()
// the pull output includes "Digest: <digest>", so find that // the pull output includes "Digest: <digest>", so find that
matches := digestRegex.FindStringSubmatch(out) matches := digestRegex.FindStringSubmatch(out)
@ -91,7 +94,7 @@ func testPullByDigest(c *testing.T) {
// pull from the registry using the <name>@<digest> reference // pull from the registry using the <name>@<digest> reference
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest) imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
out, _ := dockerCmd(c, "pull", imageReference) out := cli.DockerCmd(c, "pull", imageReference).Combined()
// the pull output includes "Digest: <digest>", so find that // the pull output includes "Digest: <digest>", so find that
matches := digestRegex.FindStringSubmatch(out) matches := digestRegex.FindStringSubmatch(out)
@ -139,8 +142,8 @@ func (s *DockerRegistrySuite) TestCreateByDigest(c *testing.T) {
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest) imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
containerName := "createByDigest" const containerName = "createByDigest"
dockerCmd(c, "create", "--name", containerName, imageReference) cli.DockerCmd(c, "create", "--name", containerName, imageReference)
res := inspectField(c, containerName, "Config.Image") res := inspectField(c, containerName, "Config.Image")
assert.Equal(c, res, imageReference) assert.Equal(c, res, imageReference)
@ -152,8 +155,8 @@ func (s *DockerRegistrySuite) TestRunByDigest(c *testing.T) {
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest) imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
containerName := "runByDigest" const containerName = "runByDigest"
out, _ := dockerCmd(c, "run", "--name", containerName, imageReference, "sh", "-c", "echo found=$digest") out := cli.DockerCmd(c, "run", "--name", containerName, imageReference, "sh", "-c", "echo found=$digest").Combined()
foundRegex := regexp.MustCompile("found=([^\n]+)") foundRegex := regexp.MustCompile("found=([^\n]+)")
matches := foundRegex.FindStringSubmatch(out) matches := foundRegex.FindStringSubmatch(out)
@ -165,13 +168,13 @@ func (s *DockerRegistrySuite) TestRunByDigest(c *testing.T) {
} }
func (s *DockerRegistrySuite) TestRemoveImageByDigest(c *testing.T) { func (s *DockerRegistrySuite) TestRemoveImageByDigest(c *testing.T) {
digest, err := setupImage(c) imgDigest, err := setupImage(c)
assert.NilError(c, err, "error setting up image") assert.NilError(c, err, "error setting up image")
imageReference := fmt.Sprintf("%s@%s", repoName, digest) imageReference := fmt.Sprintf("%s@%s", repoName, imgDigest)
// pull from the registry using the <name>@<digest> reference // pull from the registry using the <name>@<digest> reference
dockerCmd(c, "pull", imageReference) cli.DockerCmd(c, "pull", imageReference)
// make sure inspect runs ok // make sure inspect runs ok
inspectField(c, imageReference, "Id") inspectField(c, imageReference, "Id")
@ -188,19 +191,19 @@ func (s *DockerRegistrySuite) TestRemoveImageByDigest(c *testing.T) {
func (s *DockerRegistrySuite) TestBuildByDigest(c *testing.T) { func (s *DockerRegistrySuite) TestBuildByDigest(c *testing.T) {
skip.If(c, testEnv.UsingSnapshotter(), "Config.Image is not created with containerd, buildkit doesn't set it either") skip.If(c, testEnv.UsingSnapshotter(), "Config.Image is not created with containerd, buildkit doesn't set it either")
digest, err := setupImage(c) imgDigest, err := setupImage(c)
assert.NilError(c, err, "error setting up image") assert.NilError(c, err, "error setting up image")
imageReference := fmt.Sprintf("%s@%s", repoName, digest) imageReference := fmt.Sprintf("%s@%s", repoName, imgDigest)
// pull from the registry using the <name>@<digest> reference // pull from the registry using the <name>@<digest> reference
dockerCmd(c, "pull", imageReference) cli.DockerCmd(c, "pull", imageReference)
// get the image id // get the image id
imageID := inspectField(c, imageReference, "Id") imageID := inspectField(c, imageReference, "Id")
// do the build // do the build
name := "buildbydigest" const name = "buildbydigest"
buildImageSuccessfully(c, name, build.WithDockerfile(fmt.Sprintf( buildImageSuccessfully(c, name, build.WithDockerfile(fmt.Sprintf(
`FROM %s `FROM %s
CMD ["/bin/echo", "Hello World"]`, imageReference))) CMD ["/bin/echo", "Hello World"]`, imageReference)))
@ -213,17 +216,17 @@ func (s *DockerRegistrySuite) TestBuildByDigest(c *testing.T) {
} }
func (s *DockerRegistrySuite) TestTagByDigest(c *testing.T) { func (s *DockerRegistrySuite) TestTagByDigest(c *testing.T) {
digest, err := setupImage(c) imgDigest, err := setupImage(c)
assert.NilError(c, err, "error setting up image") assert.NilError(c, err, "error setting up image")
imageReference := fmt.Sprintf("%s@%s", repoName, digest) imageReference := fmt.Sprintf("%s@%s", repoName, imgDigest)
// pull from the registry using the <name>@<digest> reference // pull from the registry using the <name>@<digest> reference
dockerCmd(c, "pull", imageReference) cli.DockerCmd(c, "pull", imageReference)
// tag it // tag it
tag := "tagbydigest" const tag = "tagbydigest"
dockerCmd(c, "tag", imageReference, tag) cli.DockerCmd(c, "tag", imageReference, tag)
expectedID := inspectField(c, imageReference, "Id") expectedID := inspectField(c, imageReference, "Id")
@ -232,15 +235,15 @@ func (s *DockerRegistrySuite) TestTagByDigest(c *testing.T) {
} }
func (s *DockerRegistrySuite) TestListImagesWithoutDigests(c *testing.T) { func (s *DockerRegistrySuite) TestListImagesWithoutDigests(c *testing.T) {
digest, err := setupImage(c) imgDigest, err := setupImage(c)
assert.NilError(c, err, "error setting up image") assert.NilError(c, err, "error setting up image")
imageReference := fmt.Sprintf("%s@%s", repoName, digest) imageReference := fmt.Sprintf("%s@%s", repoName, imgDigest)
// pull from the registry using the <name>@<digest> reference // pull from the registry using the <name>@<digest> reference
dockerCmd(c, "pull", imageReference) cli.DockerCmd(c, "pull", imageReference)
out, _ := dockerCmd(c, "images") out := cli.DockerCmd(c, "images").Stdout()
assert.Assert(c, !strings.Contains(out, "DIGEST"), "list output should not have contained DIGEST header") assert.Assert(c, !strings.Contains(out, "DIGEST"), "list output should not have contained DIGEST header")
} }
@ -252,10 +255,10 @@ func (s *DockerRegistrySuite) TestListImagesWithDigests(c *testing.T) {
c.Logf("imageReference1 = %s", imageReference1) c.Logf("imageReference1 = %s", imageReference1)
// pull image1 by digest // pull image1 by digest
dockerCmd(c, "pull", imageReference1) cli.DockerCmd(c, "pull", imageReference1)
// list images // list images
out, _ := dockerCmd(c, "images", "--digests") out := cli.DockerCmd(c, "images", "--digests").Combined()
// make sure repo shown, tag=<none>, digest = $digest1 // make sure repo shown, tag=<none>, digest = $digest1
re1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1.String() + `\s`) re1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1.String() + `\s`)
@ -267,13 +270,13 @@ func (s *DockerRegistrySuite) TestListImagesWithDigests(c *testing.T) {
c.Logf("imageReference2 = %s", imageReference2) c.Logf("imageReference2 = %s", imageReference2)
// pull image1 by digest // pull image1 by digest
dockerCmd(c, "pull", imageReference1) cli.DockerCmd(c, "pull", imageReference1)
// pull image2 by digest // pull image2 by digest
dockerCmd(c, "pull", imageReference2) cli.DockerCmd(c, "pull", imageReference2)
// list images // list images
out, _ = dockerCmd(c, "images", "--digests") out = cli.DockerCmd(c, "images", "--digests").Stdout()
// make sure repo shown, tag=<none>, digest = $digest1 // make sure repo shown, tag=<none>, digest = $digest1
assert.Assert(c, re1.MatchString(out), "expected %q: %s", re1.String(), out) assert.Assert(c, re1.MatchString(out), "expected %q: %s", re1.String(), out)
@ -283,10 +286,10 @@ func (s *DockerRegistrySuite) TestListImagesWithDigests(c *testing.T) {
assert.Assert(c, re2.MatchString(out), "expected %q: %s", re2.String(), out) assert.Assert(c, re2.MatchString(out), "expected %q: %s", re2.String(), out)
// pull tag1 // pull tag1
dockerCmd(c, "pull", repoName+":tag1") cli.DockerCmd(c, "pull", repoName+":tag1")
// list images // list images
out, _ = dockerCmd(c, "images", "--digests") out = cli.DockerCmd(c, "images", "--digests").Stdout()
// make sure image 1 has repo, tag, <none> AND repo, <none>, digest // make sure image 1 has repo, tag, <none> AND repo, <none>, digest
reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*tag1\s*` + digest1.String() + `\s`) reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*tag1\s*` + digest1.String() + `\s`)
@ -295,10 +298,10 @@ func (s *DockerRegistrySuite) TestListImagesWithDigests(c *testing.T) {
assert.Assert(c, re2.MatchString(out), "expected %q: %s", re2.String(), out) assert.Assert(c, re2.MatchString(out), "expected %q: %s", re2.String(), out)
// pull tag 2 // pull tag 2
dockerCmd(c, "pull", repoName+":tag2") cli.DockerCmd(c, "pull", repoName+":tag2")
// list images // list images
out, _ = dockerCmd(c, "images", "--digests") out = cli.DockerCmd(c, "images", "--digests").Stdout()
// make sure image 1 has repo, tag, digest // make sure image 1 has repo, tag, digest
assert.Assert(c, reWithDigest1.MatchString(out), "expected %q: %s", reWithDigest1.String(), out) assert.Assert(c, reWithDigest1.MatchString(out), "expected %q: %s", reWithDigest1.String(), out)
@ -308,7 +311,7 @@ func (s *DockerRegistrySuite) TestListImagesWithDigests(c *testing.T) {
assert.Assert(c, reWithDigest2.MatchString(out), "expected %q: %s", reWithDigest2.String(), out) assert.Assert(c, reWithDigest2.MatchString(out), "expected %q: %s", reWithDigest2.String(), out)
// list images // list images
out, _ = dockerCmd(c, "images", "--digests") out = cli.DockerCmd(c, "images", "--digests").Stdout()
// make sure image 1 has repo, tag, digest // make sure image 1 has repo, tag, digest
assert.Assert(c, reWithDigest1.MatchString(out), "expected %q: %s", reWithDigest1.String(), out) assert.Assert(c, reWithDigest1.MatchString(out), "expected %q: %s", reWithDigest1.String(), out)
@ -327,10 +330,10 @@ func (s *DockerRegistrySuite) TestListDanglingImagesWithDigests(c *testing.T) {
c.Logf("imageReference1 = %s", imageReference1) c.Logf("imageReference1 = %s", imageReference1)
// pull image1 by digest // pull image1 by digest
dockerCmd(c, "pull", imageReference1) cli.DockerCmd(c, "pull", imageReference1)
// list images // list images
out, _ := dockerCmd(c, "images", "--digests") out := cli.DockerCmd(c, "images", "--digests").Stdout()
// make sure repo shown, tag=<none>, digest = $digest1 // make sure repo shown, tag=<none>, digest = $digest1
re1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1.String() + `\s`) re1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1.String() + `\s`)
@ -343,13 +346,13 @@ func (s *DockerRegistrySuite) TestListDanglingImagesWithDigests(c *testing.T) {
c.Logf("imageReference2 = %s", imageReference2) c.Logf("imageReference2 = %s", imageReference2)
// pull image1 by digest // pull image1 by digest
dockerCmd(c, "pull", imageReference1) cli.DockerCmd(c, "pull", imageReference1)
// pull image2 by digest // pull image2 by digest
dockerCmd(c, "pull", imageReference2) cli.DockerCmd(c, "pull", imageReference2)
// list images // list images
out, _ = dockerCmd(c, "images", "--digests", "--filter=dangling=true") out = cli.DockerCmd(c, "images", "--digests", "--filter=dangling=true").Stdout()
// make sure repo shown, tag=<none>, digest = $digest1 // make sure repo shown, tag=<none>, digest = $digest1
assert.Assert(c, re1.MatchString(out), "expected %q: %s", re1.String(), out) assert.Assert(c, re1.MatchString(out), "expected %q: %s", re1.String(), out)
@ -359,10 +362,10 @@ func (s *DockerRegistrySuite) TestListDanglingImagesWithDigests(c *testing.T) {
assert.Assert(c, re2.MatchString(out), "expected %q: %s", re2.String(), out) assert.Assert(c, re2.MatchString(out), "expected %q: %s", re2.String(), out)
// pull dangle1 tag // pull dangle1 tag
dockerCmd(c, "pull", repoName+":dangle1") cli.DockerCmd(c, "pull", repoName+":dangle1")
// list images // list images
out, _ = dockerCmd(c, "images", "--digests", "--filter=dangling=true") out = cli.DockerCmd(c, "images", "--digests", "--filter=dangling=true").Stdout()
// make sure image 1 has repo, tag, <none> AND repo, <none>, digest // make sure image 1 has repo, tag, <none> AND repo, <none>, digest
reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*dangle1\s*` + digest1.String() + `\s`) reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*dangle1\s*` + digest1.String() + `\s`)
@ -371,10 +374,10 @@ func (s *DockerRegistrySuite) TestListDanglingImagesWithDigests(c *testing.T) {
assert.Assert(c, re2.MatchString(out), "expected %q: %s", re2.String(), out) assert.Assert(c, re2.MatchString(out), "expected %q: %s", re2.String(), out)
// pull dangle2 tag // pull dangle2 tag
dockerCmd(c, "pull", repoName+":dangle2") cli.DockerCmd(c, "pull", repoName+":dangle2")
// list images, show tagged images // list images, show tagged images
out, _ = dockerCmd(c, "images", "--digests") out = cli.DockerCmd(c, "images", "--digests").Stdout()
// make sure image 1 has repo, tag, digest // make sure image 1 has repo, tag, digest
assert.Assert(c, reWithDigest1.MatchString(out), "expected %q: %s", reWithDigest1.String(), out) assert.Assert(c, reWithDigest1.MatchString(out), "expected %q: %s", reWithDigest1.String(), out)
@ -384,7 +387,7 @@ func (s *DockerRegistrySuite) TestListDanglingImagesWithDigests(c *testing.T) {
assert.Assert(c, reWithDigest2.MatchString(out), "expected %q: %s", reWithDigest2.String(), out) assert.Assert(c, reWithDigest2.MatchString(out), "expected %q: %s", reWithDigest2.String(), out)
// list images, no longer dangling, should not match // list images, no longer dangling, should not match
out, _ = dockerCmd(c, "images", "--digests", "--filter=dangling=true") out = cli.DockerCmd(c, "images", "--digests", "--filter=dangling=true").Stdout()
// make sure image 1 has repo, tag, digest // make sure image 1 has repo, tag, digest
assert.Assert(c, !reWithDigest1.MatchString(out), "unexpected %q: %s", reWithDigest1.String(), out) assert.Assert(c, !reWithDigest1.MatchString(out), "unexpected %q: %s", reWithDigest1.String(), out)
@ -393,15 +396,15 @@ func (s *DockerRegistrySuite) TestListDanglingImagesWithDigests(c *testing.T) {
} }
func (s *DockerRegistrySuite) TestInspectImageWithDigests(c *testing.T) { func (s *DockerRegistrySuite) TestInspectImageWithDigests(c *testing.T) {
digest, err := setupImage(c) imgDigest, err := setupImage(c)
assert.Assert(c, err == nil, "error setting up image") assert.Assert(c, err == nil, "error setting up image")
imageReference := fmt.Sprintf("%s@%s", repoName, digest) imageReference := fmt.Sprintf("%s@%s", repoName, imgDigest)
// pull from the registry using the <name>@<digest> reference // pull from the registry using the <name>@<digest> reference
dockerCmd(c, "pull", imageReference) cli.DockerCmd(c, "pull", imageReference)
out, _ := dockerCmd(c, "inspect", imageReference) out := cli.DockerCmd(c, "inspect", imageReference).Stdout()
var imageJSON []types.ImageInspect var imageJSON []types.ImageInspect
err = json.Unmarshal([]byte(out), &imageJSON) err = json.Unmarshal([]byte(out), &imageJSON)
@ -414,36 +417,36 @@ func (s *DockerRegistrySuite) TestInspectImageWithDigests(c *testing.T) {
func (s *DockerRegistrySuite) TestPsListContainersFilterAncestorImageByDigest(c *testing.T) { func (s *DockerRegistrySuite) TestPsListContainersFilterAncestorImageByDigest(c *testing.T) {
existingContainers := ExistingContainerIDs(c) existingContainers := ExistingContainerIDs(c)
digest, err := setupImage(c) imgDigest, err := setupImage(c)
assert.NilError(c, err, "error setting up image") assert.NilError(c, err, "error setting up image")
imageReference := fmt.Sprintf("%s@%s", repoName, digest) imageReference := fmt.Sprintf("%s@%s", repoName, imgDigest)
// pull from the registry using the <name>@<digest> reference // pull from the registry using the <name>@<digest> reference
dockerCmd(c, "pull", imageReference) cli.DockerCmd(c, "pull", imageReference)
// build an image from it // build an image from it
imageName1 := "images_ps_filter_test" const imageName1 = "images_ps_filter_test"
buildImageSuccessfully(c, imageName1, build.WithDockerfile(fmt.Sprintf( buildImageSuccessfully(c, imageName1, build.WithDockerfile(fmt.Sprintf(
`FROM %s `FROM %s
LABEL match me 1`, imageReference))) LABEL match me 1`, imageReference)))
// run a container based on that // run a container based on that
dockerCmd(c, "run", "--name=test1", imageReference, "echo", "hello") cli.DockerCmd(c, "run", "--name=test1", imageReference, "echo", "hello")
expectedID := getIDByName(c, "test1") expectedID := getIDByName(c, "test1")
// run a container based on the a descendant of that too // run a container based on the a descendant of that too
dockerCmd(c, "run", "--name=test2", imageName1, "echo", "hello") cli.DockerCmd(c, "run", "--name=test2", imageName1, "echo", "hello")
expectedID1 := getIDByName(c, "test2") expectedID1 := getIDByName(c, "test2")
expectedIDs := []string{expectedID, expectedID1} expectedIDs := []string{expectedID, expectedID1}
// Invalid imageReference // Invalid imageReference
out, _ := dockerCmd(c, "ps", "-a", "-q", "--no-trunc", fmt.Sprintf("--filter=ancestor=busybox@%s", digest)) out := cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc", fmt.Sprintf("--filter=ancestor=busybox@%s", imgDigest)).Stdout()
assert.Equal(c, strings.TrimSpace(out), "", "Filter container for ancestor filter should be empty") assert.Equal(c, strings.TrimSpace(out), "", "Filter container for ancestor filter should be empty")
// Valid imageReference // Valid imageReference
out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageReference) out = cli.DockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageReference).Stdout()
checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), imageReference, expectedIDs) checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), imageReference, expectedIDs)
} }
@ -453,14 +456,14 @@ func (s *DockerRegistrySuite) TestDeleteImageByIDOnlyPulledByDigest(c *testing.T
// pull from the registry using the <name>@<digest> reference // pull from the registry using the <name>@<digest> reference
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest) imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
dockerCmd(c, "pull", imageReference) cli.DockerCmd(c, "pull", imageReference)
// just in case... // just in case...
dockerCmd(c, "tag", imageReference, repoName+":sometag") cli.DockerCmd(c, "tag", imageReference, repoName+":sometag")
imageID := inspectField(c, imageReference, "Id") imageID := inspectField(c, imageReference, "Id")
dockerCmd(c, "rmi", imageID) cli.DockerCmd(c, "rmi", imageID)
_, err = inspectFieldWithError(imageID, "Id") _, err = inspectFieldWithError(imageID, "Id")
assert.ErrorContains(c, err, "", "image should have been deleted") assert.ErrorContains(c, err, "", "image should have been deleted")
@ -472,21 +475,21 @@ func (s *DockerRegistrySuite) TestDeleteImageWithDigestAndTag(c *testing.T) {
// pull from the registry using the <name>@<digest> reference // pull from the registry using the <name>@<digest> reference
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest) imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
dockerCmd(c, "pull", imageReference) cli.DockerCmd(c, "pull", imageReference)
imageID := inspectField(c, imageReference, "Id") imageID := inspectField(c, imageReference, "Id")
repoTag := repoName + ":sometag" const repoTag = repoName + ":sometag"
repoTag2 := repoName + ":othertag" const repoTag2 = repoName + ":othertag"
dockerCmd(c, "tag", imageReference, repoTag) cli.DockerCmd(c, "tag", imageReference, repoTag)
dockerCmd(c, "tag", imageReference, repoTag2) cli.DockerCmd(c, "tag", imageReference, repoTag2)
dockerCmd(c, "rmi", repoTag2) cli.DockerCmd(c, "rmi", repoTag2)
// rmi should have deleted only repoTag2, because there's another tag // rmi should have deleted only repoTag2, because there's another tag
inspectField(c, repoTag, "Id") inspectField(c, repoTag, "Id")
dockerCmd(c, "rmi", repoTag) cli.DockerCmd(c, "rmi", repoTag)
// rmi should have deleted the tag, the digest reference, and the image itself // rmi should have deleted the tag, the digest reference, and the image itself
_, err = inspectFieldWithError(imageID, "Id") _, err = inspectFieldWithError(imageID, "Id")
@ -501,16 +504,16 @@ func (s *DockerRegistrySuite) TestDeleteImageWithDigestAndMultiRepoTag(c *testin
// pull from the registry using the <name>@<digest> reference // pull from the registry using the <name>@<digest> reference
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest) imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
dockerCmd(c, "pull", imageReference) cli.DockerCmd(c, "pull", imageReference)
imageID := inspectField(c, imageReference, "Id") imageID := inspectField(c, imageReference, "Id")
repoTag := repoName + ":sometag" repoTag := repoName + ":sometag"
repoTag2 := repo2 + ":othertag" repoTag2 := repo2 + ":othertag"
dockerCmd(c, "tag", imageReference, repoTag) cli.DockerCmd(c, "tag", imageReference, repoTag)
dockerCmd(c, "tag", imageReference, repoTag2) cli.DockerCmd(c, "tag", imageReference, repoTag2)
dockerCmd(c, "rmi", repoTag) cli.DockerCmd(c, "rmi", repoTag)
// rmi should have deleted repoTag and image reference, but left repoTag2 // rmi should have deleted repoTag and image reference, but left repoTag2
inspectField(c, repoTag2, "Id") inspectField(c, repoTag2, "Id")
@ -520,7 +523,7 @@ func (s *DockerRegistrySuite) TestDeleteImageWithDigestAndMultiRepoTag(c *testin
_, err = inspectFieldWithError(repoTag, "Id") _, err = inspectFieldWithError(repoTag, "Id")
assert.ErrorContains(c, err, "", "image tag reference should have been removed") assert.ErrorContains(c, err, "", "image tag reference should have been removed")
dockerCmd(c, "rmi", repoTag2) cli.DockerCmd(c, "rmi", repoTag2)
// rmi should have deleted the tag, the digest reference, and the image itself // rmi should have deleted the tag, the digest reference, and the image itself
_, err = inspectFieldWithError(imageID, "Id") _, err = inspectFieldWithError(imageID, "Id")

View file

@ -13,6 +13,7 @@ import (
"github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest"
"github.com/docker/distribution/manifest/manifestlist" "github.com/docker/distribution/manifest/manifestlist"
"github.com/docker/distribution/manifest/schema2" "github.com/docker/distribution/manifest/schema2"
"github.com/docker/docker/integration-cli/cli"
"github.com/docker/docker/integration-cli/cli/build" "github.com/docker/docker/integration-cli/cli/build"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
@ -24,26 +25,26 @@ import (
// //
// Ref: docker/docker#8141 // Ref: docker/docker#8141
func testPullImageWithAliases(c *testing.T) { func testPullImageWithAliases(c *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/busybox"
var repos []string var repos []string
for _, tag := range []string{"recent", "fresh"} { for _, tag := range []string{"recent", "fresh"} {
repos = append(repos, fmt.Sprintf("%v:%v", repoName, tag)) repos = append(repos, fmt.Sprintf("%v:%v", imgRepo, tag))
} }
// Tag and push the same image multiple times. // Tag and push the same image multiple times.
for _, repo := range repos { for _, repo := range repos {
dockerCmd(c, "tag", "busybox", repo) cli.DockerCmd(c, "tag", "busybox", repo)
dockerCmd(c, "push", repo) cli.DockerCmd(c, "push", repo)
} }
// Clear local images store. // Clear local images store.
args := append([]string{"rmi"}, repos...) args := append([]string{"rmi"}, repos...)
dockerCmd(c, args...) cli.DockerCmd(c, args...)
// Pull a single tag and verify it doesn't bring down all aliases. // Pull a single tag and verify it doesn't bring down all aliases.
dockerCmd(c, "pull", repos[0]) cli.DockerCmd(c, "pull", repos[0])
dockerCmd(c, "inspect", repos[0]) cli.DockerCmd(c, "inspect", repos[0])
for _, repo := range repos[1:] { for _, repo := range repos[1:] {
_, _, err := dockerCmdWithError("inspect", repo) _, _, err := dockerCmdWithError("inspect", repo)
assert.ErrorContains(c, err, "", "Image %v shouldn't have been pulled down", repo) assert.ErrorContains(c, err, "", "Image %v shouldn't have been pulled down", repo)
@ -60,11 +61,11 @@ func (s *DockerSchema1RegistrySuite) TestPullImageWithAliases(c *testing.T) {
// testConcurrentPullWholeRepo pulls the same repo concurrently. // testConcurrentPullWholeRepo pulls the same repo concurrently.
func testConcurrentPullWholeRepo(c *testing.T) { func testConcurrentPullWholeRepo(c *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/busybox"
var repos []string var repos []string
for _, tag := range []string{"recent", "fresh", "todays"} { for _, tag := range []string{"recent", "fresh", "todays"} {
repo := fmt.Sprintf("%v:%v", repoName, tag) repo := fmt.Sprintf("%v:%v", imgRepo, tag)
buildImageSuccessfully(c, repo, build.WithDockerfile(fmt.Sprintf(` buildImageSuccessfully(c, repo, build.WithDockerfile(fmt.Sprintf(`
FROM busybox FROM busybox
ENTRYPOINT ["/bin/echo"] ENTRYPOINT ["/bin/echo"]
@ -72,13 +73,13 @@ func testConcurrentPullWholeRepo(c *testing.T) {
ENV BAR bar ENV BAR bar
CMD echo %s CMD echo %s
`, repo))) `, repo)))
dockerCmd(c, "push", repo) cli.DockerCmd(c, "push", repo)
repos = append(repos, repo) repos = append(repos, repo)
} }
// Clear local images store. // Clear local images store.
args := append([]string{"rmi"}, repos...) args := append([]string{"rmi"}, repos...)
dockerCmd(c, args...) cli.DockerCmd(c, args...)
// Run multiple re-pulls concurrently // Run multiple re-pulls concurrently
numPulls := 3 numPulls := 3
@ -86,7 +87,7 @@ func testConcurrentPullWholeRepo(c *testing.T) {
for i := 0; i != numPulls; i++ { for i := 0; i != numPulls; i++ {
go func() { go func() {
result := icmd.RunCommand(dockerBinary, "pull", "-a", repoName) result := icmd.RunCommand(dockerBinary, "pull", "-a", imgRepo)
results <- result.Error results <- result.Error
}() }()
} }
@ -100,8 +101,8 @@ func testConcurrentPullWholeRepo(c *testing.T) {
// Ensure all tags were pulled successfully // Ensure all tags were pulled successfully
for _, repo := range repos { for _, repo := range repos {
dockerCmd(c, "inspect", repo) cli.DockerCmd(c, "inspect", repo)
out, _ := dockerCmd(c, "run", "--rm", repo) out := cli.DockerCmd(c, "run", "--rm", repo).Combined()
assert.Equal(c, strings.TrimSpace(out), "/bin/sh -c echo "+repo) assert.Equal(c, strings.TrimSpace(out), "/bin/sh -c echo "+repo)
} }
} }
@ -116,7 +117,7 @@ func (s *DockerSchema1RegistrySuite) TestConcurrentPullWholeRepo(c *testing.T) {
// testConcurrentFailingPull tries a concurrent pull that doesn't succeed. // testConcurrentFailingPull tries a concurrent pull that doesn't succeed.
func testConcurrentFailingPull(c *testing.T) { func testConcurrentFailingPull(c *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/busybox"
// Run multiple pulls concurrently // Run multiple pulls concurrently
numPulls := 3 numPulls := 3
@ -124,7 +125,7 @@ func testConcurrentFailingPull(c *testing.T) {
for i := 0; i != numPulls; i++ { for i := 0; i != numPulls; i++ {
go func() { go func() {
result := icmd.RunCommand(dockerBinary, "pull", repoName+":asdfasdf") result := icmd.RunCommand(dockerBinary, "pull", imgRepo+":asdfasdf")
results <- result.Error results <- result.Error
}() }()
} }
@ -148,11 +149,11 @@ func (s *DockerSchema1RegistrySuite) TestConcurrentFailingPull(c *testing.T) {
// testConcurrentPullMultipleTags pulls multiple tags from the same repo // testConcurrentPullMultipleTags pulls multiple tags from the same repo
// concurrently. // concurrently.
func testConcurrentPullMultipleTags(c *testing.T) { func testConcurrentPullMultipleTags(c *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/busybox"
var repos []string var repos []string
for _, tag := range []string{"recent", "fresh", "todays"} { for _, tag := range []string{"recent", "fresh", "todays"} {
repo := fmt.Sprintf("%v:%v", repoName, tag) repo := fmt.Sprintf("%v:%v", imgRepo, tag)
buildImageSuccessfully(c, repo, build.WithDockerfile(fmt.Sprintf(` buildImageSuccessfully(c, repo, build.WithDockerfile(fmt.Sprintf(`
FROM busybox FROM busybox
ENTRYPOINT ["/bin/echo"] ENTRYPOINT ["/bin/echo"]
@ -160,13 +161,13 @@ func testConcurrentPullMultipleTags(c *testing.T) {
ENV BAR bar ENV BAR bar
CMD echo %s CMD echo %s
`, repo))) `, repo)))
dockerCmd(c, "push", repo) cli.DockerCmd(c, "push", repo)
repos = append(repos, repo) repos = append(repos, repo)
} }
// Clear local images store. // Clear local images store.
args := append([]string{"rmi"}, repos...) args := append([]string{"rmi"}, repos...)
dockerCmd(c, args...) cli.DockerCmd(c, args...)
// Re-pull individual tags, in parallel // Re-pull individual tags, in parallel
results := make(chan error, len(repos)) results := make(chan error, len(repos))
@ -187,8 +188,8 @@ func testConcurrentPullMultipleTags(c *testing.T) {
// Ensure all tags were pulled successfully // Ensure all tags were pulled successfully
for _, repo := range repos { for _, repo := range repos {
dockerCmd(c, "inspect", repo) cli.DockerCmd(c, "inspect", repo)
out, _ := dockerCmd(c, "run", "--rm", repo) out := cli.DockerCmd(c, "run", "--rm", repo).Combined()
assert.Equal(c, strings.TrimSpace(out), "/bin/sh -c echo "+repo) assert.Equal(c, strings.TrimSpace(out), "/bin/sh -c echo "+repo)
} }
} }
@ -204,8 +205,8 @@ func (s *DockerSchema1RegistrySuite) TestConcurrentPullMultipleTags(c *testing.T
// testPullIDStability verifies that pushing an image and pulling it back // testPullIDStability verifies that pushing an image and pulling it back
// preserves the image ID. // preserves the image ID.
func testPullIDStability(c *testing.T) { func testPullIDStability(c *testing.T) {
derivedImage := privateRegistryURL + "/dockercli/id-stability" const derivedImage = privateRegistryURL + "/dockercli/id-stability"
baseImage := "busybox" const baseImage = "busybox"
buildImageSuccessfully(c, derivedImage, build.WithDockerfile(fmt.Sprintf(` buildImageSuccessfully(c, derivedImage, build.WithDockerfile(fmt.Sprintf(`
FROM %s FROM %s
@ -216,10 +217,10 @@ func testPullIDStability(c *testing.T) {
`, baseImage, derivedImage))) `, baseImage, derivedImage)))
originalID := getIDByName(c, derivedImage) originalID := getIDByName(c, derivedImage)
dockerCmd(c, "push", derivedImage) cli.DockerCmd(c, "push", derivedImage)
// Pull // Pull
out, _ := dockerCmd(c, "pull", derivedImage) out := cli.DockerCmd(c, "pull", derivedImage).Combined()
if strings.Contains(out, "Pull complete") { if strings.Contains(out, "Pull complete") {
c.Fatalf("repull redownloaded a layer: %s", out) c.Fatalf("repull redownloaded a layer: %s", out)
} }
@ -231,24 +232,23 @@ func testPullIDStability(c *testing.T) {
} }
// Make sure the image runs correctly // Make sure the image runs correctly
out, _ = dockerCmd(c, "run", "--rm", derivedImage) out = cli.DockerCmd(c, "run", "--rm", derivedImage).Combined()
if strings.TrimSpace(out) != derivedImage { if strings.TrimSpace(out) != derivedImage {
c.Fatalf("expected %s; got %s", derivedImage, out) c.Fatalf("expected %s; got %s", derivedImage, out)
} }
// Confirm that repushing and repulling does not change the computed ID // Confirm that repushing and repulling does not change the computed ID
dockerCmd(c, "push", derivedImage) cli.DockerCmd(c, "push", derivedImage)
dockerCmd(c, "rmi", derivedImage) cli.DockerCmd(c, "rmi", derivedImage)
dockerCmd(c, "pull", derivedImage) cli.DockerCmd(c, "pull", derivedImage)
derivedIDAfterPull = getIDByName(c, derivedImage) derivedIDAfterPull = getIDByName(c, derivedImage)
if derivedIDAfterPull != originalID { if derivedIDAfterPull != originalID {
c.Fatal("image's ID unexpectedly changed after a repush/repull") c.Fatal("image's ID unexpectedly changed after a repush/repull")
} }
// Make sure the image still runs // Make sure the image still runs
out, _ = dockerCmd(c, "run", "--rm", derivedImage) out = cli.DockerCmd(c, "run", "--rm", derivedImage).Combined()
if strings.TrimSpace(out) != derivedImage { if strings.TrimSpace(out) != derivedImage {
c.Fatalf("expected %s; got %s", derivedImage, out) c.Fatalf("expected %s; got %s", derivedImage, out)
} }
@ -264,14 +264,14 @@ func (s *DockerSchema1RegistrySuite) TestPullIDStability(c *testing.T) {
// #21213 // #21213
func testPullNoLayers(c *testing.T) { func testPullNoLayers(c *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/scratch", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/scratch"
buildImageSuccessfully(c, repoName, build.WithDockerfile(` buildImageSuccessfully(c, imgRepo, build.WithDockerfile(`
FROM scratch FROM scratch
ENV foo bar`)) ENV foo bar`))
dockerCmd(c, "push", repoName) cli.DockerCmd(c, "push", imgRepo)
dockerCmd(c, "rmi", repoName) cli.DockerCmd(c, "rmi", imgRepo)
dockerCmd(c, "pull", repoName) cli.DockerCmd(c, "pull", imgRepo)
} }
func (s *DockerRegistrySuite) TestPullNoLayers(c *testing.T) { func (s *DockerRegistrySuite) TestPullNoLayers(c *testing.T) {
@ -348,7 +348,7 @@ func (s *DockerRegistrySuite) TestPullManifestList(c *testing.T) {
assert.NilError(c, err, "error writing tag link") assert.NilError(c, err, "error writing tag link")
// Verify that the image can be pulled through the manifest list. // Verify that the image can be pulled through the manifest list.
out, _ := dockerCmd(c, "pull", repoName) out := cli.DockerCmd(c, "pull", repoName).Combined()
// The pull output includes "Digest: <digest>", so find that // The pull output includes "Digest: <digest>", so find that
matches := digestRegex.FindStringSubmatch(out) matches := digestRegex.FindStringSubmatch(out)
@ -359,9 +359,9 @@ func (s *DockerRegistrySuite) TestPullManifestList(c *testing.T) {
assert.Equal(c, manifestListDigest.String(), pullDigest) assert.Equal(c, manifestListDigest.String(), pullDigest)
// Was the image actually created? // Was the image actually created?
dockerCmd(c, "inspect", repoName) cli.DockerCmd(c, "inspect", repoName)
dockerCmd(c, "rmi", repoName) cli.DockerCmd(c, "rmi", repoName)
} }
// #23100 // #23100
@ -375,7 +375,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestPullWithExternalAuthLoginWithSchem
testPath := fmt.Sprintf("%s%c%s", osPath, filepath.ListSeparator, absolute) testPath := fmt.Sprintf("%s%c%s", osPath, filepath.ListSeparator, absolute)
c.Setenv("PATH", testPath) c.Setenv("PATH", testPath)
repoName := fmt.Sprintf("%v/dockercli/busybox:authtest", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/busybox:authtest"
tmp, err := os.MkdirTemp("", "integration-cli-") tmp, err := os.MkdirTemp("", "integration-cli-")
assert.NilError(c, err) assert.NilError(c, err)
@ -386,25 +386,25 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestPullWithExternalAuthLoginWithSchem
err = os.WriteFile(configPath, []byte(externalAuthConfig), 0o644) err = os.WriteFile(configPath, []byte(externalAuthConfig), 0o644)
assert.NilError(c, err) assert.NilError(c, err)
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL) cli.DockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
b, err := os.ReadFile(configPath) b, err := os.ReadFile(configPath)
assert.NilError(c, err) assert.NilError(c, err)
assert.Assert(c, !strings.Contains(string(b), `"auth":`)) assert.Assert(c, !strings.Contains(string(b), `"auth":`))
dockerCmd(c, "--config", tmp, "tag", "busybox", repoName) cli.DockerCmd(c, "--config", tmp, "tag", "busybox", imgRepo)
dockerCmd(c, "--config", tmp, "push", repoName) cli.DockerCmd(c, "--config", tmp, "push", imgRepo)
dockerCmd(c, "--config", tmp, "logout", privateRegistryURL) cli.DockerCmd(c, "--config", tmp, "logout", privateRegistryURL)
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), "https://"+privateRegistryURL) cli.DockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), "https://"+privateRegistryURL)
dockerCmd(c, "--config", tmp, "pull", repoName) cli.DockerCmd(c, "--config", tmp, "pull", imgRepo)
// likewise push should work // likewise push should work
repoName2 := fmt.Sprintf("%v/dockercli/busybox:nocreds", privateRegistryURL) repoName2 := fmt.Sprintf("%v/dockercli/busybox:nocreds", privateRegistryURL)
dockerCmd(c, "tag", repoName, repoName2) cli.DockerCmd(c, "tag", imgRepo, repoName2)
dockerCmd(c, "--config", tmp, "push", repoName2) cli.DockerCmd(c, "--config", tmp, "push", repoName2)
// logout should work w scheme also because it will be stripped // logout should work w scheme also because it will be stripped
dockerCmd(c, "--config", tmp, "logout", "https://"+privateRegistryURL) cli.DockerCmd(c, "--config", tmp, "logout", "https://"+privateRegistryURL)
} }
func (s *DockerRegistryAuthHtpasswdSuite) TestPullWithExternalAuth(c *testing.T) { func (s *DockerRegistryAuthHtpasswdSuite) TestPullWithExternalAuth(c *testing.T) {
@ -417,7 +417,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestPullWithExternalAuth(c *testing.T)
testPath := fmt.Sprintf("%s%c%s", osPath, filepath.ListSeparator, absolute) testPath := fmt.Sprintf("%s%c%s", osPath, filepath.ListSeparator, absolute)
c.Setenv("PATH", testPath) c.Setenv("PATH", testPath)
repoName := fmt.Sprintf("%v/dockercli/busybox:authtest", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/busybox:authtest"
tmp, err := os.MkdirTemp("", "integration-cli-") tmp, err := os.MkdirTemp("", "integration-cli-")
assert.NilError(c, err) assert.NilError(c, err)
@ -428,34 +428,34 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestPullWithExternalAuth(c *testing.T)
err = os.WriteFile(configPath, []byte(externalAuthConfig), 0o644) err = os.WriteFile(configPath, []byte(externalAuthConfig), 0o644)
assert.NilError(c, err) assert.NilError(c, err)
dockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL) cli.DockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
b, err := os.ReadFile(configPath) b, err := os.ReadFile(configPath)
assert.NilError(c, err) assert.NilError(c, err)
assert.Assert(c, !strings.Contains(string(b), `"auth":`)) assert.Assert(c, !strings.Contains(string(b), `"auth":`))
dockerCmd(c, "--config", tmp, "tag", "busybox", repoName) cli.DockerCmd(c, "--config", tmp, "tag", "busybox", imgRepo)
dockerCmd(c, "--config", tmp, "push", repoName) cli.DockerCmd(c, "--config", tmp, "push", imgRepo)
dockerCmd(c, "--config", tmp, "pull", repoName) cli.DockerCmd(c, "--config", tmp, "pull", imgRepo)
} }
// TestRunImplicitPullWithNoTag should pull implicitly only the default tag (latest) // TestRunImplicitPullWithNoTag should pull implicitly only the default tag (latest)
func (s *DockerRegistrySuite) TestRunImplicitPullWithNoTag(c *testing.T) { func (s *DockerRegistrySuite) TestRunImplicitPullWithNoTag(c *testing.T) {
testRequires(c, DaemonIsLinux) testRequires(c, DaemonIsLinux)
repo := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/busybox"
repoTag1 := fmt.Sprintf("%v:latest", repo) const repoTag1 = imgRepo + ":latest"
repoTag2 := fmt.Sprintf("%v:t1", repo) const repoTag2 = imgRepo + ":t1"
// tag the image and upload it to the private registry // tag the image and upload it to the private registry
dockerCmd(c, "tag", "busybox", repoTag1) cli.DockerCmd(c, "tag", "busybox", repoTag1)
dockerCmd(c, "tag", "busybox", repoTag2) cli.DockerCmd(c, "tag", "busybox", repoTag2)
dockerCmd(c, "push", repo) cli.DockerCmd(c, "push", imgRepo)
dockerCmd(c, "rmi", repoTag1) cli.DockerCmd(c, "rmi", repoTag1)
dockerCmd(c, "rmi", repoTag2) cli.DockerCmd(c, "rmi", repoTag2)
out, _ := dockerCmd(c, "run", repo) out := cli.DockerCmd(c, "run", imgRepo).Combined()
assert.Assert(c, strings.Contains(out, fmt.Sprintf("Unable to find image '%s:latest' locally", repo))) assert.Assert(c, strings.Contains(out, fmt.Sprintf("Unable to find image '%s:latest' locally", imgRepo)))
// There should be only one line for repo, the one with repo:latest // There should be only one line for repo, the one with repo:latest
outImageCmd, _ := dockerCmd(c, "images", repo) outImageCmd := cli.DockerCmd(c, "images", imgRepo).Stdout()
splitOutImageCmd := strings.Split(strings.TrimSpace(outImageCmd), "\n") splitOutImageCmd := strings.Split(strings.TrimSpace(outImageCmd), "\n")
assert.Equal(c, len(splitOutImageCmd), 2) assert.Equal(c, len(splitOutImageCmd), 2)
} }

View file

@ -181,9 +181,9 @@ func (s *DockerHubPullSuite) TestPullAllTagsFromCentralRegistry(c *testing.T) {
// Ref: docker/docker#15589 // Ref: docker/docker#15589
func (s *DockerHubPullSuite) TestPullClientDisconnect(c *testing.T) { func (s *DockerHubPullSuite) TestPullClientDisconnect(c *testing.T) {
testRequires(c, DaemonIsLinux) testRequires(c, DaemonIsLinux)
repoName := "hello-world:latest" const imgRepo = "hello-world:latest"
pullCmd := s.MakeCmd("pull", repoName) pullCmd := s.MakeCmd("pull", imgRepo)
stdout, err := pullCmd.StdoutPipe() stdout, err := pullCmd.StdoutPipe()
assert.NilError(c, err) assert.NilError(c, err)
err = pullCmd.Start() err = pullCmd.Start()
@ -199,7 +199,7 @@ func (s *DockerHubPullSuite) TestPullClientDisconnect(c *testing.T) {
assert.NilError(c, err) assert.NilError(c, err)
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
_, err = s.CmdWithError("inspect", repoName) _, err = s.CmdWithError("inspect", imgRepo)
assert.ErrorContains(c, err, "", "image was pulled after client disconnected") assert.ErrorContains(c, err, "", "image was pulled after client disconnected")
} }

View file

@ -13,6 +13,7 @@ import (
"github.com/distribution/reference" "github.com/distribution/reference"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/docker/docker/integration-cli/cli"
"github.com/docker/docker/integration-cli/cli/build" "github.com/docker/docker/integration-cli/cli/build"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
"gotest.tools/v3/icmd" "gotest.tools/v3/icmd"
@ -31,11 +32,11 @@ func (s *DockerCLIPushSuite) OnTimeout(c *testing.T) {
} }
func (s *DockerRegistrySuite) TestPushBusyboxImage(c *testing.T) { func (s *DockerRegistrySuite) TestPushBusyboxImage(c *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/busybox"
// tag the image to upload it to the private registry // tag the image to upload it to the private registry
dockerCmd(c, "tag", "busybox", repoName) cli.DockerCmd(c, "tag", "busybox", imgRepo)
// push the image to the registry // push the image to the registry
dockerCmd(c, "push", repoName) cli.DockerCmd(c, "push", imgRepo)
} }
// pushing an image without a prefix should throw an error // pushing an image without a prefix should throw an error
@ -45,44 +46,44 @@ func (s *DockerCLIPushSuite) TestPushUnprefixedRepo(c *testing.T) {
} }
func (s *DockerRegistrySuite) TestPushUntagged(c *testing.T) { func (s *DockerRegistrySuite) TestPushUntagged(c *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/busybox"
expected := "An image does not exist locally with the tag"
out, _, err := dockerCmdWithError("push", repoName) out, _, err := dockerCmdWithError("push", imgRepo)
assert.ErrorContains(c, err, "", "pushing the image to the private registry should have failed: output %q", out) assert.ErrorContains(c, err, "", "pushing the image to the private registry should have failed: output %q", out)
const expected = "An image does not exist locally with the tag"
assert.Assert(c, strings.Contains(out, expected), "pushing the image failed") assert.Assert(c, strings.Contains(out, expected), "pushing the image failed")
} }
func (s *DockerRegistrySuite) TestPushBadTag(c *testing.T) { func (s *DockerRegistrySuite) TestPushBadTag(c *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/busybox:latest", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/busybox:latest"
expected := "does not exist"
out, _, err := dockerCmdWithError("push", repoName) out, _, err := dockerCmdWithError("push", imgRepo)
assert.ErrorContains(c, err, "", "pushing the image to the private registry should have failed: output %q", out) assert.ErrorContains(c, err, "", "pushing the image to the private registry should have failed: output %q", out)
const expected = "does not exist"
assert.Assert(c, strings.Contains(out, expected), "pushing the image failed") assert.Assert(c, strings.Contains(out, expected), "pushing the image failed")
} }
func (s *DockerRegistrySuite) TestPushMultipleTags(c *testing.T) { func (s *DockerRegistrySuite) TestPushMultipleTags(c *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/busybox"
repoTag1 := fmt.Sprintf("%v/dockercli/busybox:t1", privateRegistryURL) const repoTag1 = imgRepo + ":t1"
repoTag2 := fmt.Sprintf("%v/dockercli/busybox:t2", privateRegistryURL) const repoTag2 = imgRepo + ":t2"
// tag the image and upload it to the private registry // tag the image and upload it to the private registry
dockerCmd(c, "tag", "busybox", repoTag1) cli.DockerCmd(c, "tag", "busybox", repoTag1)
dockerCmd(c, "tag", "busybox", repoTag2) cli.DockerCmd(c, "tag", "busybox", repoTag2)
args := []string{"push"} args := []string{"push"}
if versions.GreaterThanOrEqualTo(DockerCLIVersion(c), "20.10.0") { if versions.GreaterThanOrEqualTo(DockerCLIVersion(c), "20.10.0") {
// 20.10 CLI removed implicit push all tags and requires the "--all" flag // 20.10 CLI removed implicit push all tags and requires the "--all" flag
args = append(args, "--all-tags") args = append(args, "--all-tags")
} }
args = append(args, repoName) args = append(args, imgRepo)
dockerCmd(c, args...) cli.DockerCmd(c, args...)
imageAlreadyExists := ": Image already exists" imageAlreadyExists := ": Image already exists"
// Ensure layer list is equivalent for repoTag1 and repoTag2 // Ensure layer list is equivalent for repoTag1 and repoTag2
out1, _ := dockerCmd(c, "push", repoTag1) out1 := cli.DockerCmd(c, "push", repoTag1).Combined()
var out1Lines []string var out1Lines []string
for _, outputLine := range strings.Split(out1, "\n") { for _, outputLine := range strings.Split(out1, "\n") {
if strings.Contains(outputLine, imageAlreadyExists) { if strings.Contains(outputLine, imageAlreadyExists) {
@ -90,7 +91,7 @@ func (s *DockerRegistrySuite) TestPushMultipleTags(c *testing.T) {
} }
} }
out2, _ := dockerCmd(c, "push", repoTag2) out2 := cli.DockerCmd(c, "push", repoTag2).Combined()
var out2Lines []string var out2Lines []string
for _, outputLine := range strings.Split(out2, "\n") { for _, outputLine := range strings.Split(out2, "\n") {
if strings.Contains(outputLine, imageAlreadyExists) { if strings.Contains(outputLine, imageAlreadyExists) {
@ -101,7 +102,8 @@ func (s *DockerRegistrySuite) TestPushMultipleTags(c *testing.T) {
} }
func (s *DockerRegistrySuite) TestPushEmptyLayer(c *testing.T) { func (s *DockerRegistrySuite) TestPushEmptyLayer(c *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/emptylayer"
emptyTarball, err := os.CreateTemp("", "empty_tarball") emptyTarball, err := os.CreateTemp("", "empty_tarball")
assert.NilError(c, err, "Unable to create test file") assert.NilError(c, err, "Unable to create test file")
@ -114,23 +116,23 @@ func (s *DockerRegistrySuite) TestPushEmptyLayer(c *testing.T) {
defer freader.Close() defer freader.Close()
icmd.RunCmd(icmd.Cmd{ icmd.RunCmd(icmd.Cmd{
Command: []string{dockerBinary, "import", "-", repoName}, Command: []string{dockerBinary, "import", "-", imgRepo},
Stdin: freader, Stdin: freader,
}).Assert(c, icmd.Success) }).Assert(c, icmd.Success)
// Now verify we can push it // Now verify we can push it
out, _, err := dockerCmdWithError("push", repoName) out, _, err := dockerCmdWithError("push", imgRepo)
assert.NilError(c, err, "pushing the image to the private registry has failed: %s", out) assert.NilError(c, err, "pushing the image to the private registry has failed: %s", out)
} }
// TestConcurrentPush pushes multiple tags to the same repo // TestConcurrentPush pushes multiple tags to the same repo
// concurrently. // concurrently.
func (s *DockerRegistrySuite) TestConcurrentPush(c *testing.T) { func (s *DockerRegistrySuite) TestConcurrentPush(c *testing.T) {
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) const imgRepo = privateRegistryURL + "/dockercli/busybox"
var repos []string var repos []string
for _, tag := range []string{"push1", "push2", "push3"} { for _, tag := range []string{"push1", "push2", "push3"} {
repo := fmt.Sprintf("%v:%v", repoName, tag) repo := fmt.Sprintf("%v:%v", imgRepo, tag)
buildImageSuccessfully(c, repo, build.WithDockerfile(fmt.Sprintf(` buildImageSuccessfully(c, repo, build.WithDockerfile(fmt.Sprintf(`
FROM busybox FROM busybox
ENTRYPOINT ["/bin/echo"] ENTRYPOINT ["/bin/echo"]
@ -158,21 +160,22 @@ func (s *DockerRegistrySuite) TestConcurrentPush(c *testing.T) {
// Clear local images store. // Clear local images store.
args := append([]string{"rmi"}, repos...) args := append([]string{"rmi"}, repos...)
dockerCmd(c, args...) cli.DockerCmd(c, args...)
// Re-pull and run individual tags, to make sure pushes succeeded // Re-pull and run individual tags, to make sure pushes succeeded
for _, repo := range repos { for _, repo := range repos {
dockerCmd(c, "pull", repo) cli.DockerCmd(c, "pull", repo)
dockerCmd(c, "inspect", repo) cli.DockerCmd(c, "inspect", repo)
out, _ := dockerCmd(c, "run", "--rm", repo) out := cli.DockerCmd(c, "run", "--rm", repo).Combined()
assert.Equal(c, strings.TrimSpace(out), "/bin/sh -c echo "+repo) assert.Equal(c, strings.TrimSpace(out), "/bin/sh -c echo "+repo)
} }
} }
func (s *DockerRegistrySuite) TestCrossRepositoryLayerPush(c *testing.T) { func (s *DockerRegistrySuite) TestCrossRepositoryLayerPush(c *testing.T) {
sourceRepoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) const sourceRepoName = privateRegistryURL + "/dockercli/busybox"
// tag the image to upload it to the private registry // tag the image to upload it to the private registry
dockerCmd(c, "tag", "busybox", sourceRepoName) cli.DockerCmd(c, "tag", "busybox", sourceRepoName)
// push the image to the registry // push the image to the registry
out1, _, err := dockerCmdWithError("push", sourceRepoName) out1, _, err := dockerCmdWithError("push", sourceRepoName)
assert.NilError(c, err, "pushing the image to the private registry has failed: %s", out1) assert.NilError(c, err, "pushing the image to the private registry has failed: %s", out1)
@ -182,9 +185,10 @@ func (s *DockerRegistrySuite) TestCrossRepositoryLayerPush(c *testing.T) {
digest1 := reference.DigestRegexp.FindString(out1) digest1 := reference.DigestRegexp.FindString(out1)
assert.Assert(c, len(digest1) > 0, "no digest found for pushed manifest") assert.Assert(c, len(digest1) > 0, "no digest found for pushed manifest")
destRepoName := fmt.Sprintf("%v/dockercli/crossrepopush", privateRegistryURL) const destRepoName = privateRegistryURL + "/dockercli/crossrepopush"
// retag the image to upload the same layers to another repo in the same registry // retag the image to upload the same layers to another repo in the same registry
dockerCmd(c, "tag", "busybox", destRepoName) cli.DockerCmd(c, "tag", "busybox", destRepoName)
// push the image to the registry // push the image to the registry
out2, _, err := dockerCmdWithError("push", destRepoName) out2, _, err := dockerCmdWithError("push", destRepoName)
assert.NilError(c, err, "pushing the image to the private registry has failed: %s", out2) assert.NilError(c, err, "pushing the image to the private registry has failed: %s", out2)
@ -205,16 +209,16 @@ func (s *DockerRegistrySuite) TestCrossRepositoryLayerPush(c *testing.T) {
assert.Equal(c, digest3, digest2) assert.Equal(c, digest3, digest2)
// ensure that we can pull and run the cross-repo-pushed repository // ensure that we can pull and run the cross-repo-pushed repository
dockerCmd(c, "rmi", destRepoName) cli.DockerCmd(c, "rmi", destRepoName)
dockerCmd(c, "pull", destRepoName) cli.DockerCmd(c, "pull", destRepoName)
out4, _ := dockerCmd(c, "run", destRepoName, "echo", "-n", "hello world") out4 := cli.DockerCmd(c, "run", destRepoName, "echo", "-n", "hello world").Combined()
assert.Equal(c, out4, "hello world") assert.Equal(c, out4, "hello world")
} }
func (s *DockerRegistryAuthHtpasswdSuite) TestPushNoCredentialsNoRetry(c *testing.T) { func (s *DockerRegistryAuthHtpasswdSuite) TestPushNoCredentialsNoRetry(c *testing.T) {
repoName := fmt.Sprintf("%s/busybox", privateRegistryURL) const imgRepo = privateRegistryURL + "/busybox"
dockerCmd(c, "tag", "busybox", repoName) cli.DockerCmd(c, "tag", "busybox", imgRepo)
out, _, err := dockerCmdWithError("push", repoName) out, _, err := dockerCmdWithError("push", imgRepo)
assert.ErrorContains(c, err, "", out) assert.ErrorContains(c, err, "", out)
assert.Assert(c, !strings.Contains(out, "Retrying")) assert.Assert(c, !strings.Contains(out, "Retrying"))
assert.Assert(c, strings.Contains(out, "no basic auth credentials")) assert.Assert(c, strings.Contains(out, "no basic auth credentials"))
@ -223,9 +227,10 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestPushNoCredentialsNoRetry(c *testin
// This may be flaky but it's needed not to regress on unauthorized push, see #21054 // This may be flaky but it's needed not to regress on unauthorized push, see #21054
func (s *DockerCLIPushSuite) TestPushToCentralRegistryUnauthorized(c *testing.T) { func (s *DockerCLIPushSuite) TestPushToCentralRegistryUnauthorized(c *testing.T) {
testRequires(c, Network) testRequires(c, Network)
repoName := "test/busybox"
dockerCmd(c, "tag", "busybox", repoName) const imgRepo = "test/busybox"
out, _, err := dockerCmdWithError("push", repoName) cli.DockerCmd(c, "tag", "busybox", imgRepo)
out, _, err := dockerCmdWithError("push", imgRepo)
assert.ErrorContains(c, err, "", out) assert.ErrorContains(c, err, "", out)
assert.Assert(c, !strings.Contains(out, "Retrying")) assert.Assert(c, !strings.Contains(out, "Retrying"))
} }
@ -252,9 +257,10 @@ func (s *DockerRegistryAuthTokenSuite) TestPushTokenServiceUnauthResponse(c *tes
ts := getTestTokenService(http.StatusUnauthorized, `{"errors": [{"Code":"UNAUTHORIZED", "message": "a message", "detail": null}]}`, 0) ts := getTestTokenService(http.StatusUnauthorized, `{"errors": [{"Code":"UNAUTHORIZED", "message": "a message", "detail": null}]}`, 0)
defer ts.Close() defer ts.Close()
s.setupRegistryWithTokenService(c, ts.URL) s.setupRegistryWithTokenService(c, ts.URL)
repoName := fmt.Sprintf("%s/busybox", privateRegistryURL)
dockerCmd(c, "tag", "busybox", repoName) const imgRepo = privateRegistryURL + "/busybox"
out, _, err := dockerCmdWithError("push", repoName) cli.DockerCmd(c, "tag", "busybox", imgRepo)
out, _, err := dockerCmdWithError("push", imgRepo)
assert.ErrorContains(c, err, "", out) assert.ErrorContains(c, err, "", out)
assert.Assert(c, !strings.Contains(out, "Retrying")) assert.Assert(c, !strings.Contains(out, "Retrying"))
assert.Assert(c, strings.Contains(out, "unauthorized: a message")) assert.Assert(c, strings.Contains(out, "unauthorized: a message"))
@ -264,9 +270,10 @@ func (s *DockerRegistryAuthTokenSuite) TestPushMisconfiguredTokenServiceResponse
ts := getTestTokenService(http.StatusUnauthorized, `{"error": "unauthorized"}`, 0) ts := getTestTokenService(http.StatusUnauthorized, `{"error": "unauthorized"}`, 0)
defer ts.Close() defer ts.Close()
s.setupRegistryWithTokenService(c, ts.URL) s.setupRegistryWithTokenService(c, ts.URL)
repoName := fmt.Sprintf("%s/busybox", privateRegistryURL)
dockerCmd(c, "tag", "busybox", repoName) const imgRepo = privateRegistryURL + "/busybox"
out, _, err := dockerCmdWithError("push", repoName) cli.DockerCmd(c, "tag", "busybox", imgRepo)
out, _, err := dockerCmdWithError("push", imgRepo)
assert.ErrorContains(c, err, "", out) assert.ErrorContains(c, err, "", out)
assert.Assert(c, !strings.Contains(out, "Retrying")) assert.Assert(c, !strings.Contains(out, "Retrying"))
split := strings.Split(out, "\n") split := strings.Split(out, "\n")
@ -277,9 +284,10 @@ func (s *DockerRegistryAuthTokenSuite) TestPushMisconfiguredTokenServiceResponse
ts := getTestTokenService(http.StatusTooManyRequests, `{"errors": [{"code":"TOOMANYREQUESTS","message":"out of tokens"}]}`, 3) ts := getTestTokenService(http.StatusTooManyRequests, `{"errors": [{"code":"TOOMANYREQUESTS","message":"out of tokens"}]}`, 3)
defer ts.Close() defer ts.Close()
s.setupRegistryWithTokenService(c, ts.URL) s.setupRegistryWithTokenService(c, ts.URL)
repoName := fmt.Sprintf("%s/busybox", privateRegistryURL)
dockerCmd(c, "tag", "busybox", repoName) const imgRepo = privateRegistryURL + "/busybox"
out, _, err := dockerCmdWithError("push", repoName) cli.DockerCmd(c, "tag", "busybox", imgRepo)
out, _, err := dockerCmdWithError("push", imgRepo)
assert.ErrorContains(c, err, "", out) assert.ErrorContains(c, err, "", out)
// TODO: isolate test so that it can be guaranteed that the 503 will trigger xfer retries // TODO: isolate test so that it can be guaranteed that the 503 will trigger xfer retries
// assert.Assert(c, strings.Contains(out, "Retrying")) // assert.Assert(c, strings.Contains(out, "Retrying"))
@ -292,9 +300,10 @@ func (s *DockerRegistryAuthTokenSuite) TestPushMisconfiguredTokenServiceResponse
ts := getTestTokenService(http.StatusForbidden, `no way`, 0) ts := getTestTokenService(http.StatusForbidden, `no way`, 0)
defer ts.Close() defer ts.Close()
s.setupRegistryWithTokenService(c, ts.URL) s.setupRegistryWithTokenService(c, ts.URL)
repoName := fmt.Sprintf("%s/busybox", privateRegistryURL)
dockerCmd(c, "tag", "busybox", repoName) const imgRepo = privateRegistryURL + "/busybox"
out, _, err := dockerCmdWithError("push", repoName) cli.DockerCmd(c, "tag", "busybox", imgRepo)
out, _, err := dockerCmdWithError("push", imgRepo)
assert.ErrorContains(c, err, "", out) assert.ErrorContains(c, err, "", out)
assert.Assert(c, !strings.Contains(out, "Retrying")) assert.Assert(c, !strings.Contains(out, "Retrying"))
split := strings.Split(out, "\n") split := strings.Split(out, "\n")
@ -305,9 +314,10 @@ func (s *DockerRegistryAuthTokenSuite) TestPushMisconfiguredTokenServiceResponse
ts := getTestTokenService(http.StatusOK, `{"something": "wrong"}`, 0) ts := getTestTokenService(http.StatusOK, `{"something": "wrong"}`, 0)
defer ts.Close() defer ts.Close()
s.setupRegistryWithTokenService(c, ts.URL) s.setupRegistryWithTokenService(c, ts.URL)
repoName := fmt.Sprintf("%s/busybox", privateRegistryURL)
dockerCmd(c, "tag", "busybox", repoName) const imgRepo = privateRegistryURL + "/busybox"
out, _, err := dockerCmdWithError("push", repoName) cli.DockerCmd(c, "tag", "busybox", imgRepo)
out, _, err := dockerCmdWithError("push", imgRepo)
assert.ErrorContains(c, err, "", out) assert.ErrorContains(c, err, "", out)
assert.Assert(c, !strings.Contains(out, "Retrying")) assert.Assert(c, !strings.Contains(out, "Retrying"))
split := strings.Split(out, "\n") split := strings.Split(out, "\n")

View file

@ -1,7 +1,6 @@
package main package main
import ( import (
"fmt"
"net/http" "net/http"
"os" "os"
"regexp" "regexp"
@ -80,7 +79,7 @@ func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *testing.T) {
defer reg.Close() defer reg.Close()
registerUserAgentHandler(reg, &ua) registerUserAgentHandler(reg, &ua)
repoName := fmt.Sprintf("%s/busybox", reg.URL()) imgRepo := reg.URL() + "/busybox"
s.d.StartWithBusybox(ctx, c, "--insecure-registry", reg.URL()) s.d.StartWithBusybox(ctx, c, "--insecure-registry", reg.URL())
@ -88,7 +87,7 @@ func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *testing.T) {
assert.NilError(c, err) assert.NilError(c, err)
defer os.RemoveAll(tmp) defer os.RemoveAll(tmp)
dockerfile, err := makefile(tmp, fmt.Sprintf("FROM %s", repoName)) dockerfile, err := makefile(tmp, "FROM "+imgRepo)
assert.NilError(c, err, "Unable to create test dockerfile") assert.NilError(c, err, "Unable to create test dockerfile")
s.d.Cmd("build", "--file", dockerfile, tmp) s.d.Cmd("build", "--file", dockerfile, tmp)
@ -97,10 +96,10 @@ func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *testing.T) {
s.d.Cmd("login", "-u", "richard", "-p", "testtest", reg.URL()) s.d.Cmd("login", "-u", "richard", "-p", "testtest", reg.URL())
regexpCheckUA(c, ua) regexpCheckUA(c, ua)
s.d.Cmd("pull", repoName) s.d.Cmd("pull", imgRepo)
regexpCheckUA(c, ua) regexpCheckUA(c, ua)
s.d.Cmd("tag", "busybox", repoName) s.d.Cmd("tag", "busybox", imgRepo)
s.d.Cmd("push", repoName) s.d.Cmd("push", imgRepo)
regexpCheckUA(c, ua) regexpCheckUA(c, ua)
} }