Export UI handlers for reuse in other tools (#113)

* export UI handlers for reuse in other tools

* bump jotframe to fix cursor issues at frame close
This commit is contained in:
Alex Goodman 2020-07-30 15:16:58 -04:00 committed by GitHub
parent 857f41b04b
commit 271ba35c85
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 108 additions and 59 deletions

View file

@ -90,7 +90,7 @@ func initAppConfig() {
} }
func initLogging() { func initLogging() {
config := logger.LogConfig{ cfg := logger.LogConfig{
EnableConsole: (appConfig.Log.FileLocation == "" || appConfig.CliOptions.Verbosity > 0) && !appConfig.Quiet, EnableConsole: (appConfig.Log.FileLocation == "" || appConfig.CliOptions.Verbosity > 0) && !appConfig.Quiet,
EnableFile: appConfig.Log.FileLocation != "", EnableFile: appConfig.Log.FileLocation != "",
Level: appConfig.Log.LevelOpt, Level: appConfig.Log.LevelOpt,
@ -98,7 +98,7 @@ func initLogging() {
FileLocation: appConfig.Log.FileLocation, FileLocation: appConfig.Log.FileLocation,
} }
logWrapper := logger.NewZapLogger(config) logWrapper := logger.NewZapLogger(cfg)
syft.SetLogger(logWrapper) syft.SetLogger(logWrapper)
stereoscope.SetLogger(logWrapper) stereoscope.SetLogger(logWrapper)
} }

View file

@ -55,6 +55,8 @@ func startWorker(userInput string) <-chan error {
Type: event.AppUpdateAvailable, Type: event.AppUpdateAvailable,
Value: newVersion, Value: newVersion,
}) })
} else {
log.Debugf("No new %s update available", internal.ApplicationName)
} }
} }

2
go.mod
View file

