Add platform selection (#866)

This commit is contained in:
Alex Goodman 2022-03-04 17:41:38 -05:00 committed by GitHub
parent 4af32c5bee
commit a86dd3704e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 99 additions and 40 deletions

View file

@ -131,7 +131,7 @@ func selectPassFunc(keypath string) (cosign.PassFunc, error) {
func attestExec(ctx context.Context, _ *cobra.Command, args []string) error {
// can only be an image for attestation or OCI DIR
userInput := args[0]
si, err := source.ParseInput(userInput, false)
si, err := source.ParseInput(userInput, appConfig.Platform, false)
if err != nil {
return fmt.Errorf("could not generate source input for attest command: %w", err)
}
@ -304,6 +304,11 @@ func setAttestFlags(flags *pflag.FlagSet) {
"output", "o", formatAliases(syftjson.ID)[0],
fmt.Sprintf("the SBOM format encapsulated within the attestation, available options=%v", formatAliases(attestFormats...)),
)
flags.StringP(
"platform", "", "",
"an optional platform specifier for container image sources (e.g. 'linux/arm64', 'linux/arm64/v8', 'arm64', 'linux')",
)
}
func bindAttestConfigOptions(flags *pflag.FlagSet) error {

View file

@ -72,8 +72,8 @@ func initCmdAliasBindings() {
panic(err)
}
case attestCmd:
// the --output option is an independently defined flag, but a shared config option
if err = bindSharedOutputConfigOption(attestCmd.Flags()); err != nil {
// the --output and --platform options are independently defined flags, but a shared config option
if err = bindSharedConfigOption(attestCmd.Flags()); err != nil {
panic(err)
}
// even though the root command or packages command is NOT being run, we still need default bindings
@ -90,11 +90,15 @@ func initCmdAliasBindings() {
}
}
func bindSharedOutputConfigOption(flags *pflag.FlagSet) error {
func bindSharedConfigOption(flags *pflag.FlagSet) error {
if err := viper.BindPFlag("output", flags.Lookup("output")); err != nil {
return err
}
if err := viper.BindPFlag("platform", flags.Lookup("platform")); err != nil {
return err
}
return nil
}

View file

@ -6,17 +6,15 @@ import (
"io/ioutil"
"os"
"github.com/anchore/syft/internal/formats/table"
"github.com/anchore/syft/syft"
"github.com/anchore/stereoscope"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/anchore"
"github.com/anchore/syft/internal/bus"
"github.com/anchore/syft/internal/formats/table"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/ui"
"github.com/anchore/syft/internal/version"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/event"
"github.com/anchore/syft/syft/pkg/cataloger"
@ -112,6 +110,11 @@ func setPackageFlags(flags *pflag.FlagSet) {
"file to write the default report output to (default is STDOUT)",
)
flags.StringP(
"platform", "", "",
"an optional platform specifier for container image sources (e.g. 'linux/arm64', 'linux/arm64/v8', 'arm64', 'linux')",
)
// Upload options //////////////////////////////////////////////////////////
flags.StringP(
"host", "H", "",
@ -153,7 +156,7 @@ func bindPackagesConfigOptions(flags *pflag.FlagSet) error {
if err := bindExclusivePackagesConfigOptions(flags); err != nil {
return err
}
if err := bindSharedOutputConfigOption(flags); err != nil {
if err := bindSharedConfigOption(flags); err != nil {
return err
}
return nil
@ -232,7 +235,7 @@ func packagesExec(_ *cobra.Command, args []string) error {
// could be an image or a directory, with or without a scheme
userInput := args[0]
si, err := source.ParseInput(userInput, true)
si, err := source.ParseInput(userInput, appConfig.Platform, true)
if err != nil {
return fmt.Errorf("could not generate source input for packages command: %w", err)
}

View file

@ -114,7 +114,7 @@ func powerUserExecWorker(userInput string, writer sbom.Writer) <-chan error {
return
}
si, err := source.ParseInput(userInput, true)
si, err := source.ParseInput(userInput, appConfig.Platform, true)
if err != nil {
errs <- err
return

2
go.mod
View file

@ -13,7 +13,7 @@ require (
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
github.com/anchore/packageurl-go v0.0.0-20210922164639-b3fa992ebd29
github.com/anchore/stereoscope v0.0.0-20220301220648-8aa8a4a0bf50
github.com/anchore/stereoscope v0.0.0-20220304014943-22a4c2bb498e
github.com/antihax/optional v1.0.0
github.com/bmatcuk/doublestar/v4 v4.0.2
github.com/docker/docker v20.10.12+incompatible

4
go.sum
View file

@ -284,8 +284,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E=
github.com/anchore/packageurl-go v0.0.0-20210922164639-b3fa992ebd29 h1:K9LfnxwhqvihqU0+MF325FNy7fsKV9EGaUxdfR4gnWk=
github.com/anchore/packageurl-go v0.0.0-20210922164639-b3fa992ebd29/go.mod h1:Oc1UkGaJwY6ND6vtAqPSlYrptKRJngHwkwB6W7l1uP0=
github.com/anchore/stereoscope v0.0.0-20220301220648-8aa8a4a0bf50 h1:+Fe67xv6NRLdZ5V9X2kw959XsKQCUx5/6RL/wQZfs44=
github.com/anchore/stereoscope v0.0.0-20220301220648-8aa8a4a0bf50/go.mod h1:QpDHHV2h1NNfu7klzU75XC8RvSlaPK6HHgi0dy8A6sk=
github.com/anchore/stereoscope v0.0.0-20220304014943-22a4c2bb498e h1:+nlnKqlR8UwG/PhTD8qSN7RphXOI9fK77q5p3PQLx0k=
github.com/anchore/stereoscope v0.0.0-20220304014943-22a4c2bb498e/go.mod h1:Juw0DqHmBSAMFVcT/kRM0GhLdIEAaiCQbq9mdCp47dY=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=

View file

@ -46,6 +46,7 @@ type Application struct {
Registry registry `yaml:"registry" json:"registry" mapstructure:"registry"`
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
Attest attest `yaml:"attest" json:"attest" mapstructure:"attest"`
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"`
}
// PowerUserCatalogerEnabledDefault switches all catalogers to be enabled when running power-user command

View file

@ -163,7 +163,9 @@
],
"manifest": "ZXlKelkyaGxiV0ZXWlhKemFXOXVJam95TENKdFpXUnBZVlI1Y0dVaU9pSmguLi4=",
"config": "ZXlKaGNtTm9hWFJsWTNSMWNtVWlPaUpoYldRMk5DSXNJbU52Ym1acC4uLg==",
"repoDigests": []
"repoDigests": [],
"architecture": "",
"os": ""
}
},
"distro": {

View file

@ -1,7 +1,7 @@
{
"artifacts": [
{
"id": "3a6c7061f86ac3f7",
"id": "d9527e708c11f8b9",
"name": "package-1",
"version": "1.0.1",
"type": "python",
@ -9,7 +9,7 @@
"locations": [
{
"path": "/somefile-1.txt",
"layerID": "sha256:135c16aca35f76c25a18cb6650c621a46b8b79864ad6f2834167de2679bb587d"
"layerID": "sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59"
}
],
"licenses": [
@ -32,7 +32,7 @@
}
},
{
"id": "4e916af2d387ce9",
"id": "73f796c846875b9e",
"name": "package-2",
"version": "2.0.1",
"type": "deb",
@ -40,7 +40,7 @@
"locations": [
{
"path": "/somefile-2.txt",
"layerID": "sha256:c751a2f31455b3049bcab3e3af5861c9431116c9f4a46213e44dbeff8ab36985"
"layerID": "sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec"
}
],
"licenses": [],
@ -67,7 +67,7 @@
"type": "image",
"target": {
"userInput": "user-image-input",
"imageID": "sha256:9998e833a66442934ad948e5cbe898630773c369ef16517623254fa46edd171b",
"imageID": "sha256:2480160b55bec40c44d3b145c7b2c1c47160db8575c3dcae086d76b9370ae7ca",
"manifestDigest": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"tags": [
@ -77,18 +77,20 @@
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:135c16aca35f76c25a18cb6650c621a46b8b79864ad6f2834167de2679bb587d",
"digest": "sha256:fb6beecb75b39f4bb813dbf177e501edd5ddb3e69bb45cedeb78c676ee1b7a59",
"size": 22
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:c751a2f31455b3049bcab3e3af5861c9431116c9f4a46213e44dbeff8ab36985",
"digest": "sha256:319b588ce64253a87b533c8ed01cf0025e0eac98e7b516e12532957e1244fdec",
"size": 16
}
],
"manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjo2NzMsImRpZ2VzdCI6InNoYTI1Njo5OTk4ZTgzM2E2NjQ0MjkzNGFkOTQ4ZTVjYmU4OTg2MzA3NzNjMzY5ZWYxNjUxNzYyMzI1NGZhNDZlZGQxNzFiIn0sImxheWVycyI6W3sibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1NjoxMzVjMTZhY2EzNWY3NmMyNWExOGNiNjY1MGM2MjFhNDZiOGI3OTg2NGFkNmYyODM0MTY3ZGUyNjc5YmI1ODdkIn0seyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmltYWdlLnJvb3Rmcy5kaWZmLnRhci5nemlwIiwic2l6ZSI6MjA0OCwiZGlnZXN0Ijoic2hhMjU2OmM3NTFhMmYzMTQ1NWIzMDQ5YmNhYjNlM2FmNTg2MWM5NDMxMTE2YzlmNGE0NjIxM2U0NGRiZWZmOGFiMzY5ODUifV19",
"config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiV29ya2luZ0RpciI6Ii8iLCJPbkJ1aWxkIjpudWxsfSwiY3JlYXRlZCI6IjIwMjItMDEtMThUMjA6MzA6MTMuMDQ0Njg1NTg5WiIsImhpc3RvcnkiOlt7ImNyZWF0ZWQiOiIyMDIyLTAxLTE4VDIwOjMwOjEyLjE5OTA3MjQxOVoiLCJjcmVhdGVkX2J5IjoiQUREIGZpbGUtMS50eHQgL3NvbWVmaWxlLTEudHh0ICMgYnVpbGRraXQiLCJjb21tZW50IjoiYnVpbGRraXQuZG9ja2VyZmlsZS52MCJ9LHsiY3JlYXRlZCI6IjIwMjItMDEtMThUMjA6MzA6MTMuMDQ0Njg1NTg5WiIsImNyZWF0ZWRfYnkiOiJBREQgZmlsZS0yLnR4dCAvc29tZWZpbGUtMi50eHQgIyBidWlsZGtpdCIsImNvbW1lbnQiOiJidWlsZGtpdC5kb2NrZXJmaWxlLnYwIn1dLCJvcyI6ImxpbnV4Iiwicm9vdGZzIjp7InR5cGUiOiJsYXllcnMiLCJkaWZmX2lkcyI6WyJzaGEyNTY6MTM1YzE2YWNhMzVmNzZjMjVhMThjYjY2NTBjNjIxYTQ2YjhiNzk4NjRhZDZmMjgzNDE2N2RlMjY3OWJiNTg3ZCIsInNoYTI1NjpjNzUxYTJmMzE0NTViMzA0OWJjYWIzZTNhZjU4NjFjOTQzMTExNmM5ZjRhNDYyMTNlNDRkYmVmZjhhYjM2OTg1Il19fQ==",
"repoDigests": []
"manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjo2NjcsImRpZ2VzdCI6InNoYTI1NjoyNDgwMTYwYjU1YmVjNDBjNDRkM2IxNDVjN2IyYzFjNDcxNjBkYjg1NzVjM2RjYWUwODZkNzZiOTM3MGFlN2NhIn0sImxheWVycyI6W3sibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1NjpmYjZiZWVjYjc1YjM5ZjRiYjgxM2RiZjE3N2U1MDFlZGQ1ZGRiM2U2OWJiNDVjZWRlYjc4YzY3NmVlMWI3YTU5In0seyJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmltYWdlLnJvb3Rmcy5kaWZmLnRhci5nemlwIiwic2l6ZSI6MjA0OCwiZGlnZXN0Ijoic2hhMjU2OjMxOWI1ODhjZTY0MjUzYTg3YjUzM2M4ZWQwMWNmMDAyNWUwZWFjOThlN2I1MTZlMTI1MzI5NTdlMTI0NGZkZWMifV19",
"config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiV29ya2luZ0RpciI6Ii8iLCJPbkJ1aWxkIjpudWxsfSwiY3JlYXRlZCI6IjIwMjEtMTAtMDRUMTE6NDA6MDAuNjM4Mzk0NVoiLCJoaXN0b3J5IjpbeyJjcmVhdGVkIjoiMjAyMS0xMC0wNFQxMTo0MDowMC41OTA3MzE2WiIsImNyZWF0ZWRfYnkiOiJBREQgZmlsZS0xLnR4dCAvc29tZWZpbGUtMS50eHQgIyBidWlsZGtpdCIsImNvbW1lbnQiOiJidWlsZGtpdC5kb2NrZXJmaWxlLnYwIn0seyJjcmVhdGVkIjoiMjAyMS0xMC0wNFQxMTo0MDowMC42MzgzOTQ1WiIsImNyZWF0ZWRfYnkiOiJBREQgZmlsZS0yLnR4dCAvc29tZWZpbGUtMi50eHQgIyBidWlsZGtpdCIsImNvbW1lbnQiOiJidWlsZGtpdC5kb2NrZXJmaWxlLnYwIn1dLCJvcyI6ImxpbnV4Iiwicm9vdGZzIjp7InR5cGUiOiJsYXllcnMiLCJkaWZmX2lkcyI6WyJzaGEyNTY6ZmI2YmVlY2I3NWIzOWY0YmI4MTNkYmYxNzdlNTAxZWRkNWRkYjNlNjliYjQ1Y2VkZWI3OGM2NzZlZTFiN2E1OSIsInNoYTI1NjozMTliNTg4Y2U2NDI1M2E4N2I1MzNjOGVkMDFjZjAwMjVlMGVhYzk4ZTdiNTE2ZTEyNTMyOTU3ZTEyNDRmZGVjIl19fQ==",
"repoDigests": [],
"architecture": "",
"os": ""
}
},
"distro": {

View file

@ -15,6 +15,9 @@ type ImageMetadata struct {
RawManifest []byte `json:"manifest"`
RawConfig []byte `json:"config"`
RepoDigests []string `json:"repoDigests"`
Architecture string `json:"architecture"`
Variant string `json:"architectureVariant,omitempty"`
OS string `json:"os"`
}
// LayerMetadata represents all static metadata that defines what a container image layer is.
@ -42,6 +45,9 @@ func NewImageMetadata(img *image.Image, userInput string) ImageMetadata {
RawConfig: img.Metadata.RawConfig,
RawManifest: img.Metadata.RawManifest,
RepoDigests: img.Metadata.RepoDigests,
Architecture: img.Metadata.Architecture,
Variant: img.Metadata.Variant,
OS: img.Metadata.OS,
}
// populate image metadata

View file

@ -40,12 +40,13 @@ type Input struct {
Scheme Scheme
ImageSource image.Source
Location string
Platform string
autoDetectAvailableImageSources bool
}
// ParseInput generates a source Input that can be used as an argument to generate a new source
// from specific providers including a registry.
func ParseInput(userInput string, detectAvailableImageSources bool) (*Input, error) {
func ParseInput(userInput string, platform string, detectAvailableImageSources bool) (*Input, error) {
fs := afero.NewOsFs()
scheme, source, location, err := DetectScheme(fs, image.DetectSource, userInput)
if err != nil {
@ -71,12 +72,17 @@ func ParseInput(userInput string, detectAvailableImageSources bool) (*Input, err
}
}
if scheme != ImageScheme && platform != "" {
return nil, fmt.Errorf("cannot specify a platform for a non-image source")
}
// collect user input for downstream consumption
return &Input{
UserInput: userInput,
Scheme: scheme,
ImageSource: source,
Location: location,
Platform: platform,
autoDetectAvailableImageSources: detectAvailableImageSources,
}, nil
}
@ -147,10 +153,19 @@ func getImageWithRetryStrategy(in Input, registryOptions *image.RegistryOptions)
opts = append(opts, stereoscope.WithRegistryOptions(*registryOptions))
}
if in.Platform != "" {
opts = append(opts, stereoscope.WithPlatform(in.Platform))
}
img, err := stereoscope.GetImageFromSource(ctx, in.Location, in.ImageSource, opts...)
cleanup := func() {
if err := img.Cleanup(); err != nil {
log.Warnf("unable to cleanup image=%q: %w", in.UserInput, err)
}
}
if err == nil {
// Success on the first try!
return img, stereoscope.Cleanup, nil
return img, cleanup, nil
}
scheme := parseScheme(in.UserInput)
@ -180,11 +195,12 @@ func getImageWithRetryStrategy(in Input, registryOptions *image.RegistryOptions)
in.ImageSource = image.DetermineDefaultImagePullSource(in.UserInput)
}
img, err = stereoscope.GetImageFromSource(ctx, in.UserInput, in.ImageSource, opts...)
if err != nil {
return nil, nil, err
cleanup = func() {
if err := img.Cleanup(); err != nil {
log.Warnf("unable to cleanup image=%q: %w", in.UserInput, err)
}
}
return img, stereoscope.Cleanup, nil
return img, cleanup, err
}
func generateDirectorySource(fs afero.Fs, location string) (*Source, func(), error) {

View file

@ -26,22 +26,34 @@ func TestParseInput(t *testing.T) {
tests := []struct {
name string
input string
platform string
expected Scheme
errFn require.ErrorAssertionFunc
}{
{
name: "ParseInput parses a file input",
input: "test-fixtures/image-simple/file-1.txt",
expected: FileScheme,
},
{
name: "errors out when using platform for non-image scheme",
input: "test-fixtures/image-simple/file-1.txt",
platform: "arm64",
errFn: require.Error,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
sourceInput, err := ParseInput(test.input, true)
if err != nil {
t.Errorf("failed to ParseInput")
if test.errFn == nil {
test.errFn = require.NoError
}
sourceInput, err := ParseInput(test.input, test.platform, true)
test.errFn(t, err)
if test.expected != "" {
require.NotNil(t, sourceInput)
assert.Equal(t, sourceInput.Scheme, test.expected)
}
assert.Equal(t, sourceInput.Scheme, test.expected)
})
}
}
@ -452,7 +464,7 @@ func TestDirectoryExclusions(t *testing.T) {
registryOpts := &image.RegistryOptions{}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
sourceInput, err := ParseInput("dir:"+test.input, false)
sourceInput, err := ParseInput("dir:"+test.input, "", false)
require.NoError(t, err)
src, fn, err := New(*sourceInput, registryOpts, test.exclusions)
defer fn()
@ -546,7 +558,7 @@ func TestImageExclusions(t *testing.T) {
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
archiveLocation := imagetest.PrepareFixtureImage(t, "docker-archive", test.input)
sourceInput, err := ParseInput(archiveLocation, false)
sourceInput, err := ParseInput(archiveLocation, "", false)
require.NoError(t, err)
src, fn, err := New(*sourceInput, registryOpts, test.exclusions)
defer fn()

View file

@ -184,6 +184,14 @@ func TestPackagesCmdFlags(t *testing.T) {
assertInOutput("search-indexed-archives: false"),
},
},
{
name: "platform-option-wired-up",
args: []string{"packages", "--platform", "arm64", "-o", "json", "registry:busybox:1.31"},
assertions: []traitAssertion{
assertInOutput("sha256:1ee006886991ad4689838d3a288e0dd3fd29b70e276622f16b67a8922831a853"), // linux/arm64 image digest
assertSuccessfulReturnCode,
},
},
}
for _, test := range tests {

View file

@ -24,7 +24,7 @@ func BenchmarkImagePackageCatalogers(b *testing.B) {
for _, c := range cataloger.ImageCatalogers(cataloger.DefaultConfig()) {
// in case of future alteration where state is persisted, assume no dependency is safe to reuse
userInput := "docker-archive:" + tarPath
sourceInput, err := source.ParseInput(userInput, false)
sourceInput, err := source.ParseInput(userInput, "", false)
require.NoError(b, err)
theSource, cleanupSource, err := source.New(*sourceInput, nil, nil)
b.Cleanup(cleanupSource)

View file

@ -17,7 +17,7 @@ func catalogFixtureImage(t *testing.T, fixtureImageName string) (sbom.SBOM, *sou
imagetest.GetFixtureImage(t, "docker-archive", fixtureImageName)
tarPath := imagetest.GetFixtureImageTarPath(t, fixtureImageName)
userInput := "docker-archive:" + tarPath
sourceInput, err := source.ParseInput(userInput, false)
sourceInput, err := source.ParseInput(userInput, "", false)
require.NoError(t, err)
theSource, cleanupSource, err := source.New(*sourceInput, nil, nil)
t.Cleanup(cleanupSource)
@ -52,7 +52,7 @@ func catalogFixtureImage(t *testing.T, fixtureImageName string) (sbom.SBOM, *sou
func catalogDirectory(t *testing.T, dir string) (sbom.SBOM, *source.Source) {
userInput := "dir:" + dir
sourceInput, err := source.ParseInput(userInput, false)
sourceInput, err := source.ParseInput(userInput, "", false)
require.NoError(t, err)
theSource, cleanupSource, err := source.New(*sourceInput, nil, nil)
t.Cleanup(cleanupSource)