diff --git a/integration-cli/docker_cli_tag_test.go b/integration-cli/docker_cli_tag_test.go deleted file mode 100644 index 278e348f4e..0000000000 --- a/integration-cli/docker_cli_tag_test.go +++ /dev/null @@ -1,139 +0,0 @@ -package main - -import ( - "strings" - - "github.com/docker/docker/integration-cli/checker" - "github.com/docker/docker/internal/testutil" - "github.com/go-check/check" -) - -// tagging a named image in a new unprefixed repo should work -func (s *DockerSuite) TestTagUnprefixedRepoByName(c *check.C) { - dockerCmd(c, "tag", "busybox:latest", "testfoobarbaz") -} - -// tagging an image by ID in a new unprefixed repo should work -func (s *DockerSuite) TestTagUnprefixedRepoByID(c *check.C) { - imageID := inspectField(c, "busybox", "Id") - dockerCmd(c, "tag", imageID, "testfoobarbaz") -} - -// ensure we don't allow the use of invalid repository names; these tag operations should fail -func (s *DockerSuite) TestTagInvalidUnprefixedRepo(c *check.C) { - invalidRepos := []string{"fo$z$", "Foo@3cc", "Foo$3", "Foo*3", "Fo^3", "Foo!3", "F)xcz(", "fo%asd", "FOO/bar"} - - for _, repo := range invalidRepos { - out, _, err := dockerCmdWithError("tag", "busybox", repo) - c.Assert(err, checker.NotNil, check.Commentf("tag busybox %v should have failed : %v", repo, out)) - } -} - -// ensure we don't allow the use of invalid tags; these tag operations should fail -func (s *DockerSuite) TestTagInvalidPrefixedRepo(c *check.C) { - longTag := testutil.GenerateRandomAlphaOnlyString(121) - - invalidTags := []string{"repo:fo$z$", "repo:Foo@3cc", "repo:Foo$3", "repo:Foo*3", "repo:Fo^3", "repo:Foo!3", "repo:%goodbye", "repo:#hashtagit", "repo:F)xcz(", "repo:-foo", "repo:..", longTag} - - for _, repotag := range invalidTags { - out, _, err := dockerCmdWithError("tag", "busybox", repotag) - c.Assert(err, checker.NotNil, check.Commentf("tag busybox %v should have failed : %v", repotag, out)) - } -} - -// ensure we allow the use of valid tags -func (s *DockerSuite) TestTagValidPrefixedRepo(c *check.C) { - validRepos := []string{"fooo/bar", "fooaa/test", "foooo:t", "HOSTNAME.DOMAIN.COM:443/foo/bar"} - - for _, repo := range validRepos { - _, _, err := dockerCmdWithError("tag", "busybox:latest", repo) - if err != nil { - c.Errorf("tag busybox %v should have worked: %s", repo, err) - continue - } - deleteImages(repo) - } -} - -// tag an image with an existed tag name without -f option should work -func (s *DockerSuite) TestTagExistedNameWithoutForce(c *check.C) { - dockerCmd(c, "tag", "busybox:latest", "busybox:test") -} - -func (s *DockerSuite) TestTagWithPrefixHyphen(c *check.C) { - // test repository name begin with '-' - out, _, err := dockerCmdWithError("tag", "busybox:latest", "-busybox:test") - c.Assert(err, checker.NotNil, check.Commentf(out)) - c.Assert(out, checker.Contains, "Error parsing reference", check.Commentf("tag a name begin with '-' should failed")) - - // test namespace name begin with '-' - out, _, err = dockerCmdWithError("tag", "busybox:latest", "-test/busybox:test") - c.Assert(err, checker.NotNil, check.Commentf(out)) - c.Assert(out, checker.Contains, "Error parsing reference", check.Commentf("tag a name begin with '-' should failed")) - - // test index name begin with '-' - out, _, err = dockerCmdWithError("tag", "busybox:latest", "-index:5000/busybox:test") - c.Assert(err, checker.NotNil, check.Commentf(out)) - c.Assert(out, checker.Contains, "Error parsing reference", check.Commentf("tag a name begin with '-' should failed")) -} - -// ensure tagging using official names works -// ensure all tags result in the same name -func (s *DockerSuite) TestTagOfficialNames(c *check.C) { - names := []string{ - "docker.io/busybox", - "index.docker.io/busybox", - "library/busybox", - "docker.io/library/busybox", - "index.docker.io/library/busybox", - } - - for _, name := range names { - out, exitCode, err := dockerCmdWithError("tag", "busybox:latest", name+":latest") - if err != nil || exitCode != 0 { - c.Errorf("tag busybox %v should have worked: %s, %s", name, err, out) - continue - } - - // ensure we don't have multiple tag names. - out, _, err = dockerCmdWithError("images") - if err != nil { - c.Errorf("listing images failed with errors: %v, %s", err, out) - } else if strings.Contains(out, name) { - c.Errorf("images should not have listed '%s'", name) - deleteImages(name + ":latest") - } - } - - for _, name := range names { - _, exitCode, err := dockerCmdWithError("tag", name+":latest", "fooo/bar:latest") - if err != nil || exitCode != 0 { - c.Errorf("tag %v fooo/bar should have worked: %s", name, err) - continue - } - deleteImages("fooo/bar:latest") - } -} - -// ensure tags can not match digests -func (s *DockerSuite) TestTagMatchesDigest(c *check.C) { - digest := "busybox@sha256:abcdef76720241213f5303bda7704ec4c2ef75613173910a56fb1b6e20251507" - // test setting tag fails - _, _, err := dockerCmdWithError("tag", "busybox:latest", digest) - if err == nil { - c.Fatal("digest tag a name should have failed") - } - // check that no new image matches the digest - _, _, err = dockerCmdWithError("inspect", digest) - if err == nil { - c.Fatal("inspecting by digest should have failed") - } -} - -func (s *DockerSuite) TestTagInvalidRepoName(c *check.C) { - // test setting tag fails - _, _, err := dockerCmdWithError("tag", "busybox:latest", "sha256:sometag") - if err == nil { - c.Fatal("tagging with image named \"sha256\" should have failed") - } -} diff --git a/integration/image/tag_test.go b/integration/image/tag_test.go new file mode 100644 index 0000000000..c396c07c5c --- /dev/null +++ b/integration/image/tag_test.go @@ -0,0 +1,139 @@ +package image // import "github.com/docker/docker/integration/image" + +import ( + "context" + "fmt" + "testing" + + "github.com/docker/docker/integration/internal/request" + "github.com/docker/docker/internal/testutil" + "github.com/gotestyourself/gotestyourself/assert" + is "github.com/gotestyourself/gotestyourself/assert/cmp" +) + +// tagging a named image in a new unprefixed repo should work +func TestTagUnprefixedRepoByNameOrName(t *testing.T) { + defer setupTest(t)() + client := request.NewAPIClient(t) + ctx := context.Background() + + // By name + err := client.ImageTag(ctx, "busybox:latest", "testfoobarbaz") + assert.NilError(t, err) + + // By ID + insp, _, err := client.ImageInspectWithRaw(ctx, "busybox") + assert.NilError(t, err) + err = client.ImageTag(ctx, insp.ID, "testfoobarbaz") + assert.NilError(t, err) +} + +// ensure we don't allow the use of invalid repository names or tags; these tag operations should fail +// TODO (yongtang): Migrate to unit tests +func TestTagInvalidReference(t *testing.T) { + defer setupTest(t)() + client := request.NewAPIClient(t) + ctx := context.Background() + + invalidRepos := []string{"fo$z$", "Foo@3cc", "Foo$3", "Foo*3", "Fo^3", "Foo!3", "F)xcz(", "fo%asd", "FOO/bar"} + + for _, repo := range invalidRepos { + err := client.ImageTag(ctx, "busybox", repo) + testutil.ErrorContains(t, err, "not a valid repository/tag") + } + + longTag := testutil.GenerateRandomAlphaOnlyString(121) + + invalidTags := []string{"repo:fo$z$", "repo:Foo@3cc", "repo:Foo$3", "repo:Foo*3", "repo:Fo^3", "repo:Foo!3", "repo:%goodbye", "repo:#hashtagit", "repo:F)xcz(", "repo:-foo", "repo:..", longTag} + + for _, repotag := range invalidTags { + err := client.ImageTag(ctx, "busybox", repotag) + testutil.ErrorContains(t, err, "not a valid repository/tag") + } + + // test repository name begin with '-' + err := client.ImageTag(ctx, "busybox:latest", "-busybox:test") + testutil.ErrorContains(t, err, "Error parsing reference") + + // test namespace name begin with '-' + err = client.ImageTag(ctx, "busybox:latest", "-test/busybox:test") + testutil.ErrorContains(t, err, "Error parsing reference") + + // test index name begin with '-' + err = client.ImageTag(ctx, "busybox:latest", "-index:5000/busybox:test") + testutil.ErrorContains(t, err, "Error parsing reference") + + // test setting tag fails + err = client.ImageTag(ctx, "busybox:latest", "sha256:sometag") + testutil.ErrorContains(t, err, "refusing to create an ambiguous tag using digest algorithm as name") +} + +// ensure we allow the use of valid tags +func TestTagValidPrefixedRepo(t *testing.T) { + defer setupTest(t)() + client := request.NewAPIClient(t) + ctx := context.Background() + + validRepos := []string{"fooo/bar", "fooaa/test", "foooo:t", "HOSTNAME.DOMAIN.COM:443/foo/bar"} + + for _, repo := range validRepos { + err := client.ImageTag(ctx, "busybox", repo) + assert.NilError(t, err) + } +} + +// tag an image with an existed tag name without -f option should work +func TestTagExistedNameWithoutForce(t *testing.T) { + defer setupTest(t)() + client := request.NewAPIClient(t) + ctx := context.Background() + + err := client.ImageTag(ctx, "busybox:latest", "busybox:test") + assert.NilError(t, err) +} + +// ensure tagging using official names works +// ensure all tags result in the same name +func TestTagOfficialNames(t *testing.T) { + defer setupTest(t)() + client := request.NewAPIClient(t) + ctx := context.Background() + + names := []string{ + "docker.io/busybox", + "index.docker.io/busybox", + "library/busybox", + "docker.io/library/busybox", + "index.docker.io/library/busybox", + } + + for _, name := range names { + err := client.ImageTag(ctx, "busybox", name+":latest") + assert.NilError(t, err) + + // ensure we don't have multiple tag names. + insp, _, err := client.ImageInspectWithRaw(ctx, "busybox") + assert.NilError(t, err) + assert.Assert(t, !is.Contains(insp.RepoTags, name)().Success()) + } + + for _, name := range names { + err := client.ImageTag(ctx, name+":latest", "fooo/bar:latest") + assert.NilError(t, err) + } +} + +// ensure tags can not match digests +func TestTagMatchesDigest(t *testing.T) { + defer setupTest(t)() + client := request.NewAPIClient(t) + ctx := context.Background() + + digest := "busybox@sha256:abcdef76720241213f5303bda7704ec4c2ef75613173910a56fb1b6e20251507" + // test setting tag fails + err := client.ImageTag(ctx, "busybox:latest", digest) + testutil.ErrorContains(t, err, "refusing to create a tag with a digest reference") + // check that no new image matches the digest + _, _, err = client.ImageInspectWithRaw(ctx, digest) + testutil.ErrorContains(t, err, fmt.Sprintf("No such image: %s", digest)) +}