syft/ui/event_handlers.go

164 lines
4.3 KiB
Go
Raw Normal View History

package ui
2020-06-25 14:39:11 +00:00
import (
"context"
"fmt"
"io"
"sync"
"time"
stereoEventParsers "github.com/anchore/stereoscope/pkg/event/parsers"
"github.com/anchore/syft/internal/ui/common"
2020-07-24 00:54:04 +00:00
syftEventParsers "github.com/anchore/syft/syft/event/parsers"
2020-06-25 14:39:11 +00:00
"github.com/gookit/color"
"github.com/wagoodman/go-partybus"
"github.com/wagoodman/go-progress"
"github.com/wagoodman/go-progress/format"
"github.com/wagoodman/jotframe/pkg/frame"
)
const maxBarWidth = 50
const statusSet = common.SpinnerDotSet // SpinnerCircleOutlineSet
const completedStatus = "✔" // "●"
2020-06-25 14:39:11 +00:00
const tileFormat = color.Bold
const statusTitleTemplate = " %s %-28s "
var auxInfoFormat = color.HEX("#777777")
func startProcess() (format.Simple, *common.Spinner) {
2020-06-25 14:39:11 +00:00
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 := common.NewSpinner(statusSet)
2020-06-25 14:39:11 +00:00
return formatter, &spinner
}
func FetchImageHandler(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error {
2020-06-25 14:39:11 +00:00
_, prog, err := stereoEventParsers.ParseFetchImage(event)
if err != nil {
return fmt.Errorf("bad FetchImage event: %w", err)
}
line, err := fr.Append()
if err != nil {
return err
}
wg.Add(1)
formatter, spinner := startProcess()
stream := progress.Stream(ctx, prog, 150*time.Millisecond)
title := tileFormat.Sprint("Fetching image...")
formatFn := func(p progress.Progress) {
progStr, err := formatter.Format(p)
spin := color.Magenta.Sprint(spinner.Next())
if err != nil {
_, _ = io.WriteString(line, fmt.Sprintf("Error: %+v", err))
} else {
auxInfo := auxInfoFormat.Sprintf("[%s]", prog.Stage())
_, _ = io.WriteString(line, fmt.Sprintf(statusTitleTemplate+"%s %s", spin, title, progStr, auxInfo))
}
}
2020-06-25 14:39:11 +00:00
go func() {
defer wg.Done()
formatFn(progress.Progress{})
2020-06-25 14:39:11 +00:00
for p := range stream {
formatFn(p)
2020-06-25 14:39:11 +00:00
}
spin := color.Green.Sprint(completedStatus)
title = tileFormat.Sprint("Fetched image")
_, _ = io.WriteString(line, fmt.Sprintf(statusTitleTemplate, spin, title))
}()
return err
}
func ReadImageHandler(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error {
2020-06-25 14:39:11 +00:00
_, prog, err := stereoEventParsers.ParseReadImage(event)
if err != nil {
return fmt.Errorf("bad ReadImage event: %w", err)
}
line, err := fr.Append()
if err != nil {
return err
}
wg.Add(1)
formatter, spinner := startProcess()
stream := progress.Stream(ctx, prog, 150*time.Millisecond)
title := tileFormat.Sprint("Reading image...")
formatFn := func(p progress.Progress) {
progStr, err := formatter.Format(p)
spin := color.Magenta.Sprint(spinner.Next())
if err != nil {
_, _ = io.WriteString(line, fmt.Sprintf("Error: %+v", err))
} else {
_, _ = io.WriteString(line, fmt.Sprintf(statusTitleTemplate+"%s", spin, title, progStr))
}
}
2020-06-25 14:39:11 +00:00
go func() {
defer wg.Done()
formatFn(progress.Progress{})
2020-06-25 14:39:11 +00:00
for p := range stream {
formatFn(p)
2020-06-25 14:39:11 +00:00
}
spin := color.Green.Sprint(completedStatus)
title = tileFormat.Sprint("Read image")
_, _ = io.WriteString(line, fmt.Sprintf(statusTitleTemplate, spin, title))
}()
return nil
}
func CatalogerStartedHandler(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error {
2020-07-24 00:54:04 +00:00
monitor, err := syftEventParsers.ParseCatalogerStarted(event)
2020-06-25 14:39:11 +00:00
if err != nil {
return fmt.Errorf("bad CatalogerStarted event: %w", err)
}
line, err := fr.Append()
if err != nil {
return err
}
wg.Add(1)
_, spinner := startProcess()
stream := progress.StreamMonitors(ctx, []progress.Monitorable{monitor.FilesProcessed, monitor.PackagesDiscovered}, 50*time.Millisecond)
title := tileFormat.Sprint("Cataloging image...")
formatFn := func(p int64) {
spin := color.Magenta.Sprint(spinner.Next())
auxInfo := auxInfoFormat.Sprintf("[packages %d]", p)
_, _ = io.WriteString(line, fmt.Sprintf(statusTitleTemplate+"%s", spin, title, auxInfo))
}
2020-06-25 14:39:11 +00:00
go func() {
defer wg.Done()
formatFn(0)
2020-06-25 14:39:11 +00:00
for p := range stream {
formatFn(p[1])
2020-06-25 14:39:11 +00:00
}
spin := color.Green.Sprint(completedStatus)
title = tileFormat.Sprint("Cataloged image")
auxInfo := auxInfoFormat.Sprintf("[%d packages]", monitor.PackagesDiscovered.Current())
_, _ = io.WriteString(line, fmt.Sprintf(statusTitleTemplate+"%s", spin, title, auxInfo))
}()
return nil
}