From 372981ccf80d4310adad2d78c3085de381a797ce Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Thu, 1 Feb 2024 16:59:05 -0500 Subject: [PATCH] fix attest reader when no TTY present Signed-off-by: Alex Goodman --- cmd/syft/internal/clio_setup_config.go | 17 +++++++++++-- cmd/syft/internal/ui/no_ui.go | 33 +++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/cmd/syft/internal/clio_setup_config.go b/cmd/syft/internal/clio_setup_config.go index d1a34a692..98aaf6a06 100644 --- a/cmd/syft/internal/clio_setup_config.go +++ b/cmd/syft/internal/clio_setup_config.go @@ -5,8 +5,10 @@ import ( "os" "github.com/anchore/clio" + "github.com/anchore/go-logger" + gologgerredact "github.com/anchore/go-logger/adapter/redact" "github.com/anchore/stereoscope" - ui2 "github.com/anchore/syft/cmd/syft/cli/ui" + handlers "github.com/anchore/syft/cmd/syft/cli/ui" "github.com/anchore/syft/cmd/syft/internal/ui" "github.com/anchore/syft/internal/bus" "github.com/anchore/syft/internal/log" @@ -18,6 +20,17 @@ func AppClioSetupConfig(id clio.Identification, out io.Writer) *clio.SetupConfig WithGlobalConfigFlag(). // add persistent -c for reading an application config from WithGlobalLoggingFlags(). // add persistent -v and -q flags tied to the logging config WithConfigInRootHelp(). // --help on the root command renders the full application config in the help text + WithLoggerConstructor( + func(cfg clio.Config, store gologgerredact.Store) (logger.Logger, error) { + if !cfg.Log.AllowUI(os.Stdin) && !cfg.Log.Quiet { + // this is a special case where the user has not explicitly disabled the UI, but the UI is not allowed + // due to the lack of a tty. In this case, we should default to info level. + cfg.Log.Level = logger.InfoLevel + cfg.Log.Verbosity = 1 + } + return clio.DefaultLogger(cfg, store) + }, + ). WithUIConstructor( // select a UI based on the logging configuration and state of stdin (if stdin is a tty) func(cfg clio.Config) ([]clio.UI, error) { @@ -28,7 +41,7 @@ func AppClioSetupConfig(id clio.Identification, out io.Writer) *clio.SetupConfig return []clio.UI{ ui.New(out, cfg.Log.Quiet, - ui2.New(ui2.DefaultHandlerConfig()), + handlers.New(handlers.DefaultHandlerConfig()), ), noUI, }, nil diff --git a/cmd/syft/internal/ui/no_ui.go b/cmd/syft/internal/ui/no_ui.go index a7a35a8cf..5c0979414 100644 --- a/cmd/syft/internal/ui/no_ui.go +++ b/cmd/syft/internal/ui/no_ui.go @@ -1,13 +1,17 @@ package ui import ( + "bufio" "io" "os" + "sync" "github.com/wagoodman/go-partybus" "github.com/anchore/clio" + "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/event" + syftEventParsers "github.com/anchore/syft/syft/event/parsers" ) var _ clio.UI = (*NoUI)(nil) @@ -18,6 +22,7 @@ type NoUI struct { finalizeEvents []partybus.Event subscription partybus.Unsubscribable quiet bool + wg *sync.WaitGroup } func None(out io.Writer, quiet bool) *NoUI { @@ -25,6 +30,7 @@ func None(out io.Writer, quiet bool) *NoUI { out: out, err: os.Stderr, quiet: quiet, + wg: &sync.WaitGroup{}, } } @@ -38,10 +44,35 @@ func (n *NoUI) Handle(e partybus.Event) error { case event.CLIReport, event.CLINotification: // keep these for when the UI is terminated to show to the screen (or perform other events) n.finalizeEvents = append(n.finalizeEvents, e) + + case event.AttestationStarted: + n.handleAttestationStarted(e) } return nil } -func (n NoUI) Teardown(_ bool) error { +func (n NoUI) Teardown(force bool) error { + if !force { + n.wg.Wait() + } return writeEvents(n.out, n.err, n.quiet, n.finalizeEvents...) } + +func (n *NoUI) handleAttestationStarted(e partybus.Event) { + n.wg.Add(1) + go func() { + defer n.wg.Done() + reader, _, _, err := syftEventParsers.ParseAttestationStartedEvent(e) + if err != nil { + log.WithFields("error", err).Warn("unable to parse event") + return + } + + s := bufio.NewScanner(reader) + + for s.Scan() { + text := s.Text() + log.Info("[COSIGN]", text) + } + }() +}