From f46de19c6be5ac81fe74a013424c614c513df3ed Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Mon, 16 Nov 2020 08:47:24 -0500 Subject: [PATCH] migrate scope option to image metadata (from source) Signed-off-by: Alex Goodman --- schema/json/schema.json | 8 ++++---- syft/lib.go | 16 +++++----------- .../snapshot/TestCycloneDxDirsPresenter.golden | 4 ++-- .../snapshot/TestCycloneDxImgsPresenter.golden | 8 ++++---- syft/presenter/json/descriptor.go | 7 +++++++ syft/presenter/json/distribution.go | 8 ++++++++ syft/presenter/json/document.go | 15 --------------- syft/presenter/json/source.go | 13 +++++++++++++ .../snapshot/TestJsonDirsPresenter.golden | 11 +++-------- .../snapshot/TestJsonImgsPresenter.golden | 13 +++++-------- syft/source/image_metadata.go | 4 +++- syft/source/metadata.go | 1 - syft/source/source.go | 7 +++---- test/integration/document_import_test.go | 4 ++-- 14 files changed, 59 insertions(+), 60 deletions(-) create mode 100644 syft/presenter/json/descriptor.go create mode 100644 syft/presenter/json/distribution.go diff --git a/schema/json/schema.json b/schema/json/schema.json index 01f9e3e10..edfef558c 100644 --- a/schema/json/schema.json +++ b/schema/json/schema.json @@ -339,16 +339,12 @@ "name": { "type": "string" }, - "scope": { - "type": "string" - }, "version": { "type": "string" } }, "required": [ "name", - "scope", "version" ], "type": "object" @@ -409,6 +405,9 @@ "mediaType": { "type": "string" }, + "scope": { + "type": "string" + }, "size": { "type": "integer" }, @@ -426,6 +425,7 @@ "digest", "layers", "mediaType", + "scope", "size", "tags", "userInput" diff --git a/syft/lib.go b/syft/lib.go index ea06a031f..d57c61f27 100644 --- a/syft/lib.go +++ b/syft/lib.go @@ -83,11 +83,11 @@ func CatalogFromScope(s source.Source) (*pkg.Catalog, error) { } // CatalogFromJSON takes an existing syft report and generates catalog primitives. -func CatalogFromJSON(reader io.Reader) (*pkg.Catalog, *distro.Distro, *source.ImageMetadata, error) { +func CatalogFromJSON(reader io.Reader) (*pkg.Catalog, *distro.Distro, source.Metadata, error) { var doc jsonPresenter.Document decoder := json.NewDecoder(reader) if err := decoder.Decode(&doc); err != nil { - return nil, nil, nil, err + return nil, nil, source.Metadata{}, err } var pkgs = make([]pkg.Package, len(doc.Artifacts)) @@ -104,18 +104,12 @@ func CatalogFromJSON(reader io.Reader) (*pkg.Catalog, *distro.Distro, *source.Im distroType = distro.Type(doc.Distro.Name) } - d, err := distro.NewDistro(distroType, doc.Distro.Version, doc.Distro.IDLike) + theDistro, err := distro.NewDistro(distroType, doc.Distro.Version, doc.Distro.IDLike) if err != nil { - return nil, nil, nil, err + return nil, nil, source.Metadata{}, err } - var imageMetadata *source.ImageMetadata - if doc.Source.Type == "image" { - payload := doc.Source.Target.(source.ImageMetadata) - imageMetadata = &payload - } - - return catalog, &d, imageMetadata, nil + return catalog, &theDistro, doc.Source.ToSourceMetadata(), nil } // SetLogger sets the logger object used for all syft logging calls. diff --git a/syft/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxDirsPresenter.golden b/syft/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxDirsPresenter.golden index 68ca8ae8e..2e2d0d8ae 100644 --- a/syft/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxDirsPresenter.golden +++ b/syft/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxDirsPresenter.golden @@ -1,5 +1,5 @@ - + package1 @@ -21,7 +21,7 @@ - 2020-09-23T18:26:58-04:00 + 2020-11-16T08:45:54-05:00 anchore syft diff --git a/syft/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxImgsPresenter.golden b/syft/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxImgsPresenter.golden index 03f34889a..b4fcc0188 100644 --- a/syft/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxImgsPresenter.golden +++ b/syft/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxImgsPresenter.golden @@ -1,5 +1,5 @@ - + package1 @@ -21,15 +21,15 @@ - 2020-09-23T18:26:58-04:00 + 2020-11-16T08:45:54-05:00 anchore syft [not provided] - index.docker.io/library/stereoscope-fixture-image-simple - 04e16e44161c8888a1a963720fd0443cbf7eef8101434c431de8725cd98cc9f7 + user-image-input + sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368 diff --git a/syft/presenter/json/descriptor.go b/syft/presenter/json/descriptor.go new file mode 100644 index 000000000..de07721fc --- /dev/null +++ b/syft/presenter/json/descriptor.go @@ -0,0 +1,7 @@ +package json + +// Descriptor describes what created the document as well as surrounding metadata +type Descriptor struct { + Name string `json:"name"` + Version string `json:"version"` +} diff --git a/syft/presenter/json/distribution.go b/syft/presenter/json/distribution.go new file mode 100644 index 000000000..567aa50f5 --- /dev/null +++ b/syft/presenter/json/distribution.go @@ -0,0 +1,8 @@ +package json + +// Distribution provides information about a detected Linux Distribution +type Distribution struct { + Name string `json:"name"` + Version string `json:"version"` + IDLike string `json:"idLike"` +} diff --git a/syft/presenter/json/document.go b/syft/presenter/json/document.go index 2c20a1a38..230c9ad8c 100644 --- a/syft/presenter/json/document.go +++ b/syft/presenter/json/document.go @@ -15,20 +15,6 @@ type Document struct { Descriptor Descriptor `json:"descriptor"` } -// Descriptor describes what created the document as well as surrounding metadata -type Descriptor struct { - Name string `json:"name"` - Version string `json:"version"` - Scope string `json:"scope"` -} - -// Distribution provides information about a detected Linux Distribution -type Distribution struct { - Name string `json:"name"` - Version string `json:"version"` - IDLike string `json:"idLike"` -} - func NewDocument(catalog *pkg.Catalog, srcMetadata source.Metadata, d distro.Distro) (Document, error) { src, err := NewSource(srcMetadata) if err != nil { @@ -51,7 +37,6 @@ func NewDocument(catalog *pkg.Catalog, srcMetadata source.Metadata, d distro.Dis Descriptor: Descriptor{ Name: internal.ApplicationName, Version: version.FromBuild().Version, - Scope: srcMetadata.Scope.String(), }, } diff --git a/syft/presenter/json/source.go b/syft/presenter/json/source.go index 14561a24f..a8a1015a4 100644 --- a/syft/presenter/json/source.go +++ b/syft/presenter/json/source.go @@ -56,3 +56,16 @@ func (s *Source) UnmarshalJSON(b []byte) error { return nil } + +func (s *Source) ToSourceMetadata() source.Metadata { + var metadata source.Metadata + switch s.Type { + case "directory": + metadata.Scheme = source.DirectoryScheme + metadata.Path = s.Target.(string) + case "image": + metadata.Scheme = source.ImageScheme + metadata.ImageMetadata = s.Target.(source.ImageMetadata) + } + return metadata +} diff --git a/syft/presenter/json/test-fixtures/snapshot/TestJsonDirsPresenter.golden b/syft/presenter/json/test-fixtures/snapshot/TestJsonDirsPresenter.golden index 7324c5349..b88f2ffef 100644 --- a/syft/presenter/json/test-fixtures/snapshot/TestJsonDirsPresenter.golden +++ b/syft/presenter/json/test-fixtures/snapshot/TestJsonDirsPresenter.golden @@ -4,9 +4,7 @@ "name": "package-1", "version": "1.0.1", "type": "python", - "foundBy": [ - "the-cataloger-1" - ], + "foundBy": "the-cataloger-1", "locations": [ { "path": "/some/path/pkg1" @@ -31,9 +29,7 @@ "name": "package-2", "version": "2.0.1", "type": "deb", - "foundBy": [ - "the-cataloger-2" - ], + "foundBy": "the-cataloger-2", "locations": [ { "path": "/some/path/pkg1" @@ -64,7 +60,6 @@ }, "descriptor": { "name": "syft", - "version": "[not provided]", - "scope": "" + "version": "[not provided]" } } diff --git a/syft/presenter/json/test-fixtures/snapshot/TestJsonImgsPresenter.golden b/syft/presenter/json/test-fixtures/snapshot/TestJsonImgsPresenter.golden index 91b28d91e..854f05ea0 100644 --- a/syft/presenter/json/test-fixtures/snapshot/TestJsonImgsPresenter.golden +++ b/syft/presenter/json/test-fixtures/snapshot/TestJsonImgsPresenter.golden @@ -4,9 +4,7 @@ "name": "package-1", "version": "1.0.1", "type": "python", - "foundBy": [ - "the-cataloger-1" - ], + "foundBy": "the-cataloger-1", "locations": [ { "path": "/somefile-1.txt", @@ -32,9 +30,7 @@ "name": "package-2", "version": "2.0.1", "type": "deb", - "foundBy": [ - "the-cataloger-2" - ], + "foundBy": "the-cataloger-2", "locations": [ { "path": "/somefile-2.txt", @@ -58,6 +54,8 @@ "source": { "type": "image", "target": { + "userInput": "user-image-input", + "scope": "AllLayers", "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", @@ -90,7 +88,6 @@ }, "descriptor": { "name": "syft", - "version": "[not provided]", - "scope": "AllLayers" + "version": "[not provided]" } } diff --git a/syft/source/image_metadata.go b/syft/source/image_metadata.go index 2a9224d7a..9bd8a30a9 100644 --- a/syft/source/image_metadata.go +++ b/syft/source/image_metadata.go @@ -4,6 +4,7 @@ import "github.com/anchore/stereoscope/pkg/image" type ImageMetadata struct { UserInput string `json:"userInput"` + Scope Scope `json:"scope"` // specific perspective to catalog Layers []LayerMetadata `json:"layers"` Size int64 `json:"size"` Digest string `json:"digest"` @@ -17,7 +18,7 @@ type LayerMetadata struct { Size int64 `json:"size"` } -func NewImageMetadata(img *image.Image, userInput string) ImageMetadata { +func NewImageMetadata(img *image.Image, userInput string, scope Scope) ImageMetadata { // populate artifacts... tags := make([]string, len(img.Metadata.Tags)) for idx, tag := range img.Metadata.Tags { @@ -25,6 +26,7 @@ func NewImageMetadata(img *image.Image, userInput string) ImageMetadata { } theImg := ImageMetadata{ UserInput: userInput, + Scope: scope, Digest: img.Metadata.Digest, Size: img.Metadata.Size, MediaType: string(img.Metadata.MediaType), diff --git a/syft/source/metadata.go b/syft/source/metadata.go index 188118b7b..ef3092564 100644 --- a/syft/source/metadata.go +++ b/syft/source/metadata.go @@ -1,7 +1,6 @@ package source type Metadata struct { - Scope Scope // specific perspective to catalog Scheme Scheme // the source data scheme type (directory or image) ImageMetadata ImageMetadata // all image info (image only) Path string // the root path to be cataloged (directory only) diff --git a/syft/source/source.go b/syft/source/source.go index 91ce1009e..182a87f71 100644 --- a/syft/source/source.go +++ b/syft/source/source.go @@ -85,12 +85,12 @@ func NewFromDirectory(path string) (Source, error) { // NewFromImage creates a new source object tailored to catalog a given container image, relative to the // option given (e.g. all-layers, squashed, etc) -func NewFromImage(img *image.Image, option Scope, userImageStr string) (Source, error) { +func NewFromImage(img *image.Image, scope Scope, userImageStr string) (Source, error) { if img == nil { return Source{}, fmt.Errorf("no image given") } - resolver, err := getImageResolver(img, option) + resolver, err := getImageResolver(img, scope) if err != nil { return Source{}, fmt.Errorf("could not determine file resolver: %w", err) } @@ -99,9 +99,8 @@ func NewFromImage(img *image.Image, option Scope, userImageStr string) (Source, Resolver: resolver, Image: img, Metadata: Metadata{ - Scope: option, Scheme: ImageScheme, - ImageMetadata: NewImageMetadata(img, userImageStr), + ImageMetadata: NewImageMetadata(img, userImageStr, scope), }, }, nil } diff --git a/test/integration/document_import_test.go b/test/integration/document_import_test.go index 432bd78d3..056e92f66 100644 --- a/test/integration/document_import_test.go +++ b/test/integration/document_import_test.go @@ -42,12 +42,12 @@ func TestCatalogFromJSON(t *testing.T) { t.Fatalf("failed to write to presenter: %+v", err) } - actualCatalog, actualDistro, imageMetadata, err := syft.CatalogFromJSON(&buf) + actualCatalog, actualDistro, sourceMetadata, err := syft.CatalogFromJSON(&buf) if err != nil { t.Fatalf("failed to import document: %+v", err) } - for _, d := range deep.Equal(*imageMetadata, expectedSource.Metadata.ImageMetadata) { + for _, d := range deep.Equal(sourceMetadata, expectedSource.Metadata) { t.Errorf(" image metadata diff: %+v", d) }