Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"context" |
| 5 | 5 |
"io" |
| 6 | 6 |
"net/url" |
| 7 |
- "sync" |
|
| 8 | 7 |
"time" |
| 9 | 8 |
|
| 10 | 9 |
"github.com/moby/moby/client/internal/timestamp" |
| ... | ... |
@@ -24,9 +23,8 @@ type TaskLogsOptions struct {
|
| 24 | 24 |
|
| 25 | 25 |
// TaskLogsResult holds the result of a task logs operation. |
| 26 | 26 |
// It implements [io.ReadCloser]. |
| 27 |
-type TaskLogsResult struct {
|
|
| 28 |
- rc io.ReadCloser |
|
| 29 |
- close func() error |
|
| 27 |
+type TaskLogsResult interface {
|
|
| 28 |
+ io.ReadCloser |
|
| 30 | 29 |
} |
| 31 | 30 |
|
| 32 | 31 |
// TaskLogs returns the logs generated by a task. |
| ... | ... |
@@ -44,7 +42,7 @@ func (cli *Client) TaskLogs(ctx context.Context, taskID string, options TaskLogs |
| 44 | 44 |
if options.Since != "" {
|
| 45 | 45 |
ts, err := timestamp.GetTimestamp(options.Since, time.Now()) |
| 46 | 46 |
if err != nil {
|
| 47 |
- return TaskLogsResult{}, err
|
|
| 47 |
+ return nil, err |
|
| 48 | 48 |
} |
| 49 | 49 |
query.Set("since", ts)
|
| 50 | 50 |
} |
| ... | ... |
@@ -64,33 +62,33 @@ func (cli *Client) TaskLogs(ctx context.Context, taskID string, options TaskLogs |
| 64 | 64 |
|
| 65 | 65 |
resp, err := cli.get(ctx, "/tasks/"+taskID+"/logs", query, nil) |
| 66 | 66 |
if err != nil {
|
| 67 |
- return TaskLogsResult{}, err
|
|
| 67 |
+ return nil, err |
|
| 68 | 68 |
} |
| 69 |
- return newTaskLogsResult(resp.Body), nil |
|
| 69 |
+ return &taskLogsResult{
|
|
| 70 |
+ body: resp.Body, |
|
| 71 |
+ }, nil |
|
| 70 | 72 |
} |
| 71 | 73 |
|
| 72 |
-func newTaskLogsResult(rc io.ReadCloser) TaskLogsResult {
|
|
| 73 |
- if rc == nil {
|
|
| 74 |
- panic("nil io.ReadCloser")
|
|
| 75 |
- } |
|
| 76 |
- return TaskLogsResult{
|
|
| 77 |
- rc: rc, |
|
| 78 |
- close: sync.OnceValue(rc.Close), |
|
| 79 |
- } |
|
| 74 |
+type taskLogsResult struct {
|
|
| 75 |
+ // body must be closed to avoid a resource leak |
|
| 76 |
+ body io.ReadCloser |
|
| 80 | 77 |
} |
| 81 | 78 |
|
| 82 |
-// Read implements [io.ReadCloser] for LogsResult. |
|
| 83 |
-func (r TaskLogsResult) Read(p []byte) (n int, err error) {
|
|
| 84 |
- if r.rc == nil {
|
|
| 79 |
+var ( |
|
| 80 |
+ _ io.ReadCloser = (*taskLogsResult)(nil) |
|
| 81 |
+ _ ContainerLogsResult = (*taskLogsResult)(nil) |
|
| 82 |
+) |
|
| 83 |
+ |
|
| 84 |
+func (r *taskLogsResult) Read(p []byte) (int, error) {
|
|
| 85 |
+ if r == nil || r.body == nil {
|
|
| 85 | 86 |
return 0, io.EOF |
| 86 | 87 |
} |
| 87 |
- return r.rc.Read(p) |
|
| 88 |
+ return r.body.Read(p) |
|
| 88 | 89 |
} |
| 89 | 90 |
|
| 90 |
-// Close implements [io.ReadCloser] for LogsResult. |
|
| 91 |
-func (r TaskLogsResult) Close() error {
|
|
| 92 |
- if r.close == nil {
|
|
| 91 |
+func (r *taskLogsResult) Close() error {
|
|
| 92 |
+ if r == nil || r.body == nil {
|
|
| 93 | 93 |
return nil |
| 94 | 94 |
} |
| 95 |
- return r.close() |
|
| 95 |
+ return r.body.Close() |
|
| 96 | 96 |
} |
| ... | ... |
@@ -4,7 +4,6 @@ import ( |
| 4 | 4 |
"context" |
| 5 | 5 |
"io" |
| 6 | 6 |
"net/url" |
| 7 |
- "sync" |
|
| 8 | 7 |
"time" |
| 9 | 8 |
|
| 10 | 9 |
"github.com/moby/moby/client/internal/timestamp" |
| ... | ... |
@@ -24,9 +23,8 @@ type TaskLogsOptions struct {
|
| 24 | 24 |
|
| 25 | 25 |
// TaskLogsResult holds the result of a task logs operation. |
| 26 | 26 |
// It implements [io.ReadCloser]. |
| 27 |
-type TaskLogsResult struct {
|
|
| 28 |
- rc io.ReadCloser |
|
| 29 |
- close func() error |
|
| 27 |
+type TaskLogsResult interface {
|
|
| 28 |
+ io.ReadCloser |
|
| 30 | 29 |
} |
| 31 | 30 |
|
| 32 | 31 |
// TaskLogs returns the logs generated by a task. |
| ... | ... |
@@ -44,7 +42,7 @@ func (cli *Client) TaskLogs(ctx context.Context, taskID string, options TaskLogs |
| 44 | 44 |
if options.Since != "" {
|
| 45 | 45 |
ts, err := timestamp.GetTimestamp(options.Since, time.Now()) |
| 46 | 46 |
if err != nil {
|
| 47 |
- return TaskLogsResult{}, err
|
|
| 47 |
+ return nil, err |
|
| 48 | 48 |
} |
| 49 | 49 |
query.Set("since", ts)
|
| 50 | 50 |
} |
| ... | ... |
@@ -64,33 +62,33 @@ func (cli *Client) TaskLogs(ctx context.Context, taskID string, options TaskLogs |
| 64 | 64 |
|
| 65 | 65 |
resp, err := cli.get(ctx, "/tasks/"+taskID+"/logs", query, nil) |
| 66 | 66 |
if err != nil {
|
| 67 |
- return TaskLogsResult{}, err
|
|
| 67 |
+ return nil, err |
|
| 68 | 68 |
} |
| 69 |
- return newTaskLogsResult(resp.Body), nil |
|
| 69 |
+ return &taskLogsResult{
|
|
| 70 |
+ body: resp.Body, |
|
| 71 |
+ }, nil |
|
| 70 | 72 |
} |
| 71 | 73 |
|
| 72 |
-func newTaskLogsResult(rc io.ReadCloser) TaskLogsResult {
|
|
| 73 |
- if rc == nil {
|
|
| 74 |
- panic("nil io.ReadCloser")
|
|
| 75 |
- } |
|
| 76 |
- return TaskLogsResult{
|
|
| 77 |
- rc: rc, |
|
| 78 |
- close: sync.OnceValue(rc.Close), |
|
| 79 |
- } |
|
| 74 |
+type taskLogsResult struct {
|
|
| 75 |
+ // body must be closed to avoid a resource leak |
|
| 76 |
+ body io.ReadCloser |
|
| 80 | 77 |
} |
| 81 | 78 |
|
| 82 |
-// Read implements [io.ReadCloser] for LogsResult. |
|
| 83 |
-func (r TaskLogsResult) Read(p []byte) (n int, err error) {
|
|
| 84 |
- if r.rc == nil {
|
|
| 79 |
+var ( |
|
| 80 |
+ _ io.ReadCloser = (*taskLogsResult)(nil) |
|
| 81 |
+ _ ContainerLogsResult = (*taskLogsResult)(nil) |
|
| 82 |
+) |
|
| 83 |
+ |
|
| 84 |
+func (r *taskLogsResult) Read(p []byte) (int, error) {
|
|
| 85 |
+ if r == nil || r.body == nil {
|
|
| 85 | 86 |
return 0, io.EOF |
| 86 | 87 |
} |
| 87 |
- return r.rc.Read(p) |
|
| 88 |
+ return r.body.Read(p) |
|
| 88 | 89 |
} |
| 89 | 90 |
|
| 90 |
-// Close implements [io.ReadCloser] for LogsResult. |
|
| 91 |
-func (r TaskLogsResult) Close() error {
|
|
| 92 |
- if r.close == nil {
|
|
| 91 |
+func (r *taskLogsResult) Close() error {
|
|
| 92 |
+ if r == nil || r.body == nil {
|
|
| 93 | 93 |
return nil |
| 94 | 94 |
} |
| 95 |
- return r.close() |
|
| 95 |
+ return r.body.Close() |
|
| 96 | 96 |
} |