github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/cmd/gosbom/cli/poweruser/poweruser.go (about) 1 package poweruser 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 8 "github.com/gookit/color" 9 "github.com/nextlinux/gosbom/cmd/gosbom/cli/eventloop" 10 "github.com/nextlinux/gosbom/cmd/gosbom/cli/options" 11 "github.com/nextlinux/gosbom/cmd/gosbom/cli/packages" 12 "github.com/nextlinux/gosbom/gosbom" 13 "github.com/nextlinux/gosbom/gosbom/artifact" 14 "github.com/nextlinux/gosbom/gosbom/event" 15 "github.com/nextlinux/gosbom/gosbom/formats/gosbomjson" 16 "github.com/nextlinux/gosbom/gosbom/sbom" 17 "github.com/nextlinux/gosbom/gosbom/source" 18 "github.com/nextlinux/gosbom/internal" 19 "github.com/nextlinux/gosbom/internal/bus" 20 "github.com/nextlinux/gosbom/internal/config" 21 "github.com/nextlinux/gosbom/internal/ui" 22 "github.com/nextlinux/gosbom/internal/version" 23 "github.com/wagoodman/go-partybus" 24 25 "github.com/anchore/stereoscope" 26 ) 27 28 func Run(_ context.Context, app *config.Application, args []string) error { 29 f := gosbomjson.Format() 30 writer, err := options.MakeSBOMWriterForFormat(f, app.File) 31 if err != nil { 32 return err 33 } 34 defer func() { 35 // inform user at end of run that command will be removed 36 deprecated := color.Style{color.Red, color.OpBold}.Sprint("DEPRECATED: This command will be removed in v1.0.0") 37 fmt.Fprintln(os.Stderr, deprecated) 38 }() 39 40 userInput := args[0] 41 si, err := source.ParseInputWithNameVersion(userInput, app.Platform, app.SourceName, app.SourceVersion, app.DefaultImagePullSource) 42 if err != nil { 43 return fmt.Errorf("could not generate source input for packages command: %w", err) 44 } 45 46 eventBus := partybus.NewBus() 47 stereoscope.SetBus(eventBus) 48 gosbom.SetBus(eventBus) 49 subscription := eventBus.Subscribe() 50 51 return eventloop.EventLoop( 52 execWorker(app, *si, writer), 53 eventloop.SetupSignals(), 54 subscription, 55 stereoscope.Cleanup, 56 ui.Select(options.IsVerbose(app), app.Quiet)..., 57 ) 58 } 59 60 func execWorker(app *config.Application, si source.Input, writer sbom.Writer) <-chan error { 61 errs := make(chan error) 62 go func() { 63 defer close(errs) 64 65 app.Secrets.Cataloger.Enabled = true 66 app.FileMetadata.Cataloger.Enabled = true 67 app.FileContents.Cataloger.Enabled = true 68 app.FileClassification.Cataloger.Enabled = true 69 tasks, err := eventloop.Tasks(app) 70 if err != nil { 71 errs <- err 72 return 73 } 74 75 src, cleanup, err := source.New(si, app.Registry.ToOptions(), app.Exclusions) 76 if err != nil { 77 errs <- err 78 return 79 } 80 if cleanup != nil { 81 defer cleanup() 82 } 83 84 s := sbom.SBOM{ 85 Source: src.Metadata, 86 Descriptor: sbom.Descriptor{ 87 Name: internal.ApplicationName, 88 Version: version.FromBuild().Version, 89 Configuration: app, 90 }, 91 } 92 93 var relationships []<-chan artifact.Relationship 94 for _, task := range tasks { 95 c := make(chan artifact.Relationship) 96 relationships = append(relationships, c) 97 98 go eventloop.RunTask(task, &s.Artifacts, src, c, errs) 99 } 100 101 s.Relationships = append(s.Relationships, packages.MergeRelationships(relationships...)...) 102 103 bus.Publish(partybus.Event{ 104 Type: event.Exit, 105 Value: func() error { return writer.Write(s) }, 106 }) 107 }() 108 109 return errs 110 }