mirror of
https://github.com/anchore/syft.git
synced 2026-11-04 08:26:38 +01:00
Add filters to package cataloger (#1021)
* Add filters to package cataloger This PR adds filters so a package without name or version doesn't go in the list of all discovered packages. Integration and cli tests were added to validate the feature. Signed-off-by: Jonas Xavier <jonasx@anchore.com> * add nolint:funlen to cataloger/catalog.go Signed-off-by: Jonas Xavier <jonasx@anchore.com> * don't require package version Signed-off-by: Jonas Xavier <jonasx@anchore.com> * add package filtering to generic and python cataloger also removes cli tests in favor of integration and unit tests Signed-off-by: Jonas Xavier <jonasx@anchore.com> * drop nolint:funlen Signed-off-by: Jonas Xavier <jonasx@anchore.com> * check for no-removal operation Signed-off-by: Jonas Xavier <jonasx@anchore.com> * remove unused fixtures Signed-off-by: Jonas Xavier <jonasx@anchore.com> * rename no-version file to hide semantic version Signed-off-by: Jonas Xavier <jonasx@anchore.com> * drop integration tests and add pkg func for validation Signed-off-by: Jonas Xavier <jonasx@anchore.com> * python cataloger use global pkg validation Signed-off-by: Jonas Xavier <jonasx@anchore.com> * check for valid packages on deb/go/rpm catalogers Signed-off-by: Jonas Xavier <jonasx@anchore.com> * update rpm cataloger after rebase Signed-off-by: Jonas Xavier <jonasx@anchore.com> * nit with pointers Signed-off-by: Jonas Xavier <jonasx@anchore.com> * simpler use of package validation Signed-off-by: Jonas Xavier <jonasx@anchore.com> * remmove double pkg validations Signed-off-by: Jonas Xavier <jonasx@anchore.com> * rename func param to artifactsToExclude Signed-off-by: Jonas Xavier <jonasx@anchore.com> * add test for relationships and bug fix Signed-off-by: Jonas Xavier <jonasx@anchore.com> * feedback changes Signed-off-by: Jonas Xavier <jonasx@anchore.com>
This commit is contained in:
@@ -7,28 +7,31 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func parser(_ string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) {
|
||||
contents, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return []*pkg.Package{
|
||||
{
|
||||
Name: string(contents),
|
||||
},
|
||||
}, nil, nil
|
||||
}
|
||||
|
||||
func TestGenericCataloger(t *testing.T) {
|
||||
allParsedPathes := make(map[string]bool)
|
||||
parser := func(path string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) {
|
||||
allParsedPathes[path] = true
|
||||
contents, err := ioutil.ReadAll(reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
p := &pkg.Package{Name: string(contents)}
|
||||
r := artifact.Relationship{From: p, To: p,
|
||||
Type: artifact.ContainsRelationship,
|
||||
}
|
||||
|
||||
return []*pkg.Package{p}, []artifact.Relationship{r}, nil
|
||||
}
|
||||
|
||||
globParsers := map[string]ParserFn{
|
||||
"**/a-path.txt": parser,
|
||||
"**/empty.txt": parser,
|
||||
}
|
||||
pathParsers := map[string]ParserFn{
|
||||
"test-fixtures/another-path.txt": parser,
|
||||
@@ -36,21 +39,27 @@ func TestGenericCataloger(t *testing.T) {
|
||||
}
|
||||
upstream := "some-other-cataloger"
|
||||
|
||||
expectedSelection := []string{"test-fixtures/last/path.txt", "test-fixtures/another-path.txt", "test-fixtures/a-path.txt"}
|
||||
expectedSelection := []string{"test-fixtures/last/path.txt", "test-fixtures/another-path.txt", "test-fixtures/a-path.txt", "test-fixtures/empty.txt"}
|
||||
resolver := source.NewMockResolverForPaths(expectedSelection...)
|
||||
cataloger := NewGenericCataloger(pathParsers, globParsers, upstream)
|
||||
|
||||
actualPkgs, relationships, err := cataloger.Catalog(resolver)
|
||||
assert.NoError(t, err)
|
||||
|
||||
expectedPkgs := make(map[string]pkg.Package)
|
||||
for _, path := range expectedSelection {
|
||||
require.True(t, allParsedPathes[path])
|
||||
expectedPkgs[path] = pkg.Package{
|
||||
FoundBy: upstream,
|
||||
Name: fmt.Sprintf("%s file contents!", path),
|
||||
}
|
||||
}
|
||||
|
||||
actualPkgs, _, err := cataloger.Catalog(resolver)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, actualPkgs, len(expectedPkgs))
|
||||
assert.Len(t, allParsedPathes, len(expectedSelection))
|
||||
// empty.txt won't become a package
|
||||
assert.Len(t, actualPkgs, len(expectedPkgs)-1)
|
||||
// right now, a relationship is created for each package, but if the relationship includes an invalid package it should be dropped.
|
||||
assert.Len(t, relationships, len(actualPkgs))
|
||||
|
||||
for _, p := range actualPkgs {
|
||||
ref := p.Locations.ToSlice()[0]
|
||||
@@ -69,3 +78,99 @@ func TestGenericCataloger(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_removeRelationshipsWithArtifactIDs(t *testing.T) {
|
||||
one := &pkg.Package{Name: "one", Version: "1.0"}
|
||||
two := &pkg.Package{Name: "two", Version: "1.0"}
|
||||
three := &pkg.Package{Name: "three", Version: "1.0"}
|
||||
four := &pkg.Package{Name: "four", Version: "bla"}
|
||||
five := &pkg.Package{Name: "five", Version: "1.0"}
|
||||
|
||||
pkgs := make([]artifact.Identifiable, 0)
|
||||
for _, p := range []*pkg.Package{one, two, three, four, five} {
|
||||
// IDs are necessary for comparison
|
||||
p.SetID()
|
||||
pkgs = append(pkgs, p)
|
||||
}
|
||||
|
||||
type args struct {
|
||||
remove map[artifact.ID]struct{}
|
||||
relationships []artifact.Relationship
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []artifact.Relationship
|
||||
}{
|
||||
{
|
||||
name: "nothing-to-remove",
|
||||
args: args{
|
||||
relationships: []artifact.Relationship{
|
||||
{From: one, To: two},
|
||||
},
|
||||
},
|
||||
want: []artifact.Relationship{
|
||||
{From: one, To: two},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "remove-all-relationships",
|
||||
args: args{
|
||||
remove: map[artifact.ID]struct{}{
|
||||
one.ID(): {},
|
||||
three.ID(): {},
|
||||
},
|
||||
relationships: []artifact.Relationship{
|
||||
{From: one, To: two},
|
||||
{From: two, To: three},
|
||||
{From: three, To: four},
|
||||
},
|
||||
},
|
||||
want: []artifact.Relationship(nil),
|
||||
},
|
||||
{
|
||||
name: "remove-half-of-relationships",
|
||||
args: args{
|
||||
remove: map[artifact.ID]struct{}{
|
||||
one.ID(): {},
|
||||
},
|
||||
relationships: []artifact.Relationship{
|
||||
{From: one, To: two},
|
||||
{From: one, To: three},
|
||||
{From: two, To: three},
|
||||
{From: three, To: four},
|
||||
},
|
||||
},
|
||||
want: []artifact.Relationship{
|
||||
{From: two, To: three},
|
||||
{From: three, To: four},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "remove-repeated-relationships",
|
||||
args: args{
|
||||
remove: map[artifact.ID]struct{}{
|
||||
one.ID(): {},
|
||||
two.ID(): {},
|
||||
},
|
||||
relationships: []artifact.Relationship{
|
||||
{From: one, To: two},
|
||||
{From: one, To: three},
|
||||
{From: two, To: three},
|
||||
{From: two, To: three},
|
||||
{From: three, To: four},
|
||||
{From: four, To: five},
|
||||
},
|
||||
},
|
||||
want: []artifact.Relationship{
|
||||
{From: three, To: four},
|
||||
{From: four, To: five},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equalf(t, tt.want, removeRelationshipsWithArtifactIDs(tt.args.remove, tt.args.relationships), "removeRelationshipsWithArtifactIDs(%v, %v)", tt.args.remove, tt.args.relationships)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user