github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/client/image_push_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/api/types" 13 "github.com/docker/docker/errdefs" 14 ) 15 16 func TestImagePushReferenceError(t *testing.T) { 17 client := &Client{ 18 client: newMockClient(func(req *http.Request) (*http.Response, error) { 19 return nil, nil 20 }), 21 } 22 // An empty reference is an invalid reference 23 _, err := client.ImagePush(context.Background(), "", types.ImagePushOptions{}) 24 if err == nil || !strings.Contains(err.Error(), "invalid reference format") { 25 t.Fatalf("expected an error, got %v", err) 26 } 27 // An canonical reference cannot be pushed 28 _, err = client.ImagePush(context.Background(), "repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", types.ImagePushOptions{}) 29 if err == nil || err.Error() != "cannot push a digest reference" { 30 t.Fatalf("expected an error, got %v", err) 31 } 32 } 33 34 func TestImagePushAnyError(t *testing.T) { 35 client := &Client{ 36 client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), 37 } 38 _, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{}) 39 if !errdefs.IsSystem(err) { 40 t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err) 41 } 42 } 43 44 func TestImagePushStatusUnauthorizedError(t *testing.T) { 45 client := &Client{ 46 client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")), 47 } 48 _, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{}) 49 if !errdefs.IsUnauthorized(err) { 50 t.Fatalf("expected a Unauthorized Error, got %[1]T: %[1]v", err) 51 } 52 } 53 54 func TestImagePushWithUnauthorizedErrorAndPrivilegeFuncError(t *testing.T) { 55 client := &Client{ 56 client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")), 57 } 58 privilegeFunc := func() (string, error) { 59 return "", fmt.Errorf("Error requesting privilege") 60 } 61 _, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{ 62 PrivilegeFunc: privilegeFunc, 63 }) 64 if err == nil || err.Error() != "Error requesting privilege" { 65 t.Fatalf("expected an error requesting privilege, got %v", err) 66 } 67 } 68 69 func TestImagePushWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T) { 70 client := &Client{ 71 client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")), 72 } 73 privilegeFunc := func() (string, error) { 74 return "a-auth-header", nil 75 } 76 _, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{ 77 PrivilegeFunc: privilegeFunc, 78 }) 79 if !errdefs.IsUnauthorized(err) { 80 t.Fatalf("expected a Unauthorized Error, got %[1]T: %[1]v", err) 81 } 82 } 83 84 func TestImagePushWithPrivilegedFuncNoError(t *testing.T) { 85 expectedURL := "/images/myimage/push" 86 client := &Client{ 87 client: newMockClient(func(req *http.Request) (*http.Response, error) { 88 if !strings.HasPrefix(req.URL.Path, expectedURL) { 89 return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) 90 } 91 auth := req.Header.Get("X-Registry-Auth") 92 if auth == "NotValid" { 93 return &http.Response{ 94 StatusCode: http.StatusUnauthorized, 95 Body: io.NopCloser(bytes.NewReader([]byte("Invalid credentials"))), 96 }, nil 97 } 98 if auth != "IAmValid" { 99 return nil, fmt.Errorf("Invalid auth header : expected %s, got %s", "IAmValid", auth) 100 } 101 query := req.URL.Query() 102 tag := query.Get("tag") 103 if tag != "tag" { 104 return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", "tag", tag) 105 } 106 return &http.Response{ 107 StatusCode: http.StatusOK, 108 Body: io.NopCloser(bytes.NewReader([]byte("hello world"))), 109 }, nil 110 }), 111 } 112 privilegeFunc := func() (string, error) { 113 return "IAmValid", nil 114 } 115 resp, err := client.ImagePush(context.Background(), "myimage:tag", types.ImagePushOptions{ 116 RegistryAuth: "NotValid", 117 PrivilegeFunc: privilegeFunc, 118 }) 119 if err != nil { 120 t.Fatal(err) 121 } 122 body, err := io.ReadAll(resp) 123 if err != nil { 124 t.Fatal(err) 125 } 126 if string(body) != "hello world" { 127 t.Fatalf("expected 'hello world', got %s", string(body)) 128 } 129 } 130 131 func TestImagePushWithoutErrors(t *testing.T) { 132 expectedOutput := "hello world" 133 expectedURLFormat := "/images/%s/push" 134 testCases := []struct { 135 all bool 136 reference string 137 expectedImage string 138 expectedTag string 139 }{ 140 { 141 all: false, 142 reference: "myimage", 143 expectedImage: "myimage", 144 expectedTag: "latest", 145 }, 146 { 147 all: false, 148 reference: "myimage:tag", 149 expectedImage: "myimage", 150 expectedTag: "tag", 151 }, 152 { 153 all: true, 154 reference: "myimage", 155 expectedImage: "myimage", 156 expectedTag: "", 157 }, 158 { 159 all: true, 160 reference: "myimage:anything", 161 expectedImage: "myimage", 162 expectedTag: "", 163 }, 164 } 165 for _, tc := range testCases { 166 tc := tc 167 t.Run(fmt.Sprintf("%s,all-tags=%t", tc.reference, tc.all), func(t *testing.T) { 168 client := &Client{ 169 client: newMockClient(func(req *http.Request) (*http.Response, error) { 170 expectedURL := fmt.Sprintf(expectedURLFormat, tc.expectedImage) 171 if !strings.HasPrefix(req.URL.Path, expectedURL) { 172 return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) 173 } 174 query := req.URL.Query() 175 tag := query.Get("tag") 176 if tag != tc.expectedTag { 177 return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", tc.expectedTag, tag) 178 } 179 return &http.Response{ 180 StatusCode: http.StatusOK, 181 Body: io.NopCloser(bytes.NewReader([]byte(expectedOutput))), 182 }, nil 183 }), 184 } 185 resp, err := client.ImagePush(context.Background(), tc.reference, types.ImagePushOptions{ 186 All: tc.all, 187 }) 188 if err != nil { 189 t.Fatal(err) 190 } 191 body, err := io.ReadAll(resp) 192 if err != nil { 193 t.Fatal(err) 194 } 195 if string(body) != expectedOutput { 196 t.Fatalf("expected '%s', got %s", expectedOutput, string(body)) 197 } 198 }) 199 } 200 }