mirror of
https://github.com/anchore/syft.git
synced 2025-11-18 17:03:17 +01:00
port dart cataloger to new generic cataloger pattern (#1285)
Signed-off-by: Alex Goodman <alex.goodman@anchore.com> Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
parent
eb8ebd9ffc
commit
fbdde6d4f4
@ -1,14 +1,13 @@
|
|||||||
package dart
|
package dart
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/common"
|
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewPubspecLockCataloger returns a new Dartlang cataloger object base on pubspec lock files.
|
const catalogerName = "dartlang-lock-cataloger"
|
||||||
func NewPubspecLockCataloger() *common.GenericCataloger {
|
|
||||||
globParsers := map[string]common.ParserFn{
|
|
||||||
"**/pubspec.lock": parsePubspecLock,
|
|
||||||
}
|
|
||||||
|
|
||||||
return common.NewGenericCataloger(nil, globParsers, "dartlang-lock-cataloger")
|
// NewPubspecLockCataloger returns a new Dartlang cataloger object base on pubspec lock files.
|
||||||
|
func NewPubspecLockCataloger() *generic.Cataloger {
|
||||||
|
return generic.NewCataloger(catalogerName).
|
||||||
|
WithParserByGlobs(parsePubspecLock, "**/pubspec.lock")
|
||||||
}
|
}
|
||||||
|
|||||||
56
syft/pkg/cataloger/dart/package.go
Normal file
56
syft/pkg/cataloger/dart/package.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package dart
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/anchore/packageurl-go"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/source"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newPubspecLockPackage(name string, raw pubspecLockPackage, locations ...source.Location) pkg.Package {
|
||||||
|
metadata := pkg.DartPubMetadata{
|
||||||
|
Name: name,
|
||||||
|
Version: raw.Version,
|
||||||
|
HostedURL: raw.getHostedURL(),
|
||||||
|
VcsURL: raw.getVcsURL(),
|
||||||
|
}
|
||||||
|
|
||||||
|
p := pkg.Package{
|
||||||
|
Name: name,
|
||||||
|
Version: raw.Version,
|
||||||
|
Locations: source.NewLocationSet(locations...),
|
||||||
|
PURL: packageURL(metadata),
|
||||||
|
Language: pkg.Dart,
|
||||||
|
Type: pkg.DartPubPkg,
|
||||||
|
MetadataType: pkg.DartPubMetadataType,
|
||||||
|
Metadata: metadata,
|
||||||
|
}
|
||||||
|
|
||||||
|
p.SetID()
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func packageURL(m pkg.DartPubMetadata) string {
|
||||||
|
var qualifiers packageurl.Qualifiers
|
||||||
|
|
||||||
|
if m.HostedURL != "" {
|
||||||
|
qualifiers = append(qualifiers, packageurl.Qualifier{
|
||||||
|
Key: "hosted_url",
|
||||||
|
Value: m.HostedURL,
|
||||||
|
})
|
||||||
|
} else if m.VcsURL != "" { // Default to using Hosted if somehow both are provided
|
||||||
|
qualifiers = append(qualifiers, packageurl.Qualifier{
|
||||||
|
Key: "vcs_url",
|
||||||
|
Value: m.VcsURL,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return packageurl.NewPackageURL(
|
||||||
|
packageurl.TypePub,
|
||||||
|
"",
|
||||||
|
m.Name,
|
||||||
|
m.Version,
|
||||||
|
qualifiers,
|
||||||
|
"",
|
||||||
|
).ToString()
|
||||||
|
}
|
||||||
@ -2,19 +2,19 @@ package dart
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"github.com/anchore/syft/internal/log"
|
"github.com/anchore/syft/internal/log"
|
||||||
"github.com/anchore/syft/syft/artifact"
|
"github.com/anchore/syft/syft/artifact"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/common"
|
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||||
|
"github.com/anchore/syft/syft/source"
|
||||||
)
|
)
|
||||||
|
|
||||||
// integrity check
|
var _ generic.Parser = parsePubspecLock
|
||||||
var _ common.ParserFn = parsePubspecLock
|
|
||||||
|
|
||||||
const defaultPubRegistry string = "https://pub.dartlang.org"
|
const defaultPubRegistry string = "https://pub.dartlang.org"
|
||||||
|
|
||||||
@ -38,8 +38,8 @@ type pubspecLockDescription struct {
|
|||||||
ResolvedRef string `yaml:"resolved-ref" mapstructure:"resolved-ref"`
|
ResolvedRef string `yaml:"resolved-ref" mapstructure:"resolved-ref"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePubspecLock(path string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) {
|
func parsePubspecLock(_ source.FileResolver, _ *generic.Environment, reader source.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var packages []*pkg.Package
|
var pkgs []pkg.Package
|
||||||
|
|
||||||
dec := yaml.NewDecoder(reader)
|
dec := yaml.NewDecoder(reader)
|
||||||
|
|
||||||
@ -48,27 +48,20 @@ func parsePubspecLock(path string, reader io.Reader) ([]*pkg.Package, []artifact
|
|||||||
return nil, nil, fmt.Errorf("failed to parse pubspec.lock file: %w", err)
|
return nil, nil, fmt.Errorf("failed to parse pubspec.lock file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, pubPkg := range p.Packages {
|
var names []string
|
||||||
packages = append(packages, newPubspecLockPackage(name, pubPkg))
|
for name := range p.Packages {
|
||||||
|
names = append(names, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return packages, nil, nil
|
// always ensure there is a stable ordering of packages
|
||||||
}
|
sort.Strings(names)
|
||||||
|
|
||||||
func newPubspecLockPackage(name string, p pubspecLockPackage) *pkg.Package {
|
for _, name := range names {
|
||||||
return &pkg.Package{
|
pubPkg := p.Packages[name]
|
||||||
Name: name,
|
pkgs = append(pkgs, newPubspecLockPackage(name, pubPkg, reader.Location))
|
||||||
Version: p.Version,
|
|
||||||
Language: pkg.Dart,
|
|
||||||
Type: pkg.DartPubPkg,
|
|
||||||
MetadataType: pkg.DartPubMetadataType,
|
|
||||||
Metadata: &pkg.DartPubMetadata{
|
|
||||||
Name: name,
|
|
||||||
Version: p.Version,
|
|
||||||
HostedURL: p.getHostedURL(),
|
|
||||||
VcsURL: p.getVcsURL(),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return pkgs, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pubspecLockPackage) getVcsURL() string {
|
func (p *pubspecLockPackage) getVcsURL() string {
|
||||||
|
|||||||
@ -4,20 +4,19 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/go-test/deep"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/source"
|
||||||
)
|
)
|
||||||
|
|
||||||
func assertPackagesEqual(t *testing.T, actual []*pkg.Package, expected map[string]*pkg.Package) {
|
|
||||||
assert.Len(t, actual, len(expected))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParsePubspecLock(t *testing.T) {
|
func TestParsePubspecLock(t *testing.T) {
|
||||||
expected := map[string]*pkg.Package{
|
expected := []pkg.Package{
|
||||||
"ale": {
|
{
|
||||||
Name: "ale",
|
Name: "ale",
|
||||||
Version: "3.3.0",
|
Version: "3.3.0",
|
||||||
|
PURL: "pkg:pub/ale@3.3.0?hosted_url=pub.hosted.org",
|
||||||
Language: pkg.Dart,
|
Language: pkg.Dart,
|
||||||
Type: pkg.DartPubPkg,
|
Type: pkg.DartPubPkg,
|
||||||
MetadataType: pkg.DartPubMetadataType,
|
MetadataType: pkg.DartPubMetadataType,
|
||||||
@ -27,9 +26,10 @@ func TestParsePubspecLock(t *testing.T) {
|
|||||||
HostedURL: "pub.hosted.org",
|
HostedURL: "pub.hosted.org",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"analyzer": {
|
{
|
||||||
Name: "analyzer",
|
Name: "analyzer",
|
||||||
Version: "0.40.7",
|
Version: "0.40.7",
|
||||||
|
PURL: "pkg:pub/analyzer@0.40.7",
|
||||||
Language: pkg.Dart,
|
Language: pkg.Dart,
|
||||||
Type: pkg.DartPubPkg,
|
Type: pkg.DartPubPkg,
|
||||||
MetadataType: pkg.DartPubMetadataType,
|
MetadataType: pkg.DartPubMetadataType,
|
||||||
@ -38,9 +38,10 @@ func TestParsePubspecLock(t *testing.T) {
|
|||||||
Version: "0.40.7",
|
Version: "0.40.7",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"ansicolor": {
|
{
|
||||||
Name: "ansicolor",
|
Name: "ansicolor",
|
||||||
Version: "1.1.1",
|
Version: "1.1.1",
|
||||||
|
PURL: "pkg:pub/ansicolor@1.1.1",
|
||||||
Language: pkg.Dart,
|
Language: pkg.Dart,
|
||||||
Type: pkg.DartPubPkg,
|
Type: pkg.DartPubPkg,
|
||||||
MetadataType: pkg.DartPubMetadataType,
|
MetadataType: pkg.DartPubMetadataType,
|
||||||
@ -49,9 +50,10 @@ func TestParsePubspecLock(t *testing.T) {
|
|||||||
Version: "1.1.1",
|
Version: "1.1.1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"archive": {
|
{
|
||||||
Name: "archive",
|
Name: "archive",
|
||||||
Version: "2.0.13",
|
Version: "2.0.13",
|
||||||
|
PURL: "pkg:pub/archive@2.0.13",
|
||||||
Language: pkg.Dart,
|
Language: pkg.Dart,
|
||||||
Type: pkg.DartPubPkg,
|
Type: pkg.DartPubPkg,
|
||||||
MetadataType: pkg.DartPubMetadataType,
|
MetadataType: pkg.DartPubMetadataType,
|
||||||
@ -60,9 +62,10 @@ func TestParsePubspecLock(t *testing.T) {
|
|||||||
Version: "2.0.13",
|
Version: "2.0.13",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"args": {
|
{
|
||||||
Name: "args",
|
Name: "args",
|
||||||
Version: "1.6.0",
|
Version: "1.6.0",
|
||||||
|
PURL: "pkg:pub/args@1.6.0",
|
||||||
Language: pkg.Dart,
|
Language: pkg.Dart,
|
||||||
Type: pkg.DartPubPkg,
|
Type: pkg.DartPubPkg,
|
||||||
MetadataType: pkg.DartPubMetadataType,
|
MetadataType: pkg.DartPubMetadataType,
|
||||||
@ -71,29 +74,33 @@ func TestParsePubspecLock(t *testing.T) {
|
|||||||
Version: "1.6.0",
|
Version: "1.6.0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"key_binder": {
|
{
|
||||||
Name: "key_binder",
|
Name: "key_binder",
|
||||||
Version: "1.11.20",
|
Version: "1.11.20",
|
||||||
|
PURL: "pkg:pub/key_binder@1.11.20?vcs_url=git%40github.com:Workiva/key_binder.git%403f7b3a6350e73c7dcac45301c0e18fbd42af02f7",
|
||||||
Language: pkg.Dart,
|
Language: pkg.Dart,
|
||||||
Type: pkg.DartPubPkg,
|
Type: pkg.DartPubPkg,
|
||||||
MetadataType: pkg.DartPubMetadataType,
|
MetadataType: pkg.DartPubMetadataType,
|
||||||
Metadata: pkg.DartPubMetadata{
|
Metadata: pkg.DartPubMetadata{
|
||||||
Name: "key_binder",
|
Name: "key_binder",
|
||||||
Version: "1.11.20",
|
Version: "1.11.20",
|
||||||
VcsURL: "git@github.com:Workiva/key_binder.git#3f7b3a6350e73c7dcac45301c0e18fbd42af02f7",
|
VcsURL: "git@github.com:Workiva/key_binder.git@3f7b3a6350e73c7dcac45301c0e18fbd42af02f7",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fixture, err := os.Open("test-fixtures/pubspec.lock")
|
fixture, err := os.Open("test-fixtures/pubspec.lock")
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("failed to open fixture: %+v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
actual, _, err := parsePubspecLock(fixture.Name(), fixture)
|
// TODO: no relationships are under test yet
|
||||||
if err != nil {
|
actual, _, err := parsePubspecLock(nil, nil, source.LocationReadCloser{
|
||||||
t.Fatalf("failed to parse pubspec.lock: %+v", err)
|
Location: source.NewLocation(fixture.Name()),
|
||||||
}
|
ReadCloser: fixture,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
assertPackagesEqual(t, actual, expected)
|
differences := deep.Equal(expected, actual)
|
||||||
|
if differences != nil {
|
||||||
|
t.Errorf("returned package list differed from expectation: %+v", differences)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,38 +1,8 @@
|
|||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/anchore/packageurl-go"
|
|
||||||
"github.com/anchore/syft/syft/linux"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DartPubMetadata struct {
|
type DartPubMetadata struct {
|
||||||
Name string `mapstructure:"name" json:"name"`
|
Name string `mapstructure:"name" json:"name"`
|
||||||
Version string `mapstructure:"version" json:"version"`
|
Version string `mapstructure:"version" json:"version"`
|
||||||
HostedURL string `mapstructure:"hosted_url" json:"hosted_url,omitempty"`
|
HostedURL string `mapstructure:"hosted_url" json:"hosted_url,omitempty"`
|
||||||
VcsURL string `mapstructure:"vcs_url" json:"vcs_url,omitempty"`
|
VcsURL string `mapstructure:"vcs_url" json:"vcs_url,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m DartPubMetadata) PackageURL(_ *linux.Release) string {
|
|
||||||
var qualifiers packageurl.Qualifiers
|
|
||||||
|
|
||||||
if m.HostedURL != "" {
|
|
||||||
qualifiers = append(qualifiers, packageurl.Qualifier{
|
|
||||||
Key: "hosted_url",
|
|
||||||
Value: m.HostedURL,
|
|
||||||
})
|
|
||||||
} else if m.VcsURL != "" { // Default to using Hosted if somehow both are provided
|
|
||||||
qualifiers = append(qualifiers, packageurl.Qualifier{
|
|
||||||
Key: "vcs_url",
|
|
||||||
Value: m.VcsURL,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return packageurl.NewPackageURL(
|
|
||||||
packageurl.TypePub,
|
|
||||||
"",
|
|
||||||
m.Name,
|
|
||||||
m.Version,
|
|
||||||
qualifiers,
|
|
||||||
"",
|
|
||||||
).ToString()
|
|
||||||
}
|
|
||||||
|
|||||||
@ -35,21 +35,6 @@ func TestPackageURL(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: "pkg:golang/go.opencensus.io@v0.23.0",
|
expected: "pkg:golang/go.opencensus.io@v0.23.0",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "pub",
|
|
||||||
pkg: Package{
|
|
||||||
Name: "bad-name",
|
|
||||||
Version: "0.1.0",
|
|
||||||
Type: DartPubPkg,
|
|
||||||
Metadata: DartPubMetadata{
|
|
||||||
Name: "name",
|
|
||||||
Version: "0.2.0",
|
|
||||||
HostedURL: "pub.hosted.org",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expected: "pkg:pub/name@0.2.0?hosted_url=pub.hosted.org",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "dotnet",
|
name: "dotnet",
|
||||||
pkg: Package{
|
pkg: Package{
|
||||||
@ -225,6 +210,7 @@ func TestPackageURL(t *testing.T) {
|
|||||||
expectedTypes.Remove(string(AlpmPkg))
|
expectedTypes.Remove(string(AlpmPkg))
|
||||||
expectedTypes.Remove(string(ApkPkg))
|
expectedTypes.Remove(string(ApkPkg))
|
||||||
expectedTypes.Remove(string(ConanPkg))
|
expectedTypes.Remove(string(ConanPkg))
|
||||||
|
expectedTypes.Remove(string(DartPubPkg))
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user