diff --git a/cmd/cmd.go b/cmd/cmd.go index 0c9b3830e..274706dd5 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -90,7 +90,7 @@ func initAppConfig() { } func initLogging() { - config := logger.LogConfig{ + cfg := logger.LogConfig{ EnableConsole: (appConfig.Log.FileLocation == "" || appConfig.CliOptions.Verbosity > 0) && !appConfig.Quiet, EnableFile: appConfig.Log.FileLocation != "", Level: appConfig.Log.LevelOpt, @@ -98,7 +98,7 @@ func initLogging() { FileLocation: appConfig.Log.FileLocation, } - logWrapper := logger.NewZapLogger(config) + logWrapper := logger.NewZapLogger(cfg) syft.SetLogger(logWrapper) stereoscope.SetLogger(logWrapper) } diff --git a/cmd/root.go b/cmd/root.go index 1ab8e1243..d4bd4ebd5 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -55,6 +55,8 @@ func startWorker(userInput string) <-chan error { Type: event.AppUpdateAvailable, Value: newVersion, }) + } else { + log.Debugf("No new %s update available", internal.ApplicationName) } } diff --git a/go.mod b/go.mod index 605a21b24..30573bcc0 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/wagoodman/go-partybus v0.0.0-20200526224238-eb215533f07d github.com/wagoodman/go-progress v0.0.0-20200621153512-2778c704bf22 github.com/wagoodman/go-rpmdb v0.0.0-20200719223757-ce54a4b0607b - github.com/wagoodman/jotframe v0.0.0-20200622123948-2995cbd43525 + github.com/wagoodman/jotframe v0.0.0-20200730190914-3517092dd163 go.uber.org/zap v1.15.0 golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 golang.org/x/sys v0.0.0-20200610111108-226ff32320da // indirect diff --git a/go.sum b/go.sum index c8bb6cd66..8e4cd5482 100644 --- a/go.sum +++ b/go.sum @@ -829,6 +829,8 @@ github.com/wagoodman/go-rpmdb v0.0.0-20200719223757-ce54a4b0607b h1:elYGLFZPymeT github.com/wagoodman/go-rpmdb v0.0.0-20200719223757-ce54a4b0607b/go.mod h1:MjoIZzKmbYfcpbC6ARWMcHijAjtLBViDaHcayXKWQWI= github.com/wagoodman/jotframe v0.0.0-20200622123948-2995cbd43525 h1:fGlwSBQrl9/axciK2+gJ9q86SeQYJpbPx4vOrExvZXY= github.com/wagoodman/jotframe v0.0.0-20200622123948-2995cbd43525/go.mod h1:DzXZ1wfRedNhC3KQTick8Gf3CEPMFHsP5k4R/ldjKtw= +github.com/wagoodman/jotframe v0.0.0-20200730190914-3517092dd163 h1:qoZwR+bHbFFNirY4Yt7lqbOXnFAMnlFfR89w0TXwjrc= +github.com/wagoodman/jotframe v0.0.0-20200730190914-3517092dd163/go.mod h1:DzXZ1wfRedNhC3KQTick8Gf3CEPMFHsP5k4R/ldjKtw= github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= github.com/xanzy/go-gitlab v0.32.0 h1:tBm+OXv1t+KBsqlXkSDFz+YUjRM0GFsjpOWYOod3Ebs= github.com/xanzy/go-gitlab v0.32.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= diff --git a/internal/ui/etui/spinner.go b/internal/ui/common/spinner.go similarity index 98% rename from internal/ui/etui/spinner.go rename to internal/ui/common/spinner.go index 0f4458035..fa86c670e 100644 --- a/internal/ui/etui/spinner.go +++ b/internal/ui/common/spinner.go @@ -1,4 +1,4 @@ -package etui +package common import ( "strings" diff --git a/internal/ui/etui/ephemeral_tui.go b/internal/ui/etui/ephemeral_tui.go index eea3bec91..2cc3cf8fa 100644 --- a/internal/ui/etui/ephemeral_tui.go +++ b/internal/ui/etui/ephemeral_tui.go @@ -6,9 +6,10 @@ import ( "os" "sync" - stereoscopeEvent "github.com/anchore/stereoscope/pkg/event" - "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/ui/common" + "github.com/anchore/syft/ui" + + "github.com/anchore/syft/internal/log" syftEvent "github.com/anchore/syft/syft/event" "github.com/wagoodman/go-partybus" "github.com/wagoodman/jotframe/pkg/frame" @@ -47,6 +48,7 @@ func OutputToEphemeralTUI(workerErrs <-chan error, subscription *partybus.Subscr var isClosed bool defer func() { if !isClosed { + fr.Close() frame.Close() } }() @@ -55,6 +57,7 @@ func OutputToEphemeralTUI(workerErrs <-chan error, subscription *partybus.Subscr var wg = &sync.WaitGroup{} events := subscription.Events() ctx := context.Background() + syftUIHandler := ui.NewHandler() eventLoop: for { @@ -67,41 +70,27 @@ eventLoop: if !ok { break eventLoop } - switch e.Type { - case syftEvent.AppUpdateAvailable: - err = appUpdateAvailableHandler(ctx, fr, e, wg) - if err != nil { - log.Errorf("unable to show AppUpdateAvailable event: %+v", err) + switch { + case syftUIHandler.RespondsTo(e): + if err = syftUIHandler.Handle(ctx, fr, e, wg); err != nil { + log.Errorf("unable to show %s event: %+v", e.Type, err) } - case stereoscopeEvent.ReadImage: - err = imageReadHandler(ctx, fr, e, wg) - if err != nil { - log.Errorf("unable to show ReadImage event: %+v", err) + case e.Type == syftEvent.AppUpdateAvailable: + if err = appUpdateAvailableHandler(ctx, fr, e, wg); err != nil { + log.Errorf("unable to show %s event: %+v", e.Type, err) } - case stereoscopeEvent.FetchImage: - err = imageFetchHandler(ctx, fr, e, wg) - if err != nil { - log.Errorf("unable to show FetchImage event: %+v", err) - } - - case syftEvent.CatalogerStarted: - err = catalogerStartedHandler(ctx, fr, e, wg) - if err != nil { - log.Errorf("unable to show CatalogerStarted event: %+v", err) - } - case syftEvent.CatalogerFinished: + case e.Type == syftEvent.CatalogerFinished: // we may have other background processes still displaying progress, wait for them to // finish before discontinuing dynamic content and showing the final report wg.Wait() + fr.Close() frame.Close() isClosed = true - fmt.Println() - err := common.CatalogerFinishedHandler(e) - if err != nil { - log.Errorf("unable to show CatalogerFinished event: %+v", err) + if err := common.CatalogerFinishedHandler(e); err != nil { + log.Errorf("unable to show %s event: %+v", e.Type, err) } // this is the last expected event diff --git a/internal/ui/etui/internal_event_handlers.go b/internal/ui/etui/internal_event_handlers.go new file mode 100644 index 000000000..50550eaab --- /dev/null +++ b/internal/ui/etui/internal_event_handlers.go @@ -0,0 +1,31 @@ +package etui + +import ( + "context" + "fmt" + "io" + "sync" + + "github.com/anchore/syft/internal" + syftEventParsers "github.com/anchore/syft/syft/event/parsers" + "github.com/gookit/color" + "github.com/wagoodman/go-partybus" + "github.com/wagoodman/jotframe/pkg/frame" +) + +func appUpdateAvailableHandler(_ context.Context, fr *frame.Frame, event partybus.Event, _ *sync.WaitGroup) error { + newVersion, err := syftEventParsers.ParseAppUpdateAvailable(event) + if err != nil { + return fmt.Errorf("bad AppUpdateAvailable event: %w", err) + } + + line, err := fr.Prepend() + if err != nil { + return err + } + + message := color.Magenta.Sprintf("New version of %s is available: %s", internal.ApplicationName, newVersion) + _, _ = io.WriteString(line, message) + + return nil +} diff --git a/syft/event/event.go b/syft/event/event.go index ea573635a..ab4e60ffc 100644 --- a/syft/event/event.go +++ b/syft/event/event.go @@ -3,7 +3,7 @@ package event import "github.com/wagoodman/go-partybus" const ( - AppUpdateAvailable partybus.EventType = "app-update-available" - CatalogerStarted partybus.EventType = "cataloger-started-event" - CatalogerFinished partybus.EventType = "cataloger-finished-event" + AppUpdateAvailable partybus.EventType = "syft-app-update-available" + CatalogerStarted partybus.EventType = "syft-cataloger-started-event" + CatalogerFinished partybus.EventType = "syft-cataloger-finished-event" ) diff --git a/internal/ui/etui/event_handlers.go b/ui/event_handlers.go similarity index 81% rename from internal/ui/etui/event_handlers.go rename to ui/event_handlers.go index 948a8afe1..8c94ec99f 100644 --- a/internal/ui/etui/event_handlers.go +++ b/ui/event_handlers.go @@ -1,4 +1,4 @@ -package etui +package ui import ( "context" @@ -8,6 +8,7 @@ import ( "time" stereoEventParsers "github.com/anchore/stereoscope/pkg/event/parsers" + "github.com/anchore/syft/internal/ui/common" syftEventParsers "github.com/anchore/syft/syft/event/parsers" "github.com/gookit/color" "github.com/wagoodman/go-partybus" @@ -17,26 +18,26 @@ import ( ) const maxBarWidth = 50 -const statusSet = SpinnerDotSet // SpinnerCircleOutlineSet -const completedStatus = "✔" //"●" +const statusSet = common.SpinnerDotSet // SpinnerCircleOutlineSet +const completedStatus = "✔" // "●" const tileFormat = color.Bold const statusTitleTemplate = " %s %-28s " var auxInfoFormat = color.HEX("#777777") -func startProcess() (format.Simple, *Spinner) { +func startProcess() (format.Simple, *common.Spinner) { width, _ := frame.GetTerminalSize() barWidth := int(0.25 * float64(width)) if barWidth > maxBarWidth { barWidth = maxBarWidth } formatter := format.NewSimpleWithTheme(barWidth, format.HeavyNoBarTheme, format.ColorCompleted, format.ColorTodo) - spinner := NewSpinner(statusSet) + spinner := common.NewSpinner(statusSet) return formatter, &spinner } -func imageFetchHandler(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error { +func FetchImageHandler(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error { _, prog, err := stereoEventParsers.ParseFetchImage(event) if err != nil { return fmt.Errorf("bad FetchImage event: %w", err) @@ -73,7 +74,7 @@ func imageFetchHandler(ctx context.Context, fr *frame.Frame, event partybus.Even return err } -func imageReadHandler(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error { +func ReadImageHandler(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error { _, prog, err := stereoEventParsers.ParseReadImage(event) if err != nil { return fmt.Errorf("bad ReadImage event: %w", err) @@ -110,7 +111,7 @@ func imageReadHandler(ctx context.Context, fr *frame.Frame, event partybus.Event return nil } -func catalogerStartedHandler(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error { +func CatalogerStartedHandler(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error { monitor, err := syftEventParsers.ParseCatalogerStarted(event) if err != nil { return fmt.Errorf("bad CatalogerStarted event: %w", err) @@ -143,20 +144,3 @@ func catalogerStartedHandler(ctx context.Context, fr *frame.Frame, event partybu return nil } - -func appUpdateAvailableHandler(_ context.Context, fr *frame.Frame, event partybus.Event, _ *sync.WaitGroup) error { - newVersion, err := syftEventParsers.ParseAppUpdateAvailable(event) - if err != nil { - return fmt.Errorf("bad AppUpdateAvailable event: %w", err) - } - - line, err := fr.Prepend() - if err != nil { - return err - } - - message := color.Magenta.Sprintf("New Update Available: %s", newVersion) - _, _ = io.WriteString(line, message) - - return nil -} diff --git a/ui/handler.go b/ui/handler.go new file mode 100644 index 000000000..62a8a9a4b --- /dev/null +++ b/ui/handler.go @@ -0,0 +1,41 @@ +package ui + +import ( + "context" + "sync" + + stereoscopeEvent "github.com/anchore/stereoscope/pkg/event" + syftEvent "github.com/anchore/syft/syft/event" + "github.com/wagoodman/go-partybus" + "github.com/wagoodman/jotframe/pkg/frame" +) + +type Handler struct { +} + +func NewHandler() *Handler { + return &Handler{} +} + +func (r *Handler) RespondsTo(event partybus.Event) bool { + switch event.Type { + case stereoscopeEvent.ReadImage, stereoscopeEvent.FetchImage, syftEvent.CatalogerStarted: + return true + default: + return false + } +} + +func (r *Handler) Handle(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error { + switch event.Type { + case stereoscopeEvent.ReadImage: + return ReadImageHandler(ctx, fr, event, wg) + + case stereoscopeEvent.FetchImage: + return FetchImageHandler(ctx, fr, event, wg) + + case syftEvent.CatalogerStarted: + return CatalogerStartedHandler(ctx, fr, event, wg) + } + return nil +}