service_logs_test.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package client // import "github.com/docker/docker/client"
  2. import (
  3. "bytes"
  4. "context"
  5. "fmt"
  6. "io"
  7. "log"
  8. "net/http"
  9. "os"
  10. "strings"
  11. "testing"
  12. "time"
  13. "github.com/docker/docker/api/types/container"
  14. "github.com/docker/docker/errdefs"
  15. "gotest.tools/v3/assert"
  16. is "gotest.tools/v3/assert/cmp"
  17. )
  18. func TestServiceLogsError(t *testing.T) {
  19. client := &Client{
  20. client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
  21. }
  22. _, err := client.ServiceLogs(context.Background(), "service_id", container.LogsOptions{})
  23. assert.Check(t, is.ErrorType(err, errdefs.IsSystem))
  24. _, err = client.ServiceLogs(context.Background(), "service_id", container.LogsOptions{
  25. Since: "2006-01-02TZ",
  26. })
  27. assert.Check(t, is.ErrorContains(err, `parsing time "2006-01-02TZ"`))
  28. }
  29. func TestServiceLogs(t *testing.T) {
  30. expectedURL := "/services/service_id/logs"
  31. cases := []struct {
  32. options container.LogsOptions
  33. expectedQueryParams map[string]string
  34. expectedError string
  35. }{
  36. {
  37. expectedQueryParams: map[string]string{
  38. "tail": "",
  39. },
  40. },
  41. {
  42. options: container.LogsOptions{
  43. Tail: "any",
  44. },
  45. expectedQueryParams: map[string]string{
  46. "tail": "any",
  47. },
  48. },
  49. {
  50. options: container.LogsOptions{
  51. ShowStdout: true,
  52. ShowStderr: true,
  53. Timestamps: true,
  54. Details: true,
  55. Follow: true,
  56. },
  57. expectedQueryParams: map[string]string{
  58. "tail": "",
  59. "stdout": "1",
  60. "stderr": "1",
  61. "timestamps": "1",
  62. "details": "1",
  63. "follow": "1",
  64. },
  65. },
  66. {
  67. options: container.LogsOptions{
  68. // timestamp will be passed as is
  69. Since: "1136073600.000000001",
  70. },
  71. expectedQueryParams: map[string]string{
  72. "tail": "",
  73. "since": "1136073600.000000001",
  74. },
  75. },
  76. {
  77. options: container.LogsOptions{
  78. // An complete invalid date will not be passed
  79. Since: "invalid value",
  80. },
  81. expectedError: `invalid value for "since": failed to parse value as time or duration: "invalid value"`,
  82. },
  83. }
  84. for _, logCase := range cases {
  85. client := &Client{
  86. client: newMockClient(func(r *http.Request) (*http.Response, error) {
  87. if !strings.HasPrefix(r.URL.Path, expectedURL) {
  88. return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, r.URL)
  89. }
  90. // Check query parameters
  91. query := r.URL.Query()
  92. for key, expected := range logCase.expectedQueryParams {
  93. actual := query.Get(key)
  94. if actual != expected {
  95. return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual)
  96. }
  97. }
  98. return &http.Response{
  99. StatusCode: http.StatusOK,
  100. Body: io.NopCloser(bytes.NewReader([]byte("response"))),
  101. }, nil
  102. }),
  103. }
  104. body, err := client.ServiceLogs(context.Background(), "service_id", logCase.options)
  105. if logCase.expectedError != "" {
  106. assert.Check(t, is.Error(err, logCase.expectedError))
  107. continue
  108. }
  109. assert.NilError(t, err)
  110. defer body.Close()
  111. content, err := io.ReadAll(body)
  112. assert.NilError(t, err)
  113. assert.Check(t, is.Contains(string(content), "response"))
  114. }
  115. }
  116. func ExampleClient_ServiceLogs_withTimeout() {
  117. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  118. defer cancel()
  119. client, _ := NewClientWithOpts(FromEnv)
  120. reader, err := client.ServiceLogs(ctx, "service_id", container.LogsOptions{})
  121. if err != nil {
  122. log.Fatal(err)
  123. }
  124. _, err = io.Copy(os.Stdout, reader)
  125. if err != nil && err != io.EOF {
  126. log.Fatal(err)
  127. }
  128. }