mirror of
https://github.com/anchore/syft
synced 2024-11-10 06:14:16 +00:00
add default table presenter
This commit is contained in:
parent
0a0bc68e95
commit
32071b0bf1
12 changed files with 162 additions and 1 deletions
|
@ -59,7 +59,7 @@ func setGlobalCliOptions() {
|
|||
// output & formatting options
|
||||
flag = "output"
|
||||
rootCmd.Flags().StringP(
|
||||
flag, "o", presenter.TextPresenter.String(),
|
||||
flag, "o", presenter.TablePresenter.String(),
|
||||
fmt.Sprintf("report output formatter, options=%v", presenter.Options),
|
||||
)
|
||||
if err := viper.BindPFlag(flag, rootCmd.Flags().Lookup(flag)); err != nil {
|
||||
|
|
1
go.mod
1
go.mod
|
@ -16,6 +16,7 @@ require (
|
|||
github.com/hashicorp/go-version v1.2.0
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/mitchellh/mapstructure v1.3.1
|
||||
github.com/olekukonko/tablewriter v0.0.4
|
||||
github.com/rogpeppe/go-internal v1.5.2
|
||||
github.com/sergi/go-diff v1.1.0
|
||||
github.com/spf13/cobra v1.0.0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -587,6 +587,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA
|
|||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw=
|
||||
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
|
@ -632,6 +634,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb
|
|||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
|
||||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
|
|
|
@ -6,17 +6,20 @@ const (
|
|||
UnknownPresenter Option = iota
|
||||
JSONPresenter
|
||||
TextPresenter
|
||||
TablePresenter
|
||||
)
|
||||
|
||||
var optionStr = []string{
|
||||
"UnknownPresenter",
|
||||
"json",
|
||||
"text",
|
||||
"table",
|
||||
}
|
||||
|
||||
var Options = []Option{
|
||||
JSONPresenter,
|
||||
TextPresenter,
|
||||
TablePresenter,
|
||||
}
|
||||
|
||||
type Option int
|
||||
|
@ -27,6 +30,8 @@ func ParseOption(userStr string) Option {
|
|||
return JSONPresenter
|
||||
case strings.ToLower(TextPresenter.String()):
|
||||
return TextPresenter
|
||||
case strings.ToLower(TablePresenter.String()):
|
||||
return TablePresenter
|
||||
default:
|
||||
return UnknownPresenter
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/presenter/json"
|
||||
"github.com/anchore/syft/syft/presenter/table"
|
||||
"github.com/anchore/syft/syft/presenter/text"
|
||||
"github.com/anchore/syft/syft/scope"
|
||||
)
|
||||
|
@ -20,6 +21,8 @@ func GetPresenter(option Option, s scope.Scope, catalog *pkg.Catalog) Presenter
|
|||
return json.NewPresenter(catalog, s)
|
||||
case TextPresenter:
|
||||
return text.NewPresenter(catalog, s)
|
||||
case TablePresenter:
|
||||
return table.NewPresenter(catalog, s)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
|
67
syft/presenter/table/presenter.go
Normal file
67
syft/presenter/table/presenter.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package table
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/scope"
|
||||
)
|
||||
|
||||
type Presenter struct {
|
||||
catalog *pkg.Catalog
|
||||
scope scope.Scope
|
||||
}
|
||||
|
||||
func NewPresenter(catalog *pkg.Catalog, s scope.Scope) *Presenter {
|
||||
return &Presenter{
|
||||
catalog: catalog,
|
||||
scope: s,
|
||||
}
|
||||
}
|
||||
|
||||
func (pres *Presenter) Present(output io.Writer) error {
|
||||
rows := make([][]string, 0)
|
||||
|
||||
columns := []string{"Name", "Version", "Type"}
|
||||
for p := range pres.catalog.Enumerate() {
|
||||
row := []string{
|
||||
p.Name,
|
||||
p.Version,
|
||||
p.Type.String(),
|
||||
}
|
||||
rows = append(rows, row)
|
||||
}
|
||||
|
||||
// sort by name, version, then type
|
||||
sort.SliceStable(rows, func(i, j int) bool {
|
||||
for col := 0; col < len(columns); col++ {
|
||||
if rows[i][0] != rows[j][0] {
|
||||
return rows[i][col] < rows[j][col]
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
table := tablewriter.NewWriter(output)
|
||||
|
||||
table.SetHeader(columns)
|
||||
table.SetHeaderLine(false)
|
||||
table.SetBorder(false)
|
||||
table.SetAutoWrapText(false)
|
||||
table.SetAutoFormatHeaders(true)
|
||||
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
|
||||
table.SetAlignment(tablewriter.ALIGN_LEFT)
|
||||
table.SetCenterSeparator("")
|
||||
table.SetColumnSeparator("")
|
||||
table.SetRowSeparator("")
|
||||
table.SetTablePadding("\t")
|
||||
table.SetNoWhiteSpace(true)
|
||||
|
||||
table.AppendBulk(rows)
|
||||
table.Render()
|
||||
|
||||
return nil
|
||||
}
|
68
syft/presenter/table/presenter_test.go
Normal file
68
syft/presenter/table/presenter_test.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
package table
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/go-testutils"
|
||||
"github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/scope"
|
||||
"github.com/sergi/go-diff/diffmatchpatch"
|
||||
)
|
||||
|
||||
var update = flag.Bool("update", false, "update the *.golden files for table presenters")
|
||||
|
||||
func TestTablePresenter(t *testing.T) {
|
||||
var buffer bytes.Buffer
|
||||
|
||||
testImage := "image-simple"
|
||||
|
||||
catalog := pkg.NewCatalog()
|
||||
img, cleanup := testutils.GetFixtureImage(t, "docker-archive", testImage)
|
||||
defer cleanup()
|
||||
|
||||
// populate catalog with test data
|
||||
catalog.Add(pkg.Package{
|
||||
Name: "package-1",
|
||||
Version: "1.0.1",
|
||||
Source: []file.Reference{
|
||||
*img.SquashedTree().File("/somefile-1.txt"),
|
||||
},
|
||||
Type: pkg.DebPkg,
|
||||
})
|
||||
catalog.Add(pkg.Package{
|
||||
Name: "package-2",
|
||||
Version: "2.0.1",
|
||||
Source: []file.Reference{
|
||||
*img.SquashedTree().File("/somefile-2.txt"),
|
||||
},
|
||||
Type: pkg.DebPkg,
|
||||
})
|
||||
|
||||
s, err := scope.NewScopeFromImage(img, scope.AllLayersScope)
|
||||
pres := NewPresenter(catalog, s)
|
||||
|
||||
// run presenter
|
||||
err = pres.Present(&buffer)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
actual := buffer.Bytes()
|
||||
|
||||
if *update {
|
||||
testutils.UpdateGoldenFileContents(t, actual)
|
||||
}
|
||||
|
||||
var expected = testutils.GetGoldenFileContents(t)
|
||||
|
||||
if !bytes.Equal(expected, actual) {
|
||||
dmp := diffmatchpatch.New()
|
||||
diffs := dmp.DiffMain(string(actual), string(expected), true)
|
||||
t.Errorf("mismatched output:\n%s", dmp.DiffPrettyText(diffs))
|
||||
}
|
||||
|
||||
// TODO: add me back in when there is a JSON schema
|
||||
// validateAgainstV1Schema(t, string(actual))
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
# Note: changes to this file will result in updating several test values. Consider making a new image fixture instead of editing this one.
|
||||
FROM scratch
|
||||
ADD file-1.txt /somefile-1.txt
|
||||
ADD file-2.txt /somefile-2.txt
|
||||
# note: adding a directory will behave differently on docker engine v18 vs v19
|
||||
ADD target /
|
|
@ -0,0 +1 @@
|
|||
this file has contents
|
|
@ -0,0 +1 @@
|
|||
file-2 contents!
|
|
@ -0,0 +1,2 @@
|
|||
another file!
|
||||
with lines...
|
|
@ -0,0 +1,3 @@
|
|||
NAME VERSION TYPE
|
||||
package-1 1.0.1 deb
|
||||
package-2 2.0.1 deb
|
Loading…
Reference in a new issue