github.com/rish1988/moby@v25.0.2+incompatible/client/image_tag_test.go (about) 1 package client // import "github.com/docker/docker/client" 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "io" 8 "net/http" 9 "strings" 10 "testing" 11 12 "github.com/docker/docker/errdefs" 13 "github.com/docker/docker/testutil" 14 "gotest.tools/v3/assert" 15 is "gotest.tools/v3/assert/cmp" 16 ) 17 18 func TestImageTagError(t *testing.T) { 19 client := &Client{ 20 client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), 21 } 22 23 err := client.ImageTag(context.Background(), "image_id", "repo:tag") 24 assert.Check(t, is.ErrorType(err, errdefs.IsSystem)) 25 } 26 27 // Note: this is not testing all the InvalidReference as it's the responsibility 28 // of distribution/reference package. 29 func TestImageTagInvalidReference(t *testing.T) { 30 client := &Client{ 31 client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), 32 } 33 34 err := client.ImageTag(context.Background(), "image_id", "aa/asdf$$^/aa") 35 if err == nil || err.Error() != `Error parsing reference: "aa/asdf$$^/aa" is not a valid repository/tag: invalid reference format` { 36 t.Fatalf("expected ErrReferenceInvalidFormat, got %v", err) 37 } 38 } 39 40 // Ensure we don't allow the use of invalid repository names or tags; these tag operations should fail. 41 func TestImageTagInvalidSourceImageName(t *testing.T) { 42 ctx := context.Background() 43 44 client := &Client{ 45 client: newMockClient(errorMock(http.StatusInternalServerError, "client should not have made an API call")), 46 } 47 48 invalidRepos := []string{"fo$z$", "Foo@3cc", "Foo$3", "Foo*3", "Fo^3", "Foo!3", "F)xcz(", "fo%asd", "aa/asdf$$^/aa"} 49 for _, repo := range invalidRepos { 50 repo := repo 51 t.Run("invalidRepo/"+repo, func(t *testing.T) { 52 t.Parallel() 53 err := client.ImageTag(ctx, "busybox", repo) 54 assert.Check(t, is.ErrorContains(err, "not a valid repository/tag")) 55 }) 56 } 57 58 longTag := testutil.GenerateRandomAlphaOnlyString(121) 59 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} 60 for _, repotag := range invalidTags { 61 repotag := repotag 62 t.Run("invalidTag/"+repotag, func(t *testing.T) { 63 t.Parallel() 64 err := client.ImageTag(ctx, "busybox", repotag) 65 assert.Check(t, is.ErrorContains(err, "not a valid repository/tag")) 66 }) 67 } 68 69 t.Run("test repository name begin with '-'", func(t *testing.T) { 70 t.Parallel() 71 err := client.ImageTag(ctx, "busybox:latest", "-busybox:test") 72 assert.Check(t, is.ErrorContains(err, "Error parsing reference")) 73 }) 74 75 t.Run("test namespace name begin with '-'", func(t *testing.T) { 76 t.Parallel() 77 err := client.ImageTag(ctx, "busybox:latest", "-test/busybox:test") 78 assert.Check(t, is.ErrorContains(err, "Error parsing reference")) 79 }) 80 81 t.Run("test index name begin with '-'", func(t *testing.T) { 82 t.Parallel() 83 err := client.ImageTag(ctx, "busybox:latest", "-index:5000/busybox:test") 84 assert.Check(t, is.ErrorContains(err, "Error parsing reference")) 85 }) 86 } 87 88 func TestImageTagHexSource(t *testing.T) { 89 client := &Client{ 90 client: newMockClient(errorMock(http.StatusOK, "OK")), 91 } 92 93 err := client.ImageTag(context.Background(), "0d409d33b27e47423b049f7f863faa08655a8c901749c2b25b93ca67d01a470d", "repo:tag") 94 if err != nil { 95 t.Fatalf("got error: %v", err) 96 } 97 } 98 99 func TestImageTag(t *testing.T) { 100 expectedURL := "/images/image_id/tag" 101 tagCases := []struct { 102 reference string 103 expectedQueryParams map[string]string 104 }{ 105 { 106 reference: "repository:tag1", 107 expectedQueryParams: map[string]string{ 108 "repo": "repository", 109 "tag": "tag1", 110 }, 111 }, { 112 reference: "another_repository:latest", 113 expectedQueryParams: map[string]string{ 114 "repo": "another_repository", 115 "tag": "latest", 116 }, 117 }, { 118 reference: "another_repository", 119 expectedQueryParams: map[string]string{ 120 "repo": "another_repository", 121 "tag": "latest", 122 }, 123 }, { 124 reference: "test/another_repository", 125 expectedQueryParams: map[string]string{ 126 "repo": "test/another_repository", 127 "tag": "latest", 128 }, 129 }, { 130 reference: "test/another_repository:tag1", 131 expectedQueryParams: map[string]string{ 132 "repo": "test/another_repository", 133 "tag": "tag1", 134 }, 135 }, { 136 reference: "test/test/another_repository:tag1", 137 expectedQueryParams: map[string]string{ 138 "repo": "test/test/another_repository", 139 "tag": "tag1", 140 }, 141 }, { 142 reference: "test:5000/test/another_repository:tag1", 143 expectedQueryParams: map[string]string{ 144 "repo": "test:5000/test/another_repository", 145 "tag": "tag1", 146 }, 147 }, { 148 reference: "test:5000/test/another_repository", 149 expectedQueryParams: map[string]string{ 150 "repo": "test:5000/test/another_repository", 151 "tag": "latest", 152 }, 153 }, 154 } 155 for _, tagCase := range tagCases { 156 client := &Client{ 157 client: newMockClient(func(req *http.Request) (*http.Response, error) { 158 if !strings.HasPrefix(req.URL.Path, expectedURL) { 159 return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, req.URL) 160 } 161 if req.Method != http.MethodPost { 162 return nil, fmt.Errorf("expected POST method, got %s", req.Method) 163 } 164 query := req.URL.Query() 165 for key, expected := range tagCase.expectedQueryParams { 166 actual := query.Get(key) 167 if actual != expected { 168 return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual) 169 } 170 } 171 return &http.Response{ 172 StatusCode: http.StatusOK, 173 Body: io.NopCloser(bytes.NewReader([]byte(""))), 174 }, nil 175 }), 176 } 177 err := client.ImageTag(context.Background(), "image_id", tagCase.reference) 178 if err != nil { 179 t.Fatal(err) 180 } 181 } 182 }