image_search_test.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package client // import "github.com/docker/docker/client"
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "net/http"
  9. "strings"
  10. "testing"
  11. "github.com/docker/docker/api/types"
  12. "github.com/docker/docker/api/types/filters"
  13. "github.com/docker/docker/api/types/registry"
  14. "github.com/docker/docker/errdefs"
  15. "gotest.tools/v3/assert"
  16. is "gotest.tools/v3/assert/cmp"
  17. )
  18. func TestImageSearchAnyError(t *testing.T) {
  19. client := &Client{
  20. client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
  21. }
  22. _, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{})
  23. assert.Check(t, is.ErrorType(err, errdefs.IsSystem))
  24. }
  25. func TestImageSearchStatusUnauthorizedError(t *testing.T) {
  26. client := &Client{
  27. client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")),
  28. }
  29. _, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{})
  30. assert.Check(t, is.ErrorType(err, errdefs.IsUnauthorized))
  31. }
  32. func TestImageSearchWithUnauthorizedErrorAndPrivilegeFuncError(t *testing.T) {
  33. client := &Client{
  34. client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")),
  35. }
  36. privilegeFunc := func() (string, error) {
  37. return "", fmt.Errorf("Error requesting privilege")
  38. }
  39. _, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{
  40. PrivilegeFunc: privilegeFunc,
  41. })
  42. if err == nil || err.Error() != "Error requesting privilege" {
  43. t.Fatalf("expected an error requesting privilege, got %v", err)
  44. }
  45. }
  46. func TestImageSearchWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T) {
  47. client := &Client{
  48. client: newMockClient(errorMock(http.StatusUnauthorized, "Unauthorized error")),
  49. }
  50. privilegeFunc := func() (string, error) {
  51. return "a-auth-header", nil
  52. }
  53. _, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{
  54. PrivilegeFunc: privilegeFunc,
  55. })
  56. assert.Check(t, is.ErrorType(err, errdefs.IsUnauthorized))
  57. }
  58. func TestImageSearchWithPrivilegedFuncNoError(t *testing.T) {
  59. expectedURL := "/images/search"
  60. client := &Client{
  61. client: newMockClient(func(req *http.Request) (*http.Response, error) {
  62. if !strings.HasPrefix(req.URL.Path, expectedURL) {
  63. return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
  64. }
  65. auth := req.Header.Get(registry.AuthHeader)
  66. if auth == "NotValid" {
  67. return &http.Response{
  68. StatusCode: http.StatusUnauthorized,
  69. Body: io.NopCloser(bytes.NewReader([]byte("Invalid credentials"))),
  70. }, nil
  71. }
  72. if auth != "IAmValid" {
  73. return nil, fmt.Errorf("invalid auth header: expected 'IAmValid', got %s", auth)
  74. }
  75. query := req.URL.Query()
  76. term := query.Get("term")
  77. if term != "some-image" {
  78. return nil, fmt.Errorf("term not set in URL query properly. Expected 'some-image', got %s", term)
  79. }
  80. content, err := json.Marshal([]registry.SearchResult{
  81. {
  82. Name: "anything",
  83. },
  84. })
  85. if err != nil {
  86. return nil, err
  87. }
  88. return &http.Response{
  89. StatusCode: http.StatusOK,
  90. Body: io.NopCloser(bytes.NewReader(content)),
  91. }, nil
  92. }),
  93. }
  94. privilegeFunc := func() (string, error) {
  95. return "IAmValid", nil
  96. }
  97. results, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{
  98. RegistryAuth: "NotValid",
  99. PrivilegeFunc: privilegeFunc,
  100. })
  101. if err != nil {
  102. t.Fatal(err)
  103. }
  104. if len(results) != 1 {
  105. t.Fatalf("expected 1 result, got %v", results)
  106. }
  107. }
  108. func TestImageSearchWithoutErrors(t *testing.T) {
  109. const expectedURL = "/images/search"
  110. const expectedFilters = `{"is-automated":{"true":true},"stars":{"3":true}}`
  111. client := &Client{
  112. client: newMockClient(func(req *http.Request) (*http.Response, error) {
  113. if !strings.HasPrefix(req.URL.Path, expectedURL) {
  114. return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
  115. }
  116. query := req.URL.Query()
  117. term := query.Get("term")
  118. if term != "some-image" {
  119. return nil, fmt.Errorf("term not set in URL query properly. Expected 'some-image', got %s", term)
  120. }
  121. fltrs := query.Get("filters")
  122. if fltrs != expectedFilters {
  123. return nil, fmt.Errorf("filters not set in URL query properly. Expected '%s', got %s", expectedFilters, fltrs)
  124. }
  125. content, err := json.Marshal([]registry.SearchResult{
  126. {
  127. Name: "anything",
  128. },
  129. })
  130. if err != nil {
  131. return nil, err
  132. }
  133. return &http.Response{
  134. StatusCode: http.StatusOK,
  135. Body: io.NopCloser(bytes.NewReader(content)),
  136. }, nil
  137. }),
  138. }
  139. results, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{
  140. Filters: filters.NewArgs(
  141. filters.Arg("is-automated", "true"),
  142. filters.Arg("stars", "3"),
  143. ),
  144. })
  145. if err != nil {
  146. t.Fatal(err)
  147. }
  148. if len(results) != 1 {
  149. t.Fatalf("expected a result, got %v", results)
  150. }
  151. }