Merge pull request #381 from docker/fix-logs-windows

Get the real width of the terminal
This commit is contained in:
Guillaume Tardif 2020-07-10 13:06:07 +02:00 committed by GitHub
commit 1fbdbbbbe3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 40 additions and 18 deletions

View File

@ -27,7 +27,6 @@ import (
"github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance" "github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance"
"github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/to" "github.com/Azure/go-autorest/autorest/to"
"github.com/buger/goterm"
tm "github.com/buger/goterm" tm "github.com/buger/goterm"
"github.com/gobwas/ws" "github.com/gobwas/ws"
"github.com/gobwas/ws/wsutil" "github.com/gobwas/ws/wsutil"
@ -245,8 +244,7 @@ func getACIContainerLogs(ctx context.Context, aciContext store.AciContext, conta
return *logs.Content, err return *logs.Content, err
} }
func streamLogs(ctx context.Context, aciContext store.AciContext, containerGroupName, containerName string, out io.Writer) error { func streamLogs(ctx context.Context, aciContext store.AciContext, containerGroupName, containerName string, req containers.LogsRequest) error {
terminalWidth := goterm.Width()
numLines := 0 numLines := 0
for { for {
select { select {
@ -266,12 +264,12 @@ func streamLogs(ctx context.Context, aciContext store.AciContext, containerGroup
// a real logs streaming api soon. // a real logs streaming api soon.
b := aec.EmptyBuilder b := aec.EmptyBuilder
b = b.Up(uint(numLines)) b = b.Up(uint(numLines))
fmt.Fprint(out, b.Column(0).ANSI) fmt.Fprint(req.Writer, b.Column(0).ANSI)
numLines = getBacktrackLines(logLines, terminalWidth) numLines = getBacktrackLines(logLines, req.Width)
for i := 0; i < currentOutput-1; i++ { for i := 0; i < currentOutput-1; i++ {
fmt.Fprintln(out, logLines[i]) fmt.Fprintln(req.Writer, logLines[i])
} }
select { select {
@ -284,6 +282,9 @@ func streamLogs(ctx context.Context, aciContext store.AciContext, containerGroup
} }
func getBacktrackLines(lines []string, terminalWidth int) int { func getBacktrackLines(lines []string, terminalWidth int) int {
if terminalWidth == 0 { // no terminal width has been set, do not divide by zero
return len(lines)
}
numLines := 0 numLines := 0
for i := 0; i < len(lines)-1; i++ { for i := 0; i < len(lines)-1; i++ {
numLines++ numLines++

View File

@ -239,7 +239,7 @@ func (cs *aciContainerService) Logs(ctx context.Context, containerName string, r
var tail *int32 var tail *int32
if req.Follow { if req.Follow {
return streamLogs(ctx, cs.ctx, groupName, containerAciName, req.Writer) return streamLogs(ctx, cs.ctx, groupName, containerAciName, req)
} }
if req.Tail != "all" { if req.Tail != "all" {

View File

@ -57,16 +57,23 @@ func runLogs(ctx context.Context, containerName string, opts logsOpts) error {
if err != nil { if err != nil {
return errors.Wrap(err, "cannot connect to backend") return errors.Wrap(err, "cannot connect to backend")
} }
var con io.Writer = os.Stdout
if c, err := console.ConsoleFromFile(os.Stdout); err == nil {
con = c
}
req := containers.LogsRequest{ req := containers.LogsRequest{
Follow: opts.Follow, Follow: opts.Follow,
Tail: opts.Tail, Tail: opts.Tail,
Writer: con,
} }
var con io.Writer = os.Stdout
if c, err := console.ConsoleFromFile(os.Stdout); err == nil {
size, err := c.Size()
if err != nil {
return err
}
req.Width = int(size.Width)
con = c
}
req.Writer = con
return c.ContainerService().Logs(ctx, containerName, req) return c.ContainerService().Logs(ctx, containerName, req)
} }

View File

@ -73,19 +73,27 @@ func runRun(ctx context.Context, image string, opts run.Opts) error {
if err != nil { if err != nil {
return err return err
} }
if !opts.Detach { if !opts.Detach {
var con io.Writer = os.Stdout var con io.Writer = os.Stdout
req := containers.LogsRequest{
Follow: true,
}
if c, err := console.ConsoleFromFile(os.Stdout); err == nil { if c, err := console.ConsoleFromFile(os.Stdout); err == nil {
size, err := c.Size()
if err != nil {
return err
}
req.Width = int(size.Width)
con = c con = c
} }
req := containers.LogsRequest{ req.Writer = con
Follow: true,
Writer: con,
}
return c.ContainerService().Logs(ctx, opts.Name, req) return c.ContainerService().Logs(ctx, opts.Name, req)
} }
fmt.Println(opts.Name) fmt.Println(opts.Name)
return nil return nil
} }

View File

@ -86,6 +86,7 @@ type ExecRequest struct {
type LogsRequest struct { type LogsRequest struct {
Follow bool Follow bool
Tail string Tail string
Width int
Writer io.Writer Writer io.Writer
} }

View File

@ -142,13 +142,18 @@ func (s *E2eACISuite) TestACIRunSingleContainer() {
outChan := make(chan string) outChan := make(chan string)
go func() { go func() {
output, _ := ctx.Exec() output, err := ctx.Exec()
// check the process is cancelled by the test, not another unexpected error
Expect(err.Error()).To(ContainSubstring("timed out"))
outChan <- output outChan <- output
}() }()
// Ensure logs -- follow is strated before we curl nginx
time.Sleep(5 * time.Second)
s.NewCommand("curl", nginxExposedURL+"/test").ExecOrDie() s.NewCommand("curl", nginxExposedURL+"/test").ExecOrDie()
// Give the `logs --follow` a little time to get logs of the curl call // Give the `logs --follow` a little time to get logs of the curl call
time.Sleep(10 * time.Second) time.Sleep(5 * time.Second)
// Trigger a timeout to make ctx.Exec exit // Trigger a timeout to make ctx.Exec exit
timeChan <- time.Now() timeChan <- time.Now()