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  }