Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
migrate json presenter to json format object
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
- Loading branch information
Showing
18 changed files
with
706 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package syftjson | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
|
||
"github.com/anchore/syft/internal/formats/syftjson/model" | ||
"github.com/anchore/syft/syft/distro" | ||
"github.com/anchore/syft/syft/pkg" | ||
"github.com/anchore/syft/syft/source" | ||
) | ||
|
||
func decoder(reader io.Reader) (*pkg.Catalog, *source.Metadata, *distro.Distro, error) { | ||
dec := json.NewDecoder(reader) | ||
|
||
var doc model.Document | ||
err := dec.Decode(&doc) | ||
if err != nil { | ||
return nil, nil, nil, fmt.Errorf("unable to decode syft-json: %w", err) | ||
} | ||
|
||
return toSyftModel(doc) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package syftjson | ||
|
||
import ( | ||
"bytes" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/anchore/syft/internal/formats/common/testutils" | ||
"github.com/go-test/deep" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestEncodeDecodeCycle(t *testing.T) { | ||
testImage := "image-simple" | ||
originalCatalog, originalMetadata, _ := testutils.ImageInput(t, testImage) | ||
|
||
var buf bytes.Buffer | ||
assert.NoError(t, encoder(&buf, originalCatalog, &originalMetadata, nil)) | ||
|
||
actualCatalog, actualMetadata, _, err := decoder(bytes.NewReader(buf.Bytes())) | ||
assert.NoError(t, err) | ||
|
||
for _, d := range deep.Equal(originalMetadata, *actualMetadata) { | ||
t.Errorf("metadata difference: %+v", d) | ||
} | ||
|
||
actualPackages := actualCatalog.Sorted() | ||
for idx, p := range originalCatalog.Sorted() { | ||
if !assert.Equal(t, p.Name, actualPackages[idx].Name) { | ||
t.Errorf("different package at idx=%d: %s vs %s", idx, p.Name, actualPackages[idx].Name) | ||
continue | ||
} | ||
|
||
// ids will never be equal | ||
p.ID = "" | ||
actualPackages[idx].ID = "" | ||
|
||
for _, d := range deep.Equal(*p, *actualPackages[idx]) { | ||
if strings.Contains(d, ".VirtualPath: ") { | ||
// location.Virtual path is not exposed in the json output | ||
continue | ||
} | ||
if strings.HasSuffix(d, "<nil slice> != []") { | ||
// semantically the same | ||
continue | ||
} | ||
t.Errorf("package difference (%s): %+v", p.Name, d) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package syftjson | ||
|
||
import ( | ||
"encoding/json" | ||
"io" | ||
|
||
"github.com/anchore/syft/syft/distro" | ||
|
||
"github.com/anchore/syft/syft/pkg" | ||
"github.com/anchore/syft/syft/source" | ||
) | ||
|
||
func encoder(output io.Writer, catalog *pkg.Catalog, srcMetadata *source.Metadata, d *distro.Distro) error { | ||
// TODO: application config not available yet | ||
doc := ToFormatModel(catalog, srcMetadata, d, nil) | ||
|
||
enc := json.NewEncoder(output) | ||
// prevent > and < from being escaped in the payload | ||
enc.SetEscapeHTML(false) | ||
enc.SetIndent("", " ") | ||
|
||
return enc.Encode(&doc) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package syftjson | ||
|
||
import "github.com/anchore/syft/syft/format" | ||
|
||
func Format() format.Format { | ||
return format.NewFormat( | ||
format.JSONOption, | ||
encoder, | ||
decoder, | ||
validator, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package model | ||
|
||
// Distro provides information about a detected Linux Distro. | ||
type Distro struct { | ||
Name string `json:"name"` // Name of the Linux distribution | ||
Version string `json:"version"` // Version of the Linux distribution (major or major.minor version) | ||
IDLike string `json:"idLike"` // the ID_LIKE field found within the /etc/os-release file | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package model | ||
|
||
// Document represents the syft cataloging findings as a JSON document | ||
type Document struct { | ||
Artifacts []Package `json:"artifacts"` // Artifacts is the list of packages discovered and placed into the catalog | ||
ArtifactRelationships []Relationship `json:"artifactRelationships"` | ||
Source Source `json:"source"` // Source represents the original object that was cataloged | ||
Distro Distro `json:"distro"` // Distro represents the Linux distribution that was detected from the source | ||
Descriptor Descriptor `json:"descriptor"` // Descriptor is a block containing self-describing information about syft | ||
Schema Schema `json:"schema"` // Schema is a block reserved for defining the version for the shape of this JSON document and where to find the schema document to validate the shape | ||
} | ||
|
||
// Descriptor describes what created the document as well as surrounding metadata | ||
type Descriptor struct { | ||
Name string `json:"name"` | ||
Version string `json:"version"` | ||
Configuration interface{} `json:"configuration,omitempty"` | ||
} | ||
|
||
type Schema struct { | ||
Version string `json:"version"` | ||
URL string `json:"url"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package model | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/anchore/syft/internal/log" | ||
"github.com/anchore/syft/syft/pkg" | ||
"github.com/anchore/syft/syft/source" | ||
) | ||
|
||
// Package represents a pkg.Package object specialized for JSON marshaling and unmarshaling. | ||
type Package struct { | ||
PackageBasicData | ||
PackageCustomData | ||
} | ||
|
||
// PackageBasicData contains non-ambiguous values (type-wise) from pkg.Package. | ||
type PackageBasicData struct { | ||
ID string `json:"id"` | ||
Name string `json:"name"` | ||
Version string `json:"version"` | ||
Type pkg.Type `json:"type"` | ||
FoundBy string `json:"foundBy"` | ||
Locations []source.Location `json:"locations"` | ||
Licenses []string `json:"licenses"` | ||
Language pkg.Language `json:"language"` | ||
CPEs []string `json:"cpes"` | ||
PURL string `json:"purl"` | ||
} | ||
|
||
// PackageCustomData contains ambiguous values (type-wise) from pkg.Package. | ||
type PackageCustomData struct { | ||
MetadataType pkg.MetadataType `json:"metadataType"` | ||
Metadata interface{} `json:"metadata"` | ||
} | ||
|
||
// packageMetadataUnpacker is all values needed from Package to disambiguate ambiguous fields during json unmarshaling. | ||
type packageMetadataUnpacker struct { | ||
MetadataType pkg.MetadataType `json:"metadataType"` | ||
Metadata json.RawMessage `json:"metadata"` | ||
} | ||
|
||
func (p *packageMetadataUnpacker) String() string { | ||
return fmt.Sprintf("metadataType: %s, metadata: %s", p.MetadataType, string(p.Metadata)) | ||
} | ||
|
||
// UnmarshalJSON is a custom unmarshaller for handling basic values and values with ambiguous types. | ||
func (p *Package) UnmarshalJSON(b []byte) error { | ||
var basic PackageBasicData | ||
if err := json.Unmarshal(b, &basic); err != nil { | ||
return err | ||
} | ||
p.PackageBasicData = basic | ||
|
||
var unpacker packageMetadataUnpacker | ||
if err := json.Unmarshal(b, &unpacker); err != nil { | ||
log.Warnf("failed to unmarshall into packageMetadataUnpacker: %v", err) | ||
return err | ||
} | ||
|
||
p.MetadataType = unpacker.MetadataType | ||
|
||
switch p.MetadataType { | ||
case pkg.ApkMetadataType: | ||
var payload pkg.ApkMetadata | ||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { | ||
return err | ||
} | ||
p.Metadata = payload | ||
case pkg.RpmdbMetadataType: | ||
var payload pkg.RpmdbMetadata | ||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { | ||
return err | ||
} | ||
p.Metadata = payload | ||
case pkg.DpkgMetadataType: | ||
var payload pkg.DpkgMetadata | ||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { | ||
return err | ||
} | ||
p.Metadata = payload | ||
case pkg.JavaMetadataType: | ||
var payload pkg.JavaMetadata | ||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { | ||
return err | ||
} | ||
p.Metadata = payload | ||
case pkg.RustCargoPackageMetadataType: | ||
var payload pkg.CargoPackageMetadata | ||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { | ||
return err | ||
} | ||
p.Metadata = payload | ||
case pkg.GemMetadataType: | ||
var payload pkg.GemMetadata | ||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { | ||
return err | ||
} | ||
p.Metadata = payload | ||
case pkg.KbPackageMetadataType: | ||
var payload pkg.KbPackageMetadata | ||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { | ||
return err | ||
} | ||
p.Metadata = payload | ||
case pkg.PythonPackageMetadataType: | ||
var payload pkg.PythonPackageMetadata | ||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { | ||
return err | ||
} | ||
p.Metadata = payload | ||
case pkg.NpmPackageJSONMetadataType: | ||
var payload pkg.NpmPackageJSONMetadata | ||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { | ||
return err | ||
} | ||
p.Metadata = payload | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package model | ||
|
||
type Relationship struct { | ||
Parent string `json:"parent"` | ||
Child string `json:"child"` | ||
Type string `json:"type"` | ||
Metadata interface{} `json:"metadata"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package model | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/anchore/syft/syft/source" | ||
) | ||
|
||
// Source object represents the thing that was cataloged | ||
type Source struct { | ||
Type string `json:"type"` | ||
Target interface{} `json:"target"` | ||
} | ||
|
||
// sourceUnpacker is used to unmarshal Source objects | ||
type sourceUnpacker struct { | ||
Type string `json:"type"` | ||
Target json.RawMessage `json:"target"` | ||
} | ||
|
||
// UnmarshalJSON populates a source object from JSON bytes. | ||
func (s *Source) UnmarshalJSON(b []byte) error { | ||
var unpacker sourceUnpacker | ||
if err := json.Unmarshal(b, &unpacker); err != nil { | ||
return err | ||
} | ||
|
||
s.Type = unpacker.Type | ||
|
||
switch s.Type { | ||
case "directory": | ||
s.Target = string(unpacker.Target[:]) | ||
case "image": | ||
var payload source.ImageMetadata | ||
if err := json.Unmarshal(unpacker.Target, &payload); err != nil { | ||
return err | ||
} | ||
s.Target = payload | ||
default: | ||
return fmt.Errorf("unsupported package metadata type: %+v", s.Type) | ||
} | ||
|
||
return nil | ||
} |
4 changes: 4 additions & 0 deletions
4
internal/formats/syftjson/test-fixtures/image-simple/Dockerfile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# 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 |
1 change: 1 addition & 0 deletions
1
internal/formats/syftjson/test-fixtures/image-simple/file-1.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
this file has contents |
1 change: 1 addition & 0 deletions
1
internal/formats/syftjson/test-fixtures/image-simple/file-2.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
file-2 contents! |
Oops, something went wrong.