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