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