image_push_test.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package client
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io/ioutil"
  6. "net/http"
  7. "strings"
  8. "testing"
  9. "golang.org/x/net/context"
  10. "github.com/docker/docker/api/types"
  11. )
  12. func TestImagePushReferenceError(t *testing.T) {
  13. client := &Client{
  14. client: newMockClient(func(req *http.Request) (*http.Response, error) {
  15. return nil, nil
  16. }),
  17. }
  18. // An empty reference is an invalid reference
  19. _, err := client.ImagePush(context.Background(), "", types.ImagePushOptions{})
  20. if err == nil || !strings.Contains(err.Error(), "invalid reference format") {
  21. t.Fatalf("expected an error, got %v", err)
  22. }
  23. // An canonical reference cannot be pushed
  24. _, err = client.ImagePush(context.Background(), "repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", types.ImagePushOptions{})
  25. if err == nil || err.Error() != "cannot push a digest reference" {
  26. t.Fatalf("expected an error, got %v", err)
  27. }
  28. }
  29. func TestImagePushAnyError(t *testing.T) {
  30. client := &Client{
  31. client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
  32. }
  33. _, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{})
  34. if err == nil || err.Error() != "Error response from daemon: Server error" {
  35. t.Fatalf("expected a Server Error, got %v", err)
  36. }
  37. }
  38. func TestImagePushStatusUnauthorizedError(t *testing.T) {
  39. client := &Client{
  40. client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")),
  41. }
  42. _, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{})
  43. if err == nil || err.Error() != "Error response from daemon: Unauthorized error" {
  44. t.Fatalf("expected an Unauthorized Error, got %v", err)
  45. }
  46. }
  47. func TestImagePushWithUnauthorizedErrorAndPrivilegeFuncError(t *testing.T) {
  48. client := &Client{
  49. client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")),
  50. }
  51. privilegeFunc := func() (string, error) {
  52. return "", fmt.Errorf("Error requesting privilege")
  53. }
  54. _, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{
  55. PrivilegeFunc: privilegeFunc,
  56. })
  57. if err == nil || err.Error() != "Error requesting privilege" {
  58. t.Fatalf("expected an error requesting privilege, got %v", err)
  59. }
  60. }
  61. func TestImagePushWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T) {
  62. client := &Client{
  63. client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")),
  64. }
  65. privilegeFunc := func() (string, error) {
  66. return "a-auth-header", nil
  67. }
  68. _, err := client.ImagePush(context.Background(), "myimage", types.ImagePushOptions{
  69. PrivilegeFunc: privilegeFunc,
  70. })
  71. if err == nil || err.Error() != "Error response from daemon: Unauthorized error" {
  72. t.Fatalf("expected an Unauthorized Error, got %v", err)
  73. }
  74. }
  75. func TestImagePushWithPrivilegedFuncNoError(t *testing.T) {
  76. expectedURL := "/images/myimage/push"
  77. client := &Client{
  78. client: newMockClient(func(req *http.Request) (*http.Response, error) {
  79. if !strings.HasPrefix(req.URL.Path, expectedURL) {
  80. return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
  81. }
  82. auth := req.Header.Get("X-Registry-Auth")
  83. if auth == "NotValid" {
  84. return &http.Response{
  85. StatusCode: http.StatusUnauthorized,
  86. Body: ioutil.NopCloser(bytes.NewReader([]byte("Invalid credentials"))),
  87. }, nil
  88. }
  89. if auth != "IAmValid" {
  90. return nil, fmt.Errorf("Invalid auth header : expected %s, got %s", "IAmValid", auth)
  91. }
  92. query := req.URL.Query()
  93. tag := query.Get("tag")
  94. if tag != "tag" {
  95. return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", "tag", tag)
  96. }
  97. return &http.Response{
  98. StatusCode: http.StatusOK,
  99. Body: ioutil.NopCloser(bytes.NewReader([]byte("hello world"))),
  100. }, nil
  101. }),
  102. }
  103. privilegeFunc := func() (string, error) {
  104. return "IAmValid", nil
  105. }
  106. resp, err := client.ImagePush(context.Background(), "myimage:tag", types.ImagePushOptions{
  107. RegistryAuth: "NotValid",
  108. PrivilegeFunc: privilegeFunc,
  109. })
  110. if err != nil {
  111. t.Fatal(err)
  112. }
  113. body, err := ioutil.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 TestImagePushWithoutErrors(t *testing.T) {
  122. expectedOutput := "hello world"
  123. expectedURLFormat := "/images/%s/push"
  124. pullCases := []struct {
  125. reference string
  126. expectedImage string
  127. expectedTag string
  128. }{
  129. {
  130. reference: "myimage",
  131. expectedImage: "myimage",
  132. expectedTag: "",
  133. },
  134. {
  135. reference: "myimage:tag",
  136. expectedImage: "myimage",
  137. expectedTag: "tag",
  138. },
  139. }
  140. for _, pullCase := range pullCases {
  141. client := &Client{
  142. client: newMockClient(func(req *http.Request) (*http.Response, error) {
  143. expectedURL := fmt.Sprintf(expectedURLFormat, pullCase.expectedImage)
  144. if !strings.HasPrefix(req.URL.Path, expectedURL) {
  145. return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
  146. }
  147. query := req.URL.Query()
  148. tag := query.Get("tag")
  149. if tag != pullCase.expectedTag {
  150. return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", pullCase.expectedTag, tag)
  151. }
  152. return &http.Response{
  153. StatusCode: http.StatusOK,
  154. Body: ioutil.NopCloser(bytes.NewReader([]byte(expectedOutput))),
  155. }, nil
  156. }),
  157. }
  158. resp, err := client.ImagePush(context.Background(), pullCase.reference, types.ImagePushOptions{})
  159. if err != nil {
  160. t.Fatal(err)
  161. }
  162. body, err := ioutil.ReadAll(resp)
  163. if err != nil {
  164. t.Fatal(err)
  165. }
  166. if string(body) != expectedOutput {
  167. t.Fatalf("expected '%s', got %s", expectedOutput, string(body))
  168. }
  169. }
  170. }