@ -24,7 +24,7 @@ require (
github.com/wagoodman/go-partybus v0.0.0-20200526224238-eb215533f07d github.com/wagoodman/go-partybus v0.0.0-20200526224238-eb215533f07d
github.com/wagoodman/go-progress v0.0.0-20200621153512-2778c704bf22 github.com/wagoodman/go-progress v0.0.0-20200621153512-2778c704bf22
github.com/wagoodman/go-rpmdb v0.0.0-20200719223757-ce54a4b0607b 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 go.uber.org/zap v1.15.0
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9
golang.org/x/sys v0.0.0-20200610111108-226ff32320da // indirect golang.org/x/sys v0.0.0-20200610111108-226ff32320da // indirect

2
go.sum
View file

@ -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/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 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-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.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 h1:tBm+OXv1t+KBsqlXkSDFz+YUjRM0GFsjpOWYOod3Ebs=
github.com/xanzy/go-gitlab v0.32.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug= github.com/xanzy/go-gitlab v0.32.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=

View file

@ -1,4 +1,4 @@
package etui package common
import ( import (
"strings" "strings"

View file

@ -6,9 +6,10 @@ import (
"os" "os"
"sync" "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/internal/ui/common"
"github.com/anchore/syft/ui"
"github.com/anchore/syft/internal/log"
syftEvent "github.com/anchore/syft/syft/event" syftEvent "github.com/anchore/syft/syft/event"
"github.com/wagoodman/go-partybus" "github.com/wagoodman/go-partybus"
"github.com/wagoodman/jotframe/pkg/frame" "github.com/wagoodman/jotframe/pkg/frame"
@ -47,6 +48,7 @@ func OutputToEphemeralTUI(workerErrs <-chan error, subscription *partybus.Subscr
var isClosed bool var isClosed bool
defer func() { defer func() {
if !isClosed { if !isClosed {
fr.Close()
frame.Close() frame.Close()
} }
}() }()
@ -55,6 +57,7 @@ func OutputToEphemeralTUI(workerErrs <-chan error, subscription *partybus.Subscr
var wg = &sync.WaitGroup{} var wg = &sync.WaitGroup{}
events := subscription.Events() events := subscription.Events()
ctx := context.Background() ctx := context.Background()
syftUIHandler := ui.NewHandler()
eventLoop: eventLoop:
for { for {
@ -67,41 +70,27 @@ eventLoop:
if !ok { if !ok {
break eventLoop break eventLoop
} }
switch e.Type { switch {
case syftEvent.AppUpdateAvailable: case syftUIHandler.RespondsTo(e):
err = appUpdateAvailableHandler(ctx, fr, e, wg) if err = syftUIHandler.Handle(ctx, fr, e, wg); err != nil {
if err != nil { log.Errorf("unable to show %s event: %+v", e.Type, err)
log.Errorf("unable to show AppUpdateAvailable event: %+v", err)
} }
case stereoscopeEvent.ReadImage: case e.Type == syftEvent.AppUpdateAvailable:
err = imageReadHandler(ctx, fr, e, wg) if err = appUpdateAvailableHandler(ctx, fr, e, wg); err != nil {
if err != nil { log.Errorf("unable to show %s event: %+v", e.Type, err)
log.Errorf("unable to show ReadImage event: %+v", err)
} }
case stereoscopeEvent.FetchImage: case e.Type == syftEvent.CatalogerFinished:
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:
// we may have other background processes still displaying progress, wait for them to // we may have other background processes still displaying progress, wait for them to
// finish before discontinuing dynamic content and showing the final report // finish before discontinuing dynamic content and showing the final report
wg.Wait() wg.Wait()
fr.Close()
frame.Close() frame.Close()
isClosed = true isClosed = true
fmt.Println()
err := common.CatalogerFinishedHandler(e) if err := common.CatalogerFinishedHandler(e); err != nil {
if err != nil { log.Errorf("unable to show %s event: %+v", e.Type, err)
log.Errorf("unable to show CatalogerFinished event: %+v", err)
} }
// this is the last expected event // this is the last expected event

View file

@ -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
}

View file

@ -3,7 +3,7 @@ package event
import "github.com/wagoodman/go-partybus" import "github.com/wagoodman/go-partybus"
const ( const (
AppUpdateAvailable partybus.EventType = "app-update-available" AppUpdateAvailable partybus.EventType = "syft-app-update-available"
CatalogerStarted partybus.EventType = "cataloger-started-event" CatalogerStarted partybus.EventType = "syft-cataloger-started-event"
CatalogerFinished partybus.EventType = "cataloger-finished-event" CatalogerFinished partybus.EventType = "syft-cataloger-finished-event"
) )

View file

@ -1,4 +1,4 @@
package etui package ui
import ( import (
"context" "context"
@ -8,6 +8,7 @@ import (
"time" "time"
stereoEventParsers "github.com/anchore/stereoscope/pkg/event/parsers" stereoEventParsers "github.com/anchore/stereoscope/pkg/event/parsers"
"github.com/anchore/syft/internal/ui/common"
syftEventParsers "github.com/anchore/syft/syft/event/parsers" syftEventParsers "github.com/anchore/syft/syft/event/parsers"
"github.com/gookit/color" "github.com/gookit/color"
"github.com/wagoodman/go-partybus" "github.com/wagoodman/go-partybus"
@ -17,26 +18,26 @@ import (
) )
const maxBarWidth = 50 const maxBarWidth = 50
const statusSet = SpinnerDotSet // SpinnerCircleOutlineSet const statusSet = common.SpinnerDotSet // SpinnerCircleOutlineSet
const completedStatus = "✔" //"●" const completedStatus = "✔" // "●"
const tileFormat = color.Bold const tileFormat = color.Bold
const statusTitleTemplate = " %s %-28s " const statusTitleTemplate = " %s %-28s "
var auxInfoFormat = color.HEX("#777777") var auxInfoFormat = color.HEX("#777777")
func startProcess() (format.Simple, *Spinner) { func startProcess() (format.Simple, *common.Spinner) {
width, _ := frame.GetTerminalSize() width, _ := frame.GetTerminalSize()
barWidth := int(0.25 * float64(width)) barWidth := int(0.25 * float64(width))
if barWidth > maxBarWidth { if barWidth > maxBarWidth {
barWidth = maxBarWidth barWidth = maxBarWidth
} }
formatter := format.NewSimpleWithTheme(barWidth, format.HeavyNoBarTheme, format.ColorCompleted, format.ColorTodo) formatter := format.NewSimpleWithTheme(barWidth, format.HeavyNoBarTheme, format.ColorCompleted, format.ColorTodo)
spinner := NewSpinner(statusSet) spinner := common.NewSpinner(statusSet)
return formatter, &spinner 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) _, prog, err := stereoEventParsers.ParseFetchImage(event)
if err != nil { if err != nil {
return fmt.Errorf("bad FetchImage event: %w", err) 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 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) _, prog, err := stereoEventParsers.ParseReadImage(event)
if err != nil { if err != nil {
return fmt.Errorf("bad ReadImage event: %w", err) 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 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) monitor, err := syftEventParsers.ParseCatalogerStarted(event)
if err != nil { if err != nil {
return fmt.Errorf("bad CatalogerStarted event: %w", err) return fmt.Errorf("bad CatalogerStarted event: %w", err)
@ -143,20 +144,3 @@ func catalogerStartedHandler(ctx context.Context, fr *frame.Frame, event partybu
return nil 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
}

41
ui/handler.go Normal file
View file

@ -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
}