image_pull_test.go 5.8 KB

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