replace panics with logging

This commit is contained in:
Alex Goodman 2020-05-21 16:53:17 -04:00
parent b7c7c5556d
commit 09c7ca8f8f
No known key found for this signature in database
GPG key ID: 86E2870463D5E890
9 changed files with 73 additions and 26 deletions

View file

@ -1,18 +1,20 @@
package cmd package cmd
import ( import (
"encoding/json"
"fmt" "fmt"
"os" "os"
"github.com/anchore/imgbom/imgbom" "github.com/anchore/imgbom/imgbom"
"github.com/anchore/imgbom/internal/config" "github.com/anchore/imgbom/internal/config"
"github.com/anchore/imgbom/internal/log"
"github.com/anchore/imgbom/internal/logger" "github.com/anchore/imgbom/internal/logger"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
var appConfig *config.Application var appConfig *config.Application
func loadAppConfig() { func initAppConfig() {
cfg, err := config.LoadConfigFromFile(viper.GetViper(), &cliOpts) cfg, err := config.LoadConfigFromFile(viper.GetViper(), &cliOpts)
if err != nil { if err != nil {
fmt.Printf("failed to load application config: \n\t%+v\n", err) fmt.Printf("failed to load application config: \n\t%+v\n", err)
@ -21,7 +23,7 @@ func loadAppConfig() {
appConfig = cfg appConfig = cfg
} }
func setupLoggingFromAppConfig() { func initLogging() {
config := logger.LogConfig{ config := logger.LogConfig{
EnableConsole: appConfig.Log.FileLocation == "" && !appConfig.Quiet, EnableConsole: appConfig.Log.FileLocation == "" && !appConfig.Quiet,
EnableFile: appConfig.Log.FileLocation != "", EnableFile: appConfig.Log.FileLocation != "",
@ -32,3 +34,12 @@ func setupLoggingFromAppConfig() {
imgbom.SetLogger(logger.NewZapLogger(config)) imgbom.SetLogger(logger.NewZapLogger(config))
} }
func logAppConfig() {
appCfgStr, err := json.MarshalIndent(&appConfig, " ", " ")
if err != nil {
log.Debugf("Could not display application config: %+v", err)
} else {
log.Debugf("Application config:\n%+v", string(appCfgStr))
}
}

View file

@ -1,7 +1,6 @@
package cmd package cmd
import ( import (
"encoding/json"
"fmt" "fmt"
"os" "os"
@ -31,8 +30,9 @@ Supports the following image sources:
func init() { func init() {
setCliOptions() setCliOptions()
cobra.OnInitialize(loadAppConfig) cobra.OnInitialize(initAppConfig)
cobra.OnInitialize(setupLoggingFromAppConfig) cobra.OnInitialize(initLogging)
cobra.OnInitialize(logAppConfig)
} }
func Execute() { func Execute() {
@ -43,15 +43,8 @@ func Execute() {
} }
func doRunCmd(cmd *cobra.Command, args []string) { func doRunCmd(cmd *cobra.Command, args []string) {
appCfgStr, err := json.MarshalIndent(&appConfig, " ", " ")
if err != nil {
log.Debugf("could not display application config: %+v", err)
} else {
log.Debugf("application config:\n%+v", string(appCfgStr))
}
userImageStr := args[0] userImageStr := args[0]
log.Infof("fetching image %s...", userImageStr) log.Infof("Fetching image '%s'", userImageStr)
img, err := stereoscope.GetImage(userImageStr) img, err := stereoscope.GetImage(userImageStr)
if err != nil { if err != nil {
log.Errorf("could not fetch image '%s': %w", userImageStr, err) log.Errorf("could not fetch image '%s': %w", userImageStr, err)
@ -59,14 +52,14 @@ func doRunCmd(cmd *cobra.Command, args []string) {
} }
defer stereoscope.Cleanup() defer stereoscope.Cleanup()
log.Info("cataloging image...") log.Info("Cataloging image")
catalog, err := imgbom.CatalogImage(img, appConfig.ScopeOpt) catalog, err := imgbom.CatalogImage(img, appConfig.ScopeOpt)
if err != nil { if err != nil {
log.Errorf("could not catalog image: %w", err) log.Errorf("could not catalog image: %w", err)
os.Exit(1) os.Exit(1)
} }
log.Info("done!") log.Info("Complete!")
err = presenter.GetPresenter(appConfig.PresenterOpt).Present(os.Stdout, img, catalog) err = presenter.GetPresenter(appConfig.PresenterOpt).Present(os.Stdout, img, catalog)
if err != nil { if err != nil {
log.Errorf("could not format catalog results: %w", err) log.Errorf("could not format catalog results: %w", err)

View file

@ -7,6 +7,7 @@ import (
) )
type Analyzer interface { type Analyzer interface {
Name() string
// TODO: add ID / Name for analyze for uniquely identifying this analyzer type // TODO: add ID / Name for analyze for uniquely identifying this analyzer type
SelectFiles([]*tree.FileTree) []file.Reference SelectFiles([]*tree.FileTree) []file.Reference
// NOTE: one of the errors which is returned is "IterationNeeded", which indicates to the driver to // NOTE: one of the errors which is returned is "IterationNeeded", which indicates to the driver to

View file

@ -4,6 +4,7 @@ import (
"github.com/anchore/imgbom/imgbom/analyzer/dpkg" "github.com/anchore/imgbom/imgbom/analyzer/dpkg"
"github.com/anchore/imgbom/imgbom/pkg" "github.com/anchore/imgbom/imgbom/pkg"
"github.com/anchore/imgbom/imgbom/scope" "github.com/anchore/imgbom/imgbom/scope"
"github.com/anchore/imgbom/internal/log"
"github.com/anchore/stereoscope/pkg/file" "github.com/anchore/stereoscope/pkg/file"
"github.com/hashicorp/go-multierror" "github.com/hashicorp/go-multierror"
) )
@ -26,6 +27,7 @@ type controller struct {
} }
func (c *controller) add(a Analyzer) { func (c *controller) add(a Analyzer) {
log.Debugf("adding analyzer: %s", a.Name())
c.analyzers = append(c.analyzers, a) c.analyzers = append(c.analyzers, a)
} }
@ -36,6 +38,7 @@ func (c *controller) analyze(s scope.Scope) (pkg.Catalog, error) {
// ask analyzers for files to extract from the image tar // ask analyzers for files to extract from the image tar
for _, a := range c.analyzers { for _, a := range c.analyzers {
fileSelection = append(fileSelection, a.SelectFiles(s.Trees)...) fileSelection = append(fileSelection, a.SelectFiles(s.Trees)...)
log.Debugf("analyzer '%s' selected '%d' files", a.Name(), len(fileSelection))
} }
// fetch contents for requested selection by analyzers // fetch contents for requested selection by analyzers
@ -47,11 +50,15 @@ func (c *controller) analyze(s scope.Scope) (pkg.Catalog, error) {
// perform analysis, accumulating errors for each failed analysis // perform analysis, accumulating errors for each failed analysis
var errs error var errs error
for _, a := range c.analyzers { for _, a := range c.analyzers {
packages, err := a.Analyze(contents)
// TODO: check for multiple rounds of analyses by Iterate error // TODO: check for multiple rounds of analyses by Iterate error
packages, err := a.Analyze(contents)
if err != nil { if err != nil {
errs = multierror.Append(errs, err) errs = multierror.Append(errs, err)
continue
} }
log.Debugf("analyzer '%s' discovered '%d' packages", a.Name(), len(packages))
for _, p := range packages { for _, p := range packages {
catalog.Add(p) catalog.Add(p)
} }

View file

@ -4,6 +4,7 @@ import (
"strings" "strings"
"github.com/anchore/imgbom/imgbom/pkg" "github.com/anchore/imgbom/imgbom/pkg"
"github.com/anchore/imgbom/internal/log"
"github.com/anchore/stereoscope/pkg/file" "github.com/anchore/stereoscope/pkg/file"
"github.com/anchore/stereoscope/pkg/tree" "github.com/anchore/stereoscope/pkg/tree"
) )
@ -16,6 +17,10 @@ func NewAnalyzer() *Analyzer {
return &Analyzer{} return &Analyzer{}
} }
func (a *Analyzer) Name() string {
return "dpkg-analyzer"
}
func (a *Analyzer) SelectFiles(trees []*tree.FileTree) []file.Reference { func (a *Analyzer) SelectFiles(trees []*tree.FileTree) []file.Reference {
files := make([]file.Reference, 0) files := make([]file.Reference, 0)
for _, tree := range trees { for _, tree := range trees {
@ -36,14 +41,26 @@ func (a *Analyzer) Analyze(contents map[file.Reference]string) ([]pkg.Package, e
for _, reference := range a.selectedFiles { for _, reference := range a.selectedFiles {
content, ok := contents[reference] content, ok := contents[reference]
if !ok { if !ok {
// TODO: this needs handling // TODO: test case
panic(reference) log.WithFields(map[string]interface{}{
"path": reference.Path,
"id": reference.ID(),
"analyzer": a.Name(),
}).Errorf("analyzer file content missing")
continue
} }
entries, err := ParseEntries(strings.NewReader(content)) entries, err := ParseEntries(strings.NewReader(content))
if err != nil { if err != nil {
// TODO: punt for now, we need to handle this // TODO: test case
panic(err) log.WithFields(map[string]interface{}{
"path": reference.Path,
"id": reference.ID(),
"analyzer": a.Name(),
}).Errorf("analyzer failed to parse entries: %w", err)
continue
} }
for _, entry := range entries { for _, entry := range entries {
packages = append(packages, pkg.Package{ packages = append(packages, pkg.Package{
@ -55,5 +72,6 @@ func (a *Analyzer) Analyze(contents map[file.Reference]string) ([]pkg.Package, e
}) })
} }
} }
return packages, nil return packages, nil
} }

View file

@ -54,7 +54,7 @@ func TestSinglePackage(t *testing.T) {
defer func() { defer func() {
err := file.Close() err := file.Close()
if err != nil { if err != nil {
panic(err) t.Fatal("closing file failed:", err)
} }
}() }()
@ -123,7 +123,7 @@ func TestMultiplePackages(t *testing.T) {
defer func() { defer func() {
err := file.Close() err := file.Close()
if err != nil { if err != nil {
panic(err) t.Fatal("closing file failed:", err)
} }
}() }()

4
imgbom/constants.go Normal file
View file

@ -0,0 +1,4 @@
package imgbom
// note: must be a single word, all lowercase
const LibraryName = "imgbom"

View file

@ -8,3 +8,9 @@ import (
func SetLogger(logger logger.Logger) { func SetLogger(logger logger.Logger) {
log.Log = logger log.Log = logger
} }
func SetLoggerWithTags(logger logger.Logger, tags map[string]interface{}) {
log.Log = logger.WithFields(map[string]interface{}{
"source": LibraryName,
})
}

View file

@ -5,6 +5,7 @@ import (
"io" "io"
"github.com/anchore/imgbom/imgbom/pkg" "github.com/anchore/imgbom/imgbom/pkg"
"github.com/anchore/imgbom/internal/log"
stereoscopeImg "github.com/anchore/stereoscope/pkg/image" stereoscopeImg "github.com/anchore/stereoscope/pkg/image"
) )
@ -88,8 +89,13 @@ func (pres *Presenter) Present(output io.Writer, img *stereoscopeImg.Image, cata
for idx, src := range p.Source { for idx, src := range p.Source {
fileMetadata, err := img.FileCatalog.Get(src) fileMetadata, err := img.FileCatalog.Get(src)
if err != nil { if err != nil {
// TODO: replace // TODO: test case
panic(err) log.WithFields(map[string]interface{}{
"path": src.Path,
"id": src.ID(),
"presenter": "json",
}).Errorf("could not get metadata from catalog")
} }
srcObj := source{ srcObj := source{
@ -105,8 +111,9 @@ func (pres *Presenter) Present(output io.Writer, img *stereoscopeImg.Image, cata
bytes, err := json.Marshal(&doc) bytes, err := json.Marshal(&doc)
if err != nil { if err != nil {
// TODO: replace log.WithFields(map[string]interface{}{
panic(err) "presenter": "json",
}).Errorf("failed to marshal json: %w", err)
} }
_, err = output.Write(bytes) _, err = output.Write(bytes)