github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/api/server/router/swarm/helpers.go (about) 1 package swarm 2 3 import ( 4 "fmt" 5 "net/http" 6 7 "github.com/docker/docker/api/server/httputils" 8 basictypes "github.com/docker/docker/api/types" 9 "github.com/docker/docker/api/types/backend" 10 "golang.org/x/net/context" 11 ) 12 13 // swarmLogs takes an http response, request, and selector, and writes the logs 14 // specified by the selector to the response 15 func (sr *swarmRouter) swarmLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, selector *backend.LogSelector) error { 16 // Args are validated before the stream starts because when it starts we're 17 // sending HTTP 200 by writing an empty chunk of data to tell the client that 18 // daemon is going to stream. By sending this initial HTTP 200 we can't report 19 // any error after the stream starts (i.e. container not found, wrong parameters) 20 // with the appropriate status code. 21 stdout, stderr := httputils.BoolValue(r, "stdout"), httputils.BoolValue(r, "stderr") 22 if !(stdout || stderr) { 23 return fmt.Errorf("Bad parameters: you must choose at least one stream") 24 } 25 26 // there is probably a neater way to manufacture the ContainerLogsOptions 27 // struct, probably in the caller, to eliminate the dependency on net/http 28 logsConfig := &basictypes.ContainerLogsOptions{ 29 Follow: httputils.BoolValue(r, "follow"), 30 Timestamps: httputils.BoolValue(r, "timestamps"), 31 Since: r.Form.Get("since"), 32 Tail: r.Form.Get("tail"), 33 ShowStdout: stdout, 34 ShowStderr: stderr, 35 Details: httputils.BoolValue(r, "details"), 36 } 37 38 tty := false 39 // checking for whether logs are TTY involves iterating over every service 40 // and task. idk if there is a better way 41 for _, service := range selector.Services { 42 s, err := sr.backend.GetService(service, false) 43 if err != nil { 44 // maybe should return some context with this error? 45 return err 46 } 47 tty = s.Spec.TaskTemplate.ContainerSpec.TTY || tty 48 } 49 for _, task := range selector.Tasks { 50 t, err := sr.backend.GetTask(task) 51 if err != nil { 52 // as above 53 return err 54 } 55 tty = t.Spec.ContainerSpec.TTY || tty 56 } 57 58 msgs, err := sr.backend.ServiceLogs(ctx, selector, logsConfig) 59 if err != nil { 60 return err 61 } 62 63 httputils.WriteLogStream(ctx, w, msgs, logsConfig, !tty) 64 return nil 65 }