progress: explicitly fail if tty requested but not available

The NewPrinter function is mostly borrowed from buildkit. However, at
some point, it seems that the implementations drifted.

This patch updates buildx to be more similar in behavior to it's
buildkit counterpart, specifically, it will explicitly fail if a TTY
output is requested using "--progress=tty", but the output is not
available.

To gracefully fallback to plain progress in this scenario,
"--progress=plain" is required.

Signed-off-by: Justin Chadwell <me@jedevc.com>
pull/1371/head
Justin Chadwell 2 years ago
parent e84ed65525
commit a50e89c38e

@ -75,7 +75,10 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error
ctx2, cancel := context.WithCancel(context.TODO()) ctx2, cancel := context.WithCancel(context.TODO())
defer cancel() defer cancel()
printer := progress.NewPrinter(ctx2, os.Stderr, os.Stderr, in.progress) printer, err := progress.NewPrinter(ctx2, os.Stderr, os.Stderr, in.progress)
if err != nil {
return err
}
defer func() { defer func() {
if printer != nil { if printer != nil {

@ -109,7 +109,7 @@ func runBuild(dockerCli command.Cli, in buildOptions) (err error) {
return errors.Errorf("--no-cache and --no-cache-filter cannot currently be used together") return errors.Errorf("--no-cache and --no-cache-filter cannot currently be used together")
} }
if in.quiet && in.progress != "auto" && in.progress != "quiet" { if in.quiet && in.progress != progress.PrinterModeAuto && in.progress != progress.PrinterModeQuiet {
return errors.Errorf("progress=%s and quiet cannot be used together", in.progress) return errors.Errorf("progress=%s and quiet cannot be used together", in.progress)
} else if in.quiet { } else if in.quiet {
in.progress = "quiet" in.progress = "quiet"
@ -284,7 +284,10 @@ func buildTargets(ctx context.Context, dockerCli command.Cli, opts map[string]bu
ctx2, cancel := context.WithCancel(context.TODO()) ctx2, cancel := context.WithCancel(context.TODO())
defer cancel() defer cancel()
printer := progress.NewPrinter(ctx2, os.Stderr, os.Stderr, progressMode) printer, err := progress.NewPrinter(ctx2, os.Stderr, os.Stderr, progressMode)
if err != nil {
return "", nil, err
}
var mu sync.Mutex var mu sync.Mutex
var idx int var idx int

@ -182,7 +182,10 @@ func runCreate(dockerCli command.Cli, in createOptions, args []string) error {
ctx2, cancel := context.WithCancel(context.TODO()) ctx2, cancel := context.WithCancel(context.TODO())
defer cancel() defer cancel()
printer := progress.NewPrinter(ctx2, os.Stderr, os.Stderr, in.progress) printer, err := progress.NewPrinter(ctx2, os.Stderr, os.Stderr, in.progress)
if err != nil {
return err
}
eg, _ := errgroup.WithContext(ctx) eg, _ := errgroup.WithContext(ctx)
pw := progress.WithPrefix(printer, "internal", true) pw := progress.WithPrefix(printer, "internal", true)

@ -460,7 +460,10 @@ func boot(ctx context.Context, ngi *nginfo) (bool, error) {
return false, nil return false, nil
} }
printer := progress.NewPrinter(context.TODO(), os.Stderr, os.Stderr, "auto") printer, err := progress.NewPrinter(context.TODO(), os.Stderr, os.Stderr, progress.PrinterModeAuto)
if err != nil {
return false, err
}
baseCtx := ctx baseCtx := ctx
eg, _ := errgroup.WithContext(ctx) eg, _ := errgroup.WithContext(ctx)
@ -477,7 +480,7 @@ func boot(ctx context.Context, ngi *nginfo) (bool, error) {
}(idx) }(idx)
} }
err := eg.Wait() err = eg.Wait()
err1 := printer.Wait() err1 := printer.Wait()
if err == nil { if err == nil {
err = err1 err = err1

@ -11,6 +11,7 @@ import (
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
"github.com/moby/buildkit/util/progress/progressui" "github.com/moby/buildkit/util/progress/progressui"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -69,7 +70,7 @@ func (p *Printer) ClearLogSource(v interface{}) {
} }
} }
func NewPrinter(ctx context.Context, w io.Writer, out console.File, mode string) *Printer { func NewPrinter(ctx context.Context, w io.Writer, out console.File, mode string) (*Printer, error) {
statusCh := make(chan *client.SolveStatus) statusCh := make(chan *client.SolveStatus)
doneCh := make(chan struct{}) doneCh := make(chan struct{})
@ -83,7 +84,6 @@ func NewPrinter(ctx context.Context, w io.Writer, out console.File, mode string)
mode = v mode = v
} }
go func() {
var c console.Console var c console.Console
switch mode { switch mode {
case PrinterModeQuiet: case PrinterModeQuiet:
@ -91,13 +91,19 @@ func NewPrinter(ctx context.Context, w io.Writer, out console.File, mode string)
case PrinterModeAuto, PrinterModeTty: case PrinterModeAuto, PrinterModeTty:
if cons, err := console.ConsoleFromFile(out); err == nil { if cons, err := console.ConsoleFromFile(out); err == nil {
c = cons c = cons
} else {
if mode == PrinterModeTty {
return nil, errors.Wrap(err, "failed to get console")
}
} }
} }
go func() {
resumeLogs := logutil.Pause(logrus.StandardLogger()) resumeLogs := logutil.Pause(logrus.StandardLogger())
// not using shared context to not disrupt display but let is finish reporting errors // not using shared context to not disrupt display but let is finish reporting errors
pw.warnings, pw.err = progressui.DisplaySolveStatus(ctx, "", c, w, statusCh) pw.warnings, pw.err = progressui.DisplaySolveStatus(ctx, "", c, w, statusCh)
resumeLogs() resumeLogs()
close(doneCh) close(doneCh)
}() }()
return pw return pw, nil
} }

Loading…
Cancel
Save