mirror of
https://github.com/anchore/syft
synced 2024-11-10 14:24:12 +00:00
metadata decoding should be optional (#1154)
Signed-off-by: Alex Goodman <alex.goodman@anchore.com> Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
parent
1344889766
commit
2693a8c19a
2 changed files with 148 additions and 15 deletions
|
@ -2,6 +2,7 @@ package model
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/anchore/syft/syft/source"
|
||||
|
@ -10,6 +11,8 @@ import (
|
|||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
var errUnknownMetadataType = errors.New("unknown metadata type")
|
||||
|
||||
// Package represents a pkg.Package object specialized for JSON marshaling and unmarshalling.
|
||||
type Package struct {
|
||||
PackageBasicData
|
||||
|
@ -60,13 +63,22 @@ func (p *Package) UnmarshalJSON(b []byte) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return unpackMetadata(p, unpacker)
|
||||
err := unpackMetadata(p, unpacker)
|
||||
if errors.Is(err, errUnknownMetadataType) {
|
||||
log.Warnf("unknown package metadata type=%q for packageID=%q", p.MetadataType, p.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// nolint:funlen,gocognit,gocyclo
|
||||
func unpackMetadata(p *Package, unpacker packageMetadataUnpacker) error {
|
||||
p.MetadataType = unpacker.MetadataType
|
||||
switch p.MetadataType {
|
||||
case "":
|
||||
// there is no metadata, skip
|
||||
break
|
||||
case pkg.AlpmMetadataType:
|
||||
var payload pkg.AlpmMetadata
|
||||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
||||
|
@ -176,8 +188,7 @@ func unpackMetadata(p *Package, unpacker packageMetadataUnpacker) error {
|
|||
}
|
||||
p.Metadata = payload
|
||||
default:
|
||||
log.Warnf("unknown package metadata type=%q for packageID=%q", p.MetadataType, p.ID)
|
||||
return errUnknownMetadataType
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,21 +1,95 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"encoding/json"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUnmarshalPackageGolang(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
p *Package
|
||||
packageData []byte
|
||||
assert func(*Package)
|
||||
}{
|
||||
{
|
||||
name: "Package.UnmarshalJSON unmarshals PackageBasicData",
|
||||
p: &Package{},
|
||||
name: "unmarshal package metadata",
|
||||
packageData: []byte(`{
|
||||
"id": "8b594519bc23da50",
|
||||
"name": "gopkg.in/square/go-jose.v2",
|
||||
"version": "v2.6.0",
|
||||
"type": "go-module",
|
||||
"foundBy": "go-module-binary-cataloger",
|
||||
"locations": [
|
||||
{
|
||||
"path": "/Users/hal/go/bin/syft"
|
||||
}
|
||||
],
|
||||
"licenses": [],
|
||||
"language": "go",
|
||||
"cpes": [],
|
||||
"purl": "pkg:golang/gopkg.in/square/go-jose.v2@v2.6.0",
|
||||
"metadataType": "GolangBinMetadata",
|
||||
"metadata": {
|
||||
"goCompiledVersion": "go1.18",
|
||||
"architecture": "amd64",
|
||||
"h1Digest": "h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI="
|
||||
}
|
||||
}`),
|
||||
assert: func(p *Package) {
|
||||
assert.NotNil(t, p.Metadata)
|
||||
golangMetadata := p.Metadata.(pkg.GolangBinMetadata)
|
||||
assert.NotEmpty(t, golangMetadata)
|
||||
assert.Equal(t, "go1.18", golangMetadata.GoCompiledVersion)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "can handle package without metadata",
|
||||
packageData: []byte(`{
|
||||
"id": "8b594519bc23da50",
|
||||
"name": "gopkg.in/square/go-jose.v2",
|
||||
"version": "v2.6.0",
|
||||
"type": "go-module",
|
||||
"foundBy": "go-mod-cataloger",
|
||||
"locations": [
|
||||
{
|
||||
"path": "/Users/hal/go/bin/syft"
|
||||
}
|
||||
],
|
||||
"licenses": [],
|
||||
"language": "go",
|
||||
"cpes": [],
|
||||
"purl": "pkg:golang/gopkg.in/square/go-jose.v2@v2.6.0"
|
||||
}`),
|
||||
assert: func(p *Package) {
|
||||
assert.Empty(t, p.MetadataType)
|
||||
assert.Empty(t, p.Metadata)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
p := &Package{}
|
||||
err := p.UnmarshalJSON(test.packageData)
|
||||
require.NoError(t, err)
|
||||
test.assert(p)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_unpackMetadata(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
packageData []byte
|
||||
metadataType pkg.MetadataType
|
||||
wantErr require.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "unmarshal package metadata",
|
||||
metadataType: pkg.GolangBinMetadataType,
|
||||
packageData: []byte(`{
|
||||
"id": "8b594519bc23da50",
|
||||
"name": "gopkg.in/square/go-jose.v2",
|
||||
|
@ -39,19 +113,67 @@ func TestUnmarshalPackageGolang(t *testing.T) {
|
|||
}
|
||||
}`),
|
||||
},
|
||||
{
|
||||
name: "can handle package without metadata",
|
||||
metadataType: "",
|
||||
packageData: []byte(`{
|
||||
"id": "8b594519bc23da50",
|
||||
"name": "gopkg.in/square/go-jose.v2",
|
||||
"version": "v2.6.0",
|
||||
"type": "go-module",
|
||||
"foundBy": "go-mod-cataloger",
|
||||
"locations": [
|
||||
{
|
||||
"path": "/Users/hal/go/bin/syft"
|
||||
}
|
||||
],
|
||||
"licenses": [],
|
||||
"language": "go",
|
||||
"cpes": [],
|
||||
"purl": "pkg:golang/gopkg.in/square/go-jose.v2@v2.6.0"
|
||||
}`),
|
||||
},
|
||||
{
|
||||
name: "bad metadata type is an error",
|
||||
metadataType: "BOGOSITY",
|
||||
wantErr: require.Error,
|
||||
packageData: []byte(`{
|
||||
"id": "8b594519bc23da50",
|
||||
"name": "gopkg.in/square/go-jose.v2",
|
||||
"version": "v2.6.0",
|
||||
"type": "go-module",
|
||||
"foundBy": "go-mod-cataloger",
|
||||
"locations": [
|
||||
{
|
||||
"path": "/Users/hal/go/bin/syft"
|
||||
}
|
||||
],
|
||||
"licenses": [],
|
||||
"language": "go",
|
||||
"cpes": [],
|
||||
"purl": "pkg:golang/gopkg.in/square/go-jose.v2@v2.6.0",
|
||||
"metadataType": "BOGOSITY"
|
||||
}`),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
err := test.p.UnmarshalJSON(test.packageData)
|
||||
if err != nil {
|
||||
t.Fatalf("could not unmarshal packageData: %v", err)
|
||||
if test.wantErr == nil {
|
||||
test.wantErr = require.NoError
|
||||
}
|
||||
p := &Package{}
|
||||
|
||||
assert.NotNil(t, test.p.Metadata)
|
||||
golangMetadata := test.p.Metadata.(pkg.GolangBinMetadata)
|
||||
assert.NotEmpty(t, golangMetadata)
|
||||
assert.Equal(t, "go1.18", golangMetadata.GoCompiledVersion)
|
||||
var basic PackageBasicData
|
||||
require.NoError(t, json.Unmarshal(test.packageData, &basic))
|
||||
p.PackageBasicData = basic
|
||||
|
||||
var unpacker packageMetadataUnpacker
|
||||
require.NoError(t, json.Unmarshal(test.packageData, &unpacker))
|
||||
|
||||
err := unpackMetadata(p, unpacker)
|
||||
assert.Equal(t, test.metadataType, p.MetadataType)
|
||||
test.wantErr(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue