From 2ec74c2e66dd84d635c7eff39e9814bdb7123e7a Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Sat, 25 Jul 2020 23:35:52 -0700 Subject: [PATCH] docker-container: show logs on bootstrap error Signed-off-by: Tonis Tiigi --- driver/docker-container/driver.go | 51 ++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/driver/docker-container/driver.go b/driver/docker-container/driver.go index e9b24dde02c5..f949d2d4a4d5 100644 --- a/driver/docker-container/driver.go +++ b/driver/docker-container/driver.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "net" "os" + "syscall" "time" "github.com/docker/buildx/driver" @@ -44,7 +45,7 @@ func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error { if err := d.start(ctx, sub); err != nil { return err } - if err := d.wait(ctx); err != nil { + if err := d.wait(ctx, sub); err != nil { return err } return nil @@ -106,7 +107,7 @@ func (d *Driver) create(ctx context.Context, l progress.SubLogger) error { if err := d.start(ctx, l); err != nil { return err } - if err := d.wait(ctx); err != nil { + if err := d.wait(ctx, l); err != nil { return err } return nil @@ -116,11 +117,22 @@ func (d *Driver) create(ctx context.Context, l progress.SubLogger) error { return nil } -func (d *Driver) wait(ctx context.Context) error { +func (d *Driver) wait(ctx context.Context, l progress.SubLogger) error { try := 0 for { - if err := d.run(ctx, []string{"buildctl", "debug", "workers"}); err != nil { + bufStdout := &bytes.Buffer{} + bufStderr := &bytes.Buffer{} + if err := d.run(ctx, []string{"buildctl", "debug", "workers"}, bufStdout, bufStderr); err != nil { if try > 10 { + if err != nil { + d.copyLogs(context.TODO(), l) + if bufStdout.Len() != 0 { + l.Log(syscall.Stdout, bufStdout.Bytes()) + } + if bufStderr.Len() != 0 { + l.Log(syscall.Stderr, bufStderr.Bytes()) + } + } return err } select { @@ -135,6 +147,21 @@ func (d *Driver) wait(ctx context.Context) error { } } +func (d *Driver) copyLogs(ctx context.Context, l progress.SubLogger) error { + rc, err := d.DockerAPI.ContainerLogs(ctx, d.Name, types.ContainerLogsOptions{ + ShowStdout: true, ShowStderr: true, + }) + if err != nil { + return err + } + stdout := &logWriter{logger: l, stream: syscall.Stdout} + stderr := &logWriter{logger: l, stream: syscall.Stderr} + if _, err := stdcopy.StdCopy(stdout, stderr, rc); err != nil { + return err + } + return rc.Close() +} + func (d *Driver) exec(ctx context.Context, cmd []string) (string, net.Conn, error) { execConfig := types.ExecConfig{ Cmd: cmd, @@ -159,12 +186,12 @@ func (d *Driver) exec(ctx context.Context, cmd []string) (string, net.Conn, erro return execID, resp.Conn, nil } -func (d *Driver) run(ctx context.Context, cmd []string) error { +func (d *Driver) run(ctx context.Context, cmd []string, stdout, stderr io.Writer) (err error) { id, conn, err := d.exec(ctx, cmd) if err != nil { return err } - if _, err := io.Copy(ioutil.Discard, conn); err != nil { + if _, err := stdcopy.StdCopy(stdout, stderr, conn); err != nil { return err } conn.Close() @@ -259,7 +286,7 @@ func (d *Driver) Features() map[driver.Feature]bool { func demuxConn(c net.Conn) net.Conn { pr, pw := io.Pipe() // TODO: rewrite parser with Reader() to avoid goroutine switch - go stdcopy.StdCopy(pw, os.Stdout, c) + go stdcopy.StdCopy(pw, os.Stderr, c) return &demux{ Conn: c, Reader: pr, @@ -297,3 +324,13 @@ func readFileToTar(fn string) (*bytes.Buffer, error) { } return buf, nil } + +type logWriter struct { + logger progress.SubLogger + stream int +} + +func (l *logWriter) Write(dt []byte) (int, error) { + l.logger.Log(l.stream, dt) + return len(dt), nil +}