mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 08:23:15 +01:00
working
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
parent
c348d97fe0
commit
206fd8b7d3
@ -117,7 +117,7 @@ func initLogging() {
|
||||
logWrapper := logger.NewLogrusLogger(cfg)
|
||||
syft.SetLogger(logWrapper)
|
||||
stereoscope.SetLogger(&logger.LogrusNestedLogger{
|
||||
Logger: logWrapper.Logger.WithField("from-lib", "steroscope"),
|
||||
Logger: logWrapper.Logger.WithField("from-lib", "stereoscope"),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
2
go.mod
2
go.mod
@ -17,7 +17,7 @@ require (
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/gookit/color v1.2.7
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 // indirect
|
||||
github.com/hashicorp/go-hclog v0.9.2
|
||||
github.com/hashicorp/go-hclog v0.14.1
|
||||
github.com/hashicorp/go-multierror v1.1.0
|
||||
github.com/hashicorp/go-plugin v1.3.0
|
||||
github.com/hashicorp/go-version v1.2.0
|
||||
|
||||
4
go.sum
4
go.sum
@ -477,6 +477,8 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU=
|
||||
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
@ -597,6 +599,7 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
@ -1025,6 +1028,7 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package log
|
||||
|
||||
import "github.com/anchore/syft/syft/logger"
|
||||
import (
|
||||
"github.com/anchore/syft/syft/logger"
|
||||
)
|
||||
|
||||
var Log logger.Logger = &nopLogger{}
|
||||
|
||||
@ -8,6 +10,10 @@ func Errorf(format string, args ...interface{}) {
|
||||
Log.Errorf(format, args...)
|
||||
}
|
||||
|
||||
func Error(args ...interface{}) {
|
||||
Log.Error(args...)
|
||||
}
|
||||
|
||||
func Infof(format string, args ...interface{}) {
|
||||
Log.Infof(format, args...)
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package log
|
||||
type nopLogger struct{}
|
||||
|
||||
func (l *nopLogger) Errorf(format string, args ...interface{}) {}
|
||||
func (l *nopLogger) Error(args ...interface{}) {}
|
||||
func (l *nopLogger) Infof(format string, args ...interface{}) {}
|
||||
func (l *nopLogger) Info(args ...interface{}) {}
|
||||
func (l *nopLogger) Debugf(format string, args ...interface{}) {}
|
||||
|
||||
78
internal/logger/hclog_stdlog_adapter.go
Normal file
78
internal/logger/hclog_stdlog_adapter.go
Normal file
@ -0,0 +1,78 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
)
|
||||
|
||||
// Source: https://github.com/hashicorp/go-hclog/blob/master/stdlog.go (MIT License)
|
||||
|
||||
// Provides a io.Writer to shim the data out of *log.Logger
|
||||
// and back into our Logger. This is basically the only way to
|
||||
// build upon *log.Logger.
|
||||
type HCLogStdlogAdapter struct {
|
||||
log hclog.Logger
|
||||
inferLevels bool
|
||||
forceLevel hclog.Level
|
||||
}
|
||||
|
||||
// Take the data, infer the levels if configured, and send it through
|
||||
// a regular Logger.
|
||||
func (s *HCLogStdlogAdapter) Write(data []byte) (int, error) {
|
||||
str := string(bytes.TrimRight(data, " \t\n"))
|
||||
|
||||
if s.forceLevel != hclog.NoLevel {
|
||||
// Use pickLevel to strip log levels included in the line since we are
|
||||
// forcing the level
|
||||
_, str := s.pickLevel(str)
|
||||
|
||||
// Log at the forced level
|
||||
s.dispatch(str, s.forceLevel)
|
||||
} else if s.inferLevels {
|
||||
level, str := s.pickLevel(str)
|
||||
s.dispatch(str, level)
|
||||
} else {
|
||||
s.log.Info(str)
|
||||
}
|
||||
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
func (s *HCLogStdlogAdapter) dispatch(str string, level hclog.Level) {
|
||||
switch level {
|
||||
case hclog.Trace:
|
||||
s.log.Trace(str)
|
||||
case hclog.Debug:
|
||||
s.log.Debug(str)
|
||||
case hclog.Info:
|
||||
s.log.Info(str)
|
||||
case hclog.Warn:
|
||||
s.log.Warn(str)
|
||||
case hclog.Error:
|
||||
s.log.Error(str)
|
||||
default:
|
||||
s.log.Info(str)
|
||||
}
|
||||
}
|
||||
|
||||
// Detect, based on conventions, what log level this is.
|
||||
func (s *HCLogStdlogAdapter) pickLevel(str string) (hclog.Level, string) {
|
||||
switch {
|
||||
case strings.HasPrefix(str, "[DEBUG]"):
|
||||
return hclog.Debug, strings.TrimSpace(str[7:])
|
||||
case strings.HasPrefix(str, "[TRACE]"):
|
||||
return hclog.Trace, strings.TrimSpace(str[7:])
|
||||
case strings.HasPrefix(str, "[INFO]"):
|
||||
return hclog.Info, strings.TrimSpace(str[6:])
|
||||
case strings.HasPrefix(str, "[WARN]"):
|
||||
return hclog.Warn, strings.TrimSpace(str[7:])
|
||||
case strings.HasPrefix(str, "[ERROR]"):
|
||||
return hclog.Error, strings.TrimSpace(str[7:])
|
||||
case strings.HasPrefix(str, "[ERR]"):
|
||||
return hclog.Error, strings.TrimSpace(str[5:])
|
||||
default:
|
||||
return hclog.Info, str
|
||||
}
|
||||
}
|
||||
148
internal/logger/logger_hclog_adapter.go
Normal file
148
internal/logger/logger_hclog_adapter.go
Normal file
@ -0,0 +1,148 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
|
||||
"github.com/anchore/syft/syft/logger"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
)
|
||||
|
||||
// integrity check
|
||||
var _ hclog.Logger = &LoggerHCLogAdapter{}
|
||||
|
||||
// LoggerHCLogAdapter is used to (partially) adapt a syft logger.Logger object to the hclog.Logger interface for syft plugins.
|
||||
// Note: this does not implement all functionality required by the hclog.Logger.
|
||||
type LoggerHCLogAdapter struct {
|
||||
Logger logger.Logger
|
||||
}
|
||||
|
||||
func NewLoggerHCLogAdapter(logger logger.Logger) *LoggerHCLogAdapter {
|
||||
return &LoggerHCLogAdapter{
|
||||
Logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// Args are alternating key, val pairs
|
||||
// keys must be strings
|
||||
// vals can be any type, but display is implementation specific
|
||||
// Emit a message and key/value pairs at a provided log level
|
||||
func (l *LoggerHCLogAdapter) Log(level hclog.Level, msg string, args ...interface{}) {
|
||||
l.Logger.Info(append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Emit a message and key/value pairs at the TRACE level
|
||||
func (l *LoggerHCLogAdapter) Trace(msg string, args ...interface{}) {
|
||||
l.Logger.Debug(append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Emit a message and key/value pairs at the DEBUG level
|
||||
func (l *LoggerHCLogAdapter) Debug(msg string, args ...interface{}) {
|
||||
l.Logger.Debug(append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Emit a message and key/value pairs at the INFO level
|
||||
func (l *LoggerHCLogAdapter) Info(msg string, args ...interface{}) {
|
||||
l.Logger.Info(append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Emit a message and key/value pairs at the WARN level
|
||||
func (l *LoggerHCLogAdapter) Warn(msg string, args ...interface{}) {
|
||||
l.Logger.Error(append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Emit a message and key/value pairs at the ERROR level
|
||||
func (l *LoggerHCLogAdapter) Error(msg string, args ...interface{}) {
|
||||
l.Logger.Error(append([]interface{}{msg}, args...)...)
|
||||
}
|
||||
|
||||
// Indicate if TRACE logs would be emitted. This and the other Is* guards
|
||||
// are used to elide expensive logging code based on the current level.
|
||||
func (l *LoggerHCLogAdapter) IsTrace() bool {
|
||||
// TODO: not implemented
|
||||
return true
|
||||
}
|
||||
|
||||
// Indicate if DEBUG logs would be emitted. This and the other Is* guards
|
||||
// are used to elide expensive logging code based on the current level.
|
||||
func (l *LoggerHCLogAdapter) IsDebug() bool {
|
||||
// TODO: not implemented
|
||||
return true
|
||||
}
|
||||
|
||||
// Indicate if INFO logs would be emitted. This and the other Is* guards
|
||||
// are used to elide expensive logging code based on the current level.
|
||||
func (l *LoggerHCLogAdapter) IsInfo() bool {
|
||||
// TODO: not implemented
|
||||
return true
|
||||
}
|
||||
|
||||
// Indicate if WARN logs would be emitted. This and the other Is* guards
|
||||
// are used to elide expensive logging code based on the current level.
|
||||
func (l *LoggerHCLogAdapter) IsWarn() bool {
|
||||
// TODO: not implemented
|
||||
return true
|
||||
}
|
||||
|
||||
// Indicate if ERROR logs would be emitted. This and the other Is* guards
|
||||
// are used to elide expensive logging code based on the current level.
|
||||
func (l *LoggerHCLogAdapter) IsError() bool {
|
||||
// TODO: not implemented
|
||||
return true
|
||||
}
|
||||
|
||||
// ImpliedArgs returns With key/value pairs
|
||||
func (l *LoggerHCLogAdapter) ImpliedArgs() []interface{} {
|
||||
// TODO: not implemented
|
||||
return nil
|
||||
}
|
||||
|
||||
// Creates a sublogger that will always have the given key/value pairs
|
||||
func (l *LoggerHCLogAdapter) With(args ...interface{}) hclog.Logger {
|
||||
// TODO: not implemented
|
||||
return l
|
||||
}
|
||||
|
||||
// Returns the Name of the logger
|
||||
func (l *LoggerHCLogAdapter) Name() string {
|
||||
// TODO: not implemented
|
||||
return ""
|
||||
}
|
||||
|
||||
// Create a logger that will prepend the name string on the front of all messages.
|
||||
// If the logger already has a name, the new value will be appended to the current
|
||||
// name. That way, a major subsystem can use this to decorate all it's own logs
|
||||
// without losing context.
|
||||
func (l *LoggerHCLogAdapter) Named(name string) hclog.Logger {
|
||||
// TODO: not implemented
|
||||
return l
|
||||
}
|
||||
|
||||
// Create a logger that will prepend the name string on the front of all messages.
|
||||
// This sets the name of the logger to the value directly, unlike Named which honor
|
||||
// the current name as well.
|
||||
func (l *LoggerHCLogAdapter) ResetNamed(name string) hclog.Logger {
|
||||
// TODO: not implemented
|
||||
return l
|
||||
}
|
||||
|
||||
// Updates the level. This should affect all sub-loggers as well. If an
|
||||
// implementation cannot update the level on the fly, it should no-op.
|
||||
func (l *LoggerHCLogAdapter) SetLevel(level hclog.Level) {
|
||||
// TODO: not implemented
|
||||
}
|
||||
|
||||
// Return a value that conforms to the stdlib log.Logger interface
|
||||
func (l *LoggerHCLogAdapter) StandardLogger(opts *hclog.StandardLoggerOptions) *log.Logger {
|
||||
return log.New(l.StandardWriter(opts), "", log.LstdFlags)
|
||||
}
|
||||
|
||||
// Return a value that conforms to io.Writer, which can be passed into log.SetOutput()
|
||||
func (l *LoggerHCLogAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writer {
|
||||
return &HCLogStdlogAdapter{
|
||||
log: l,
|
||||
inferLevels: opts.InferLevels,
|
||||
forceLevel: opts.ForceLevel,
|
||||
}
|
||||
}
|
||||
@ -6,10 +6,15 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/anchore/syft/syft/logger"
|
||||
"github.com/sirupsen/logrus"
|
||||
prefixed "github.com/x-cray/logrus-prefixed-formatter"
|
||||
)
|
||||
|
||||
// integrity check
|
||||
var _ logger.Logger = &LogrusLogger{}
|
||||
var _ logger.Logger = &LogrusNestedLogger{}
|
||||
|
||||
type LogrusConfig struct {
|
||||
EnableConsole bool
|
||||
EnableFile bool
|
||||
@ -76,42 +81,50 @@ func NewLogrusLogger(cfg LogrusConfig) *LogrusLogger {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *LogrusLogger) Debugf(format string, args ...interface{}) {
|
||||
l.Logger.Debugf(format, args...)
|
||||
func (l *LogrusLogger) Errorf(format string, args ...interface{}) {
|
||||
l.Logger.Errorf(format, args...)
|
||||
}
|
||||
|
||||
func (l *LogrusLogger) Infof(format string, args ...interface{}) {
|
||||
l.Logger.Infof(format, args...)
|
||||
}
|
||||
|
||||
func (l *LogrusLogger) Debug(args ...interface{}) {
|
||||
l.Logger.Debug(args...)
|
||||
func (l *LogrusLogger) Debugf(format string, args ...interface{}) {
|
||||
l.Logger.Debugf(format, args...)
|
||||
}
|
||||
|
||||
func (l *LogrusLogger) Error(args ...interface{}) {
|
||||
l.Logger.Error(args...)
|
||||
}
|
||||
|
||||
func (l *LogrusLogger) Info(args ...interface{}) {
|
||||
l.Logger.Info(args...)
|
||||
}
|
||||
|
||||
func (l *LogrusLogger) Errorf(format string, args ...interface{}) {
|
||||
l.Logger.Errorf(format, args...)
|
||||
func (l *LogrusLogger) Debug(args ...interface{}) {
|
||||
l.Logger.Debug(args...)
|
||||
}
|
||||
|
||||
func (l *LogrusNestedLogger) Debugf(format string, args ...interface{}) {
|
||||
l.Logger.Debugf(format, args...)
|
||||
func (l *LogrusNestedLogger) Errorf(format string, args ...interface{}) {
|
||||
l.Logger.Errorf(format, args...)
|
||||
}
|
||||
|
||||
func (l *LogrusNestedLogger) Infof(format string, args ...interface{}) {
|
||||
l.Logger.Infof(format, args...)
|
||||
}
|
||||
|
||||
func (l *LogrusNestedLogger) Debug(args ...interface{}) {
|
||||
l.Logger.Debug(args...)
|
||||
func (l *LogrusNestedLogger) Debugf(format string, args ...interface{}) {
|
||||
l.Logger.Debugf(format, args...)
|
||||
}
|
||||
|
||||
func (l *LogrusNestedLogger) Error(args ...interface{}) {
|
||||
l.Logger.Error(args...)
|
||||
}
|
||||
|
||||
func (l *LogrusNestedLogger) Info(args ...interface{}) {
|
||||
l.Logger.Info(args...)
|
||||
}
|
||||
|
||||
func (l *LogrusNestedLogger) Errorf(format string, args ...interface{}) {
|
||||
l.Logger.Errorf(format, args...)
|
||||
func (l *LogrusNestedLogger) Debug(args ...interface{}) {
|
||||
l.Logger.Debug(args...)
|
||||
}
|
||||
|
||||
181
internal/logger/logrus_hclog_adapter.go
Normal file
181
internal/logger/logrus_hclog_adapter.go
Normal file
@ -0,0 +1,181 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// integrity check
|
||||
var _ hclog.Logger = &LogrusHCLogAdapter{}
|
||||
|
||||
var levels = map[hclog.Level]logrus.Level{
|
||||
hclog.NoLevel: logrus.PanicLevel,
|
||||
hclog.Error: logrus.ErrorLevel,
|
||||
hclog.Warn: logrus.WarnLevel,
|
||||
hclog.Info: logrus.InfoLevel,
|
||||
hclog.Debug: logrus.DebugLevel,
|
||||
hclog.Trace: logrus.TraceLevel,
|
||||
}
|
||||
|
||||
// LogrusHCLogAdapter is used to adapt a logrus logger object to the hclog.Logger interface for syft plugins.
|
||||
type LogrusHCLogAdapter struct {
|
||||
logger *logrus.Logger
|
||||
entry *logrus.Entry
|
||||
}
|
||||
|
||||
func NewLogrusHCLogAdapter(logger *logrus.Logger, fields map[string]interface{}) *LogrusHCLogAdapter {
|
||||
if fields != nil {
|
||||
return &LogrusHCLogAdapter{
|
||||
logger: logger,
|
||||
entry: logger.WithFields(fields),
|
||||
}
|
||||
}
|
||||
return &LogrusHCLogAdapter{
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *LogrusHCLogAdapter) log(level hclog.Level, msg string, args ...interface{}) {
|
||||
if l.entry != nil {
|
||||
l.entry.WithFields(makeArgFields(args...)).Log(levels[level], msg)
|
||||
return
|
||||
}
|
||||
l.logger.WithFields(makeArgFields(args...)).Log(levels[level], msg)
|
||||
}
|
||||
|
||||
// Args are alternating key, val pairs
|
||||
// keys must be strings
|
||||
// vals can be any type, but display is implementation specific
|
||||
// Emit a message and key/value pairs at a provided log level
|
||||
func (l *LogrusHCLogAdapter) Log(level hclog.Level, msg string, args ...interface{}) {
|
||||
l.log(level, msg, args...)
|
||||
}
|
||||
|
||||
// Emit a message and key/value pairs at the TRACE level
|
||||
func (l *LogrusHCLogAdapter) Trace(msg string, args ...interface{}) {
|
||||
l.log(hclog.Trace, msg, args...)
|
||||
}
|
||||
|
||||
// Emit a message and key/value pairs at the DEBUG level
|
||||
func (l *LogrusHCLogAdapter) Debug(msg string, args ...interface{}) {
|
||||
l.log(hclog.Debug, msg, args...)
|
||||
}
|
||||
|
||||
// Emit a message and key/value pairs at the INFO level
|
||||
func (l *LogrusHCLogAdapter) Info(msg string, args ...interface{}) {
|
||||
l.log(hclog.Info, msg, args...)
|
||||
}
|
||||
|
||||
// Emit a message and key/value pairs at the WARN level
|
||||
func (l *LogrusHCLogAdapter) Warn(msg string, args ...interface{}) {
|
||||
l.log(hclog.Warn, msg, args...)
|
||||
}
|
||||
|
||||
// Emit a message and key/value pairs at the ERROR level
|
||||
func (l *LogrusHCLogAdapter) Error(msg string, args ...interface{}) {
|
||||
l.log(hclog.Error, msg, args...)
|
||||
}
|
||||
|
||||
// Indicate if TRACE logs would be emitted. This and the other Is* guards
|
||||
// are used to elide expensive logging code based on the current level.
|
||||
func (l *LogrusHCLogAdapter) IsTrace() bool {
|
||||
return l.logger.Level <= logrus.TraceLevel
|
||||
}
|
||||
|
||||
// Indicate if DEBUG logs would be emitted. This and the other Is* guards
|
||||
// are used to elide expensive logging code based on the current level.
|
||||
func (l *LogrusHCLogAdapter) IsDebug() bool {
|
||||
return l.logger.Level <= logrus.DebugLevel
|
||||
}
|
||||
|
||||
// Indicate if INFO logs would be emitted. This and the other Is* guards
|
||||
// are used to elide expensive logging code based on the current level.
|
||||
func (l *LogrusHCLogAdapter) IsInfo() bool {
|
||||
return l.logger.Level <= logrus.InfoLevel
|
||||
}
|
||||
|
||||
// Indicate if WARN logs would be emitted. This and the other Is* guards
|
||||
// are used to elide expensive logging code based on the current level.
|
||||
func (l *LogrusHCLogAdapter) IsWarn() bool {
|
||||
return l.logger.Level <= logrus.WarnLevel
|
||||
}
|
||||
|
||||
// Indicate if ERROR logs would be emitted. This and the other Is* guards
|
||||
// are used to elide expensive logging code based on the current level.
|
||||
func (l *LogrusHCLogAdapter) IsError() bool {
|
||||
return l.logger.Level <= logrus.ErrorLevel
|
||||
}
|
||||
|
||||
// ImpliedArgs returns With key/value pairs
|
||||
func (l *LogrusHCLogAdapter) ImpliedArgs() []interface{} {
|
||||
// TODO: not implemented
|
||||
return nil
|
||||
}
|
||||
|
||||
// Creates a sublogger that will always have the given key/value pairs
|
||||
func (l *LogrusHCLogAdapter) With(args ...interface{}) hclog.Logger {
|
||||
l.entry = l.logger.WithFields(makeArgFields(args...))
|
||||
return l
|
||||
}
|
||||
|
||||
// Returns the Name of the logger
|
||||
func (l *LogrusHCLogAdapter) Name() string {
|
||||
// TODO: not implemented
|
||||
return ""
|
||||
}
|
||||
|
||||
// Create a logger that will prepend the name string on the front of all messages.
|
||||
// If the logger already has a name, the new value will be appended to the current
|
||||
// name. That way, a major subsystem can use this to decorate all it's own logs
|
||||
// without losing context.
|
||||
func (l *LogrusHCLogAdapter) Named(name string) hclog.Logger {
|
||||
return NewLogrusHCLogAdapter(l.logger, logrus.Fields{"name": name})
|
||||
}
|
||||
|
||||
// Create a logger that will prepend the name string on the front of all messages.
|
||||
// This sets the name of the logger to the value directly, unlike Named which honor
|
||||
// the current name as well.
|
||||
func (l *LogrusHCLogAdapter) ResetNamed(name string) hclog.Logger {
|
||||
return NewLogrusHCLogAdapter(l.logger, logrus.Fields{"name": name})
|
||||
}
|
||||
|
||||
// Updates the level. This should affect all sub-loggers as well. If an
|
||||
// implementation cannot update the level on the fly, it should no-op.
|
||||
func (l *LogrusHCLogAdapter) SetLevel(level hclog.Level) {
|
||||
l.logger.SetLevel(levels[level])
|
||||
}
|
||||
|
||||
// Return a value that conforms to the stdlib log.Logger interface
|
||||
func (l *LogrusHCLogAdapter) StandardLogger(opts *hclog.StandardLoggerOptions) *log.Logger {
|
||||
return log.New(l.StandardWriter(opts), "", log.LstdFlags)
|
||||
}
|
||||
|
||||
// Return a value that conforms to io.Writer, which can be passed into log.SetOutput()
|
||||
func (l *LogrusHCLogAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writer {
|
||||
return &HCLogStdlogAdapter{
|
||||
log: l,
|
||||
inferLevels: opts.InferLevels,
|
||||
forceLevel: opts.ForceLevel,
|
||||
}
|
||||
}
|
||||
|
||||
func makeArgFields(args ...interface{}) logrus.Fields {
|
||||
if len(args)%2 != 0 {
|
||||
panic(fmt.Errorf("odd number of logger key-value pairs (%d): %+v", len(args), args))
|
||||
}
|
||||
|
||||
var key string
|
||||
var fields = make(logrus.Fields)
|
||||
for i, arg := range args {
|
||||
if i%2 == 0 {
|
||||
key = arg.(string)
|
||||
} else {
|
||||
fields[key] = arg
|
||||
}
|
||||
}
|
||||
return fields
|
||||
}
|
||||
@ -24,8 +24,9 @@ func Catalog(resolver scope.Resolver, catalogers ...Cataloger) (*pkg.Catalog, er
|
||||
|
||||
// ask catalogers for files to extract from the image tar
|
||||
for _, a := range catalogers {
|
||||
fileSelection = append(fileSelection, a.SelectFiles(resolver)...)
|
||||
log.Debugf("cataloger '%s' selected '%d' files", a.Name(), len(fileSelection))
|
||||
catalogerSelection := a.SelectFiles(resolver)
|
||||
fileSelection = append(fileSelection, catalogerSelection...)
|
||||
log.Debugf("cataloger '%s' selected '%d' files", a.Name(), len(catalogerSelection))
|
||||
filesProcessed.N += int64(len(fileSelection))
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,8 @@ package cataloger
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/anchore/syft/syft/cataloger/dpkg"
|
||||
|
||||
"github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/anchore/syft/syft/cataloger/apkdb"
|
||||
"github.com/anchore/syft/syft/cataloger/bundler"
|
||||
@ -36,7 +38,7 @@ type Cataloger interface {
|
||||
// All returns a slice of all locally defined catalogers (defined in child packages).
|
||||
func BuiltIn() []Cataloger {
|
||||
return []Cataloger{
|
||||
//dpkg.New(),
|
||||
dpkg.New(),
|
||||
bundler.New(),
|
||||
python.New(),
|
||||
rpmdb.New(),
|
||||
|
||||
@ -5,6 +5,7 @@ package logger
|
||||
|
||||
type Logger interface {
|
||||
Errorf(format string, args ...interface{})
|
||||
Error(args ...interface{})
|
||||
Infof(format string, args ...interface{})
|
||||
Info(args ...interface{})
|
||||
Debugf(format string, args ...interface{})
|
||||
|
||||
@ -6,5 +6,5 @@ type Config struct {
|
||||
Command string
|
||||
Args []string
|
||||
Env []string
|
||||
//Sha256 []byte
|
||||
Sha256 []byte
|
||||
}
|
||||
|
||||
@ -3,11 +3,11 @@ package grpc
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/cataloger"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/anchore/syft/syft/cataloger"
|
||||
|
||||
"github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/plugin/proto"
|
||||
@ -57,8 +57,6 @@ func (c *CatalogerClient) SelectFiles(resolver scope.FileResolver) []file.Refere
|
||||
FileResolverBrokerId: brokerID,
|
||||
})
|
||||
|
||||
log.Debugf("Select Files Response: %+v", resp)
|
||||
|
||||
if err != nil {
|
||||
// TODO: nope
|
||||
panic(err)
|
||||
|
||||
@ -2,6 +2,7 @@ package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
|
||||
"github.com/anchore/stereoscope/pkg/file"
|
||||
|
||||
@ -2,7 +2,6 @@ package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
|
||||
"github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/anchore/syft/syft/plugin/proto"
|
||||
@ -37,15 +36,11 @@ func (m *FileResolverServer) FilesByPath(ctx context.Context, req *proto.FileRes
|
||||
}
|
||||
|
||||
func (m *FileResolverServer) FilesByGlob(ctx context.Context, req *proto.FileResolverRequest) (resp *proto.FileResolverResponse, err error) {
|
||||
log.Debugf("FilesByGlob Request: %+v", req)
|
||||
|
||||
r, err := m.Impl.FilesByGlob(req.Paths...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debugf("FilesByGlob Result: %+v", r)
|
||||
|
||||
var refs []*proto.FileReference
|
||||
for _, ref := range r {
|
||||
refs = append(refs, &proto.FileReference{
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/internal/logger"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/go-plugin"
|
||||
)
|
||||
|
||||
@ -24,27 +26,33 @@ type Plugin struct {
|
||||
// TODO: type should be in the name like with terraform "terraform-<TYPE>-<NAME>"
|
||||
|
||||
func NewPlugin(config Config) Plugin {
|
||||
cmd := exec.Command("sh", "-c", config.Command) //, config.Args...)
|
||||
//cmd := exec.Command("sh", "-c", config.Command) //, config.Args...)
|
||||
cmd := exec.Command(config.Command)
|
||||
cmd.Env = append(cmd.Env, config.Env...)
|
||||
|
||||
//secureConfig := &plugin.SecureConfig{
|
||||
// Checksum: config.Sha256,
|
||||
// Hash: sha256.New(),
|
||||
//}
|
||||
var secureConfig *plugin.SecureConfig
|
||||
if len(config.Sha256) > 0 {
|
||||
secureConfig = &plugin.SecureConfig{
|
||||
Checksum: config.Sha256,
|
||||
Hash: sha256.New(),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: temp?
|
||||
logger := hclog.New(&hclog.LoggerOptions{
|
||||
Name: config.Name,
|
||||
Level: hclog.Trace,
|
||||
Output: os.Stderr,
|
||||
})
|
||||
var pluginLogger hclog.Logger
|
||||
if logrusLogger, ok := log.Log.(*logger.LogrusLogger); ok {
|
||||
pluginLogger = logger.NewLogrusHCLogAdapter(logrusLogger.Logger, map[string]interface{}{"plugin": config.Name})
|
||||
} else {
|
||||
// TODO: this does not fully map features, thus logging will be awkward
|
||||
// TODO: find a better way to map loggers (expand our interface?)
|
||||
pluginLogger = logger.NewLoggerHCLogAdapter(log.Log)
|
||||
}
|
||||
|
||||
clientConfig := plugin.ClientConfig{
|
||||
HandshakeConfig: config.Type.HandshakeConfig(),
|
||||
VersionedPlugins: versionedPlugins,
|
||||
//SecureConfig: secureConfig,
|
||||
Cmd: cmd,
|
||||
Logger: logger,
|
||||
SecureConfig: secureConfig,
|
||||
Cmd: cmd,
|
||||
Logger: pluginLogger,
|
||||
AllowedProtocols: []plugin.Protocol{
|
||||
plugin.ProtocolGRPC,
|
||||
},
|
||||
@ -56,7 +64,7 @@ func NewPlugin(config Config) Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
func (p Plugin) Start() (interface{}, error) {
|
||||
func (p *Plugin) Start() (interface{}, error) {
|
||||
if p.client != nil {
|
||||
return nil, fmt.Errorf("plugin already started")
|
||||
}
|
||||
@ -79,7 +87,7 @@ func (p Plugin) Start() (interface{}, error) {
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
func (p Plugin) Stop() error {
|
||||
func (p *Plugin) Stop() error {
|
||||
if p.client == nil {
|
||||
return fmt.Errorf("plugin has not been started")
|
||||
}
|
||||
|
||||
@ -2,8 +2,11 @@ package plugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/anchore/syft/syft/cataloger"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/cataloger"
|
||||
)
|
||||
|
||||
type Repository struct {
|
||||
@ -35,8 +38,11 @@ func (c *Repository) AddFromDirectory(dir string, pluginTypes ...Type) error {
|
||||
return err
|
||||
}
|
||||
for _, plugin := range plugins {
|
||||
log.Debugf("added plugin: %q", plugin.Config.Name)
|
||||
c.Add(plugin)
|
||||
}
|
||||
log.Debugf("%d plugins added", len(plugins))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -49,8 +55,9 @@ func (c *Repository) ActivateCatalogers() ([]cataloger.Cataloger, func(), error)
|
||||
var plugins []Plugin
|
||||
var deactivateFn = func() {
|
||||
for _, plugin := range plugins {
|
||||
// TODO: handle error by log
|
||||
plugin.Stop()
|
||||
if err := plugin.Stop(); err != nil {
|
||||
log.Errorf("failed to stop plugin: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,10 +95,10 @@ func Discover(dir string, pluginTypes ...Type) ([]Plugin, error) {
|
||||
var plugins []Plugin
|
||||
|
||||
for _, pluginType := range pluginTypes {
|
||||
// look into a sub dir named by the plugin type
|
||||
searchDir := filepath.Join(dir, pluginType.String())
|
||||
pluginPrefix := pluginType.String()
|
||||
pluginGlob := fmt.Sprintf("%s-*", pluginPrefix)
|
||||
paths, err := filepath.Glob(filepath.Join(dir, pluginGlob))
|
||||
|
||||
paths, err := filepath.Glob(filepath.Join(searchDir, "*"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -100,7 +107,7 @@ func Discover(dir string, pluginTypes ...Type) ([]Plugin, error) {
|
||||
// TODO: should we use a config for some of this?
|
||||
plugins = append(plugins, NewPlugin(Config{
|
||||
// TODO: should the name be org/name instead of just name? this implies changing the dir storage too
|
||||
Name: filepath.Base(path),
|
||||
Name: strings.TrimPrefix(filepath.Base(path), pluginPrefix+"-"),
|
||||
Type: pluginType,
|
||||
Command: path,
|
||||
Args: nil, // TODO
|
||||
|
||||
@ -31,7 +31,7 @@ func (p Type) HandshakeConfig() plugin.HandshakeConfig {
|
||||
case TypeCataloger:
|
||||
return plugin.HandshakeConfig{
|
||||
ProtocolVersion: 1,
|
||||
MagicCookieKey: "SYFT_CATALOGER_PLUGIN",
|
||||
MagicCookieKey: "SYFT_PLUGIN_MAGIC_COOKIE",
|
||||
MagicCookieValue: "0f86cc7f-6f97-410e-a844-087cd12e36e3",
|
||||
}
|
||||
default:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user