service logs: Support no-follow mode

Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
This commit is contained in:
Andrea Luzzardi 2016-11-18 12:38:36 -08:00
parent e350d44dbe
commit c2d435e4f0
4 changed files with 44 additions and 13 deletions

View File

@ -237,10 +237,6 @@ func (sr *swarmRouter) getServiceLogs(ctx context.Context, w http.ResponseWriter
OutStream: w, OutStream: w,
} }
if !logsConfig.Follow {
return fmt.Errorf("Bad parameters: Only follow mode is currently supported")
}
if logsConfig.Details { if logsConfig.Details {
return fmt.Errorf("Bad parameters: details is not currently supported") return fmt.Errorf("Bad parameters: details is not currently supported")
} }

View File

@ -1275,7 +1275,7 @@ func (c *Cluster) ServiceLogs(ctx context.Context, input string, config *backend
ServiceIDs: []string{service.ID}, ServiceIDs: []string{service.ID},
}, },
Options: &swarmapi.LogSubscriptionOptions{ Options: &swarmapi.LogSubscriptionOptions{
Follow: true, Follow: config.Follow,
}, },
}) })
if err != nil { if err != nil {

View File

@ -419,7 +419,11 @@ func (c *containerAdapter) logs(ctx context.Context, options api.LogSubscription
} }
chStarted := make(chan struct{}) chStarted := make(chan struct{})
go c.backend.ContainerLogs(ctx, c.container.name(), apiOptions, chStarted) go func() {
defer writer.Close()
c.backend.ContainerLogs(ctx, c.container.name(), apiOptions, chStarted)
}()
return reader, nil return reader, nil
} }

View File

@ -4,6 +4,7 @@ package main
import ( import (
"bufio" "bufio"
"fmt"
"io" "io"
"os/exec" "os/exec"
"strings" "strings"
@ -24,7 +25,27 @@ func (s *DockerSwarmSuite) TestServiceLogs(c *check.C) {
name := "TestServiceLogs" name := "TestServiceLogs"
out, err := d.Cmd("service", "create", "--name", name, "busybox", "sh", "-c", "while true; do echo log test; sleep 1; done") out, err := d.Cmd("service", "create", "--name", name, "--restart-condition", "none", "busybox", "sh", "-c", "echo hello world")
c.Assert(err, checker.IsNil)
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
// make sure task has been deployed.
waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 1)
out, err = d.Cmd("service", "logs", name)
fmt.Println(out)
c.Assert(err, checker.IsNil)
c.Assert(out, checker.Contains, "hello world")
}
func (s *DockerSwarmSuite) TestServiceLogsFollow(c *check.C) {
testRequires(c, ExperimentalDaemon)
d := s.AddDaemon(c, true, true)
name := "TestServiceLogsFollow"
out, err := d.Cmd("service", "create", "--name", name, "busybox", "sh", "-c", "while true; do echo log test; sleep 0.1; done")
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
@ -40,16 +61,26 @@ func (s *DockerSwarmSuite) TestServiceLogs(c *check.C) {
// Make sure pipe is written to // Make sure pipe is written to
ch := make(chan *logMessage) ch := make(chan *logMessage)
done := make(chan struct{})
go func() { go func() {
reader := bufio.NewReader(r) reader := bufio.NewReader(r)
for {
msg := &logMessage{} msg := &logMessage{}
msg.data, _, msg.err = reader.ReadLine() msg.data, _, msg.err = reader.ReadLine()
ch <- msg select {
case ch <- msg:
case <-done:
return
}
}
}() }()
for i := 0; i < 3; i++ {
msg := <-ch msg := <-ch
c.Assert(msg.err, checker.IsNil) c.Assert(msg.err, checker.IsNil)
c.Assert(string(msg.data), checker.Contains, "log test") c.Assert(string(msg.data), checker.Contains, "log test")
}
close(done)
c.Assert(cmd.Process.Kill(), checker.IsNil) c.Assert(cmd.Process.Kill(), checker.IsNil)
} }