File: helpers.go

package info (click to toggle)
docker.io 18.09.1%2Bdfsg1-7.1%2Bdeb10u3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 66,144 kB
  • sloc: sh: 9,753; makefile: 827; ansic: 239; python: 162; asm: 10
file content (66 lines) | stat: -rw-r--r-- 2,294 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package swarm // import "github.com/docker/docker/api/server/router/swarm"

import (
	"context"
	"fmt"
	"io"
	"net/http"

	"github.com/docker/docker/api/server/httputils"
	basictypes "github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/backend"
)

// swarmLogs takes an http response, request, and selector, and writes the logs
// specified by the selector to the response
func (sr *swarmRouter) swarmLogs(ctx context.Context, w io.Writer, r *http.Request, selector *backend.LogSelector) error {
	// Args are validated before the stream starts because when it starts we're
	// sending HTTP 200 by writing an empty chunk of data to tell the client that
	// daemon is going to stream. By sending this initial HTTP 200 we can't report
	// any error after the stream starts (i.e. container not found, wrong parameters)
	// with the appropriate status code.
	stdout, stderr := httputils.BoolValue(r, "stdout"), httputils.BoolValue(r, "stderr")
	if !(stdout || stderr) {
		return fmt.Errorf("Bad parameters: you must choose at least one stream")
	}

	// there is probably a neater way to manufacture the ContainerLogsOptions
	// struct, probably in the caller, to eliminate the dependency on net/http
	logsConfig := &basictypes.ContainerLogsOptions{
		Follow:     httputils.BoolValue(r, "follow"),
		Timestamps: httputils.BoolValue(r, "timestamps"),
		Since:      r.Form.Get("since"),
		Tail:       r.Form.Get("tail"),
		ShowStdout: stdout,
		ShowStderr: stderr,
		Details:    httputils.BoolValue(r, "details"),
	}

	tty := false
	// checking for whether logs are TTY involves iterating over every service
	// and task. idk if there is a better way
	for _, service := range selector.Services {
		s, err := sr.backend.GetService(service, false)
		if err != nil {
			// maybe should return some context with this error?
			return err
		}
		tty = (s.Spec.TaskTemplate.ContainerSpec != nil && s.Spec.TaskTemplate.ContainerSpec.TTY) || tty
	}
	for _, task := range selector.Tasks {
		t, err := sr.backend.GetTask(task)
		if err != nil {
			// as above
			return err
		}
		tty = t.Spec.ContainerSpec.TTY || tty
	}

	msgs, err := sr.backend.ServiceLogs(ctx, selector, logsConfig)
	if err != nil {
		return err
	}

	httputils.WriteLogStream(ctx, w, msgs, logsConfig, !tty)
	return nil
}