fix: update attestation code to remove library dependencies and shellout for keyless flow (#1442)

Co-authored-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
Christopher Angelo Phillips
2023-01-12 17:22:05 +00:00
committed by GitHub
co-authored by Alex Goodman
parent ac8f72fdd1
commit 44e8ae2577
23 changed files with 345 additions and 2025 deletions
+111 -42
View File
@@ -1,7 +1,10 @@
package ui
import (
"bufio"
"container/list"
"context"
"errors"
"fmt"
"io"
"strings"
@@ -25,6 +28,7 @@ import (
const maxBarWidth = 50
const statusSet = components.SpinnerDotSet
const completedStatus = "✔"
const failedStatus = "✘"
const tileFormat = color.Bold
const interval = 150 * time.Millisecond
@@ -226,48 +230,6 @@ func FetchImageHandler(ctx context.Context, fr *frame.Frame, event partybus.Even
return err
}
func UploadAttestationHandler(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error {
prog, err := syftEventParsers.ParseUploadAttestation(event)
if err != nil {
return fmt.Errorf("bad %s event: %w", event.Type, err)
}
line, err := fr.Append()
if err != nil {
return err
}
wg.Add(1)
formatter, spinner := startProcess()
stream := progress.Stream(ctx, prog, interval)
title := tileFormat.Sprint("Uploading attestation")
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))
}
}
go func() {
defer wg.Done()
formatFn(progress.Progress{})
for p := range stream {
formatFn(p)
}
spin := color.Green.Sprint(completedStatus)
title = tileFormat.Sprint("Uploaded attestation")
_, _ = io.WriteString(line, fmt.Sprintf(statusTitleTemplate, spin, title))
}()
return err
}
// ReadImageHandler periodically writes a the image read/parse/build-tree status in the form of a progress bar.
func ReadImageHandler(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error {
_, prog, err := stereoEventParsers.ParseReadImage(event)
@@ -570,3 +532,110 @@ func ImportStartedHandler(ctx context.Context, fr *frame.Frame, event partybus.E
}()
return err
}
// AttestationStartedHandler takes bytes from a event.ShellOutput and publishes them to the frame.
//
//nolint:funlen,gocognit
func AttestationStartedHandler(ctx context.Context, fr *frame.Frame, event partybus.Event, wg *sync.WaitGroup) error {
reader, prog, taskInfo, err := syftEventParsers.ParseAttestationStartedEvent(event)
if err != nil {
return fmt.Errorf("bad %s event: %w", event.Type, err)
}
titleLine, err := fr.Append()
if err != nil {
return err
}
wg.Add(2)
_, spinner := startProcess()
title := tileFormat.Sprintf(taskInfo.Title.WhileRunning)
s := bufio.NewScanner(reader)
l := list.New()
formatFn := func() {
auxInfo := auxInfoFormat.Sprintf("[running %s]", taskInfo.Context)
spin := color.Magenta.Sprint(spinner.Next())
_, _ = io.WriteString(titleLine, fmt.Sprintf(statusTitleTemplate+"%s", spin, title, auxInfo))
}
formatFn()
var failed bool
formatComplete := func(aux string) {
spin := color.Green.Sprint(completedStatus)
if failed {
spin = color.Red.Sprint(failedStatus)
aux = prog.Error().Error()
} else {
title = tileFormat.Sprintf(taskInfo.Title.OnSuccess)
}
auxInfo := auxInfoFormat.Sprintf("[%s]", aux)
_, _ = io.WriteString(titleLine, fmt.Sprintf(statusTitleTemplate+"%s", spin, title, auxInfo))
}
endWg := &sync.WaitGroup{}
endWg.Add(1)
go func() {
defer wg.Done()
defer endWg.Done()
stream := progress.Stream(ctx, prog, interval)
for range stream {
formatFn()
}
err := prog.Error()
if err != nil && !errors.Is(err, io.EOF) {
failed = true
}
}()
go func() {
defer wg.Done()
var tlogEntry string
// only show the last 5 lines of the shell output
for s.Scan() {
line, _ := fr.Append()
if l.Len() > 5 {
elem := l.Front()
line := elem.Value.(*frame.Line)
err = line.Remove()
if err != nil {
return
}
l.Remove(elem)
}
l.PushBack(line)
text := s.Text()
if strings.Contains(text, "tlog entry created with index") {
tlogEntry = text
}
_, err = line.Write([]byte(fmt.Sprintf(" %s %s", auxInfoFormat.Sprintf("░░"), text)))
if err != nil {
return
}
}
endWg.Wait()
if !failed {
// roll up logs into completed status (only if successful)
for e := l.Back(); e != nil; e = e.Prev() {
line := e.Value.(*frame.Line)
err = line.Remove()
if err != nil {
return
}
}
}
formatComplete(tlogEntry)
}()
return nil
}
+5 -5
View File
@@ -31,13 +31,13 @@ func (r *Handler) RespondsTo(event partybus.Event) bool {
case stereoscopeEvent.PullDockerImage,
stereoscopeEvent.ReadImage,
stereoscopeEvent.FetchImage,
syftEvent.UploadAttestation,
syftEvent.PackageCatalogerStarted,
syftEvent.SecretsCatalogerStarted,
syftEvent.FileDigestsCatalogerStarted,
syftEvent.FileMetadataCatalogerStarted,
syftEvent.FileIndexingStarted,
syftEvent.ImportStarted:
syftEvent.ImportStarted,
syftEvent.AttestationStarted:
return true
default:
return false
@@ -56,9 +56,6 @@ func (r *Handler) Handle(ctx context.Context, fr *frame.Frame, event partybus.Ev
case stereoscopeEvent.FetchImage:
return FetchImageHandler(ctx, fr, event, wg)
case syftEvent.UploadAttestation:
return UploadAttestationHandler(ctx, fr, event, wg)
case syftEvent.PackageCatalogerStarted:
return PackageCatalogerStartedHandler(ctx, fr, event, wg)
@@ -76,6 +73,9 @@ func (r *Handler) Handle(ctx context.Context, fr *frame.Frame, event partybus.Ev
case syftEvent.ImportStarted:
return ImportStartedHandler(ctx, fr, event, wg)
case syftEvent.AttestationStarted:
return AttestationStartedHandler(ctx, fr, event, wg)
}
return nil
}